From a9a7e23d1ccce99214a33bb6f02cf6efec64e960 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 3 Jun 2023 20:55:54 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor:=20post=E3=81=AE=E3=82=B5=E3=83=BC?= =?UTF-8?q?=E3=83=93=E3=82=B9=E3=82=92=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF?= =?UTF-8?q?=E3=82=BF=E3=83=AA=E3=83=B3=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/dev/usbharu/hideout/Application.kt | 14 +- .../dev/usbharu/hideout/plugins/Routing.kt | 19 +- .../hideout/routing/api/internal/v1/Posts.kt | 48 +-- .../hideout/routing/api/internal/v1/Users.kt | 4 +- .../routing/api/mastodon/v1/Statuses.kt | 35 +- .../hideout/service/api/IPostApiService.kt | 24 ++ .../hideout/service/post/IPostService.kt | 58 +--- .../hideout/service/post/PostService.kt | 130 -------- .../routing/api/internal/v1/PostsTest.kt | 305 +++++++++--------- .../hideout/service/post/PostServiceTest.kt | 166 ---------- 10 files changed, 225 insertions(+), 578 deletions(-) create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/post/PostService.kt delete mode 100644 src/test/kotlin/dev/usbharu/hideout/service/post/PostServiceTest.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt index c8bfc06e..254d7a59 100644 --- a/src/main/kotlin/dev/usbharu/hideout/Application.kt +++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt @@ -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().value, ) configureRouting( - httpSignatureVerifyService = inject().value, - activityPubService = inject().value, - userService = inject().value, - activityPubUserService = inject().value, - postService = inject().value, - userApiService = inject().value, + httpSignatureVerifyService = inject().value, + activityPubService = inject().value, + userService = inject().value, + activityPubUserService = inject().value, + postService = inject().value, + userApiService = inject().value, ) } diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt index a424a5fa..6a52f394 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt @@ -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) diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt index 34772aff..ee533159 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt @@ -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() 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()?.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()?.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()?.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) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt index b9a8b068..9f357120 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt @@ -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())) diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/api/mastodon/v1/Statuses.kt b/src/main/kotlin/dev/usbharu/hideout/routing/api/mastodon/v1/Statuses.kt index 5d83463e..ba757257 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/api/mastodon/v1/Statuses.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/api/mastodon/v1/Statuses.kt @@ -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) +// // } +// // } +// } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt new file mode 100644 index 00000000..d54d48cb --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt @@ -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 + + suspend fun getByUser(nameOrId: String, + since: Instant? = null, + until: Instant? = null, + minId: Long? = null, + maxId: Long? = null, + limit: Int? = null, + userId: Long? = null): List +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt index af290950..970eaa26 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt @@ -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 - - 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 - - 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 - - suspend fun delete(id: String) + suspend fun createLocal(post: Post): Post + suspend fun createRemote(note: Note): Post } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/PostService.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/PostService.kt deleted file mode 100644 index 3ec2b071..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/PostService.kt +++ /dev/null @@ -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 { - 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 { - 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 { - TODO("Not yet implemented") - } - - override suspend fun delete(id: String) { - TODO("Not yet implemented") - } -} diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt index af38a764..50b54ded 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt @@ -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 { + val postService = mock { 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 { + val postService = mock { 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 { - onBlocking { findByIdForUser(any(), anyOrNull()) } doReturn post + val postService = mock { + 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 { - onBlocking { findByIdForUser(any(), isNotNull()) } doReturn post + val postService = mock { + onBlocking { getById(any(), isNotNull()) } doReturn post } val claim = mock { on { asLong() } doReturn 1234 @@ -239,17 +239,17 @@ class PostsTest { val payload = mock { on { getClaim(eq("uid")) } doReturn claim } - val postService = mock { - onBlocking { create(any()) } doAnswer { + val postService = mock { + onBlocking { createPost(any()) } doAnswer { val argument = it.getArgument(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 { - 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 { + val postService = mock { 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 { + val postService = mock { 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 { + val postService = mock { 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 { + val postService = mock { 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 { - onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post + val postService = mock { + 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 { - onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post + val postService = mock { + 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 { - onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post + val postService = mock { + 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 { - onBlocking { findByIdForUser(eq(12345L), anyOrNull()) } doReturn post + val postService = mock { + onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post } application { configureSerialization() diff --git a/src/test/kotlin/dev/usbharu/hideout/service/post/PostServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/post/PostServiceTest.kt deleted file mode 100644 index 92c517a6..00000000 --- a/src/test/kotlin/dev/usbharu/hideout/service/post/PostServiceTest.kt +++ /dev/null @@ -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) - } -} From 3b188f3033034d2a8cd68042e49cfc5d775e59c5 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:25:54 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20PostApiService=E3=82=92=E5=AE=9F?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/repository/IPostRepository.kt | 14 +++++- .../hideout/routing/api/internal/v1/Posts.kt | 12 +---- .../hideout/service/api/IPostApiService.kt | 3 +- .../hideout/service/api/PostApiServiceImpl.kt | 45 +++++++++++++++++++ .../hideout/service/post/IPostService.kt | 3 +- 5 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt index 3b77248e..7321fbf7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt @@ -1,11 +1,23 @@ package dev.usbharu.hideout.repository import dev.usbharu.hideout.domain.model.hideout.entity.Post +import java.time.Instant interface IPostRepository { suspend fun generateId(): Long suspend fun save(post: Post): Post - suspend fun findOneById(id: Long): Post? + suspend fun findOneById(id: Long, userId: Long? = null): Post? suspend fun findByUrl(url: String): Post? suspend fun delete(id: Long) + suspend fun findAll(since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List + suspend fun findByUserNameAndDomain(username: String, + s: String, + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long?): List + + suspend fun findByUserId(idOrNull: Long, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List } diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt index ee533159..2312d575 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Posts.kt @@ -1,9 +1,7 @@ package dev.usbharu.hideout.routing.api.internal.v1 -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.api.IPostApiService import dev.usbharu.hideout.util.InstantParseUtil @@ -24,15 +22,7 @@ fun Route.posts(postApiService: IPostApiService) { val userId = principal.payload.getClaim("uid").asLong() val receive = call.receive() - val postCreateDto = PostCreateDto( - text = receive.text, - overview = receive.overview, - visibility = receive.visibility, - repostId = receive.repostId, - repolyId = receive.replyId, - userId = userId - ) - val create = postApiService.createPost(postCreateDto) + val create = postApiService.createPost(receive, userId) call.response.header("Location", create.url) call.respond(HttpStatusCode.OK) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt index d54d48cb..00b6ff03 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt @@ -1,11 +1,10 @@ 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 createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): Post suspend fun getById(id: Long, userId: Long?): Post suspend fun getAll(since: Instant? = null, until: Instant? = null, diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt new file mode 100644 index 00000000..9061224e --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt @@ -0,0 +1,45 @@ +package dev.usbharu.hideout.service.api + +import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto +import dev.usbharu.hideout.domain.model.hideout.entity.Post +import dev.usbharu.hideout.exception.PostNotFoundException +import dev.usbharu.hideout.repository.IPostRepository +import dev.usbharu.hideout.service.post.IPostService +import dev.usbharu.hideout.util.AcctUtil +import org.koin.core.annotation.Single +import java.time.Instant + +@Single +class PostApiServiceImpl(private val postService: IPostService, private val postRepository: IPostRepository) : IPostApiService { + override suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): Post { + return postService.createLocal(PostCreateDto( + text = postForm.text, + overview = postForm.overview, + visibility = postForm.visibility, + repostId = postForm.repostId, + repolyId = postForm.replyId, + userId = userId + )) + } + + override suspend fun getById(id: Long, userId: Long?): Post { + return postRepository.findOneById(id, userId) + ?: throw PostNotFoundException("$id was not found or is not authorized.") + } + + override suspend fun getAll(since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + return postRepository.findAll(since, until, minId, maxId, limit, userId) + } + + override suspend fun getByUser(nameOrId: String, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + val idOrNull = nameOrId.toLongOrNull() + return if (idOrNull == null) { + val acct = AcctUtil.parse(nameOrId) + postRepository.findByUserNameAndDomain(acct.username, acct.domain + ?: Config.configData.domain, since, until, minId, maxId, limit, userId) + } else { + postRepository.findByUserId(idOrNull, since, until, minId, maxId, limit, userId) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt index 970eaa26..298dae0a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt @@ -1,9 +1,10 @@ package dev.usbharu.hideout.service.post import dev.usbharu.hideout.domain.model.ap.Note +import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto import dev.usbharu.hideout.domain.model.hideout.entity.Post interface IPostService { - suspend fun createLocal(post: Post): Post + suspend fun createLocal(post: PostCreateDto): Post suspend fun createRemote(note: Note): Post } From 4d60a7eeb8600f227a52eba73475a27af3d2e0be Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 3 Jun 2023 23:31:33 +0900 Subject: [PATCH 3/7] =?UTF-8?q?test:=20=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/routing/api/internal/v1/PostsTest.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt index 50b54ded..d4777c46 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/PostsTest.kt @@ -4,7 +4,6 @@ import com.auth0.jwt.interfaces.Claim import com.auth0.jwt.interfaces.Payload import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.config.Config -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.plugins.TOKEN_AUTH @@ -240,11 +239,12 @@ class PostsTest { on { getClaim(eq("uid")) } doReturn claim } val postService = mock { - onBlocking { createPost(any()) } doAnswer { - val argument = it.getArgument(0) + onBlocking { createPost(any(), any()) } doAnswer { + val argument = it.getArgument(0) + val userId = it.getArgument(1) Post( 123L, - argument.userId, + userId, null, argument.text, Instant.now().toEpochMilli(), @@ -279,9 +279,9 @@ class PostsTest { assertEquals(HttpStatusCode.OK, status) assertEquals("https://example.com", headers["Location"]) } - argumentCaptor { - verify(postService).createPost(capture()) - assertEquals(PostCreateDto("test", userId = 1234), firstValue) + argumentCaptor { + verify(postService).createPost(capture(), any()) + assertEquals(dev.usbharu.hideout.domain.model.hideout.form.Post("test"), firstValue) } } From cec78bff00f8fe593a307e7c661f6e589cbe13bd Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 3 Jun 2023 23:33:20 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20PostService=E3=82=92=E5=AE=9F?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/repository/PostRepositoryImpl.kt | 19 +++++++--- .../hideout/service/post/IPostService.kt | 2 -- .../hideout/service/post/PostServiceImpl.kt | 35 +++++++++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index b547f446..e50a0f09 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -9,6 +9,7 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import org.jetbrains.exposed.sql.transactions.transaction import org.koin.core.annotation.Single +import java.time.Instant @Single class PostRepositoryImpl(database: Database, private val idGenerateService: IdGenerateService) : IPostRepository { @@ -45,10 +46,8 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe } } - override suspend fun findOneById(id: Long): Post? { - return query { - Posts.select { Posts.id eq id }.singleOrNull()?.toPost() - } + override suspend fun findOneById(id: Long, userId: Long?): Post? { + TODO("Not yet implemented") } override suspend fun findByUrl(url: String): Post? { @@ -62,6 +61,18 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe Posts.deleteWhere { Posts.id eq id } } } + + override suspend fun findAll(since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + TODO("Not yet implemented") + } + + override suspend fun findByUserNameAndDomain(username: String, s: String, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + TODO("Not yet implemented") + } + + override suspend fun findByUserId(idOrNull: Long, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + TODO("Not yet implemented") + } } object Posts : Table() { diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt index 298dae0a..4459b8d2 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt @@ -1,10 +1,8 @@ package dev.usbharu.hideout.service.post -import dev.usbharu.hideout.domain.model.ap.Note import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto import dev.usbharu.hideout.domain.model.hideout.entity.Post interface IPostService { suspend fun createLocal(post: PostCreateDto): Post - suspend fun createRemote(note: Note): Post } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt new file mode 100644 index 00000000..fa9e20f1 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt @@ -0,0 +1,35 @@ +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.exception.UserNotFoundException +import dev.usbharu.hideout.repository.IPostRepository +import dev.usbharu.hideout.repository.IUserRepository +import dev.usbharu.hideout.service.activitypub.ActivityPubNoteService +import org.koin.core.annotation.Single +import java.time.Instant + +@Single +class PostServiceImpl(private val postRepository: IPostRepository, private val userRepository: IUserRepository, private val activityPubNoteService: ActivityPubNoteService) : IPostService { + override suspend fun createLocal(post: PostCreateDto): Post { + val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found") + val id = postRepository.generateId() + val createPost = Post( + id = id, + userId = post.userId, + overview = post.overview, + text = post.text, + createdAt = Instant.now().toEpochMilli(), + visibility = post.visibility, + url = "${user.url}/posts/$id", + repostId = null, + replyId = null + ) + activityPubNoteService.createNote(createPost) + return internalCreate(createPost) + } + + private suspend fun internalCreate(post: Post): Post { + return postRepository.save(post) + } +} From d3d91fc2bc2c2e218cbbc05d7019745fbe94526d Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 3 Jun 2023 23:54:13 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20Post=E3=81=AEid=E3=81=8C=E5=90=8C?= =?UTF-8?q?=E3=81=98=E6=99=82=E3=80=81=E4=B8=8A=E6=9B=B8=E3=81=8D=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/repository/PostRepositoryImpl.kt | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index e50a0f09..1c00fce0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -25,22 +25,38 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe @Suppress("InjectDispatcher") suspend fun query(block: suspend () -> T): T = - newSuspendedTransaction(Dispatchers.IO) { block() } + newSuspendedTransaction(Dispatchers.IO) { block() } override suspend fun save(post: Post): Post { return query { - Posts.insert { - it[id] = post.id - it[userId] = post.userId - it[overview] = post.overview - it[text] = post.text - it[createdAt] = post.createdAt - it[visibility] = post.visibility.ordinal - it[url] = post.url - it[repostId] = post.repostId - it[replyId] = post.replyId - it[sensitive] = post.sensitive - it[apId] = post.apId + val singleOrNull = Posts.select { Posts.id eq post.id }.singleOrNull() + if (singleOrNull == null) { + Posts.insert { + it[id] = post.id + it[userId] = post.userId + it[overview] = post.overview + it[text] = post.text + it[createdAt] = post.createdAt + it[visibility] = post.visibility.ordinal + it[url] = post.url + it[repostId] = post.repostId + it[replyId] = post.replyId + it[sensitive] = post.sensitive + it[apId] = post.apId + } + } else { + Posts.update({ Posts.id eq post.id }) { + it[userId] = post.userId + it[overview] = post.overview + it[text] = post.text + it[createdAt] = post.createdAt + it[visibility] = post.visibility.ordinal + it[url] = post.url + it[repostId] = post.repostId + it[replyId] = post.replyId + it[sensitive] = post.sensitive + it[apId] = post.apId + } } return@query post } @@ -92,16 +108,16 @@ object Posts : Table() { fun ResultRow.toPost(): Post { return Post( - id = this[Posts.id], - userId = this[Posts.userId], - overview = this[Posts.overview], - text = this[Posts.text], - createdAt = this[Posts.createdAt], - visibility = Visibility.values().first { visibility -> visibility.ordinal == this[Posts.visibility] }, - url = this[Posts.url], - repostId = this[Posts.repostId], - replyId = this[Posts.replyId], - sensitive = this[Posts.sensitive], - apId = this[Posts.apId] + id = this[Posts.id], + userId = this[Posts.userId], + overview = this[Posts.overview], + text = this[Posts.text], + createdAt = this[Posts.createdAt], + visibility = Visibility.values().first { visibility -> visibility.ordinal == this[Posts.visibility] }, + url = this[Posts.url], + repostId = this[Posts.repostId], + replyId = this[Posts.replyId], + sensitive = this[Posts.sensitive], + apId = this[Posts.apId] ) } From 1a63ae104c3374c34433da62c6c8700cf8241ca1 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sun, 4 Jun 2023 00:47:09 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20ActivityPub=E3=81=AEid=E3=81=8C?= =?UTF-8?q?=E9=87=8D=E8=A4=87=E3=81=97=E3=81=9F=E9=9A=9B=E3=81=AE=E5=87=A6?= =?UTF-8?q?=E7=90=86=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/repository/IPostRepository.kt | 1 + .../hideout/repository/PostRepositoryImpl.kt | 6 + .../activitypub/ActivityPubNoteServiceImpl.kt | 124 ++++++++++-------- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt index 7321fbf7..b8b3d9eb 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt @@ -20,4 +20,5 @@ interface IPostRepository { userId: Long?): List suspend fun findByUserId(idOrNull: Long, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List + suspend fun findByApId(id: String): Post? } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index 1c00fce0..6545d520 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -89,6 +89,12 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe override suspend fun findByUserId(idOrNull: Long, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { TODO("Not yet implemented") } + + override suspend fun findByApId(id: String): Post? { + return query { + Posts.select { Posts.apId eq id }.singleOrNull()?.toPost() + } + } } object Posts : Table() { diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt index cfbb564b..372d12ad 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt @@ -22,11 +22,11 @@ import java.time.Instant @Single class ActivityPubNoteServiceImpl( - private val httpClient: HttpClient, - private val jobQueueParentService: JobQueueParentService, - private val userService: IUserService, - private val postRepository: IPostRepository, - private val activityPubUserService: ActivityPubUserService + private val httpClient: HttpClient, + private val jobQueueParentService: JobQueueParentService, + private val userService: IUserService, + private val postRepository: IPostRepository, + private val activityPubUserService: ActivityPubUserService ) : ActivityPubNoteService { private val logger = LoggerFactory.getLogger(this::class.java) @@ -48,33 +48,44 @@ class ActivityPubNoteServiceImpl( val actor = props[DeliverPostJob.actor] val postEntity = Config.configData.objectMapper.readValue(props[DeliverPostJob.post]) val note = Note( - name = "Note", - id = postEntity.url, - attributedTo = actor, - content = postEntity.text, - published = Instant.ofEpochMilli(postEntity.createdAt).toString(), - to = listOf(public, actor + "/follower") + name = "Note", + id = postEntity.url, + attributedTo = actor, + content = postEntity.text, + published = Instant.ofEpochMilli(postEntity.createdAt).toString(), + to = listOf(public, actor + "/follower") ) val inbox = props[DeliverPostJob.inbox] logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox) httpClient.postAp( - urlString = inbox, - username = "$actor#pubkey", - jsonLd = Create( - name = "Create Note", - `object` = note, - actor = note.attributedTo, - id = "${Config.configData.url}/create/note/${postEntity.id}" - ) + urlString = inbox, + username = "$actor#pubkey", + jsonLd = Create( + name = "Create Note", + `object` = note, + actor = note.attributedTo, + id = "${Config.configData.url}/create/note/${postEntity.id}" + ) ) } override suspend fun fetchNote(url: String, targetActor: String?): Note { val post = postRepository.findByUrl(url) if (post != null) { - val user = userService.findById(post.userId) - val reply = post.replyId?.let { postRepository.findOneById(it) } - return Note( + return postToNote(post) + } + val response = httpClient.getAp( + url, + "$targetActor#pubkey" + ) + val note = response.body() + return note(note, targetActor, url) + } + + private suspend fun postToNote(post: Post): Note { + val user = userService.findById(post.userId) + val reply = post.replyId?.let { postRepository.findOneById(it) } + return Note( name = "Post", id = post.apId, attributedTo = user.url, @@ -84,38 +95,35 @@ class ActivityPubNoteServiceImpl( sensitive = post.sensitive, cc = listOf(public, user.url + "/follower"), inReplyTo = reply?.url - ) - } - val response = httpClient.getAp( - url, - "$targetActor#pubkey" ) - val note = response.body() - return note(note, targetActor, url) } private suspend fun ActivityPubNoteServiceImpl.note( - note: Note, - targetActor: String?, - url: String + note: Note, + targetActor: String?, + url: String ): Note { + val findByApId = postRepository.findByApId(url) + if (findByApId != null) { + return postToNote(findByApId) + } val person = activityPubUserService.fetchPerson( - note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"), - targetActor + note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"), + targetActor ) val user = - userService.findByUrl(person.url ?: throw IllegalActivityPubObjectException("person.url is null")) + userService.findByUrl(person.url ?: throw IllegalActivityPubObjectException("person.url is null")) val visibility = - if (note.to.contains(public) && note.cc.contains(public)) { - Visibility.PUBLIC - } else if (note.to.find { it.endsWith("/followers") } != null && note.cc.contains(public)) { - Visibility.UNLISTED - } else if (note.to.find { it.endsWith("/followers") } != null) { - Visibility.FOLLOWERS - } else { - Visibility.DIRECT - } + if (note.to.contains(public) && note.cc.contains(public)) { + Visibility.PUBLIC + } else if (note.to.find { it.endsWith("/followers") } != null && note.cc.contains(public)) { + Visibility.UNLISTED + } else if (note.to.find { it.endsWith("/followers") } != null) { + Visibility.FOLLOWERS + } else { + Visibility.DIRECT + } val reply = note.inReplyTo?.let { fetchNote(it, targetActor) @@ -123,25 +131,25 @@ class ActivityPubNoteServiceImpl( } postRepository.save( - Post( - id = postRepository.generateId(), - userId = user.id, - overview = null, - text = note.content.orEmpty(), - createdAt = Instant.parse(note.published).toEpochMilli(), - visibility = visibility, - url = note.id ?: url, - repostId = null, - replyId = reply?.id, - sensitive = note.sensitive, - apId = note.id ?: url, - ) + Post( + id = postRepository.generateId(), + userId = user.id, + overview = null, + text = note.content.orEmpty(), + createdAt = Instant.parse(note.published).toEpochMilli(), + visibility = visibility, + url = note.id ?: url, + repostId = null, + replyId = reply?.id, + sensitive = note.sensitive, + apId = note.id ?: url, + ) ) return note } override suspend fun fetchNote(note: Note, targetActor: String?): Note = - note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null")) + note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null")) companion object { val public: String = "https://www.w3.org/ns/activitystreams#Public" From 31e6b0f8d29bead8a0b5564aa01eae5531f3cd00 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sun, 4 Jun 2023 00:59:47 +0900 Subject: [PATCH 7/7] =?UTF-8?q?style:=20=E3=82=B9=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/repository/IPostRepository.kt | 40 +++++++++---- .../hideout/repository/PostRepositoryImpl.kt | 32 ++++++++-- .../hideout/routing/api/internal/v1/Users.kt | 8 ++- .../activitypub/ActivityPubNoteServiceImpl.kt | 2 +- .../hideout/service/api/IPostApiService.kt | 30 ++++++---- .../hideout/service/api/PostApiServiceImpl.kt | 60 ++++++++++++++----- .../hideout/service/post/PostServiceImpl.kt | 10 ++-- 7 files changed, 132 insertions(+), 50 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt index b8b3d9eb..8887853e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt @@ -3,22 +3,42 @@ package dev.usbharu.hideout.repository import dev.usbharu.hideout.domain.model.hideout.entity.Post import java.time.Instant +@Suppress("LongParameterList") interface IPostRepository { suspend fun generateId(): Long suspend fun save(post: Post): Post suspend fun findOneById(id: Long, userId: Long? = null): Post? suspend fun findByUrl(url: String): Post? suspend fun delete(id: Long) - suspend fun findAll(since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List - suspend fun findByUserNameAndDomain(username: String, - s: String, - since: Instant?, - until: Instant?, - minId: Long?, - maxId: Long?, - limit: Int?, - userId: Long?): List + suspend fun findAll( + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List + + suspend fun findByUserNameAndDomain( + username: String, + s: String, + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List + + suspend fun findByUserId( + idOrNull: Long, + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List - suspend fun findByUserId(idOrNull: Long, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List suspend fun findByApId(id: String): Post? } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index 6545d520..859bbd66 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -25,7 +25,7 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe @Suppress("InjectDispatcher") suspend fun query(block: suspend () -> T): T = - newSuspendedTransaction(Dispatchers.IO) { block() } + newSuspendedTransaction(Dispatchers.IO) { block() } override suspend fun save(post: Post): Post { return query { @@ -78,15 +78,39 @@ class PostRepositoryImpl(database: Database, private val idGenerateService: IdGe } } - override suspend fun findAll(since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + override suspend fun findAll( + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List { TODO("Not yet implemented") } - override suspend fun findByUserNameAndDomain(username: String, s: String, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + override suspend fun findByUserNameAndDomain( + username: String, + s: String, + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List { TODO("Not yet implemented") } - override suspend fun findByUserId(idOrNull: Long, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + override suspend fun findByUserId( + idOrNull: Long, + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List { TODO("Not yet implemented") } diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt index 9f357120..23142bd7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/api/internal/v1/Users.kt @@ -43,7 +43,9 @@ 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 +93,9 @@ 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())) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt index 372d12ad..4ccd223f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt @@ -152,6 +152,6 @@ class ActivityPubNoteServiceImpl( note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null")) companion object { - val public: String = "https://www.w3.org/ns/activitystreams#Public" + const val public: String = "https://www.w3.org/ns/activitystreams#Public" } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt index 00b6ff03..3d205faa 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt @@ -6,18 +6,22 @@ import java.time.Instant interface IPostApiService { suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): 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 + suspend fun getAll( + since: Instant? = null, + until: Instant? = null, + minId: Long? = null, + maxId: Long? = null, + limit: Int? = null, + userId: Long? = null + ): List - suspend fun getByUser(nameOrId: String, - since: Instant? = null, - until: Instant? = null, - minId: Long? = null, - maxId: Long? = null, - limit: Int? = null, - userId: Long? = null): List + suspend fun getByUser( + nameOrId: String, + since: Instant? = null, + until: Instant? = null, + minId: Long? = null, + maxId: Long? = null, + limit: Int? = null, + userId: Long? = null + ): List } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt index 9061224e..92ceb999 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt @@ -9,18 +9,24 @@ import dev.usbharu.hideout.service.post.IPostService import dev.usbharu.hideout.util.AcctUtil import org.koin.core.annotation.Single import java.time.Instant +import dev.usbharu.hideout.domain.model.hideout.form.Post as FormPost @Single -class PostApiServiceImpl(private val postService: IPostService, private val postRepository: IPostRepository) : IPostApiService { - override suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): Post { - return postService.createLocal(PostCreateDto( - text = postForm.text, - overview = postForm.overview, - visibility = postForm.visibility, - repostId = postForm.repostId, - repolyId = postForm.replyId, - userId = userId - )) +class PostApiServiceImpl( + private val postService: IPostService, + private val postRepository: IPostRepository +) : IPostApiService { + override suspend fun createPost(postForm: FormPost, userId: Long): Post { + return postService.createLocal( + PostCreateDto( + text = postForm.text, + overview = postForm.overview, + visibility = postForm.visibility, + repostId = postForm.repostId, + repolyId = postForm.replyId, + userId = userId + ) + ) } override suspend fun getById(id: Long, userId: Long?): Post { @@ -28,16 +34,38 @@ class PostApiServiceImpl(private val postService: IPostService, private val post ?: throw PostNotFoundException("$id was not found or is not authorized.") } - override suspend fun getAll(since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { - return postRepository.findAll(since, until, minId, maxId, limit, userId) - } + override suspend fun getAll( + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List = postRepository.findAll(since, until, minId, maxId, limit, userId) - override suspend fun getByUser(nameOrId: String, since: Instant?, until: Instant?, minId: Long?, maxId: Long?, limit: Int?, userId: Long?): List { + override suspend fun getByUser( + nameOrId: String, + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List { val idOrNull = nameOrId.toLongOrNull() return if (idOrNull == null) { val acct = AcctUtil.parse(nameOrId) - postRepository.findByUserNameAndDomain(acct.username, acct.domain - ?: Config.configData.domain, since, until, minId, maxId, limit, userId) + postRepository.findByUserNameAndDomain( + acct.username, + acct.domain + ?: Config.configData.domain, + since, + until, + minId, + maxId, + limit, + userId + ) } else { postRepository.findByUserId(idOrNull, since, until, minId, maxId, limit, userId) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt index fa9e20f1..d9384fe5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt @@ -10,7 +10,11 @@ import org.koin.core.annotation.Single import java.time.Instant @Single -class PostServiceImpl(private val postRepository: IPostRepository, private val userRepository: IUserRepository, private val activityPubNoteService: ActivityPubNoteService) : IPostService { +class PostServiceImpl( + private val postRepository: IPostRepository, + private val userRepository: IUserRepository, + private val activityPubNoteService: ActivityPubNoteService +) : IPostService { override suspend fun createLocal(post: PostCreateDto): Post { val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found") val id = postRepository.generateId() @@ -29,7 +33,5 @@ class PostServiceImpl(private val postRepository: IPostRepository, private val u return internalCreate(createPost) } - private suspend fun internalCreate(post: Post): Post { - return postRepository.save(post) - } + private suspend fun internalCreate(post: Post): Post = postRepository.save(post) }