mirror of https://github.com/usbharu/Hideout.git
refactor: postのサービスをリファクタリング
This commit is contained in:
parent
56bc156aa2
commit
de44bd7fc6
|
@ -14,6 +14,7 @@ import dev.usbharu.hideout.repository.IUserRepository
|
|||
import dev.usbharu.hideout.routing.register
|
||||
import dev.usbharu.hideout.service.activitypub.ActivityPubService
|
||||
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
|
||||
import dev.usbharu.hideout.service.api.IPostApiService
|
||||
import dev.usbharu.hideout.service.api.IUserApiService
|
||||
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
||||
import dev.usbharu.hideout.service.auth.IJwtService
|
||||
|
@ -23,7 +24,6 @@ import dev.usbharu.hideout.service.core.IdGenerateService
|
|||
import dev.usbharu.hideout.service.core.TwitterSnowflakeIdGenerateService
|
||||
import dev.usbharu.hideout.service.job.JobQueueParentService
|
||||
import dev.usbharu.hideout.service.job.KJobJobQueueParentService
|
||||
import dev.usbharu.hideout.service.post.IPostService
|
||||
import dev.usbharu.hideout.service.user.IUserAuthService
|
||||
import dev.usbharu.hideout.service.user.IUserService
|
||||
import dev.usbharu.kjob.exposed.ExposedKJob
|
||||
|
@ -107,12 +107,12 @@ fun Application.parent() {
|
|||
inject<JwkProvider>().value,
|
||||
)
|
||||
configureRouting(
|
||||
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
|
||||
activityPubService = inject<ActivityPubService>().value,
|
||||
userService = inject<IUserService>().value,
|
||||
activityPubUserService = inject<ActivityPubUserService>().value,
|
||||
postService = inject<IPostService>().value,
|
||||
userApiService = inject<IUserApiService>().value,
|
||||
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
|
||||
activityPubService = inject<ActivityPubService>().value,
|
||||
userService = inject<IUserService>().value,
|
||||
activityPubUserService = inject<ActivityPubUserService>().value,
|
||||
postService = inject<IPostApiService>().value,
|
||||
userApiService = inject<IUserApiService>().value,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,12 @@ import dev.usbharu.hideout.routing.activitypub.outbox
|
|||
import dev.usbharu.hideout.routing.activitypub.usersAP
|
||||
import dev.usbharu.hideout.routing.api.internal.v1.posts
|
||||
import dev.usbharu.hideout.routing.api.internal.v1.users
|
||||
import dev.usbharu.hideout.routing.api.mastodon.v1.statuses
|
||||
import dev.usbharu.hideout.routing.wellknown.webfinger
|
||||
import dev.usbharu.hideout.service.activitypub.ActivityPubService
|
||||
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
|
||||
import dev.usbharu.hideout.service.api.IPostApiService
|
||||
import dev.usbharu.hideout.service.api.IUserApiService
|
||||
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
|
||||
import dev.usbharu.hideout.service.post.IPostService
|
||||
import dev.usbharu.hideout.service.user.IUserService
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.autohead.*
|
||||
|
@ -19,12 +18,12 @@ import io.ktor.server.routing.*
|
|||
|
||||
@Suppress("LongParameterList")
|
||||
fun Application.configureRouting(
|
||||
httpSignatureVerifyService: HttpSignatureVerifyService,
|
||||
activityPubService: ActivityPubService,
|
||||
userService: IUserService,
|
||||
activityPubUserService: ActivityPubUserService,
|
||||
postService: IPostService,
|
||||
userApiService: IUserApiService
|
||||
httpSignatureVerifyService: HttpSignatureVerifyService,
|
||||
activityPubService: ActivityPubService,
|
||||
userService: IUserService,
|
||||
activityPubUserService: ActivityPubUserService,
|
||||
postService: IPostApiService,
|
||||
userApiService: IUserApiService
|
||||
) {
|
||||
install(AutoHeadResponse)
|
||||
routing {
|
||||
|
@ -32,10 +31,6 @@ fun Application.configureRouting(
|
|||
outbox()
|
||||
usersAP(activityPubUserService, userService)
|
||||
webfinger(userService)
|
||||
|
||||
route("/api/v1") {
|
||||
statuses(postService)
|
||||
}
|
||||
route("/api/internal/v1") {
|
||||
posts(postService)
|
||||
users(userService, userApiService)
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package dev.usbharu.hideout.routing.api.internal.v1
|
||||
|
||||
import dev.usbharu.hideout.config.Config
|
||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||
import dev.usbharu.hideout.domain.model.hideout.form.Post
|
||||
import dev.usbharu.hideout.exception.ParameterNotExistException
|
||||
import dev.usbharu.hideout.exception.PostNotFoundException
|
||||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||
import dev.usbharu.hideout.service.post.IPostService
|
||||
import dev.usbharu.hideout.util.AcctUtil
|
||||
import dev.usbharu.hideout.service.api.IPostApiService
|
||||
import dev.usbharu.hideout.util.InstantParseUtil
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
|
@ -18,7 +16,7 @@ import io.ktor.server.response.*
|
|||
import io.ktor.server.routing.*
|
||||
|
||||
@Suppress("LongMethod")
|
||||
fun Route.posts(postService: IPostService) {
|
||||
fun Route.posts(postApiService: IPostApiService) {
|
||||
route("/posts") {
|
||||
authenticate(TOKEN_AUTH) {
|
||||
post {
|
||||
|
@ -27,14 +25,14 @@ fun Route.posts(postService: IPostService) {
|
|||
|
||||
val receive = call.receive<Post>()
|
||||
val postCreateDto = PostCreateDto(
|
||||
text = receive.text,
|
||||
overview = receive.overview,
|
||||
visibility = receive.visibility,
|
||||
repostId = receive.repostId,
|
||||
repolyId = receive.replyId,
|
||||
userId = userId
|
||||
text = receive.text,
|
||||
overview = receive.overview,
|
||||
visibility = receive.visibility,
|
||||
repostId = receive.repostId,
|
||||
repolyId = receive.replyId,
|
||||
userId = userId
|
||||
)
|
||||
val create = postService.create(postCreateDto)
|
||||
val create = postApiService.createPost(postCreateDto)
|
||||
call.response.header("Location", create.url)
|
||||
call.respond(HttpStatusCode.OK)
|
||||
}
|
||||
|
@ -47,16 +45,13 @@ fun Route.posts(postService: IPostService) {
|
|||
val minId = call.request.queryParameters["minId"]?.toLong()
|
||||
val maxId = call.request.queryParameters["maxId"]?.toLong()
|
||||
val limit = call.request.queryParameters["limit"]?.toInt()
|
||||
call.respond(HttpStatusCode.OK, postService.findAll(since, until, minId, maxId, limit, userId))
|
||||
call.respond(HttpStatusCode.OK, postApiService.getAll(since, until, minId, maxId, limit, userId))
|
||||
}
|
||||
get("/{id}") {
|
||||
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
||||
val id = call.parameters["id"]?.toLong()
|
||||
?: throw ParameterNotExistException("Parameter(id='postsId') does not exist.")
|
||||
val post = (
|
||||
postService.findByIdForUser(id, userId)
|
||||
?: throw PostNotFoundException("$id was not found or is not authorized.")
|
||||
)
|
||||
val post = postApiService.getById(id, userId)
|
||||
call.respond(post)
|
||||
}
|
||||
}
|
||||
|
@ -66,28 +61,15 @@ fun Route.posts(postService: IPostService) {
|
|||
get {
|
||||
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
||||
val targetUserName = call.parameters["name"]
|
||||
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
||||
val targetUserId = targetUserName.toLongOrNull()
|
||||
val posts = if (targetUserId == null) {
|
||||
val acct = AcctUtil.parse(targetUserName)
|
||||
postService.findByUserNameAndDomainForUser(
|
||||
acct.username,
|
||||
acct.domain ?: Config.configData.domain,
|
||||
forUserId = userId
|
||||
)
|
||||
} else {
|
||||
postService.findByUserIdForUser(targetUserId, forUserId = userId)
|
||||
}
|
||||
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
||||
val posts = postApiService.getByUser(targetUserName, userId = userId)
|
||||
call.respond(posts)
|
||||
}
|
||||
get("/{id}") {
|
||||
val userId = call.principal<JWTPrincipal>()?.payload?.getClaim("uid")?.asLong()
|
||||
val id = call.parameters["id"]?.toLong()
|
||||
?: throw ParameterNotExistException("Parameter(name='postsId' does not exist.")
|
||||
val post = (
|
||||
postService.findByIdForUser(id, userId)
|
||||
?: throw PostNotFoundException("$id was not found or is not authorized.")
|
||||
)
|
||||
?: throw ParameterNotExistException("Parameter(name='postsId' does not exist.")
|
||||
val post = postApiService.getById(id, userId)
|
||||
call.respond(post)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ fun Route.users(userService: IUserService, userApiService: IUserApiService) {
|
|||
get {
|
||||
val userParameter = (
|
||||
call.parameters["name"]
|
||||
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
||||
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
||||
)
|
||||
if (userParameter.toLongOrNull() != null) {
|
||||
return@get call.respond(userApiService.findById(userParameter.toLong()))
|
||||
|
@ -91,7 +91,7 @@ fun Route.users(userService: IUserService, userApiService: IUserApiService) {
|
|||
get {
|
||||
val userParameter = (
|
||||
call.parameters["name"]
|
||||
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
||||
?: throw ParameterNotExistException("Parameter(name='userName@domain') does not exist.")
|
||||
)
|
||||
if (userParameter.toLongOrNull() != null) {
|
||||
return@get call.respond(userApiService.findFollowings(userParameter.toLong()))
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
package dev.usbharu.hideout.routing.api.mastodon.v1
|
||||
|
||||
import dev.usbharu.hideout.service.post.IPostService
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
fun Route.statuses(postService: IPostService) {
|
||||
// route("/statuses") {
|
||||
// post {
|
||||
// val status: StatusForPost = call.receive()
|
||||
// val post = dev.usbharu.hideout.domain.model.hideout.form.Post(
|
||||
// userId = status.userId,
|
||||
// createdAt = System.currentTimeMillis(),
|
||||
// text = status.status,
|
||||
// visibility = 1
|
||||
// )
|
||||
// postService.create(post)
|
||||
// call.respond(status)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
// @Suppress("UnusedPrivateMember")
|
||||
// fun Route.statuses(postService: IPostService) {
|
||||
// // route("/statuses") {
|
||||
// // post {
|
||||
// // val status: StatusForPost = call.receive()
|
||||
// // val post = dev.usbharu.hideout.domain.model.hideout.form.Post(
|
||||
// // userId = status.userId,
|
||||
// // createdAt = System.currentTimeMillis(),
|
||||
// // text = status.status,
|
||||
// // visibility = 1
|
||||
// // )
|
||||
// // postService.create(post)
|
||||
// // call.respond(status)
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package dev.usbharu.hideout.service.api
|
||||
|
||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||
import java.time.Instant
|
||||
|
||||
interface IPostApiService {
|
||||
suspend fun createPost(postCreateDto: PostCreateDto): Post
|
||||
suspend fun getById(id: Long, userId: Long?): Post
|
||||
suspend fun getAll(since: Instant? = null,
|
||||
until: Instant? = null,
|
||||
minId: Long? = null,
|
||||
maxId: Long? = null,
|
||||
limit: Int? = null,
|
||||
userId: Long? = null): List<Post>
|
||||
|
||||
suspend fun getByUser(nameOrId: String,
|
||||
since: Instant? = null,
|
||||
until: Instant? = null,
|
||||
minId: Long? = null,
|
||||
maxId: Long? = null,
|
||||
limit: Int? = null,
|
||||
userId: Long? = null): List<Post>
|
||||
}
|
|
@ -1,61 +1,9 @@
|
|||
package dev.usbharu.hideout.service.post
|
||||
|
||||
import dev.usbharu.hideout.config.Config
|
||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||
import dev.usbharu.hideout.domain.model.ap.Note
|
||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||
import java.time.Instant
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
interface IPostService {
|
||||
suspend fun create(post: Post): Post
|
||||
suspend fun create(post: PostCreateDto): Post
|
||||
suspend fun findAll(
|
||||
since: Instant? = null,
|
||||
until: Instant? = null,
|
||||
minId: Long? = null,
|
||||
maxId: Long? = null,
|
||||
limit: Int? = 10,
|
||||
userId: Long? = null
|
||||
): List<Post>
|
||||
|
||||
suspend fun findById(id: String): Post
|
||||
|
||||
/**
|
||||
* 権限を考慮して投稿を取得します。
|
||||
*
|
||||
* @param id
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
suspend fun findByIdForUser(id: Long, userId: Long?): Post?
|
||||
|
||||
/**
|
||||
* 権限を考慮してユーザーの投稿を取得します。
|
||||
*
|
||||
* @param userId
|
||||
* @param forUserId
|
||||
* @return
|
||||
*/
|
||||
suspend fun findByUserIdForUser(
|
||||
userId: Long,
|
||||
since: Instant? = null,
|
||||
until: Instant? = null,
|
||||
minId: Long? = null,
|
||||
maxId: Long? = null,
|
||||
limit: Int? = null,
|
||||
forUserId: Long? = null
|
||||
): List<Post>
|
||||
|
||||
suspend fun findByUserNameAndDomainForUser(
|
||||
userName: String,
|
||||
domain: String = Config.configData.domain,
|
||||
since: Instant? = null,
|
||||
until: Instant? = null,
|
||||
minId: Long? = null,
|
||||
maxId: Long? = null,
|
||||
limit: Int? = null,
|
||||
forUserId: Long? = null
|
||||
): List<Post>
|
||||
|
||||
suspend fun delete(id: String)
|
||||
suspend fun createLocal(post: Post): Post
|
||||
suspend fun createRemote(note: Note): Post
|
||||
}
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
package dev.usbharu.hideout.service.post
|
||||
|
||||
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
|
||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||
import dev.usbharu.hideout.repository.IPostRepository
|
||||
import dev.usbharu.hideout.repository.Posts
|
||||
import dev.usbharu.hideout.repository.UsersFollowers
|
||||
import dev.usbharu.hideout.repository.toPost
|
||||
import dev.usbharu.hideout.service.activitypub.ActivityPubNoteService
|
||||
import dev.usbharu.hideout.service.user.IUserService
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.inSubQuery
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.orIfNotNull
|
||||
import org.jetbrains.exposed.sql.orWhere
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.koin.core.annotation.Single
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.time.Instant
|
||||
|
||||
@Single
|
||||
class PostService(
|
||||
private val postRepository: IPostRepository,
|
||||
private val activityPubNoteService: ActivityPubNoteService,
|
||||
private val userService: IUserService
|
||||
) : IPostService {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(this::class.java)
|
||||
|
||||
override suspend fun create(post: Post): Post {
|
||||
logger.debug("create post={}", post)
|
||||
val postEntity = postRepository.save(post)
|
||||
activityPubNoteService.createNote(postEntity)
|
||||
return post
|
||||
}
|
||||
|
||||
override suspend fun create(post: PostCreateDto): Post {
|
||||
logger.debug("create post={}", post)
|
||||
val user = userService.findById(post.userId)
|
||||
val id = postRepository.generateId()
|
||||
val postEntity = Post(
|
||||
id = id,
|
||||
userId = user.id,
|
||||
overview = null,
|
||||
text = post.text,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
visibility = Visibility.PUBLIC,
|
||||
url = "${user.url}/posts/$id",
|
||||
repostId = null,
|
||||
replyId = null
|
||||
)
|
||||
postRepository.save(postEntity)
|
||||
return postEntity
|
||||
}
|
||||
|
||||
override suspend fun findAll(
|
||||
since: Instant?,
|
||||
until: Instant?,
|
||||
minId: Long?,
|
||||
maxId: Long?,
|
||||
limit: Int?,
|
||||
userId: Long?
|
||||
): List<Post> {
|
||||
return transaction {
|
||||
val select = Posts.select {
|
||||
Posts.visibility.eq(Visibility.PUBLIC.ordinal)
|
||||
}
|
||||
if (userId != null) {
|
||||
select.orWhere {
|
||||
Posts.userId.inSubQuery(
|
||||
UsersFollowers.slice(UsersFollowers.userId).select(UsersFollowers.followerId eq userId)
|
||||
)
|
||||
}
|
||||
}
|
||||
select.map { it.toPost() }
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun findById(id: String): Post {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByIdForUser(id: Long, userId: Long?): Post? {
|
||||
return transaction {
|
||||
val select = Posts.select(
|
||||
Posts.id.eq(id).and(
|
||||
Posts.visibility.eq(Visibility.PUBLIC.ordinal).orIfNotNull(
|
||||
userId?.let {
|
||||
Posts.userId.inSubQuery(
|
||||
UsersFollowers.slice(UsersFollowers.userId).select(UsersFollowers.followerId.eq(userId))
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
select.singleOrNull()?.toPost()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun findByUserIdForUser(
|
||||
userId: Long,
|
||||
since: Instant?,
|
||||
until: Instant?,
|
||||
minId: Long?,
|
||||
maxId: Long?,
|
||||
limit: Int?,
|
||||
forUserId: Long?
|
||||
): List<Post> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun findByUserNameAndDomainForUser(
|
||||
userName: String,
|
||||
domain: String,
|
||||
since: Instant?,
|
||||
until: Instant?,
|
||||
minId: Long?,
|
||||
maxId: Long?,
|
||||
limit: Int?,
|
||||
forUserId: Long?
|
||||
): List<Post> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override suspend fun delete(id: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
|||
import dev.usbharu.hideout.plugins.TOKEN_AUTH
|
||||
import dev.usbharu.hideout.plugins.configureSecurity
|
||||
import dev.usbharu.hideout.plugins.configureSerialization
|
||||
import dev.usbharu.hideout.service.post.IPostService
|
||||
import dev.usbharu.hideout.service.api.IPostApiService
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
|
@ -42,24 +42,24 @@ class PostsTest {
|
|||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
),
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 4322,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 4322,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking {
|
||||
findAll(
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = isNull()
|
||||
getAll(
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = isNull()
|
||||
)
|
||||
} doReturn posts
|
||||
}
|
||||
|
@ -118,15 +118,15 @@ class PostsTest {
|
|||
)
|
||||
)
|
||||
|
||||
val postService = mock<IPostService> {
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking {
|
||||
findAll(
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = isNotNull()
|
||||
getAll(
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = isNotNull()
|
||||
)
|
||||
} doReturn posts
|
||||
}
|
||||
|
@ -158,15 +158,15 @@ class PostsTest {
|
|||
config = ApplicationConfig("empty.conf")
|
||||
}
|
||||
val post = Post(
|
||||
12345,
|
||||
1234,
|
||||
text = "aaa",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
12345,
|
||||
1234,
|
||||
text = "aaa",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
onBlocking { findByIdForUser(any(), anyOrNull()) } doReturn post
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking { getById(any(), anyOrNull()) } doReturn post
|
||||
}
|
||||
application {
|
||||
configureSerialization()
|
||||
|
@ -189,15 +189,15 @@ class PostsTest {
|
|||
config = ApplicationConfig("empty.conf")
|
||||
}
|
||||
val post = Post(
|
||||
12345,
|
||||
1234,
|
||||
text = "aaa",
|
||||
visibility = Visibility.FOLLOWERS,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
12345,
|
||||
1234,
|
||||
text = "aaa",
|
||||
visibility = Visibility.FOLLOWERS,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
onBlocking { findByIdForUser(any(), isNotNull()) } doReturn post
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking { getById(any(), isNotNull()) } doReturn post
|
||||
}
|
||||
val claim = mock<Claim> {
|
||||
on { asLong() } doReturn 1234
|
||||
|
@ -239,17 +239,17 @@ class PostsTest {
|
|||
val payload = mock<Payload> {
|
||||
on { getClaim(eq("uid")) } doReturn claim
|
||||
}
|
||||
val postService = mock<IPostService> {
|
||||
onBlocking { create(any<PostCreateDto>()) } doAnswer {
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking { createPost(any<PostCreateDto>()) } doAnswer {
|
||||
val argument = it.getArgument<PostCreateDto>(0)
|
||||
Post(
|
||||
123L,
|
||||
argument.userId,
|
||||
null,
|
||||
argument.text,
|
||||
Instant.now().toEpochMilli(),
|
||||
Visibility.PUBLIC,
|
||||
"https://example.com"
|
||||
123L,
|
||||
argument.userId,
|
||||
null,
|
||||
argument.text,
|
||||
Instant.now().toEpochMilli(),
|
||||
Visibility.PUBLIC,
|
||||
"https://example.com"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ class PostsTest {
|
|||
assertEquals("https://example.com", headers["Location"])
|
||||
}
|
||||
argumentCaptor<PostCreateDto> {
|
||||
verify(postService).create(capture())
|
||||
verify(postService).createPost(capture())
|
||||
assertEquals(PostCreateDto("test", userId = 1234), firstValue)
|
||||
}
|
||||
}
|
||||
|
@ -299,25 +299,25 @@ class PostsTest {
|
|||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
),
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking {
|
||||
findByUserIdForUser(
|
||||
userId = any(),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
forUserId = anyOrNull()
|
||||
getByUser(
|
||||
nameOrId = any(),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = anyOrNull()
|
||||
)
|
||||
} doReturn posts
|
||||
}
|
||||
|
@ -351,26 +351,25 @@ class PostsTest {
|
|||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
),
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking {
|
||||
findByUserNameAndDomainForUser(
|
||||
userName = eq("test1"),
|
||||
domain = eq(Config.configData.domain),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
forUserId = anyOrNull()
|
||||
getByUser(
|
||||
nameOrId = eq("test1"),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = anyOrNull()
|
||||
)
|
||||
} doReturn posts
|
||||
}
|
||||
|
@ -404,26 +403,25 @@ class PostsTest {
|
|||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
),
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking {
|
||||
findByUserNameAndDomainForUser(
|
||||
userName = eq("test1"),
|
||||
domain = eq("example.com"),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
forUserId = anyOrNull()
|
||||
getByUser(
|
||||
nameOrId = eq("test1@example.com"),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = anyOrNull()
|
||||
)
|
||||
} doReturn posts
|
||||
}
|
||||
|
@ -457,26 +455,25 @@ class PostsTest {
|
|||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/1"
|
||||
),
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking {
|
||||
findByUserNameAndDomainForUser(
|
||||
userName = eq("test1"),
|
||||
domain = eq("example.com"),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
forUserId = anyOrNull()
|
||||
getByUser(
|
||||
nameOrId = eq("@test1@example.com"),
|
||||
since = anyOrNull(),
|
||||
until = anyOrNull(),
|
||||
minId = anyOrNull(),
|
||||
maxId = anyOrNull(),
|
||||
limit = anyOrNull(),
|
||||
userId = anyOrNull()
|
||||
)
|
||||
} doReturn posts
|
||||
}
|
||||
|
@ -502,15 +499,15 @@ class PostsTest {
|
|||
config = ApplicationConfig("empty.conf")
|
||||
}
|
||||
val post = Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||
}
|
||||
application {
|
||||
configureSerialization()
|
||||
|
@ -534,15 +531,15 @@ class PostsTest {
|
|||
config = ApplicationConfig("empty.conf")
|
||||
}
|
||||
val post = Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||
}
|
||||
application {
|
||||
configureSerialization()
|
||||
|
@ -566,15 +563,15 @@ class PostsTest {
|
|||
config = ApplicationConfig("empty.conf")
|
||||
}
|
||||
val post = Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||
}
|
||||
application {
|
||||
configureSerialization()
|
||||
|
@ -598,15 +595,15 @@ class PostsTest {
|
|||
config = ApplicationConfig("empty.conf")
|
||||
}
|
||||
val post = Post(
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
id = 123456,
|
||||
userId = 1,
|
||||
text = "test2",
|
||||
visibility = Visibility.PUBLIC,
|
||||
createdAt = Instant.now().toEpochMilli(),
|
||||
url = "https://example.com/posts/2"
|
||||
)
|
||||
val postService = mock<IPostService> {
|
||||
onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post
|
||||
val postService = mock<IPostApiService> {
|
||||
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
|
||||
}
|
||||
application {
|
||||
configureSerialization()
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
package dev.usbharu.hideout.service.post
|
||||
|
||||
import dev.usbharu.hideout.domain.model.hideout.entity.Post
|
||||
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
|
||||
import dev.usbharu.hideout.repository.Posts
|
||||
import dev.usbharu.hideout.repository.UsersFollowers
|
||||
import dev.usbharu.hideout.service.core.TwitterSnowflakeIdGenerateService
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.batchInsert
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.kotlin.mock
|
||||
import java.time.Instant
|
||||
import kotlin.test.assertContentEquals
|
||||
|
||||
class PostServiceTest {
|
||||
|
||||
lateinit var db: Database
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
db = Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
|
||||
transaction(db) {
|
||||
SchemaUtils.create(Posts)
|
||||
connection.prepareStatement("SET REFERENTIAL_INTEGRITY FALSE", false).executeUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
transaction(db) {
|
||||
SchemaUtils.drop(Posts)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `findAll 公開投稿を取得できる`() = runTest {
|
||||
val postService = PostService(mock(), mock(), mock())
|
||||
|
||||
suspend fun createPost(userId: Long, text: String, visibility: Visibility = Visibility.PUBLIC): Post {
|
||||
return Post(
|
||||
TwitterSnowflakeIdGenerateService.generateId(),
|
||||
userId,
|
||||
null,
|
||||
text,
|
||||
Instant.now().toEpochMilli(),
|
||||
visibility,
|
||||
"https://example.com${(userId.toString() + text).hashCode()}"
|
||||
)
|
||||
}
|
||||
|
||||
val userA: Long = 1
|
||||
val userB: Long = 2
|
||||
|
||||
val posts = listOf(
|
||||
createPost(userA, "hello"),
|
||||
createPost(userA, "hello1"),
|
||||
createPost(userA, "hello2"),
|
||||
createPost(userA, "hello3"),
|
||||
createPost(userA, "hello4"),
|
||||
createPost(userA, "hello5"),
|
||||
createPost(userA, "hello6"),
|
||||
createPost(userB, "good bay ", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay1", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay2", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay3", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay4", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay5", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay6", Visibility.FOLLOWERS),
|
||||
)
|
||||
|
||||
transaction {
|
||||
Posts.batchInsert(posts) {
|
||||
this[Posts.id] = it.id
|
||||
this[Posts.userId] = it.userId
|
||||
this[Posts.overview] = it.overview
|
||||
this[Posts.text] = it.text
|
||||
this[Posts.createdAt] = it.createdAt
|
||||
this[Posts.visibility] = it.visibility.ordinal
|
||||
this[Posts.url] = it.url
|
||||
this[Posts.replyId] = it.replyId
|
||||
this[Posts.repostId] = it.repostId
|
||||
this[Posts.sensitive] = it.sensitive
|
||||
this[Posts.apId] = it.apId
|
||||
}
|
||||
}
|
||||
|
||||
val expect = posts.filter { it.visibility == Visibility.PUBLIC }
|
||||
|
||||
val actual = postService.findAll()
|
||||
assertContentEquals(expect, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `findAll フォロー限定投稿を見れる`() = runTest {
|
||||
val postService = PostService(mock(), mock(), mock())
|
||||
|
||||
suspend fun createPost(userId: Long, text: String, visibility: Visibility = Visibility.PUBLIC): Post {
|
||||
return Post(
|
||||
TwitterSnowflakeIdGenerateService.generateId(),
|
||||
userId,
|
||||
null,
|
||||
text,
|
||||
Instant.now().toEpochMilli(),
|
||||
visibility,
|
||||
"https://example.com${(userId.toString() + text).hashCode()}"
|
||||
)
|
||||
}
|
||||
|
||||
val userA: Long = 1
|
||||
val userB: Long = 2
|
||||
|
||||
val posts = listOf(
|
||||
createPost(userA, "hello"),
|
||||
createPost(userA, "hello1"),
|
||||
createPost(userA, "hello2"),
|
||||
createPost(userA, "hello3"),
|
||||
createPost(userA, "hello4"),
|
||||
createPost(userA, "hello5"),
|
||||
createPost(userA, "hello6"),
|
||||
createPost(userB, "good bay ", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay1", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay2", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay3", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay4", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay5", Visibility.FOLLOWERS),
|
||||
createPost(userB, "good bay6", Visibility.FOLLOWERS),
|
||||
)
|
||||
|
||||
transaction(db) {
|
||||
SchemaUtils.create(UsersFollowers)
|
||||
}
|
||||
|
||||
transaction {
|
||||
Posts.batchInsert(posts) {
|
||||
this[Posts.id] = it.id
|
||||
this[Posts.userId] = it.userId
|
||||
this[Posts.overview] = it.overview
|
||||
this[Posts.text] = it.text
|
||||
this[Posts.createdAt] = it.createdAt
|
||||
this[Posts.visibility] = it.visibility.ordinal
|
||||
this[Posts.url] = it.url
|
||||
this[Posts.replyId] = it.replyId
|
||||
this[Posts.repostId] = it.repostId
|
||||
this[Posts.sensitive] = it.sensitive
|
||||
this[Posts.apId] = it.apId
|
||||
}
|
||||
UsersFollowers.insert {
|
||||
it[id] = 100L
|
||||
it[userId] = userB
|
||||
it[followerId] = userA
|
||||
}
|
||||
}
|
||||
|
||||
val actual = postService.findAll(userId = userA)
|
||||
assertContentEquals(posts, actual)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue