From 5f85a25daf6d9b57ba4c40c28c0c157aa8ba263b Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:29:52 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20ActivityPub=E3=82=92AP=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/dev/usbharu/hideout/Application.kt | 18 ++++----- .../domain/model/ap/ObjectDeserializer.kt | 2 +- .../dev/usbharu/hideout/plugins/Routing.kt | 12 +++--- .../routing/activitypub/InboxRouting.kt | 10 ++--- .../routing/activitypub/UserRouting.kt | 6 +-- .../APAcceptService.kt} | 4 +- .../APAcceptServiceImpl.kt} | 6 +-- .../APCreateService.kt} | 4 +- .../APCreateServiceImpl.kt} | 10 ++--- .../APLikeService.kt} | 4 +- .../APLikeServiceImpl.kt} | 14 +++---- .../APNoteService.kt} | 4 +- .../APNoteServiceImpl.kt} | 15 +++++--- .../APReactionService.kt} | 4 +- .../APReactionServiceImpl.kt} | 6 +-- .../APReceiveFollowService.kt} | 4 +- .../APReceiveFollowServiceImpl.kt} | 10 ++--- .../APSendFollowService.kt} | 4 +- .../APSendFollowServiceImpl.kt} | 4 +- .../ActivityPubService.kt => ap/APService.kt} | 4 +- .../APServiceImpl.kt} | 38 +++++++++---------- .../APUndoService.kt} | 4 +- .../APUndoServiceImpl.kt} | 10 ++--- .../APUserService.kt} | 4 +- .../APUserServiceImpl.kt} | 6 +-- .../hideout/service/post/PostServiceImpl.kt | 6 +-- .../service/reaction/ReactionServiceImpl.kt | 6 +-- .../hideout/service/user/UserService.kt | 6 +-- .../routing/activitypub/InboxRoutingKtTest.kt | 16 ++++---- .../routing/activitypub/UsersAPTest.kt | 10 ++--- .../APNoteServiceImplTest.kt} | 8 ++-- .../APReceiveFollowServiceImplTest.kt} | 12 +++--- 32 files changed, 137 insertions(+), 134 deletions(-) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubAcceptService.kt => ap/APAcceptService.kt} (68%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubAcceptServiceImpl.kt => ap/APAcceptServiceImpl.kt} (92%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubCreateService.kt => ap/APCreateService.kt} (68%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubCreateServiceImpl.kt => ap/APCreateServiceImpl.kt} (80%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubLikeService.kt => ap/APLikeService.kt} (67%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubLikeServiceImpl.kt => ap/APLikeServiceImpl.kt} (80%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubNoteService.kt => ap/APNoteService.kt} (84%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubNoteServiceImpl.kt => ap/APNoteServiceImpl.kt} (95%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubReactionService.kt => ap/APReactionService.kt} (84%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubReactionServiceImpl.kt => ap/APReactionServiceImpl.kt} (96%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubReceiveFollowService.kt => ap/APReceiveFollowService.kt} (78%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubReceiveFollowServiceImpl.kt => ap/APReceiveFollowServiceImpl.kt} (90%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubSendFollowService.kt => ap/APSendFollowService.kt} (58%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubSendFollowServiceImpl.kt => ap/APSendFollowServiceImpl.kt} (80%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubService.kt => ap/APService.kt} (96%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubServiceImpl.kt => ap/APServiceImpl.kt} (58%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubUndoService.kt => ap/APUndoService.kt} (67%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubUndoServiceImpl.kt => ap/APUndoServiceImpl.kt} (87%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubUserService.kt => ap/APUserService.kt} (79%) rename src/main/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubUserServiceImpl.kt => ap/APUserServiceImpl.kt} (97%) rename src/test/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubNoteServiceImplTest.kt => ap/APNoteServiceImplTest.kt} (95%) rename src/test/kotlin/dev/usbharu/hideout/service/{activitypub/ActivityPubReceiveFollowServiceImplTest.kt => ap/APReceiveFollowServiceImplTest.kt} (95%) diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt index dc4d2788..2af9ef54 100644 --- a/src/main/kotlin/dev/usbharu/hideout/Application.kt +++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt @@ -15,8 +15,8 @@ import dev.usbharu.hideout.plugins.* import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.UserQueryService 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.ap.APService +import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.UserAuthApiService @@ -109,9 +109,9 @@ fun Application.parent() { ) configureRouting( httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value, - activityPubService = inject<ActivityPubService>().value, + apService = inject<APService>().value, userService = inject<IUserService>().value, - activityPubUserService = inject<ActivityPubUserService>().value, + apUserService = inject<APUserService>().value, postService = inject<IPostApiService>().value, userApiService = inject<IUserApiService>().value, userQueryService = inject<UserQueryService>().value, @@ -128,28 +128,28 @@ fun Application.worker() { connectionDatabase = inject<Database>().value }.start() - val activityPubService = inject<ActivityPubService>().value + val apService = inject<APService>().value kJob.register(ReceiveFollowJob) { execute { - activityPubService.processActivity(this, it) + apService.processActivity(this, it) } } kJob.register(DeliverPostJob) { execute { - activityPubService.processActivity(this, it) + apService.processActivity(this, it) } } kJob.register(DeliverReactionJob) { execute { - activityPubService.processActivity(this, it) + apService.processActivity(this, it) } } kJob.register(DeliverRemoveReactionJob) { execute { - activityPubService.processActivity(this, it) + apService.processActivity(this, it) } } } diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt index d3b47879..66af888a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt +++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/ObjectDeserializer.kt @@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.JsonNode -import dev.usbharu.hideout.service.activitypub.ExtendedActivityVocabulary +import dev.usbharu.hideout.service.ap.ExtendedActivityVocabulary class ObjectDeserializer : JsonDeserializer<Object>() { @Suppress("LongMethod", "CyclomaticComplexMethod") diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt index 5fcd18de..0567db26 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt @@ -9,8 +9,8 @@ import dev.usbharu.hideout.routing.api.internal.v1.auth import dev.usbharu.hideout.routing.api.internal.v1.posts import dev.usbharu.hideout.routing.api.internal.v1.users 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.ap.APService +import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.UserAuthApiService @@ -25,9 +25,9 @@ import io.ktor.server.routing.* @Suppress("LongParameterList") fun Application.configureRouting( httpSignatureVerifyService: HttpSignatureVerifyService, - activityPubService: ActivityPubService, + apService: APService, userService: IUserService, - activityPubUserService: ActivityPubUserService, + apUserService: APUserService, postService: IPostApiService, userApiService: IUserApiService, userQueryService: UserQueryService, @@ -38,9 +38,9 @@ fun Application.configureRouting( ) { install(AutoHeadResponse) routing { - inbox(httpSignatureVerifyService, activityPubService) + inbox(httpSignatureVerifyService, apService) outbox() - usersAP(activityPubUserService, userQueryService, followerQueryService, transaction) + usersAP(apUserService, userQueryService, followerQueryService, transaction) webfinger(webFingerApiService) route("/api/internal/v1") { posts(postService) diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRouting.kt index 92a216bb..dbdcd666 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRouting.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRouting.kt @@ -13,7 +13,7 @@ import io.ktor.server.routing.* fun Routing.inbox( httpSignatureVerifyService: HttpSignatureVerifyService, - activityPubService: dev.usbharu.hideout.service.activitypub.ActivityPubService + apService: dev.usbharu.hideout.service.ap.APService ) { route("/inbox") { get { @@ -25,9 +25,9 @@ fun Routing.inbox( } val json = call.receiveText() call.application.log.trace("Received: $json") - val activityTypes = activityPubService.parseActivity(json) + val activityTypes = apService.parseActivity(json) call.application.log.debug("ActivityTypes: ${activityTypes.name}") - val response = activityPubService.processActivity(json, activityTypes) + val response = apService.processActivity(json, activityTypes) when (response) { is ActivityPubObjectResponse -> call.respond( response.httpStatusCode, @@ -54,9 +54,9 @@ fun Routing.inbox( } val json = call.receiveText() call.application.log.trace("Received: $json") - val activityTypes = activityPubService.parseActivity(json) + val activityTypes = apService.parseActivity(json) call.application.log.debug("ActivityTypes: ${activityTypes.name}") - val response = activityPubService.processActivity(json, activityTypes) + val response = apService.processActivity(json, activityTypes) when (response) { is ActivityPubObjectResponse -> call.respond( response.httpStatusCode, diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt index 734c45c8..c4b03cba 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt @@ -5,7 +5,7 @@ import dev.usbharu.hideout.exception.ParameterNotExistException import dev.usbharu.hideout.plugins.respondAp import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.activitypub.ActivityPubUserService +import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.util.HttpUtil.Activity import dev.usbharu.hideout.util.HttpUtil.JsonLd @@ -16,7 +16,7 @@ import io.ktor.server.response.* import io.ktor.server.routing.* fun Routing.usersAP( - activityPubUserService: ActivityPubUserService, + apUserService: APUserService, userQueryService: UserQueryService, followerQueryService: FollowerQueryService, transaction: Transaction @@ -27,7 +27,7 @@ fun Routing.usersAP( call.application.log.debug("Authorization: ${call.request.header("Authorization")}") val name = call.parameters["name"] ?: throw ParameterNotExistException("Parameter(name='name') does not exist.") - val person = activityPubUserService.getPersonByName(name) + val person = apUserService.getPersonByName(name) return@handle call.respondAp( person, HttpStatusCode.OK diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubAcceptService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt similarity index 68% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubAcceptService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt index d0746c44..fdcbbf61 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubAcceptService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt @@ -1,8 +1,8 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ap.Accept -interface ActivityPubAcceptService { +interface APAcceptService { suspend fun receiveAccept(accept: Accept): ActivityPubResponse } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubAcceptServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptServiceImpl.kt similarity index 92% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubAcceptServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptServiceImpl.kt index 19df2c97..b8fd337f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubAcceptServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ActivityPubStringResponse @@ -11,10 +11,10 @@ import io.ktor.http.* import org.koin.core.annotation.Single @Single -class ActivityPubAcceptServiceImpl( +class APAcceptServiceImpl( private val userService: IUserService, private val userQueryService: UserQueryService -) : ActivityPubAcceptService { +) : APAcceptService { override suspend fun receiveAccept(accept: Accept): ActivityPubResponse { val value = accept.`object` ?: throw IllegalActivityPubObjectException("object is null") if (value.type.contains("Follow").not()) { diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateService.kt similarity index 68% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateService.kt index 632c801e..29fa38de 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateService.kt @@ -1,8 +1,8 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ap.Create -interface ActivityPubCreateService { +interface APCreateService { suspend fun receiveCreate(create: Create): ActivityPubResponse } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateServiceImpl.kt similarity index 80% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateServiceImpl.kt index 85e88b57..2f1e4bd0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubCreateServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ActivityPubStringResponse @@ -10,10 +10,10 @@ import io.ktor.http.* import org.koin.core.annotation.Single @Single -class ActivityPubCreateServiceImpl( - private val activityPubNoteService: ActivityPubNoteService, +class APCreateServiceImpl( + private val apNoteService: APNoteService, private val transaction: Transaction -) : ActivityPubCreateService { +) : APCreateService { override suspend fun receiveCreate(create: Create): ActivityPubResponse { val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null") if (value.type.contains("Note").not()) { @@ -22,7 +22,7 @@ class ActivityPubCreateServiceImpl( return transaction.transaction { val note = value as Note - activityPubNoteService.fetchNote(note) + apNoteService.fetchNote(note) ActivityPubStringResponse(HttpStatusCode.OK, "Created") } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubLikeService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt similarity index 67% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubLikeService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt index 19d3f341..0ecb30a6 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubLikeService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt @@ -1,8 +1,8 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ap.Like -interface ActivityPubLikeService { +interface APLikeService { suspend fun receiveLike(like: Like): ActivityPubResponse } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubLikeServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeServiceImpl.kt similarity index 80% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubLikeServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeServiceImpl.kt index a9f12cfa..929f79c5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubLikeServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ActivityPubStringResponse @@ -12,21 +12,21 @@ import io.ktor.http.* import org.koin.core.annotation.Single @Single -class ActivityPubLikeServiceImpl( +class APLikeServiceImpl( private val reactionService: IReactionService, - private val activityPubUserService: ActivityPubUserService, - private val activityPubNoteService: ActivityPubNoteService, + private val apUserService: APUserService, + private val apNoteService: APNoteService, private val userQueryService: UserQueryService, private val postQueryService: PostQueryService, private val transaction: Transaction -) : ActivityPubLikeService { +) : APLikeService { override suspend fun receiveLike(like: Like): ActivityPubResponse { val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null") val content = like.content ?: throw IllegalActivityPubObjectException("content is null") like.`object` ?: throw IllegalActivityPubObjectException("object is null") transaction.transaction { - val person = activityPubUserService.fetchPerson(actor) - activityPubNoteService.fetchNote(like.`object`!!) + val person = apUserService.fetchPerson(actor) + apNoteService.fetchNote(like.`object`!!) val user = userQueryService.findByUrl( person.url diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt similarity index 84% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt index 2c289415..33b9d457 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt @@ -1,11 +1,11 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ap.Note import dev.usbharu.hideout.domain.model.hideout.entity.Post import dev.usbharu.hideout.domain.model.job.DeliverPostJob import kjob.core.job.JobProps -interface ActivityPubNoteService { +interface APNoteService { suspend fun createNote(post: Post) suspend fun createNoteJob(props: JobProps<DeliverPostJob>) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImpl.kt similarity index 95% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImpl.kt index a6cdce08..d46d02a7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.config.Config @@ -23,15 +23,15 @@ import org.slf4j.LoggerFactory import java.time.Instant @Single -class ActivityPubNoteServiceImpl( +class APNoteServiceImpl( private val httpClient: HttpClient, private val jobQueueParentService: JobQueueParentService, private val postRepository: IPostRepository, - private val activityPubUserService: ActivityPubUserService, + private val apUserService: APUserService, private val userQueryService: UserQueryService, private val followerQueryService: FollowerQueryService, private val postQueryService: PostQueryService -) : ActivityPubNoteService { +) : APNoteService { private val logger = LoggerFactory.getLogger(this::class.java) @@ -75,9 +75,12 @@ class ActivityPubNoteServiceImpl( override suspend fun fetchNote(url: String, targetActor: String?): Note { val post = postQueryService.findByUrl(url) - if (post != null) { + try { return postToNote(post) + } catch (_: NoSuchElementException) { + } catch (_: IllegalArgumentException) { } + val response = httpClient.getAp( url, targetActor?.let { "$targetActor#pubkey" } @@ -118,7 +121,7 @@ class ActivityPubNoteServiceImpl( } private suspend fun internalNote(note: Note, targetActor: String?, url: String): Note { - val person = activityPubUserService.fetchPerson( + val person = apUserService.fetchPerson( note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"), targetActor ) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt similarity index 84% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReactionService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt index f3ac458c..aa12198c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt @@ -1,11 +1,11 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.hideout.entity.Reaction import dev.usbharu.hideout.domain.model.job.DeliverReactionJob import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob import kjob.core.job.JobProps -interface ActivityPubReactionService { +interface APReactionService { suspend fun reaction(like: Reaction) suspend fun removeReaction(like: Reaction) suspend fun reactionJob(props: JobProps<DeliverReactionJob>) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReactionServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionServiceImpl.kt similarity index 96% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReactionServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionServiceImpl.kt index 3a6f1771..3635836b 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReactionServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.config.Config @@ -19,14 +19,14 @@ import org.koin.core.annotation.Single import java.time.Instant @Single -class ActivityPubReactionServiceImpl( +class APReactionServiceImpl( private val jobQueueParentService: JobQueueParentService, private val iPostRepository: IPostRepository, private val httpClient: HttpClient, private val userQueryService: UserQueryService, private val followerQueryService: FollowerQueryService, private val postQueryService: PostQueryService -) : ActivityPubReactionService { +) : APReactionService { override suspend fun reaction(like: Reaction) { val followers = followerQueryService.findFollowersById(like.userId) val user = userQueryService.findById(like.userId) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt similarity index 78% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt index 378b0db6..7aaf21e5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt @@ -1,11 +1,11 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob import kjob.core.job.JobProps -interface ActivityPubReceiveFollowService { +interface APReceiveFollowService { suspend fun receiveFollow(follow: Follow): ActivityPubResponse suspend fun receiveFollowJob(props: JobProps<ReceiveFollowJob>) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImpl.kt similarity index 90% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImpl.kt index 94392412..3e8500df 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.config.Config @@ -18,14 +18,14 @@ import kjob.core.job.JobProps import org.koin.core.annotation.Single @Single -class ActivityPubReceiveFollowServiceImpl( +class APReceiveFollowServiceImpl( private val jobQueueParentService: JobQueueParentService, - private val activityPubUserService: ActivityPubUserService, + private val apUserService: APUserService, private val userService: IUserService, private val httpClient: HttpClient, private val userQueryService: UserQueryService, private val transaction: Transaction -) : ActivityPubReceiveFollowService { +) : APReceiveFollowService { override suspend fun receiveFollow(follow: Follow): ActivityPubResponse { // TODO: Verify HTTP Signature jobQueueParentService.schedule(ReceiveFollowJob) { @@ -40,7 +40,7 @@ class ActivityPubReceiveFollowServiceImpl( transaction.transaction { val actor = props[ReceiveFollowJob.actor] val targetActor = props[ReceiveFollowJob.targetActor] - val person = activityPubUserService.fetchPerson(actor, targetActor) + val person = apUserService.fetchPerson(actor, targetActor) val follow = Config.configData.objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow]) httpClient.postAp( urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"), diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubSendFollowService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowService.kt similarity index 58% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubSendFollowService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowService.kt index 8d0dd1f2..d4058113 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubSendFollowService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowService.kt @@ -1,7 +1,7 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto -interface ActivityPubSendFollowService { +interface APSendFollowService { suspend fun sendFollow(sendFollowDto: SendFollowDto) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubSendFollowServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowServiceImpl.kt similarity index 80% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubSendFollowServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowServiceImpl.kt index e73e9266..a2ccb74f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubSendFollowServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto @@ -7,7 +7,7 @@ import io.ktor.client.* import org.koin.core.annotation.Single @Single -class ActivityPubSendFollowServiceImpl(private val httpClient: HttpClient) : ActivityPubSendFollowService { +class APSendFollowServiceImpl(private val httpClient: HttpClient) : APSendFollowService { override suspend fun sendFollow(sendFollowDto: SendFollowDto) { val follow = Follow( name = "Follow", diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt similarity index 96% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt index bec7f2fb..719149c1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt @@ -1,10 +1,10 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.job.HideoutJob import kjob.core.dsl.JobContextWithProps -interface ActivityPubService { +interface APService { fun parseActivity(json: String): ActivityType suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse? diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APServiceImpl.kt similarity index 58% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APServiceImpl.kt index 95355d2a..f2cd4000 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.readValue @@ -14,15 +14,15 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory @Single -class ActivityPubServiceImpl( - private val activityPubReceiveFollowService: ActivityPubReceiveFollowService, - private val activityPubNoteService: ActivityPubNoteService, - private val activityPubUndoService: ActivityPubUndoService, - private val activityPubAcceptService: ActivityPubAcceptService, - private val activityPubCreateService: ActivityPubCreateService, - private val activityPubLikeService: ActivityPubLikeService, - private val activityPubReactionService: ActivityPubReactionService -) : ActivityPubService { +class APServiceImpl( + private val apReceiveFollowService: APReceiveFollowService, + private val apNoteService: APNoteService, + private val apUndoService: APUndoService, + private val apAcceptService: APAcceptService, + private val apCreateService: APCreateService, + private val apLikeService: APLikeService, + private val apReactionService: APReactionService +) : APService { val logger: Logger = LoggerFactory.getLogger(this::class.java) override fun parseActivity(json: String): ActivityType { @@ -44,17 +44,17 @@ class ActivityPubServiceImpl( override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse { logger.debug("proccess activity: {}", type) return when (type) { - ActivityType.Accept -> activityPubAcceptService.receiveAccept(configData.objectMapper.readValue(json)) - ActivityType.Follow -> activityPubReceiveFollowService.receiveFollow( + ActivityType.Accept -> apAcceptService.receiveAccept(configData.objectMapper.readValue(json)) + ActivityType.Follow -> apReceiveFollowService.receiveFollow( configData.objectMapper.readValue( json, Follow::class.java ) ) - ActivityType.Create -> activityPubCreateService.receiveCreate(configData.objectMapper.readValue(json)) - ActivityType.Like -> activityPubLikeService.receiveLike(configData.objectMapper.readValue(json)) - ActivityType.Undo -> activityPubUndoService.receiveUndo(configData.objectMapper.readValue(json)) + ActivityType.Create -> apCreateService.receiveCreate(configData.objectMapper.readValue(json)) + ActivityType.Like -> apLikeService.receiveLike(configData.objectMapper.readValue(json)) + ActivityType.Undo -> apUndoService.receiveUndo(configData.objectMapper.readValue(json)) else -> { throw IllegalArgumentException("$type is not supported.") @@ -65,13 +65,13 @@ class ActivityPubServiceImpl( override suspend fun <T : HideoutJob> processActivity(job: JobContextWithProps<T>, hideoutJob: HideoutJob) { logger.debug("processActivity: ${hideoutJob.name}") when (hideoutJob) { - ReceiveFollowJob -> activityPubReceiveFollowService.receiveFollowJob( + ReceiveFollowJob -> apReceiveFollowService.receiveFollowJob( job.props as JobProps<ReceiveFollowJob> ) - DeliverPostJob -> activityPubNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>) - DeliverReactionJob -> activityPubReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>) - DeliverRemoveReactionJob -> activityPubReactionService.removeReactionJob( + DeliverPostJob -> apNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>) + DeliverReactionJob -> apReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>) + DeliverRemoveReactionJob -> apReactionService.removeReactionJob( job.props as JobProps<DeliverRemoveReactionJob> ) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt similarity index 67% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt index d0972608..f3b0c587 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt @@ -1,8 +1,8 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ap.Undo -interface ActivityPubUndoService { +interface APUndoService { suspend fun receiveUndo(undo: Undo): ActivityPubResponse } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoServiceImpl.kt similarity index 87% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoServiceImpl.kt index 612146a6..381e4160 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUndoServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse import dev.usbharu.hideout.domain.model.ActivityPubStringResponse @@ -12,12 +12,12 @@ import org.koin.core.annotation.Single @Single @Suppress("UnsafeCallOnNullableType") -class ActivityPubUndoServiceImpl( +class APUndoServiceImpl( private val userService: IUserService, - private val activityPubUserService: ActivityPubUserService, + private val apUserService: APUserService, private val userQueryService: UserQueryService, private val transaction: Transaction -) : ActivityPubUndoService { +) : APUndoService { override suspend fun receiveUndo(undo: Undo): ActivityPubResponse { if (undo.actor == null) { return ActivityPubStringResponse(HttpStatusCode.BadRequest, "actor is null") @@ -36,7 +36,7 @@ class ActivityPubUndoServiceImpl( return ActivityPubStringResponse(HttpStatusCode.BadRequest, "object.object is null") } transaction.transaction { - activityPubUserService.fetchPerson(undo.actor!!, follow.`object`) + apUserService.fetchPerson(undo.actor!!, follow.`object`) val follower = userQueryService.findByUrl(undo.actor!!) val target = userQueryService.findByUrl(follow.`object`!!) userService.unfollow(target.id, follower.id) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt similarity index 79% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt index 3ee34667..d0c71b66 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt @@ -1,8 +1,8 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ap.Person -interface ActivityPubUserService { +interface APUserService { suspend fun getPersonByName(name: String): Person /** diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserServiceImpl.kt similarity index 97% rename from src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt rename to src/main/kotlin/dev/usbharu/hideout/service/ap/APUserServiceImpl.kt index 504bbdba..ec846191 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserServiceImpl.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.config.Config @@ -19,13 +19,13 @@ import io.ktor.http.* import org.koin.core.annotation.Single @Single -class ActivityPubUserServiceImpl( +class APUserServiceImpl( private val userService: IUserService, private val httpClient: HttpClient, private val userQueryService: UserQueryService, private val transaction: Transaction ) : - ActivityPubUserService { + APUserService { override suspend fun getPersonByName(name: String): Person { val userEntity = transaction.transaction { 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 fbd204e8..0ca22f77 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt @@ -5,7 +5,7 @@ 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 dev.usbharu.hideout.service.ap.APNoteService import org.koin.core.annotation.Single import java.time.Instant @@ -13,7 +13,7 @@ import java.time.Instant class PostServiceImpl( private val postRepository: IPostRepository, private val userRepository: IUserRepository, - private val activityPubNoteService: ActivityPubNoteService + private val apNoteService: APNoteService ) : IPostService { override suspend fun createLocal(post: PostCreateDto): Post { val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found") @@ -29,7 +29,7 @@ class PostServiceImpl( repostId = null, replyId = null ) - activityPubNoteService.createNote(createPost) + apNoteService.createNote(createPost) return internalCreate(createPost) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt index b9166326..4eb42ea3 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt @@ -3,13 +3,13 @@ package dev.usbharu.hideout.service.reaction import dev.usbharu.hideout.domain.model.hideout.entity.Reaction import dev.usbharu.hideout.query.ReactionQueryService import dev.usbharu.hideout.repository.ReactionRepository -import dev.usbharu.hideout.service.activitypub.ActivityPubReactionService +import dev.usbharu.hideout.service.ap.APReactionService import org.koin.core.annotation.Single @Single class ReactionServiceImpl( private val reactionRepository: ReactionRepository, - private val activityPubReactionService: ActivityPubReactionService, + private val apReactionService: APReactionService, private val reactionQueryService: ReactionQueryService ) : IReactionService { override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) { @@ -27,7 +27,7 @@ class ReactionServiceImpl( } else { val reaction = Reaction(reactionRepository.generateId(), 0, postId, userId) reactionRepository.save(reaction) - activityPubReactionService.reaction(reaction) + apReactionService.reaction(reaction) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt index 89876aaf..febc8ac6 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt @@ -9,7 +9,7 @@ import dev.usbharu.hideout.exception.UserNotFoundException import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.repository.IUserRepository -import dev.usbharu.hideout.service.activitypub.ActivityPubSendFollowService +import dev.usbharu.hideout.service.ap.APSendFollowService import org.koin.core.annotation.Single import java.time.Instant @@ -17,7 +17,7 @@ import java.time.Instant class UserService( private val userRepository: IUserRepository, private val userAuthService: IUserAuthService, - private val activityPubSendFollowService: ActivityPubSendFollowService, + private val apSendFollowService: APSendFollowService, private val userQueryService: UserQueryService, private val followerQueryService: FollowerQueryService ) : @@ -77,7 +77,7 @@ class UserService( if (userRepository.findFollowRequestsById(id, followerId)) { // do-nothing } else { - activityPubSendFollowService.sendFollow(SendFollowDto(follower, user)) + apSendFollowService.sendFollow(SendFollowDto(follower, user)) } false } diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt index 9260848c..29f220bf 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt @@ -3,8 +3,8 @@ package dev.usbharu.hideout.routing.activitypub import dev.usbharu.hideout.exception.JsonParseException import dev.usbharu.hideout.plugins.configureSerialization import dev.usbharu.hideout.plugins.configureStatusPages -import dev.usbharu.hideout.service.activitypub.ActivityPubService -import dev.usbharu.hideout.service.activitypub.ActivityPubUserService +import dev.usbharu.hideout.service.ap.APService +import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.user.IUserService import io.ktor.client.request.* @@ -44,16 +44,16 @@ class InboxRoutingKtTest { val httpSignatureVerifyService = mock<HttpSignatureVerifyService> { on { verify(any()) } doReturn true } - val activityPubService = mock<ActivityPubService> { + val apService = mock<APService> { on { parseActivity(any()) } doThrow JsonParseException() } mock<IUserService>() - mock<ActivityPubUserService>() + mock<APUserService>() application { configureStatusPages() configureSerialization() routing { - inbox(httpSignatureVerifyService, activityPubService) + inbox(httpSignatureVerifyService, apService) } } client.post("/inbox").let { @@ -85,16 +85,16 @@ class InboxRoutingKtTest { val httpSignatureVerifyService = mock<HttpSignatureVerifyService> { on { verify(any()) } doReturn true } - val activityPubService = mock<ActivityPubService> { + val apService = mock<APService> { on { parseActivity(any()) } doThrow JsonParseException() } mock<IUserService>() - mock<ActivityPubUserService>() + mock<APUserService>() application { configureStatusPages() configureSerialization() routing { - inbox(httpSignatureVerifyService, activityPubService) + inbox(httpSignatureVerifyService, apService) } } client.post("/users/test/inbox").let { diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt index 3aaa4168..8fbb324f 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt @@ -12,7 +12,7 @@ import dev.usbharu.hideout.domain.model.ap.Person import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.plugins.configureSerialization import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.activitypub.ActivityPubUserService +import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.util.HttpUtil.Activity import dev.usbharu.hideout.util.HttpUtil.JsonLd import io.ktor.client.request.* @@ -63,14 +63,14 @@ class UsersAPTest { ) person.context = listOf("https://www.w3.org/ns/activitystreams") - val activityPubUserService = mock<ActivityPubUserService> { + val apUserService = mock<APUserService> { onBlocking { getPersonByName(anyString()) } doReturn person } application { configureSerialization() routing { - usersAP(activityPubUserService, mock(), mock(), TestTransaction) + usersAP(apUserService, mock(), mock(), TestTransaction) } } client.get("/users/test") { @@ -121,14 +121,14 @@ class UsersAPTest { ) person.context = listOf("https://www.w3.org/ns/activitystreams") - val activityPubUserService = mock<ActivityPubUserService> { + val apUserService = mock<APUserService> { onBlocking { getPersonByName(anyString()) } doReturn person } application { configureSerialization() routing { - usersAP(activityPubUserService, mock(), mock(), TestTransaction) + usersAP(apUserService, mock(), mock(), TestTransaction) } } client.get("/users/test") { diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImplTest.kt similarity index 95% rename from src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt rename to src/test/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImplTest.kt index c02f65ae..df22d1e1 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImplTest.kt @@ -1,7 +1,7 @@ @file:OptIn(ExperimentalCoroutinesApi::class) @file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.ConfigData @@ -25,7 +25,7 @@ import utils.JsonObjectMapper import java.time.Instant import kotlin.test.assertEquals -class ActivityPubNoteServiceImplTest { +class APNoteServiceImplTest { @Test fun `createPost 新しい投稿`() = runTest { val followers = listOf<User>( @@ -76,7 +76,7 @@ class ActivityPubNoteServiceImplTest { } val jobQueueParentService = mock<JobQueueParentService>() val activityPubNoteService = - ActivityPubNoteServiceImpl( + APNoteServiceImpl( mock(), jobQueueParentService, mock(), @@ -107,7 +107,7 @@ class ActivityPubNoteServiceImplTest { respondOk() } ) - val activityPubNoteService = ActivityPubNoteServiceImpl( + val activityPubNoteService = APNoteServiceImpl( httpClient, mock(), mock(), diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImplTest.kt similarity index 95% rename from src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowServiceImplTest.kt rename to src/test/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImplTest.kt index 66f7b338..6e5fbe30 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubReceiveFollowServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImplTest.kt @@ -1,7 +1,7 @@ @file:OptIn(ExperimentalCoroutinesApi::class) @file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") -package dev.usbharu.hideout.service.activitypub +package dev.usbharu.hideout.service.ap import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.config.Config @@ -27,14 +27,14 @@ import utils.JsonObjectMapper import utils.TestTransaction import java.time.Instant -class ActivityPubReceiveFollowServiceImplTest { +class APReceiveFollowServiceImplTest { @Test fun `receiveFollow フォロー受付処理`() = runTest { val jobQueueParentService = mock<JobQueueParentService> { onBlocking { schedule(eq(ReceiveFollowJob), any()) } doReturn Unit } val activityPubFollowService = - ActivityPubReceiveFollowServiceImpl(jobQueueParentService, mock(), mock(), mock(), mock(), TestTransaction) + APReceiveFollowServiceImpl(jobQueueParentService, mock(), mock(), mock(), mock(), TestTransaction) activityPubFollowService.receiveFollow( Follow( emptyList(), @@ -96,7 +96,7 @@ class ActivityPubReceiveFollowServiceImplTest { ) ) - val activityPubUserService = mock<ActivityPubUserService> { + val apUserService = mock<APUserService> { onBlocking { fetchPerson(anyString(), any()) } doReturn person } val userQueryService = mock<UserQueryService> { @@ -132,9 +132,9 @@ class ActivityPubReceiveFollowServiceImplTest { onBlocking { followRequest(any(), any()) } doReturn false } val activityPubFollowService = - ActivityPubReceiveFollowServiceImpl( + APReceiveFollowServiceImpl( mock(), - activityPubUserService, + apUserService, userService, HttpClient( MockEngine { httpRequestData -> From 60f0e1a4bf4ef3025bf2f411778c1909bda4b6b3 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:38:56 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20interface=E3=81=A8=E3=83=87?= =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E5=AE=9F=E8=A3=85=E3=82=92?= =?UTF-8?q?=E5=90=8C=E3=81=98=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/service/ap/APAcceptService.kt | 28 +++ .../hideout/service/ap/APAcceptServiceImpl.kt | 32 ---- .../hideout/service/ap/APCreateService.kt | 25 +++ .../hideout/service/ap/APCreateServiceImpl.kt | 29 --- .../hideout/service/ap/APLikeService.kt | 38 ++++ .../hideout/service/ap/APLikeServiceImpl.kt | 42 ----- .../hideout/service/ap/APNoteService.kt | 165 +++++++++++++++++ .../hideout/service/ap/APNoteServiceImpl.kt | 171 ------------------ .../hideout/service/ap/APReactionService.kt | 90 +++++++++ .../service/ap/APReactionServiceImpl.kt | 96 ---------- .../service/ap/APReceiveFollowService.kt | 56 ++++++ .../service/ap/APReceiveFollowServiceImpl.kt | 62 ------- .../hideout/service/ap/APSendFollowService.kt | 20 ++ .../service/ap/APSendFollowServiceImpl.kt | 23 --- .../usbharu/hideout/service/ap/APService.kt | 76 +++++++- .../hideout/service/ap/APServiceImpl.kt | 79 -------- .../hideout/service/ap/APUndoService.kt | 46 +++++ .../hideout/service/ap/APUndoServiceImpl.kt | 50 ----- .../hideout/service/ap/APUserService.kt | 112 ++++++++++++ .../hideout/service/ap/APUserServiceImpl.kt | 115 ------------ .../hideout/service/api/IPostApiService.kt | 91 ++++++++++ .../hideout/service/api/IUserApiService.kt | 51 ++++++ .../hideout/service/api/PostApiServiceImpl.kt | 96 ---------- .../hideout/service/api/UserApiServiceImpl.kt | 55 ------ .../hideout/service/api/UserAuthApiService.kt | 31 ++++ .../service/api/UserAuthApiServiceImpl.kt | 35 ---- .../service/api/WebFingerApiService.kt | 13 ++ .../service/api/WebFingerApiServiceImpl.kt | 16 -- .../auth/HttpSignatureVerifyService.kt | 26 +++ .../auth/HttpSignatureVerifyServiceImpl.kt | 29 --- .../hideout/service/auth/IJwtService.kt | 90 +++++++++ .../hideout/service/auth/JwtServiceImpl.kt | 95 ---------- 32 files changed, 957 insertions(+), 1026 deletions(-) delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/ap/APUserServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/api/UserApiServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImpl.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt index fdcbbf61..951a8c78 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt @@ -1,8 +1,36 @@ package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse +import dev.usbharu.hideout.domain.model.ActivityPubStringResponse import dev.usbharu.hideout.domain.model.ap.Accept +import dev.usbharu.hideout.domain.model.ap.Follow +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.user.IUserService +import io.ktor.http.* +import org.koin.core.annotation.Single interface APAcceptService { suspend fun receiveAccept(accept: Accept): ActivityPubResponse } + +@Single +class APAcceptServiceImpl( + private val userService: IUserService, + private val userQueryService: UserQueryService +) : APAcceptService { + override suspend fun receiveAccept(accept: Accept): ActivityPubResponse { + val value = accept.`object` ?: throw IllegalActivityPubObjectException("object is null") + if (value.type.contains("Follow").not()) { + throw IllegalActivityPubObjectException("Invalid type ${value.type}") + } + + val follow = value as Follow + val userUrl = follow.`object` ?: throw IllegalActivityPubObjectException("object is null") + val followerUrl = follow.actor ?: throw IllegalActivityPubObjectException("actor is null") + val user = userQueryService.findByUrl(userUrl) + val follower = userQueryService.findByUrl(followerUrl) + userService.follow(user.id, follower.id) + return ActivityPubStringResponse(HttpStatusCode.OK, "accepted") + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptServiceImpl.kt deleted file mode 100644 index b8fd337f..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptServiceImpl.kt +++ /dev/null @@ -1,32 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import dev.usbharu.hideout.domain.model.ActivityPubResponse -import dev.usbharu.hideout.domain.model.ActivityPubStringResponse -import dev.usbharu.hideout.domain.model.ap.Accept -import dev.usbharu.hideout.domain.model.ap.Follow -import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.user.IUserService -import io.ktor.http.* -import org.koin.core.annotation.Single - -@Single -class APAcceptServiceImpl( - private val userService: IUserService, - private val userQueryService: UserQueryService -) : APAcceptService { - override suspend fun receiveAccept(accept: Accept): ActivityPubResponse { - val value = accept.`object` ?: throw IllegalActivityPubObjectException("object is null") - if (value.type.contains("Follow").not()) { - throw IllegalActivityPubObjectException("Invalid type ${value.type}") - } - - val follow = value as Follow - val userUrl = follow.`object` ?: throw IllegalActivityPubObjectException("object is null") - val followerUrl = follow.actor ?: throw IllegalActivityPubObjectException("actor is null") - val user = userQueryService.findByUrl(userUrl) - val follower = userQueryService.findByUrl(followerUrl) - userService.follow(user.id, follower.id) - return ActivityPubStringResponse(HttpStatusCode.OK, "accepted") - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateService.kt index 29fa38de..b3e84557 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateService.kt @@ -1,8 +1,33 @@ package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse +import dev.usbharu.hideout.domain.model.ActivityPubStringResponse import dev.usbharu.hideout.domain.model.ap.Create +import dev.usbharu.hideout.domain.model.ap.Note +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException +import dev.usbharu.hideout.service.core.Transaction +import io.ktor.http.* +import org.koin.core.annotation.Single interface APCreateService { suspend fun receiveCreate(create: Create): ActivityPubResponse } + +@Single +class APCreateServiceImpl( + private val apNoteService: APNoteService, + private val transaction: Transaction +) : APCreateService { + override suspend fun receiveCreate(create: Create): ActivityPubResponse { + val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null") + if (value.type.contains("Note").not()) { + throw IllegalActivityPubObjectException("object is not Note") + } + + return transaction.transaction { + val note = value as Note + apNoteService.fetchNote(note) + ActivityPubStringResponse(HttpStatusCode.OK, "Created") + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateServiceImpl.kt deleted file mode 100644 index 2f1e4bd0..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APCreateServiceImpl.kt +++ /dev/null @@ -1,29 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import dev.usbharu.hideout.domain.model.ActivityPubResponse -import dev.usbharu.hideout.domain.model.ActivityPubStringResponse -import dev.usbharu.hideout.domain.model.ap.Create -import dev.usbharu.hideout.domain.model.ap.Note -import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException -import dev.usbharu.hideout.service.core.Transaction -import io.ktor.http.* -import org.koin.core.annotation.Single - -@Single -class APCreateServiceImpl( - private val apNoteService: APNoteService, - private val transaction: Transaction -) : APCreateService { - override suspend fun receiveCreate(create: Create): ActivityPubResponse { - val value = create.`object` ?: throw IllegalActivityPubObjectException("object is null") - if (value.type.contains("Note").not()) { - throw IllegalActivityPubObjectException("object is not Note") - } - - return transaction.transaction { - val note = value as Note - apNoteService.fetchNote(note) - ActivityPubStringResponse(HttpStatusCode.OK, "Created") - } - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt index 0ecb30a6..e8be8ec7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt @@ -1,8 +1,46 @@ package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse +import dev.usbharu.hideout.domain.model.ActivityPubStringResponse import dev.usbharu.hideout.domain.model.ap.Like +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException +import dev.usbharu.hideout.query.PostQueryService +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.core.Transaction +import dev.usbharu.hideout.service.reaction.IReactionService +import io.ktor.http.* +import org.koin.core.annotation.Single interface APLikeService { suspend fun receiveLike(like: Like): ActivityPubResponse } + +@Single +class APLikeServiceImpl( + private val reactionService: IReactionService, + private val apUserService: APUserService, + private val apNoteService: APNoteService, + private val userQueryService: UserQueryService, + private val postQueryService: PostQueryService, + private val transaction: Transaction +) : APLikeService { + override suspend fun receiveLike(like: Like): ActivityPubResponse { + val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null") + val content = like.content ?: throw IllegalActivityPubObjectException("content is null") + like.`object` ?: throw IllegalActivityPubObjectException("object is null") + transaction.transaction { + val person = apUserService.fetchPerson(actor) + apNoteService.fetchNote(like.`object`!!) + + val user = userQueryService.findByUrl( + person.url + ?: throw IllegalActivityPubObjectException("actor is not found") + ) + + val post = postQueryService.findByUrl(like.`object`!!) + + reactionService.receiveReaction(content, actor.substringAfter("://").substringBefore("/"), user.id, post.id) + } + return ActivityPubStringResponse(HttpStatusCode.OK, "") + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeServiceImpl.kt deleted file mode 100644 index 929f79c5..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeServiceImpl.kt +++ /dev/null @@ -1,42 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import dev.usbharu.hideout.domain.model.ActivityPubResponse -import dev.usbharu.hideout.domain.model.ActivityPubStringResponse -import dev.usbharu.hideout.domain.model.ap.Like -import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException -import dev.usbharu.hideout.query.PostQueryService -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.reaction.IReactionService -import io.ktor.http.* -import org.koin.core.annotation.Single - -@Single -class APLikeServiceImpl( - private val reactionService: IReactionService, - private val apUserService: APUserService, - private val apNoteService: APNoteService, - private val userQueryService: UserQueryService, - private val postQueryService: PostQueryService, - private val transaction: Transaction -) : APLikeService { - override suspend fun receiveLike(like: Like): ActivityPubResponse { - val actor = like.actor ?: throw IllegalActivityPubObjectException("actor is null") - val content = like.content ?: throw IllegalActivityPubObjectException("content is null") - like.`object` ?: throw IllegalActivityPubObjectException("object is null") - transaction.transaction { - val person = apUserService.fetchPerson(actor) - apNoteService.fetchNote(like.`object`!!) - - val user = userQueryService.findByUrl( - person.url - ?: throw IllegalActivityPubObjectException("actor is not found") - ) - - val post = postQueryService.findByUrl(like.`object`!!) - - reactionService.receiveReaction(content, actor.substringAfter("://").substringBefore("/"), user.id, post.id) - } - return ActivityPubStringResponse(HttpStatusCode.OK, "") - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt index 33b9d457..f32f7b4e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt @@ -1,9 +1,26 @@ package dev.usbharu.hideout.service.ap +import com.fasterxml.jackson.module.kotlin.readValue +import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.domain.model.ap.Create import dev.usbharu.hideout.domain.model.ap.Note import dev.usbharu.hideout.domain.model.hideout.entity.Post +import dev.usbharu.hideout.domain.model.hideout.entity.Visibility import dev.usbharu.hideout.domain.model.job.DeliverPostJob +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException +import dev.usbharu.hideout.plugins.getAp +import dev.usbharu.hideout.plugins.postAp +import dev.usbharu.hideout.query.FollowerQueryService +import dev.usbharu.hideout.query.PostQueryService +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.repository.IPostRepository +import dev.usbharu.hideout.service.job.JobQueueParentService +import io.ktor.client.* +import io.ktor.client.statement.* import kjob.core.job.JobProps +import org.koin.core.annotation.Single +import org.slf4j.LoggerFactory +import java.time.Instant interface APNoteService { @@ -13,3 +30,151 @@ interface APNoteService { suspend fun fetchNote(url: String, targetActor: String? = null): Note suspend fun fetchNote(note: Note, targetActor: String? = null): Note } + +@Single +class APNoteServiceImpl( + private val httpClient: HttpClient, + private val jobQueueParentService: JobQueueParentService, + private val postRepository: IPostRepository, + private val apUserService: APUserService, + private val userQueryService: UserQueryService, + private val followerQueryService: FollowerQueryService, + private val postQueryService: PostQueryService +) : APNoteService { + + private val logger = LoggerFactory.getLogger(this::class.java) + + override suspend fun createNote(post: Post) { + val followers = followerQueryService.findFollowersById(post.userId) + val userEntity = userQueryService.findById(post.userId) + val note = Config.configData.objectMapper.writeValueAsString(post) + followers.forEach { followerEntity -> + jobQueueParentService.schedule(DeliverPostJob) { + props[DeliverPostJob.actor] = userEntity.url + props[DeliverPostJob.post] = note + props[DeliverPostJob.inbox] = followerEntity.inbox + } + } + } + + override suspend fun createNoteJob(props: JobProps<DeliverPostJob>) { + val actor = props[DeliverPostJob.actor] + val postEntity = Config.configData.objectMapper.readValue<Post>(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") + ) + 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}" + ) + ) + } + + override suspend fun fetchNote(url: String, targetActor: String?): Note { + val post = postQueryService.findByUrl(url) + try { + return postToNote(post) + } catch (_: NoSuchElementException) { + } catch (_: IllegalArgumentException) { + } + + val response = httpClient.getAp( + url, + targetActor?.let { "$targetActor#pubkey" } + ) + val note = Config.configData.objectMapper.readValue<Note>(response.bodyAsText()) + return note(note, targetActor, url) + } + + private suspend fun postToNote(post: Post): Note { + val user = userQueryService.findById(post.userId) + val reply = post.replyId?.let { postQueryService.findById(it) } + return Note( + name = "Post", + id = post.apId, + attributedTo = user.url, + content = post.text, + published = Instant.ofEpochMilli(post.createdAt).toString(), + to = listOf(public, user.url + "/follower"), + sensitive = post.sensitive, + cc = listOf(public, user.url + "/follower"), + inReplyTo = reply?.url + ) + } + + private suspend fun note( + note: Note, + targetActor: String?, + url: String + ): Note { + val findByApId = try { + postQueryService.findByApId(url) + } catch (_: NoSuchElementException) { + return internalNote(note, targetActor, url) + } catch (_: IllegalArgumentException) { + return internalNote(note, targetActor, url) + } + return postToNote(findByApId) + } + + private suspend fun internalNote(note: Note, targetActor: String?, url: String): Note { + val person = apUserService.fetchPerson( + note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"), + targetActor + ) + val user = + userQueryService.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 + } + + val reply = note.inReplyTo?.let { + fetchNote(it, targetActor) + postQueryService.findByUrl(it) + } + + 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, + ) + ) + return note + } + + override suspend fun fetchNote(note: Note, targetActor: String?): Note = + note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null")) + + companion object { + const val public: String = "https://www.w3.org/ns/activitystreams#Public" + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImpl.kt deleted file mode 100644 index d46d02a7..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteServiceImpl.kt +++ /dev/null @@ -1,171 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import com.fasterxml.jackson.module.kotlin.readValue -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.domain.model.ap.Create -import dev.usbharu.hideout.domain.model.ap.Note -import dev.usbharu.hideout.domain.model.hideout.entity.Post -import dev.usbharu.hideout.domain.model.hideout.entity.Visibility -import dev.usbharu.hideout.domain.model.job.DeliverPostJob -import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException -import dev.usbharu.hideout.plugins.getAp -import dev.usbharu.hideout.plugins.postAp -import dev.usbharu.hideout.query.FollowerQueryService -import dev.usbharu.hideout.query.PostQueryService -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IPostRepository -import dev.usbharu.hideout.service.job.JobQueueParentService -import io.ktor.client.* -import io.ktor.client.statement.* -import kjob.core.job.JobProps -import org.koin.core.annotation.Single -import org.slf4j.LoggerFactory -import java.time.Instant - -@Single -class APNoteServiceImpl( - private val httpClient: HttpClient, - private val jobQueueParentService: JobQueueParentService, - private val postRepository: IPostRepository, - private val apUserService: APUserService, - private val userQueryService: UserQueryService, - private val followerQueryService: FollowerQueryService, - private val postQueryService: PostQueryService -) : APNoteService { - - private val logger = LoggerFactory.getLogger(this::class.java) - - override suspend fun createNote(post: Post) { - val followers = followerQueryService.findFollowersById(post.userId) - val userEntity = userQueryService.findById(post.userId) - val note = Config.configData.objectMapper.writeValueAsString(post) - followers.forEach { followerEntity -> - jobQueueParentService.schedule(DeliverPostJob) { - props[it.actor] = userEntity.url - props[it.post] = note - props[it.inbox] = followerEntity.inbox - } - } - } - - override suspend fun createNoteJob(props: JobProps<DeliverPostJob>) { - val actor = props[DeliverPostJob.actor] - val postEntity = Config.configData.objectMapper.readValue<Post>(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") - ) - 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}" - ) - ) - } - - override suspend fun fetchNote(url: String, targetActor: String?): Note { - val post = postQueryService.findByUrl(url) - try { - return postToNote(post) - } catch (_: NoSuchElementException) { - } catch (_: IllegalArgumentException) { - } - - val response = httpClient.getAp( - url, - targetActor?.let { "$targetActor#pubkey" } - ) - val note = Config.configData.objectMapper.readValue<Note>(response.bodyAsText()) - return note(note, targetActor, url) - } - - private suspend fun postToNote(post: Post): Note { - val user = userQueryService.findById(post.userId) - val reply = post.replyId?.let { postQueryService.findById(it) } - return Note( - name = "Post", - id = post.apId, - attributedTo = user.url, - content = post.text, - published = Instant.ofEpochMilli(post.createdAt).toString(), - to = listOf(public, user.url + "/follower"), - sensitive = post.sensitive, - cc = listOf(public, user.url + "/follower"), - inReplyTo = reply?.url - ) - } - - private suspend fun note( - note: Note, - targetActor: String?, - url: String - ): Note { - val findByApId = try { - postQueryService.findByApId(url) - } catch (_: NoSuchElementException) { - return internalNote(note, targetActor, url) - } catch (_: IllegalArgumentException) { - return internalNote(note, targetActor, url) - } - return postToNote(findByApId) - } - - private suspend fun internalNote(note: Note, targetActor: String?, url: String): Note { - val person = apUserService.fetchPerson( - note.attributedTo ?: throw IllegalActivityPubObjectException("note.attributedTo is null"), - targetActor - ) - val user = - userQueryService.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 - } - - val reply = note.inReplyTo?.let { - fetchNote(it, targetActor) - postQueryService.findByUrl(it) - } - - 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, - ) - ) - return note - } - - override suspend fun fetchNote(note: Note, targetActor: String?): Note = - note(note, targetActor, note.id ?: throw IllegalArgumentException("note.id is null")) - - companion object { - const val public: String = "https://www.w3.org/ns/activitystreams#Public" - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt index aa12198c..e8b21f84 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt @@ -1,9 +1,22 @@ package dev.usbharu.hideout.service.ap +import com.fasterxml.jackson.module.kotlin.readValue +import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.domain.model.ap.Like +import dev.usbharu.hideout.domain.model.ap.Undo import dev.usbharu.hideout.domain.model.hideout.entity.Reaction import dev.usbharu.hideout.domain.model.job.DeliverReactionJob import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob +import dev.usbharu.hideout.plugins.postAp +import dev.usbharu.hideout.query.FollowerQueryService +import dev.usbharu.hideout.query.PostQueryService +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.repository.IPostRepository +import dev.usbharu.hideout.service.job.JobQueueParentService +import io.ktor.client.* import kjob.core.job.JobProps +import org.koin.core.annotation.Single +import java.time.Instant interface APReactionService { suspend fun reaction(like: Reaction) @@ -11,3 +24,80 @@ interface APReactionService { suspend fun reactionJob(props: JobProps<DeliverReactionJob>) suspend fun removeReactionJob(props: JobProps<DeliverRemoveReactionJob>) } + +@Single +class APReactionServiceImpl( + private val jobQueueParentService: JobQueueParentService, + private val iPostRepository: IPostRepository, + private val httpClient: HttpClient, + private val userQueryService: UserQueryService, + private val followerQueryService: FollowerQueryService, + private val postQueryService: PostQueryService +) : APReactionService { + override suspend fun reaction(like: Reaction) { + val followers = followerQueryService.findFollowersById(like.userId) + val user = userQueryService.findById(like.userId) + val post = + postQueryService.findById(like.postId) + followers.forEach { follower -> + jobQueueParentService.schedule(DeliverReactionJob) { + props[DeliverReactionJob.actor] = user.url + props[DeliverReactionJob.reaction] = "❤" + props[DeliverReactionJob.inbox] = follower.inbox + props[DeliverReactionJob.postUrl] = post.url + props[DeliverReactionJob.id] = post.id.toString() + } + } + } + + override suspend fun removeReaction(like: Reaction) { + val followers = followerQueryService.findFollowersById(like.userId) + val user = userQueryService.findById(like.userId) + val post = + postQueryService.findById(like.postId) + followers.forEach { follower -> + jobQueueParentService.schedule(DeliverRemoveReactionJob) { + props[DeliverRemoveReactionJob.actor] = user.url + props[DeliverRemoveReactionJob.inbox] = follower.inbox + props[DeliverRemoveReactionJob.id] = post.id.toString() + props[DeliverRemoveReactionJob.like] = Config.configData.objectMapper.writeValueAsString(like) + } + } + } + + override suspend fun reactionJob(props: JobProps<DeliverReactionJob>) { + val inbox = props[DeliverReactionJob.inbox] + val actor = props[DeliverReactionJob.actor] + val postUrl = props[DeliverReactionJob.postUrl] + val id = props[DeliverReactionJob.id] + val content = props[DeliverReactionJob.reaction] + httpClient.postAp( + urlString = inbox, + username = "$actor#pubkey", + jsonLd = Like( + name = "Like", + actor = actor, + `object` = postUrl, + id = "${Config.configData.url}/like/note/$id", + content = content + ) + ) + } + + override suspend fun removeReactionJob(props: JobProps<DeliverRemoveReactionJob>) { + val inbox = props[DeliverRemoveReactionJob.inbox] + val actor = props[DeliverRemoveReactionJob.actor] + val like = Config.configData.objectMapper.readValue<Like>(props[DeliverRemoveReactionJob.like]) + httpClient.postAp( + urlString = inbox, + username = "$actor#pubkey", + jsonLd = Undo( + name = "Undo Reaction", + actor = actor, + `object` = like, + id = "${Config.configData.url}/undo/note/${like.id}", + published = Instant.now() + ) + ) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionServiceImpl.kt deleted file mode 100644 index 3635836b..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionServiceImpl.kt +++ /dev/null @@ -1,96 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import com.fasterxml.jackson.module.kotlin.readValue -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.domain.model.ap.Like -import dev.usbharu.hideout.domain.model.ap.Undo -import dev.usbharu.hideout.domain.model.hideout.entity.Reaction -import dev.usbharu.hideout.domain.model.job.DeliverReactionJob -import dev.usbharu.hideout.domain.model.job.DeliverRemoveReactionJob -import dev.usbharu.hideout.plugins.postAp -import dev.usbharu.hideout.query.FollowerQueryService -import dev.usbharu.hideout.query.PostQueryService -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IPostRepository -import dev.usbharu.hideout.service.job.JobQueueParentService -import io.ktor.client.* -import kjob.core.job.JobProps -import org.koin.core.annotation.Single -import java.time.Instant - -@Single -class APReactionServiceImpl( - private val jobQueueParentService: JobQueueParentService, - private val iPostRepository: IPostRepository, - private val httpClient: HttpClient, - private val userQueryService: UserQueryService, - private val followerQueryService: FollowerQueryService, - private val postQueryService: PostQueryService -) : APReactionService { - override suspend fun reaction(like: Reaction) { - val followers = followerQueryService.findFollowersById(like.userId) - val user = userQueryService.findById(like.userId) - val post = - postQueryService.findById(like.postId) - followers.forEach { follower -> - jobQueueParentService.schedule(DeliverReactionJob) { - props[it.actor] = user.url - props[it.reaction] = "❤" - props[it.inbox] = follower.inbox - props[it.postUrl] = post.url - props[it.id] = post.id.toString() - } - } - } - - override suspend fun removeReaction(like: Reaction) { - val followers = followerQueryService.findFollowersById(like.userId) - val user = userQueryService.findById(like.userId) - val post = - postQueryService.findById(like.postId) - followers.forEach { follower -> - jobQueueParentService.schedule(DeliverRemoveReactionJob) { - props[it.actor] = user.url - props[it.inbox] = follower.inbox - props[it.id] = post.id.toString() - props[it.like] = Config.configData.objectMapper.writeValueAsString(like) - } - } - } - - override suspend fun reactionJob(props: JobProps<DeliverReactionJob>) { - val inbox = props[DeliverReactionJob.inbox] - val actor = props[DeliverReactionJob.actor] - val postUrl = props[DeliverReactionJob.postUrl] - val id = props[DeliverReactionJob.id] - val content = props[DeliverReactionJob.reaction] - httpClient.postAp( - urlString = inbox, - username = "$actor#pubkey", - jsonLd = Like( - name = "Like", - actor = actor, - `object` = postUrl, - id = "${Config.configData.url}/like/note/$id", - content = content - ) - ) - } - - override suspend fun removeReactionJob(props: JobProps<DeliverRemoveReactionJob>) { - val inbox = props[DeliverRemoveReactionJob.inbox] - val actor = props[DeliverRemoveReactionJob.actor] - val like = Config.configData.objectMapper.readValue<Like>(props[DeliverRemoveReactionJob.like]) - httpClient.postAp( - urlString = inbox, - username = "$actor#pubkey", - jsonLd = Undo( - name = "Undo Reaction", - actor = actor, - `object` = like, - id = "${Config.configData.url}/undo/note/${like.id}", - published = Instant.now() - ) - ) - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt index 7aaf21e5..54c0d39d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt @@ -1,11 +1,67 @@ package dev.usbharu.hideout.service.ap +import com.fasterxml.jackson.module.kotlin.readValue +import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.ActivityPubResponse +import dev.usbharu.hideout.domain.model.ActivityPubStringResponse +import dev.usbharu.hideout.domain.model.ap.Accept import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob +import dev.usbharu.hideout.plugins.postAp +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.core.Transaction +import dev.usbharu.hideout.service.job.JobQueueParentService +import dev.usbharu.hideout.service.user.IUserService +import io.ktor.client.* +import io.ktor.http.* import kjob.core.job.JobProps +import org.koin.core.annotation.Single interface APReceiveFollowService { suspend fun receiveFollow(follow: Follow): ActivityPubResponse suspend fun receiveFollowJob(props: JobProps<ReceiveFollowJob>) } + +@Single +class APReceiveFollowServiceImpl( + private val jobQueueParentService: JobQueueParentService, + private val apUserService: APUserService, + private val userService: IUserService, + private val httpClient: HttpClient, + private val userQueryService: UserQueryService, + private val transaction: Transaction +) : APReceiveFollowService { + override suspend fun receiveFollow(follow: Follow): ActivityPubResponse { + // TODO: Verify HTTP Signature + jobQueueParentService.schedule(ReceiveFollowJob) { + props[ReceiveFollowJob.actor] = follow.actor + props[ReceiveFollowJob.follow] = Config.configData.objectMapper.writeValueAsString(follow) + props[ReceiveFollowJob.targetActor] = follow.`object` + } + return ActivityPubStringResponse(HttpStatusCode.OK, "{}", ContentType.Application.Json) + } + + override suspend fun receiveFollowJob(props: JobProps<ReceiveFollowJob>) { + transaction.transaction { + val actor = props[ReceiveFollowJob.actor] + val targetActor = props[ReceiveFollowJob.targetActor] + val person = apUserService.fetchPerson(actor, targetActor) + val follow = Config.configData.objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow]) + httpClient.postAp( + urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"), + username = "$targetActor#pubkey", + jsonLd = Accept( + name = "Follow", + `object` = follow, + actor = targetActor + ) + ) + + val targetEntity = userQueryService.findByUrl(targetActor) + val followActorEntity = + userQueryService.findByUrl(follow.actor ?: throw java.lang.IllegalArgumentException("Actor is null")) + + userService.followRequest(targetEntity.id, followActorEntity.id) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImpl.kt deleted file mode 100644 index 3e8500df..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImpl.kt +++ /dev/null @@ -1,62 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import com.fasterxml.jackson.module.kotlin.readValue -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.domain.model.ActivityPubResponse -import dev.usbharu.hideout.domain.model.ActivityPubStringResponse -import dev.usbharu.hideout.domain.model.ap.Accept -import dev.usbharu.hideout.domain.model.ap.Follow -import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob -import dev.usbharu.hideout.plugins.postAp -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.job.JobQueueParentService -import dev.usbharu.hideout.service.user.IUserService -import io.ktor.client.* -import io.ktor.http.* -import kjob.core.job.JobProps -import org.koin.core.annotation.Single - -@Single -class APReceiveFollowServiceImpl( - private val jobQueueParentService: JobQueueParentService, - private val apUserService: APUserService, - private val userService: IUserService, - private val httpClient: HttpClient, - private val userQueryService: UserQueryService, - private val transaction: Transaction -) : APReceiveFollowService { - override suspend fun receiveFollow(follow: Follow): ActivityPubResponse { - // TODO: Verify HTTP Signature - jobQueueParentService.schedule(ReceiveFollowJob) { - props[it.actor] = follow.actor - props[it.follow] = Config.configData.objectMapper.writeValueAsString(follow) - props[it.targetActor] = follow.`object` - } - return ActivityPubStringResponse(HttpStatusCode.OK, "{}", ContentType.Application.Json) - } - - override suspend fun receiveFollowJob(props: JobProps<ReceiveFollowJob>) { - transaction.transaction { - val actor = props[ReceiveFollowJob.actor] - val targetActor = props[ReceiveFollowJob.targetActor] - val person = apUserService.fetchPerson(actor, targetActor) - val follow = Config.configData.objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow]) - httpClient.postAp( - urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"), - username = "$targetActor#pubkey", - jsonLd = Accept( - name = "Follow", - `object` = follow, - actor = targetActor - ) - ) - - val targetEntity = userQueryService.findByUrl(targetActor) - val followActorEntity = - userQueryService.findByUrl(follow.actor ?: throw java.lang.IllegalArgumentException("Actor is null")) - - userService.followRequest(targetEntity.id, followActorEntity.id) - } - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowService.kt index d4058113..58ae74f5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowService.kt @@ -1,7 +1,27 @@ package dev.usbharu.hideout.service.ap +import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto +import dev.usbharu.hideout.plugins.postAp +import io.ktor.client.* +import org.koin.core.annotation.Single interface APSendFollowService { suspend fun sendFollow(sendFollowDto: SendFollowDto) } + +@Single +class APSendFollowServiceImpl(private val httpClient: HttpClient) : APSendFollowService { + override suspend fun sendFollow(sendFollowDto: SendFollowDto) { + val follow = Follow( + name = "Follow", + `object` = sendFollowDto.followTargetUserId.url, + actor = sendFollowDto.userId.url + ) + httpClient.postAp( + urlString = sendFollowDto.followTargetUserId.inbox, + username = sendFollowDto.userId.url, + jsonLd = follow + ) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowServiceImpl.kt deleted file mode 100644 index a2ccb74f..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APSendFollowServiceImpl.kt +++ /dev/null @@ -1,23 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import dev.usbharu.hideout.domain.model.ap.Follow -import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto -import dev.usbharu.hideout.plugins.postAp -import io.ktor.client.* -import org.koin.core.annotation.Single - -@Single -class APSendFollowServiceImpl(private val httpClient: HttpClient) : APSendFollowService { - override suspend fun sendFollow(sendFollowDto: SendFollowDto) { - val follow = Follow( - name = "Follow", - `object` = sendFollowDto.followTargetUserId.url, - actor = sendFollowDto.userId.url - ) - httpClient.postAp( - urlString = sendFollowDto.followTargetUserId.inbox, - username = sendFollowDto.userId.url, - jsonLd = follow - ) - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt index 719149c1..baf1b023 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APService.kt @@ -1,8 +1,17 @@ package dev.usbharu.hideout.service.ap +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.module.kotlin.readValue +import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.ActivityPubResponse -import dev.usbharu.hideout.domain.model.job.HideoutJob +import dev.usbharu.hideout.domain.model.ap.Follow +import dev.usbharu.hideout.domain.model.job.* +import dev.usbharu.hideout.exception.JsonParseException import kjob.core.dsl.JobContextWithProps +import kjob.core.job.JobProps +import org.koin.core.annotation.Single +import org.slf4j.Logger +import org.slf4j.LoggerFactory interface APService { fun parseActivity(json: String): ActivityType @@ -162,3 +171,68 @@ enum class ExtendedActivityVocabulary { enum class ExtendedVocabulary { Emoji } + +@Single +class APServiceImpl( + private val apReceiveFollowService: APReceiveFollowService, + private val apNoteService: APNoteService, + private val apUndoService: APUndoService, + private val apAcceptService: APAcceptService, + private val apCreateService: APCreateService, + private val apLikeService: APLikeService, + private val apReactionService: APReactionService +) : APService { + + val logger: Logger = LoggerFactory.getLogger(this::class.java) + override fun parseActivity(json: String): ActivityType { + val readTree = Config.configData.objectMapper.readTree(json) + logger.trace("readTree: {}", readTree) + if (readTree.isObject.not()) { + throw JsonParseException("Json is not object.") + } + val type = readTree["type"] + if (type.isArray) { + return type.firstNotNullOf { jsonNode: JsonNode -> + ActivityType.values().firstOrNull { it.name.equals(jsonNode.asText(), true) } + } + } + return ActivityType.values().first { it.name.equals(type.asText(), true) } + } + + @Suppress("CyclomaticComplexMethod", "NotImplementedDeclaration") + override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse { + logger.debug("proccess activity: {}", type) + return when (type) { + ActivityType.Accept -> apAcceptService.receiveAccept(Config.configData.objectMapper.readValue(json)) + ActivityType.Follow -> apReceiveFollowService.receiveFollow( + Config.configData.objectMapper.readValue( + json, + Follow::class.java + ) + ) + + ActivityType.Create -> apCreateService.receiveCreate(Config.configData.objectMapper.readValue(json)) + ActivityType.Like -> apLikeService.receiveLike(Config.configData.objectMapper.readValue(json)) + ActivityType.Undo -> apUndoService.receiveUndo(Config.configData.objectMapper.readValue(json)) + + else -> { + throw IllegalArgumentException("$type is not supported.") + } + } + } + + override suspend fun <T : HideoutJob> processActivity(job: JobContextWithProps<T>, hideoutJob: HideoutJob) { + logger.debug("processActivity: ${hideoutJob.name}") + when (hideoutJob) { + ReceiveFollowJob -> apReceiveFollowService.receiveFollowJob( + job.props as JobProps<ReceiveFollowJob> + ) + + DeliverPostJob -> apNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>) + DeliverReactionJob -> apReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>) + DeliverRemoveReactionJob -> apReactionService.removeReactionJob( + job.props as JobProps<DeliverRemoveReactionJob> + ) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APServiceImpl.kt deleted file mode 100644 index f2cd4000..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APServiceImpl.kt +++ /dev/null @@ -1,79 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.module.kotlin.readValue -import dev.usbharu.hideout.config.Config.configData -import dev.usbharu.hideout.domain.model.ActivityPubResponse -import dev.usbharu.hideout.domain.model.ap.Follow -import dev.usbharu.hideout.domain.model.job.* -import dev.usbharu.hideout.exception.JsonParseException -import kjob.core.dsl.JobContextWithProps -import kjob.core.job.JobProps -import org.koin.core.annotation.Single -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -@Single -class APServiceImpl( - private val apReceiveFollowService: APReceiveFollowService, - private val apNoteService: APNoteService, - private val apUndoService: APUndoService, - private val apAcceptService: APAcceptService, - private val apCreateService: APCreateService, - private val apLikeService: APLikeService, - private val apReactionService: APReactionService -) : APService { - - val logger: Logger = LoggerFactory.getLogger(this::class.java) - override fun parseActivity(json: String): ActivityType { - val readTree = configData.objectMapper.readTree(json) - logger.trace("readTree: {}", readTree) - if (readTree.isObject.not()) { - throw JsonParseException("Json is not object.") - } - val type = readTree["type"] - if (type.isArray) { - return type.firstNotNullOf { jsonNode: JsonNode -> - ActivityType.values().firstOrNull { it.name.equals(jsonNode.asText(), true) } - } - } - return ActivityType.values().first { it.name.equals(type.asText(), true) } - } - - @Suppress("CyclomaticComplexMethod", "NotImplementedDeclaration") - override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse { - logger.debug("proccess activity: {}", type) - return when (type) { - ActivityType.Accept -> apAcceptService.receiveAccept(configData.objectMapper.readValue(json)) - ActivityType.Follow -> apReceiveFollowService.receiveFollow( - configData.objectMapper.readValue( - json, - Follow::class.java - ) - ) - - ActivityType.Create -> apCreateService.receiveCreate(configData.objectMapper.readValue(json)) - ActivityType.Like -> apLikeService.receiveLike(configData.objectMapper.readValue(json)) - ActivityType.Undo -> apUndoService.receiveUndo(configData.objectMapper.readValue(json)) - - else -> { - throw IllegalArgumentException("$type is not supported.") - } - } - } - - override suspend fun <T : HideoutJob> processActivity(job: JobContextWithProps<T>, hideoutJob: HideoutJob) { - logger.debug("processActivity: ${hideoutJob.name}") - when (hideoutJob) { - ReceiveFollowJob -> apReceiveFollowService.receiveFollowJob( - job.props as JobProps<ReceiveFollowJob> - ) - - DeliverPostJob -> apNoteService.createNoteJob(job.props as JobProps<DeliverPostJob>) - DeliverReactionJob -> apReactionService.reactionJob(job.props as JobProps<DeliverReactionJob>) - DeliverRemoveReactionJob -> apReactionService.removeReactionJob( - job.props as JobProps<DeliverRemoveReactionJob> - ) - } - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt index f3b0c587..a058dbd5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt @@ -1,8 +1,54 @@ package dev.usbharu.hideout.service.ap import dev.usbharu.hideout.domain.model.ActivityPubResponse +import dev.usbharu.hideout.domain.model.ActivityPubStringResponse +import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.ap.Undo +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.core.Transaction +import dev.usbharu.hideout.service.user.IUserService +import io.ktor.http.* +import org.koin.core.annotation.Single interface APUndoService { suspend fun receiveUndo(undo: Undo): ActivityPubResponse } + +@Single +@Suppress("UnsafeCallOnNullableType") +class APUndoServiceImpl( + private val userService: IUserService, + private val apUserService: APUserService, + private val userQueryService: UserQueryService, + private val transaction: Transaction +) : APUndoService { + override suspend fun receiveUndo(undo: Undo): ActivityPubResponse { + if (undo.actor == null) { + return ActivityPubStringResponse(HttpStatusCode.BadRequest, "actor is null") + } + + val type = + undo.`object`?.type.orEmpty() + .firstOrNull { it == "Block" || it == "Follow" || it == "Like" || it == "Announce" || it == "Accept" } + ?: return ActivityPubStringResponse(HttpStatusCode.BadRequest, "unknown type ${undo.`object`?.type}") + + when (type) { + "Follow" -> { + val follow = undo.`object` as Follow + + if (follow.`object` == null) { + return ActivityPubStringResponse(HttpStatusCode.BadRequest, "object.object is null") + } + transaction.transaction { + apUserService.fetchPerson(undo.actor!!, follow.`object`) + val follower = userQueryService.findByUrl(undo.actor!!) + val target = userQueryService.findByUrl(follow.`object`!!) + userService.unfollow(target.id, follower.id) + } + } + + else -> {} + } + TODO() + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoServiceImpl.kt deleted file mode 100644 index 381e4160..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoServiceImpl.kt +++ /dev/null @@ -1,50 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import dev.usbharu.hideout.domain.model.ActivityPubResponse -import dev.usbharu.hideout.domain.model.ActivityPubStringResponse -import dev.usbharu.hideout.domain.model.ap.Follow -import dev.usbharu.hideout.domain.model.ap.Undo -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.IUserService -import io.ktor.http.* -import org.koin.core.annotation.Single - -@Single -@Suppress("UnsafeCallOnNullableType") -class APUndoServiceImpl( - private val userService: IUserService, - private val apUserService: APUserService, - private val userQueryService: UserQueryService, - private val transaction: Transaction -) : APUndoService { - override suspend fun receiveUndo(undo: Undo): ActivityPubResponse { - if (undo.actor == null) { - return ActivityPubStringResponse(HttpStatusCode.BadRequest, "actor is null") - } - - val type = - undo.`object`?.type.orEmpty() - .firstOrNull { it == "Block" || it == "Follow" || it == "Like" || it == "Announce" || it == "Accept" } - ?: return ActivityPubStringResponse(HttpStatusCode.BadRequest, "unknown type ${undo.`object`?.type}") - - when (type) { - "Follow" -> { - val follow = undo.`object` as Follow - - if (follow.`object` == null) { - return ActivityPubStringResponse(HttpStatusCode.BadRequest, "object.object is null") - } - transaction.transaction { - apUserService.fetchPerson(undo.actor!!, follow.`object`) - val follower = userQueryService.findByUrl(undo.actor!!) - val target = userQueryService.findByUrl(follow.`object`!!) - userService.unfollow(target.id, follower.id) - } - } - - else -> {} - } - TODO() - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt index d0c71b66..c31803eb 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt @@ -1,6 +1,22 @@ package dev.usbharu.hideout.service.ap +import com.fasterxml.jackson.module.kotlin.readValue +import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.domain.model.ap.Image +import dev.usbharu.hideout.domain.model.ap.Key import dev.usbharu.hideout.domain.model.ap.Person +import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto +import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException +import dev.usbharu.hideout.plugins.getAp +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.core.Transaction +import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.util.HttpUtil.Activity +import io.ktor.client.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.http.* +import org.koin.core.annotation.Single interface APUserService { suspend fun getPersonByName(name: String): Person @@ -14,3 +30,99 @@ interface APUserService { */ suspend fun fetchPerson(url: String, targetActor: String? = null): Person } + +@Single +class APUserServiceImpl( + private val userService: IUserService, + private val httpClient: HttpClient, + private val userQueryService: UserQueryService, + private val transaction: Transaction +) : + APUserService { + + override suspend fun getPersonByName(name: String): Person { + val userEntity = transaction.transaction { + userQueryService.findByNameAndDomain(name, Config.configData.domain) + } + // TODO: JOINで書き直し + val userUrl = "${Config.configData.url}/users/$name" + return Person( + type = emptyList(), + name = userEntity.name, + id = userUrl, + preferredUsername = name, + summary = userEntity.description, + inbox = "$userUrl/inbox", + outbox = "$userUrl/outbox", + url = userUrl, + icon = Image( + type = emptyList(), + name = "$userUrl/icon.png", + mediaType = "image/png", + url = "$userUrl/icon.png" + ), + publicKey = Key( + type = emptyList(), + name = "Public Key", + id = "$userUrl#pubkey", + owner = userUrl, + publicKeyPem = userEntity.publicKey + ) + ) + } + + override suspend fun fetchPerson(url: String, targetActor: String?): Person { + return try { + val userEntity = userQueryService.findByUrl(url) + return Person( + type = emptyList(), + name = userEntity.name, + id = url, + preferredUsername = userEntity.name, + summary = userEntity.description, + inbox = "$url/inbox", + outbox = "$url/outbox", + url = url, + icon = Image( + type = emptyList(), + name = "$url/icon.png", + mediaType = "image/png", + url = "$url/icon.png" + ), + publicKey = Key( + type = emptyList(), + name = "Public Key", + id = "$url#pubkey", + owner = url, + publicKeyPem = userEntity.publicKey + ) + ) + } catch (ignore: NoSuchElementException) { + val httpResponse = if (targetActor != null) { + httpClient.getAp(url, "$targetActor#pubkey") + } else { + httpClient.get(url) { + accept(ContentType.Application.Activity) + } + } + val person = Config.configData.objectMapper.readValue<Person>(httpResponse.bodyAsText()) + + userService.createRemoteUser( + RemoteUserCreateDto( + name = person.preferredUsername + ?: throw IllegalActivityPubObjectException("preferredUsername is null"), + domain = url.substringAfter("://").substringBefore("/"), + screenName = (person.name ?: person.preferredUsername) + ?: throw IllegalActivityPubObjectException("preferredUsername is null"), + description = person.summary.orEmpty(), + inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"), + outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"), + url = url, + publicKey = person.publicKey?.publicKeyPem + ?: throw IllegalActivityPubObjectException("publicKey is null"), + ) + ) + person + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserServiceImpl.kt deleted file mode 100644 index ec846191..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserServiceImpl.kt +++ /dev/null @@ -1,115 +0,0 @@ -package dev.usbharu.hideout.service.ap - -import com.fasterxml.jackson.module.kotlin.readValue -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.domain.model.ap.Image -import dev.usbharu.hideout.domain.model.ap.Key -import dev.usbharu.hideout.domain.model.ap.Person -import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto -import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException -import dev.usbharu.hideout.plugins.getAp -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.IUserService -import dev.usbharu.hideout.util.HttpUtil.Activity -import io.ktor.client.* -import io.ktor.client.request.* -import io.ktor.client.statement.* -import io.ktor.http.* -import org.koin.core.annotation.Single - -@Single -class APUserServiceImpl( - private val userService: IUserService, - private val httpClient: HttpClient, - private val userQueryService: UserQueryService, - private val transaction: Transaction -) : - APUserService { - - override suspend fun getPersonByName(name: String): Person { - val userEntity = transaction.transaction { - userQueryService.findByNameAndDomain(name, Config.configData.domain) - } - // TODO: JOINで書き直し - val userUrl = "${Config.configData.url}/users/$name" - return Person( - type = emptyList(), - name = userEntity.name, - id = userUrl, - preferredUsername = name, - summary = userEntity.description, - inbox = "$userUrl/inbox", - outbox = "$userUrl/outbox", - url = userUrl, - icon = Image( - type = emptyList(), - name = "$userUrl/icon.png", - mediaType = "image/png", - url = "$userUrl/icon.png" - ), - publicKey = Key( - type = emptyList(), - name = "Public Key", - id = "$userUrl#pubkey", - owner = userUrl, - publicKeyPem = userEntity.publicKey - ) - ) - } - - override suspend fun fetchPerson(url: String, targetActor: String?): Person { - return try { - val userEntity = userQueryService.findByUrl(url) - return Person( - type = emptyList(), - name = userEntity.name, - id = url, - preferredUsername = userEntity.name, - summary = userEntity.description, - inbox = "$url/inbox", - outbox = "$url/outbox", - url = url, - icon = Image( - type = emptyList(), - name = "$url/icon.png", - mediaType = "image/png", - url = "$url/icon.png" - ), - publicKey = Key( - type = emptyList(), - name = "Public Key", - id = "$url#pubkey", - owner = url, - publicKeyPem = userEntity.publicKey - ) - ) - } catch (ignore: NoSuchElementException) { - val httpResponse = if (targetActor != null) { - httpClient.getAp(url, "$targetActor#pubkey") - } else { - httpClient.get(url) { - accept(ContentType.Application.Activity) - } - } - val person = Config.configData.objectMapper.readValue<Person>(httpResponse.bodyAsText()) - - userService.createRemoteUser( - RemoteUserCreateDto( - name = person.preferredUsername - ?: throw IllegalActivityPubObjectException("preferredUsername is null"), - domain = url.substringAfter("://").substringBefore("/"), - screenName = (person.name ?: person.preferredUsername) - ?: throw IllegalActivityPubObjectException("preferredUsername is null"), - description = person.summary.orEmpty(), - inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"), - outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"), - url = url, - publicKey = person.publicKey?.publicKeyPem - ?: throw IllegalActivityPubObjectException("publicKey is null"), - ) - ) - person - } - } -} 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 3ce027fb..61715cc0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt @@ -1,7 +1,18 @@ 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.dto.PostResponse import dev.usbharu.hideout.domain.model.hideout.dto.ReactionResponse +import dev.usbharu.hideout.domain.model.hideout.form.Post +import dev.usbharu.hideout.query.PostResponseQueryService +import dev.usbharu.hideout.query.ReactionQueryService +import dev.usbharu.hideout.repository.IUserRepository +import dev.usbharu.hideout.service.core.Transaction +import dev.usbharu.hideout.service.post.IPostService +import dev.usbharu.hideout.service.reaction.IReactionService +import dev.usbharu.hideout.util.AcctUtil +import org.koin.core.annotation.Single import java.time.Instant @Suppress("LongParameterList") @@ -31,3 +42,83 @@ interface IPostApiService { suspend fun appendReaction(reaction: String, userId: Long, postId: Long) suspend fun removeReaction(userId: Long, postId: Long) } + +@Single +class PostApiServiceImpl( + private val postService: IPostService, + private val userRepository: IUserRepository, + private val postResponseQueryService: PostResponseQueryService, + private val reactionQueryService: ReactionQueryService, + private val reactionService: IReactionService, + private val transaction: Transaction +) : IPostApiService { + override suspend fun createPost(postForm: Post, userId: Long): PostResponse { + return transaction.transaction { + val createdPost = postService.createLocal( + PostCreateDto( + text = postForm.text, + overview = postForm.overview, + visibility = postForm.visibility, + repostId = postForm.repostId, + repolyId = postForm.replyId, + userId = userId + ) + ) + val creator = userRepository.findById(userId) + PostResponse.from(createdPost, creator!!) + } + } + + override suspend fun getById(id: Long, userId: Long?): PostResponse = postResponseQueryService.findById(id, userId) + + override suspend fun getAll( + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List<PostResponse> = transaction.transaction { + postResponseQueryService.findAll( + since = since?.toEpochMilli(), + until = until?.toEpochMilli(), + minId = minId, + maxId = maxId, + limit = limit, + userId = userId + ) + } + + override suspend fun getByUser( + nameOrId: String, + since: Instant?, + until: Instant?, + minId: Long?, + maxId: Long?, + limit: Int?, + userId: Long? + ): List<PostResponse> { + val idOrNull = nameOrId.toLongOrNull() + return if (idOrNull == null) { + val acct = AcctUtil.parse(nameOrId) + postResponseQueryService.findByUserNameAndUserDomain(acct.username, acct.domain ?: Config.configData.domain) + } else { + postResponseQueryService.findByUserId(idOrNull) + } + } + + override suspend fun getReactionByPostId(postId: Long, userId: Long?): List<ReactionResponse> = + transaction.transaction { reactionQueryService.findByPostIdWithUsers(postId, userId) } + + override suspend fun appendReaction(reaction: String, userId: Long, postId: Long) { + transaction.transaction { + reactionService.sendReaction(reaction, userId, postId) + } + } + + override suspend fun removeReaction(userId: Long, postId: Long) { + transaction.transaction { + reactionService.removeReaction(userId, postId) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/IUserApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/IUserApiService.kt index 7d902de3..26135f8a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/IUserApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/IUserApiService.kt @@ -1,7 +1,16 @@ package dev.usbharu.hideout.service.api +import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.Acct +import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse +import dev.usbharu.hideout.exception.UsernameAlreadyExistException +import dev.usbharu.hideout.query.FollowerQueryService +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.core.Transaction +import dev.usbharu.hideout.service.user.IUserService +import org.koin.core.annotation.Single +import kotlin.math.min interface IUserApiService { suspend fun findAll(limit: Int? = 100, offset: Long = 0): List<UserResponse> @@ -22,3 +31,45 @@ interface IUserApiService { suspend fun createUser(username: String, password: String): UserResponse } + +@Single +class UserApiServiceImpl( + private val userQueryService: UserQueryService, + private val followerQueryService: FollowerQueryService, + private val userService: IUserService, + private val transaction: Transaction +) : IUserApiService { + override suspend fun findAll(limit: Int?, offset: Long): List<UserResponse> = + userQueryService.findAll(min(limit ?: 100, 100), offset).map { UserResponse.from(it) } + + override suspend fun findById(id: Long): UserResponse = UserResponse.from(userQueryService.findById(id)) + + override suspend fun findByIds(ids: List<Long>): List<UserResponse> = + userQueryService.findByIds(ids).map { UserResponse.from(it) } + + override suspend fun findByAcct(acct: Acct): UserResponse = + UserResponse.from(userQueryService.findByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain)) + + override suspend fun findFollowers(userId: Long): List<UserResponse> = + followerQueryService.findFollowersById(userId).map { UserResponse.from(it) } + + override suspend fun findFollowings(userId: Long): List<UserResponse> = + followerQueryService.findFollowingById(userId).map { UserResponse.from(it) } + + override suspend fun findFollowersByAcct(acct: Acct): List<UserResponse> = + followerQueryService.findFollowersByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain) + .map { UserResponse.from(it) } + + override suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse> = + followerQueryService.findFollowingByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain) + .map { UserResponse.from(it) } + + override suspend fun createUser(username: String, password: String): UserResponse { + return transaction.transaction { + if (userQueryService.existByNameAndDomain(username, Config.configData.domain)) { + throw UsernameAlreadyExistException() + } + UserResponse.from(userService.createLocalUser(UserCreateDto(username, username, "", password))) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt deleted file mode 100644 index ee08b7d9..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiServiceImpl.kt +++ /dev/null @@ -1,96 +0,0 @@ -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.dto.PostResponse -import dev.usbharu.hideout.domain.model.hideout.dto.ReactionResponse -import dev.usbharu.hideout.query.PostResponseQueryService -import dev.usbharu.hideout.query.ReactionQueryService -import dev.usbharu.hideout.repository.IUserRepository -import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.post.IPostService -import dev.usbharu.hideout.service.reaction.IReactionService -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 userRepository: IUserRepository, - private val postResponseQueryService: PostResponseQueryService, - private val reactionQueryService: ReactionQueryService, - private val reactionService: IReactionService, - private val transaction: Transaction -) : IPostApiService { - override suspend fun createPost(postForm: FormPost, userId: Long): PostResponse { - return transaction.transaction { - val createdPost = postService.createLocal( - PostCreateDto( - text = postForm.text, - overview = postForm.overview, - visibility = postForm.visibility, - repostId = postForm.repostId, - repolyId = postForm.replyId, - userId = userId - ) - ) - val creator = userRepository.findById(userId) - PostResponse.from(createdPost, creator!!) - } - } - - override suspend fun getById(id: Long, userId: Long?): PostResponse = postResponseQueryService.findById(id, userId) - - override suspend fun getAll( - since: Instant?, - until: Instant?, - minId: Long?, - maxId: Long?, - limit: Int?, - userId: Long? - ): List<PostResponse> = transaction.transaction { - postResponseQueryService.findAll( - since = since?.toEpochMilli(), - until = until?.toEpochMilli(), - minId = minId, - maxId = maxId, - limit = limit, - userId = userId - ) - } - - override suspend fun getByUser( - nameOrId: String, - since: Instant?, - until: Instant?, - minId: Long?, - maxId: Long?, - limit: Int?, - userId: Long? - ): List<PostResponse> { - val idOrNull = nameOrId.toLongOrNull() - return if (idOrNull == null) { - val acct = AcctUtil.parse(nameOrId) - postResponseQueryService.findByUserNameAndUserDomain(acct.username, acct.domain ?: Config.configData.domain) - } else { - postResponseQueryService.findByUserId(idOrNull) - } - } - - override suspend fun getReactionByPostId(postId: Long, userId: Long?): List<ReactionResponse> = - transaction.transaction { reactionQueryService.findByPostIdWithUsers(postId, userId) } - - override suspend fun appendReaction(reaction: String, userId: Long, postId: Long) { - transaction.transaction { - reactionService.sendReaction(reaction, userId, postId) - } - } - - override suspend fun removeReaction(userId: Long, postId: Long) { - transaction.transaction { - reactionService.removeReaction(userId, postId) - } - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/UserApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/UserApiServiceImpl.kt deleted file mode 100644 index 0cd675c2..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/UserApiServiceImpl.kt +++ /dev/null @@ -1,55 +0,0 @@ -package dev.usbharu.hideout.service.api - -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.domain.model.Acct -import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto -import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse -import dev.usbharu.hideout.exception.UsernameAlreadyExistException -import dev.usbharu.hideout.query.FollowerQueryService -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.IUserService -import org.koin.core.annotation.Single -import kotlin.math.min - -@Single -class UserApiServiceImpl( - private val userQueryService: UserQueryService, - private val followerQueryService: FollowerQueryService, - private val userService: IUserService, - private val transaction: Transaction -) : IUserApiService { - override suspend fun findAll(limit: Int?, offset: Long): List<UserResponse> = - userQueryService.findAll(min(limit ?: 100, 100), offset).map { UserResponse.from(it) } - - override suspend fun findById(id: Long): UserResponse = UserResponse.from(userQueryService.findById(id)) - - override suspend fun findByIds(ids: List<Long>): List<UserResponse> = - userQueryService.findByIds(ids).map { UserResponse.from(it) } - - override suspend fun findByAcct(acct: Acct): UserResponse = - UserResponse.from(userQueryService.findByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain)) - - override suspend fun findFollowers(userId: Long): List<UserResponse> = - followerQueryService.findFollowersById(userId).map { UserResponse.from(it) } - - override suspend fun findFollowings(userId: Long): List<UserResponse> = - followerQueryService.findFollowingById(userId).map { UserResponse.from(it) } - - override suspend fun findFollowersByAcct(acct: Acct): List<UserResponse> = - followerQueryService.findFollowersByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain) - .map { UserResponse.from(it) } - - override suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse> = - followerQueryService.findFollowingByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain) - .map { UserResponse.from(it) } - - override suspend fun createUser(username: String, password: String): UserResponse { - return transaction.transaction { - if (userQueryService.existByNameAndDomain(username, Config.configData.domain)) { - throw UsernameAlreadyExistException() - } - UserResponse.from(userService.createLocalUser(UserCreateDto(username, username, "", password))) - } - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt index 0c8d35f5..d56bbc4f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt @@ -1,9 +1,40 @@ package dev.usbharu.hideout.service.api +import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken +import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.auth.IJwtService +import dev.usbharu.hideout.service.core.Transaction +import dev.usbharu.hideout.service.user.UserAuthService +import org.koin.core.annotation.Single interface UserAuthApiService { suspend fun login(username: String, password: String): JwtToken suspend fun refreshToken(refreshToken: RefreshToken): JwtToken } + +@Single +class UserAuthApiServiceImpl( + private val userAuthService: UserAuthService, + private val userQueryService: UserQueryService, + private val jwtService: IJwtService, + private val transaction: Transaction +) : UserAuthApiService { + override suspend fun login(username: String, password: String): JwtToken { + return transaction.transaction { + if (userAuthService.verifyAccount(username, password).not()) { + throw InvalidUsernameOrPasswordException() + } + val user = userQueryService.findByNameAndDomain(username, Config.configData.domain) + jwtService.createToken(user) + } + } + + override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken { + return transaction.transaction { + jwtService.refreshToken(refreshToken) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiServiceImpl.kt deleted file mode 100644 index 6896419b..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiServiceImpl.kt +++ /dev/null @@ -1,35 +0,0 @@ -package dev.usbharu.hideout.service.api - -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken -import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken -import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.auth.IJwtService -import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.UserAuthService -import org.koin.core.annotation.Single - -@Single -class UserAuthApiServiceImpl( - private val userAuthService: UserAuthService, - private val userQueryService: UserQueryService, - private val jwtService: IJwtService, - private val transaction: Transaction -) : UserAuthApiService { - override suspend fun login(username: String, password: String): JwtToken { - return transaction.transaction { - if (userAuthService.verifyAccount(username, password).not()) { - throw InvalidUsernameOrPasswordException() - } - val user = userQueryService.findByNameAndDomain(username, Config.configData.domain) - jwtService.createToken(user) - } - } - - override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken { - return transaction.transaction { - jwtService.refreshToken(refreshToken) - } - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiService.kt index cdda80b7..5311723c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiService.kt @@ -1,7 +1,20 @@ package dev.usbharu.hideout.service.api import dev.usbharu.hideout.domain.model.hideout.entity.User +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.core.Transaction +import org.koin.core.annotation.Single interface WebFingerApiService { suspend fun findByNameAndDomain(name: String, domain: String): User } + +@Single +class WebFingerApiServiceImpl(private val transaction: Transaction, private val userQueryService: UserQueryService) : + WebFingerApiService { + override suspend fun findByNameAndDomain(name: String, domain: String): User { + return transaction.transaction { + userQueryService.findByNameAndDomain(name, domain) + } + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiServiceImpl.kt deleted file mode 100644 index 66934625..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/WebFingerApiServiceImpl.kt +++ /dev/null @@ -1,16 +0,0 @@ -package dev.usbharu.hideout.service.api - -import dev.usbharu.hideout.domain.model.hideout.entity.User -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.core.Transaction -import org.koin.core.annotation.Single - -@Single -class WebFingerApiServiceImpl(private val transaction: Transaction, private val userQueryService: UserQueryService) : - WebFingerApiService { - override suspend fun findByNameAndDomain(name: String, domain: String): User { - return transaction.transaction { - userQueryService.findByNameAndDomain(name, domain) - } - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyService.kt b/src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyService.kt index ad326e3b..eb30c903 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyService.kt @@ -1,7 +1,33 @@ package dev.usbharu.hideout.service.auth +import dev.usbharu.hideout.plugins.KtorKeyMap +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.service.core.Transaction import io.ktor.http.* +import org.koin.core.annotation.Single +import tech.barbero.http.message.signing.SignatureHeaderVerifier interface HttpSignatureVerifyService { fun verify(headers: Headers): Boolean } + +@Single +class HttpSignatureVerifyServiceImpl( + private val userQueryService: UserQueryService, + private val transaction: Transaction +) : HttpSignatureVerifyService { + override fun verify(headers: Headers): Boolean { + val build = SignatureHeaderVerifier.builder().keyMap(KtorKeyMap(userQueryService, transaction)).build() + return true +// build.verify(object : HttpMessage { +// override fun headerValues(name: String?): MutableList<String> { +// return name?.let { headers.getAll(it) }?.toMutableList() ?: mutableListOf() +// } +// +// override fun addHeader(name: String?, value: String?) { +// TODO() +// } +// +// }) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyServiceImpl.kt deleted file mode 100644 index e9282d34..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/auth/HttpSignatureVerifyServiceImpl.kt +++ /dev/null @@ -1,29 +0,0 @@ -package dev.usbharu.hideout.service.auth - -import dev.usbharu.hideout.plugins.KtorKeyMap -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.core.Transaction -import io.ktor.http.* -import org.koin.core.annotation.Single -import tech.barbero.http.message.signing.SignatureHeaderVerifier - -@Single -class HttpSignatureVerifyServiceImpl( - private val userQueryService: UserQueryService, - private val transaction: Transaction -) : HttpSignatureVerifyService { - override fun verify(headers: Headers): Boolean { - val build = SignatureHeaderVerifier.builder().keyMap(KtorKeyMap(userQueryService, transaction)).build() - return true -// build.verify(object : HttpMessage { -// override fun headerValues(name: String?): MutableList<String> { -// return name?.let { headers.getAll(it) }?.toMutableList() ?: mutableListOf() -// } -// -// override fun addHeader(name: String?, value: String?) { -// TODO() -// } -// -// }) - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/auth/IJwtService.kt b/src/main/kotlin/dev/usbharu/hideout/service/auth/IJwtService.kt index e1976818..2f74c2fa 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/auth/IJwtService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/auth/IJwtService.kt @@ -1,8 +1,23 @@ package dev.usbharu.hideout.service.auth +import com.auth0.jwt.JWT +import com.auth0.jwt.algorithms.Algorithm +import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken +import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken +import dev.usbharu.hideout.exception.InvalidRefreshTokenException +import dev.usbharu.hideout.query.JwtRefreshTokenQueryService +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository +import dev.usbharu.hideout.service.core.IMetaService +import dev.usbharu.hideout.util.RsaUtil +import kotlinx.coroutines.runBlocking +import org.koin.core.annotation.Single +import java.time.Instant +import java.time.temporal.ChronoUnit +import java.util.* interface IJwtService { suspend fun createToken(user: User): JwtToken @@ -12,3 +27,78 @@ interface IJwtService { suspend fun revokeToken(user: User) suspend fun revokeAll() } + +@Suppress("InjectDispatcher") +@Single +class JwtServiceImpl( + private val metaService: IMetaService, + private val refreshTokenRepository: IJwtRefreshTokenRepository, + private val userQueryService: UserQueryService, + private val refreshTokenQueryService: JwtRefreshTokenQueryService +) : IJwtService { + + private val privateKey = runBlocking { + RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey) + } + + private val publicKey = runBlocking { + RsaUtil.decodeRsaPublicKey(metaService.getJwtMeta().publicKey) + } + + private val keyId = runBlocking { metaService.getJwtMeta().kid } + + @Suppress("MagicNumber") + override suspend fun createToken(user: User): JwtToken { + val now = Instant.now() + val token = JWT.create() + .withAudience("${Config.configData.url}/users/${user.name}") + .withIssuer(Config.configData.url) + .withKeyId(keyId.toString()) + .withClaim("uid", user.id) + .withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) + .sign(Algorithm.RSA256(publicKey, privateKey)) + + val jwtRefreshToken = JwtRefreshToken( + id = refreshTokenRepository.generateId(), + userId = user.id, + refreshToken = UUID.randomUUID().toString(), + createdAt = now, + expiresAt = now.plus(14, ChronoUnit.DAYS) + ) + refreshTokenRepository.save(jwtRefreshToken) + return JwtToken(token, jwtRefreshToken.refreshToken) + } + + override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken { + val token = try { + refreshTokenQueryService.findByToken(refreshToken.refreshToken) + } catch (_: NoSuchElementException) { + throw InvalidRefreshTokenException("Invalid Refresh Token") + } + + val user = userQueryService.findById(token.userId) + + val now = Instant.now() + if (token.createdAt.isAfter(now)) { + throw InvalidRefreshTokenException("Invalid Refresh Token") + } + + if (token.expiresAt.isBefore(now)) { + throw InvalidRefreshTokenException("Refresh Token Expired") + } + + return createToken(user) + } + + override suspend fun revokeToken(refreshToken: RefreshToken) { + refreshTokenQueryService.deleteByToken(refreshToken.refreshToken) + } + + override suspend fun revokeToken(user: User) { + refreshTokenQueryService.deleteByUserId(user.id) + } + + override suspend fun revokeAll() { + refreshTokenQueryService.deleteAll() + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImpl.kt deleted file mode 100644 index a04dc2f9..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImpl.kt +++ /dev/null @@ -1,95 +0,0 @@ -package dev.usbharu.hideout.service.auth - -import com.auth0.jwt.JWT -import com.auth0.jwt.algorithms.Algorithm -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken -import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken -import dev.usbharu.hideout.domain.model.hideout.entity.User -import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken -import dev.usbharu.hideout.exception.InvalidRefreshTokenException -import dev.usbharu.hideout.query.JwtRefreshTokenQueryService -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository -import dev.usbharu.hideout.service.core.IMetaService -import dev.usbharu.hideout.util.RsaUtil -import kotlinx.coroutines.runBlocking -import org.koin.core.annotation.Single -import java.time.Instant -import java.time.temporal.ChronoUnit -import java.util.* - -@Suppress("InjectDispatcher") -@Single -class JwtServiceImpl( - private val metaService: IMetaService, - private val refreshTokenRepository: IJwtRefreshTokenRepository, - private val userQueryService: UserQueryService, - private val refreshTokenQueryService: JwtRefreshTokenQueryService -) : IJwtService { - - private val privateKey = runBlocking { - RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey) - } - - private val publicKey = runBlocking { - RsaUtil.decodeRsaPublicKey(metaService.getJwtMeta().publicKey) - } - - private val keyId = runBlocking { metaService.getJwtMeta().kid } - - @Suppress("MagicNumber") - override suspend fun createToken(user: User): JwtToken { - val now = Instant.now() - val token = JWT.create() - .withAudience("${Config.configData.url}/users/${user.name}") - .withIssuer(Config.configData.url) - .withKeyId(keyId.toString()) - .withClaim("uid", user.id) - .withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) - .sign(Algorithm.RSA256(publicKey, privateKey)) - - val jwtRefreshToken = JwtRefreshToken( - id = refreshTokenRepository.generateId(), - userId = user.id, - refreshToken = UUID.randomUUID().toString(), - createdAt = now, - expiresAt = now.plus(14, ChronoUnit.DAYS) - ) - refreshTokenRepository.save(jwtRefreshToken) - return JwtToken(token, jwtRefreshToken.refreshToken) - } - - override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken { - val token = try { - refreshTokenQueryService.findByToken(refreshToken.refreshToken) - } catch (_: NoSuchElementException) { - throw InvalidRefreshTokenException("Invalid Refresh Token") - } - - val user = userQueryService.findById(token.userId) - - val now = Instant.now() - if (token.createdAt.isAfter(now)) { - throw InvalidRefreshTokenException("Invalid Refresh Token") - } - - if (token.expiresAt.isBefore(now)) { - throw InvalidRefreshTokenException("Refresh Token Expired") - } - - return createToken(user) - } - - override suspend fun revokeToken(refreshToken: RefreshToken) { - refreshTokenQueryService.deleteByToken(refreshToken.refreshToken) - } - - override suspend fun revokeToken(user: User) { - refreshTokenQueryService.deleteByUserId(user.id) - } - - override suspend fun revokeAll() { - refreshTokenQueryService.deleteAll() - } -} From e4ff750f2501e9d756e13fea92438014adc675f2 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:44:23 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=E5=91=BD=E5=90=8D=E8=A6=8F?= =?UTF-8?q?=E5=89=87=E3=82=92=E7=B5=B1=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/dev/usbharu/hideout/Application.kt | 18 +-- .../usbharu/hideout/plugins/ActivityPub.kt | 4 +- .../dev/usbharu/hideout/plugins/Routing.kt | 12 +- .../dev/usbharu/hideout/plugins/Security.kt | 4 +- .../hideout/repository/IUserRepository.kt | 18 --- ...sitory.kt => JwtRefreshTokenRepository.kt} | 2 +- .../JwtRefreshTokenRepositoryImpl.kt | 2 +- .../{IMetaRepository.kt => MetaRepository.kt} | 2 +- .../hideout/repository/MetaRepositoryImpl.kt | 2 +- .../{IPostRepository.kt => PostRepository.kt} | 2 +- .../hideout/repository/PostRepositoryImpl.kt | 2 +- .../hideout/repository/UserRepository.kt | 135 +---------------- .../hideout/repository/UserRepositoryImpl.kt | 137 ++++++++++++++++++ .../hideout/routing/RegisterRouting.kt | 4 +- .../hideout/routing/api/internal/v1/Posts.kt | 4 +- .../hideout/routing/api/internal/v1/Users.kt | 6 +- .../hideout/service/ap/APAcceptService.kt | 4 +- .../hideout/service/ap/APLikeService.kt | 4 +- .../hideout/service/ap/APNoteService.kt | 4 +- .../hideout/service/ap/APReactionService.kt | 4 +- .../service/ap/APReceiveFollowService.kt | 4 +- .../hideout/service/ap/APUndoService.kt | 4 +- .../hideout/service/ap/APUserService.kt | 4 +- .../{IPostApiService.kt => PostApiService.kt} | 16 +- .../{IUserApiService.kt => UserApiService.kt} | 8 +- .../hideout/service/api/UserAuthApiService.kt | 8 +- .../auth/{IJwtService.kt => JwtService.kt} | 12 +- .../core/{IMetaService.kt => MetaService.kt} | 2 +- .../hideout/service/core/MetaServiceImpl.kt | 6 +- ...eService.kt => ServerInitialiseService.kt} | 2 +- .../core/ServerInitialiseServiceImpl.kt | 6 +- .../post/{IPostService.kt => PostService.kt} | 2 +- .../hideout/service/post/PostServiceImpl.kt | 10 +- ...IReactionService.kt => ReactionService.kt} | 2 +- .../service/reaction/ReactionServiceImpl.kt | 2 +- .../hideout/service/user/IUserAuthService.kt | 13 -- .../hideout/service/user/IUserService.kt | 34 ----- .../hideout/service/user/UserAuthService.kt | 52 +------ .../service/user/UserAuthServiceImpl.kt | 53 +++++++ .../hideout/service/user/UserService.kt | 105 +++----------- .../hideout/service/user/UserServiceImpl.kt | 97 +++++++++++++ .../usbharu/hideout/plugins/SecurityKtTest.kt | 26 ++-- .../routing/activitypub/InboxRoutingKtTest.kt | 6 +- .../routing/api/internal/v1/PostsTest.kt | 28 ++-- .../routing/api/internal/v1/UsersTest.kt | 42 +++--- .../ap/APReceiveFollowServiceImplTest.kt | 4 +- .../service/auth/JwtServiceImplTest.kt | 18 +-- .../service/core/MetaServiceImplTest.kt | 12 +- .../core/ServerInitialiseServiceImplTest.kt | 8 +- .../hideout/service/user/UserServiceTest.kt | 12 +- 50 files changed, 484 insertions(+), 484 deletions(-) delete mode 100644 src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt rename src/main/kotlin/dev/usbharu/hideout/repository/{IJwtRefreshTokenRepository.kt => JwtRefreshTokenRepository.kt} (88%) rename src/main/kotlin/dev/usbharu/hideout/repository/{IMetaRepository.kt => MetaRepository.kt} (85%) rename src/main/kotlin/dev/usbharu/hideout/repository/{IPostRepository.kt => PostRepository.kt} (90%) create mode 100644 src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt rename src/main/kotlin/dev/usbharu/hideout/service/api/{IPostApiService.kt => PostApiService.kt} (92%) rename src/main/kotlin/dev/usbharu/hideout/service/api/{IUserApiService.kt => UserApiService.kt} (95%) rename src/main/kotlin/dev/usbharu/hideout/service/auth/{IJwtService.kt => JwtService.kt} (92%) rename src/main/kotlin/dev/usbharu/hideout/service/core/{IMetaService.kt => MetaService.kt} (91%) rename src/main/kotlin/dev/usbharu/hideout/service/core/{IServerInitialiseService.kt => ServerInitialiseService.kt} (64%) rename src/main/kotlin/dev/usbharu/hideout/service/post/{IPostService.kt => PostService.kt} (90%) rename src/main/kotlin/dev/usbharu/hideout/service/reaction/{IReactionService.kt => ReactionService.kt} (90%) delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/user/IUserAuthService.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/service/user/IUserService.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthServiceImpl.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt index 2af9ef54..0acd75e5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/Application.kt +++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt @@ -17,15 +17,15 @@ import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.routing.register import dev.usbharu.hideout.service.ap.APService import dev.usbharu.hideout.service.ap.APUserService -import dev.usbharu.hideout.service.api.IPostApiService -import dev.usbharu.hideout.service.api.IUserApiService +import dev.usbharu.hideout.service.api.PostApiService +import dev.usbharu.hideout.service.api.UserApiService import dev.usbharu.hideout.service.api.UserAuthApiService import dev.usbharu.hideout.service.api.WebFingerApiService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.core.* import dev.usbharu.hideout.service.job.JobQueueParentService import dev.usbharu.hideout.service.job.KJobJobQueueParentService -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import dev.usbharu.kjob.exposed.ExposedKJob import io.ktor.client.* import io.ktor.client.engine.cio.* @@ -94,26 +94,26 @@ fun Application.parent() { configureKoin(module, HideoutModule().module) configureStatusPages() runBlocking { - inject<IServerInitialiseService>().value.init() + inject<ServerInitialiseService>().value.init() } configureCompression() configureHTTP() configureStaticRouting() configureMonitoring() configureSerialization() - register(inject<IUserApiService>().value) + register(inject<UserApiService>().value) configureSecurity( inject<JwkProvider>().value, - inject<IMetaService>().value + inject<MetaService>().value ) configureRouting( httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value, apService = inject<APService>().value, - userService = inject<IUserService>().value, + userService = inject<UserService>().value, apUserService = inject<APUserService>().value, - postService = inject<IPostApiService>().value, - userApiService = inject<IUserApiService>().value, + postService = inject<PostApiService>().value, + userApiService = inject<UserApiService>().value, userQueryService = inject<UserQueryService>().value, followerQueryService = inject<FollowerQueryService>().value, userAuthApiService = inject<UserAuthApiService>().value, diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt index bb30773b..f501fa98 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt @@ -4,7 +4,7 @@ import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.ap.JsonLd import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.UserAuthService +import dev.usbharu.hideout.service.user.UserAuthServiceImpl import dev.usbharu.hideout.util.HttpUtil.Activity import io.ktor.client.* import io.ktor.client.plugins.api.* @@ -73,7 +73,7 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo println("Digest !!") // UserAuthService.sha256.reset() val digest = - Base64.getEncoder().encodeToString(UserAuthService.sha256.digest(body.toByteArray(Charsets.UTF_8))) + Base64.getEncoder().encodeToString(UserAuthServiceImpl.sha256.digest(body.toByteArray(Charsets.UTF_8))) request.headers.append("Digest", "sha-256=$digest") } diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt index 0567db26..178127b5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt @@ -11,13 +11,13 @@ import dev.usbharu.hideout.routing.api.internal.v1.users import dev.usbharu.hideout.routing.wellknown.webfinger import dev.usbharu.hideout.service.ap.APService import dev.usbharu.hideout.service.ap.APUserService -import dev.usbharu.hideout.service.api.IPostApiService -import dev.usbharu.hideout.service.api.IUserApiService +import dev.usbharu.hideout.service.api.PostApiService +import dev.usbharu.hideout.service.api.UserApiService import dev.usbharu.hideout.service.api.UserAuthApiService import dev.usbharu.hideout.service.api.WebFingerApiService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import io.ktor.server.application.* import io.ktor.server.plugins.autohead.* import io.ktor.server.routing.* @@ -26,10 +26,10 @@ import io.ktor.server.routing.* fun Application.configureRouting( httpSignatureVerifyService: HttpSignatureVerifyService, apService: APService, - userService: IUserService, + userService: UserService, apUserService: APUserService, - postService: IPostApiService, - userApiService: IUserApiService, + postService: PostApiService, + userApiService: UserApiService, userQueryService: UserQueryService, followerQueryService: FollowerQueryService, userAuthApiService: UserAuthApiService, diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt index 84966882..a4d7d34d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt +++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt @@ -2,7 +2,7 @@ package dev.usbharu.hideout.plugins import com.auth0.jwk.JwkProvider import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.service.core.IMetaService +import dev.usbharu.hideout.service.core.MetaService import dev.usbharu.hideout.util.JsonWebKeyUtil import io.ktor.http.* import io.ktor.server.application.* @@ -16,7 +16,7 @@ const val TOKEN_AUTH = "jwt-auth" @Suppress("MagicNumber") fun Application.configureSecurity( jwkProvider: JwkProvider, - metaService: IMetaService + metaService: MetaService ) { val issuer = Config.configData.url install(Authentication) { diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt deleted file mode 100644 index e717f7b0..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt +++ /dev/null @@ -1,18 +0,0 @@ -package dev.usbharu.hideout.repository - -import dev.usbharu.hideout.domain.model.hideout.entity.User - -@Suppress("TooManyFunctions") -interface IUserRepository { - suspend fun save(user: User): User - - suspend fun findById(id: Long): User? - - suspend fun delete(id: Long) - - suspend fun deleteFollowRequest(id: Long, follower: Long) - - suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean - - suspend fun nextId(): Long -} diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IJwtRefreshTokenRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepository.kt similarity index 88% rename from src/main/kotlin/dev/usbharu/hideout/repository/IJwtRefreshTokenRepository.kt rename to src/main/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepository.kt index 19f8774a..d6bc5638 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IJwtRefreshTokenRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepository.kt @@ -2,7 +2,7 @@ package dev.usbharu.hideout.repository import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken -interface IJwtRefreshTokenRepository { +interface JwtRefreshTokenRepository { suspend fun generateId(): Long suspend fun save(token: JwtRefreshToken) diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImpl.kt index d93797d2..0fdc79dd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/JwtRefreshTokenRepositoryImpl.kt @@ -13,7 +13,7 @@ class JwtRefreshTokenRepositoryImpl( private val database: Database, private val idGenerateService: IdGenerateService ) : - IJwtRefreshTokenRepository { + JwtRefreshTokenRepository { init { transaction(database) { diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IMetaRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/MetaRepository.kt similarity index 85% rename from src/main/kotlin/dev/usbharu/hideout/repository/IMetaRepository.kt rename to src/main/kotlin/dev/usbharu/hideout/repository/MetaRepository.kt index b90be212..5fda5200 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IMetaRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/MetaRepository.kt @@ -2,7 +2,7 @@ package dev.usbharu.hideout.repository import dev.usbharu.hideout.domain.model.hideout.entity.Meta -interface IMetaRepository { +interface MetaRepository { suspend fun save(meta: Meta) diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/MetaRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/MetaRepositoryImpl.kt index 86dbc786..d0de63a1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/MetaRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/MetaRepositoryImpl.kt @@ -7,7 +7,7 @@ import org.koin.core.annotation.Single import java.util.* @Single -class MetaRepositoryImpl(private val database: Database) : IMetaRepository { +class MetaRepositoryImpl(private val database: Database) : MetaRepository { init { transaction(database) { diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepository.kt similarity index 90% rename from src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt rename to src/main/kotlin/dev/usbharu/hideout/repository/PostRepository.kt index 2e0faf91..21a9bec8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/IPostRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepository.kt @@ -3,7 +3,7 @@ package dev.usbharu.hideout.repository import dev.usbharu.hideout.domain.model.hideout.entity.Post @Suppress("LongParameterList") -interface IPostRepository { +interface PostRepository { suspend fun generateId(): Long suspend fun save(post: Post): Post suspend fun delete(id: Long) diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt index b9ca5f77..8782a54f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/PostRepositoryImpl.kt @@ -9,7 +9,7 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.koin.core.annotation.Single @Single -class PostRepositoryImpl(database: Database, private val idGenerateService: IdGenerateService) : IPostRepository { +class PostRepositoryImpl(database: Database, private val idGenerateService: IdGenerateService) : PostRepository { init { transaction(database) { diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt index b9064bf8..17344d24 100644 --- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt @@ -1,137 +1,18 @@ package dev.usbharu.hideout.repository import dev.usbharu.hideout.domain.model.hideout.entity.User -import dev.usbharu.hideout.service.core.IdGenerateService -import org.jetbrains.exposed.dao.id.LongIdTable -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.jetbrains.exposed.sql.transactions.transaction -import org.koin.core.annotation.Single -import java.time.Instant -@Single -class UserRepository(private val database: Database, private val idGenerateService: IdGenerateService) : - IUserRepository { - init { - transaction(database) { - SchemaUtils.create(Users) - SchemaUtils.create(UsersFollowers) - SchemaUtils.createMissingTablesAndColumns(Users) - SchemaUtils.createMissingTablesAndColumns(UsersFollowers) - SchemaUtils.create(FollowRequests) - SchemaUtils.createMissingTablesAndColumns(FollowRequests) - } - } +@Suppress("TooManyFunctions") +interface UserRepository { + suspend fun save(user: User): User - override suspend fun save(user: User): User { - val singleOrNull = Users.select { Users.id eq user.id }.singleOrNull() - if (singleOrNull == null) { - Users.insert { - it[id] = user.id - it[name] = user.name - it[domain] = user.domain - it[screenName] = user.screenName - it[description] = user.description - it[password] = user.password - it[inbox] = user.inbox - it[outbox] = user.outbox - it[url] = user.url - it[createdAt] = user.createdAt.toEpochMilli() - it[publicKey] = user.publicKey - it[privateKey] = user.privateKey - } - } else { - Users.update({ Users.id eq user.id }) { - it[name] = user.name - it[domain] = user.domain - it[screenName] = user.screenName - it[description] = user.description - it[password] = user.password - it[inbox] = user.inbox - it[outbox] = user.outbox - it[url] = user.url - it[createdAt] = user.createdAt.toEpochMilli() - it[publicKey] = user.publicKey - it[privateKey] = user.privateKey - } - } - return user - } + suspend fun findById(id: Long): User? - override suspend fun findById(id: Long): User? { - return Users.select { Users.id eq id }.map { - it.toUser() - }.singleOrNull() - } + suspend fun delete(id: Long) - override suspend fun deleteFollowRequest(id: Long, follower: Long) { - FollowRequests.deleteWhere { userId.eq(id) and followerId.eq(follower) } - } + suspend fun deleteFollowRequest(id: Long, follower: Long) - override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean { - return FollowRequests.select { (FollowRequests.userId eq id) and (FollowRequests.followerId eq follower) } - .singleOrNull() != null - } + suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean - override suspend fun delete(id: Long) { - Users.deleteWhere { Users.id.eq(id) } - } - - override suspend fun nextId(): Long = idGenerateService.generateId() -} - -object Users : Table("users") { - val id = long("id") - val name = varchar("name", length = 64) - val domain = varchar("domain", length = 255) - val screenName = varchar("screen_name", length = 64) - val description = varchar("description", length = 600) - val password = varchar("password", length = 255).nullable() - val inbox = varchar("inbox", length = 255).uniqueIndex() - val outbox = varchar("outbox", length = 255).uniqueIndex() - val url = varchar("url", length = 255).uniqueIndex() - val publicKey = varchar("public_key", length = 10000) - val privateKey = varchar("private_key", length = 10000).nullable() - val createdAt = long("created_at") - - override val primaryKey: PrimaryKey = PrimaryKey(id) - - init { - uniqueIndex(name, domain) - } -} - -fun ResultRow.toUser(): User { - return User( - id = this[Users.id], - name = this[Users.name], - domain = this[Users.domain], - screenName = this[Users.screenName], - description = this[Users.description], - password = this[Users.password], - inbox = this[Users.inbox], - outbox = this[Users.outbox], - url = this[Users.url], - publicKey = this[Users.publicKey], - privateKey = this[Users.privateKey], - createdAt = Instant.ofEpochMilli((this[Users.createdAt])) - ) -} - -object UsersFollowers : LongIdTable("users_followers") { - val userId = long("user_id").references(Users.id).index() - val followerId = long("follower_id").references(Users.id) - - init { - uniqueIndex(userId, followerId) - } -} - -object FollowRequests : LongIdTable("follow_requests") { - val userId = long("user_id").references(Users.id) - val followerId = long("follower_id").references(Users.id) - - init { - uniqueIndex(userId, followerId) - } + suspend fun nextId(): Long } diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt new file mode 100644 index 00000000..43ea37ef --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepositoryImpl.kt @@ -0,0 +1,137 @@ +package dev.usbharu.hideout.repository + +import dev.usbharu.hideout.domain.model.hideout.entity.User +import dev.usbharu.hideout.service.core.IdGenerateService +import org.jetbrains.exposed.dao.id.LongIdTable +import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.transactions.transaction +import org.koin.core.annotation.Single +import java.time.Instant + +@Single +class UserRepositoryImpl(private val database: Database, private val idGenerateService: IdGenerateService) : + UserRepository { + init { + transaction(database) { + SchemaUtils.create(Users) + SchemaUtils.create(UsersFollowers) + SchemaUtils.createMissingTablesAndColumns(Users) + SchemaUtils.createMissingTablesAndColumns(UsersFollowers) + SchemaUtils.create(FollowRequests) + SchemaUtils.createMissingTablesAndColumns(FollowRequests) + } + } + + override suspend fun save(user: User): User { + val singleOrNull = Users.select { Users.id eq user.id }.singleOrNull() + if (singleOrNull == null) { + Users.insert { + it[id] = user.id + it[name] = user.name + it[domain] = user.domain + it[screenName] = user.screenName + it[description] = user.description + it[password] = user.password + it[inbox] = user.inbox + it[outbox] = user.outbox + it[url] = user.url + it[createdAt] = user.createdAt.toEpochMilli() + it[publicKey] = user.publicKey + it[privateKey] = user.privateKey + } + } else { + Users.update({ Users.id eq user.id }) { + it[name] = user.name + it[domain] = user.domain + it[screenName] = user.screenName + it[description] = user.description + it[password] = user.password + it[inbox] = user.inbox + it[outbox] = user.outbox + it[url] = user.url + it[createdAt] = user.createdAt.toEpochMilli() + it[publicKey] = user.publicKey + it[privateKey] = user.privateKey + } + } + return user + } + + override suspend fun findById(id: Long): User? { + return Users.select { Users.id eq id }.map { + it.toUser() + }.singleOrNull() + } + + override suspend fun deleteFollowRequest(id: Long, follower: Long) { + FollowRequests.deleteWhere { userId.eq(id) and followerId.eq(follower) } + } + + override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean { + return FollowRequests.select { (FollowRequests.userId eq id) and (FollowRequests.followerId eq follower) } + .singleOrNull() != null + } + + override suspend fun delete(id: Long) { + Users.deleteWhere { Users.id.eq(id) } + } + + override suspend fun nextId(): Long = idGenerateService.generateId() +} + +object Users : Table("users") { + val id = long("id") + val name = varchar("name", length = 64) + val domain = varchar("domain", length = 255) + val screenName = varchar("screen_name", length = 64) + val description = varchar("description", length = 600) + val password = varchar("password", length = 255).nullable() + val inbox = varchar("inbox", length = 255).uniqueIndex() + val outbox = varchar("outbox", length = 255).uniqueIndex() + val url = varchar("url", length = 255).uniqueIndex() + val publicKey = varchar("public_key", length = 10000) + val privateKey = varchar("private_key", length = 10000).nullable() + val createdAt = long("created_at") + + override val primaryKey: PrimaryKey = PrimaryKey(id) + + init { + uniqueIndex(name, domain) + } +} + +fun ResultRow.toUser(): User { + return User( + id = this[Users.id], + name = this[Users.name], + domain = this[Users.domain], + screenName = this[Users.screenName], + description = this[Users.description], + password = this[Users.password], + inbox = this[Users.inbox], + outbox = this[Users.outbox], + url = this[Users.url], + publicKey = this[Users.publicKey], + privateKey = this[Users.privateKey], + createdAt = Instant.ofEpochMilli((this[Users.createdAt])) + ) +} + +object UsersFollowers : LongIdTable("users_followers") { + val userId = long("user_id").references(Users.id).index() + val followerId = long("follower_id").references(Users.id) + + init { + uniqueIndex(userId, followerId) + } +} + +object FollowRequests : LongIdTable("follow_requests") { + val userId = long("user_id").references(Users.id) + val followerId = long("follower_id").references(Users.id) + + init { + uniqueIndex(userId, followerId) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt index 2e01c939..8628f340 100644 --- a/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt +++ b/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt @@ -1,6 +1,6 @@ package dev.usbharu.hideout.routing -import dev.usbharu.hideout.service.api.IUserApiService +import dev.usbharu.hideout.service.api.UserApiService import io.ktor.http.* import io.ktor.server.application.* import io.ktor.server.auth.* @@ -8,7 +8,7 @@ import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* -fun Application.register(userApiService: IUserApiService) { +fun Application.register(userApiService: UserApiService) { routing { get("/register") { val principal = call.principal<UserIdPrincipal>() 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 bbc23835..a3c3cd23 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 @@ -4,7 +4,7 @@ import dev.usbharu.hideout.domain.model.hideout.form.Post import dev.usbharu.hideout.domain.model.hideout.form.Reaction import dev.usbharu.hideout.exception.ParameterNotExistException import dev.usbharu.hideout.plugins.TOKEN_AUTH -import dev.usbharu.hideout.service.api.IPostApiService +import dev.usbharu.hideout.service.api.PostApiService import dev.usbharu.hideout.util.InstantParseUtil import io.ktor.http.* import io.ktor.server.application.* @@ -15,7 +15,7 @@ import io.ktor.server.response.* import io.ktor.server.routing.* @Suppress("LongMethod") -fun Route.posts(postApiService: IPostApiService) { +fun Route.posts(postApiService: PostApiService) { route("/posts") { authenticate(TOKEN_AUTH) { 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 6bf0e5ad..1a73c694 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 @@ -5,8 +5,8 @@ import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto import dev.usbharu.hideout.domain.model.hideout.form.UserCreate import dev.usbharu.hideout.exception.ParameterNotExistException import dev.usbharu.hideout.plugins.TOKEN_AUTH -import dev.usbharu.hideout.service.api.IUserApiService -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.api.UserApiService +import dev.usbharu.hideout.service.user.UserService import dev.usbharu.hideout.util.AcctUtil import io.ktor.http.* import io.ktor.server.application.* @@ -17,7 +17,7 @@ import io.ktor.server.response.* import io.ktor.server.routing.* @Suppress("LongMethod", "CognitiveComplexMethod") -fun Route.users(userService: IUserService, userApiService: IUserApiService) { +fun Route.users(userService: UserService, userApiService: UserApiService) { route("/users") { get { call.respond(userApiService.findAll()) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt index 951a8c78..b1fbc9b2 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APAcceptService.kt @@ -6,7 +6,7 @@ import dev.usbharu.hideout.domain.model.ap.Accept import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import io.ktor.http.* import org.koin.core.annotation.Single @@ -16,7 +16,7 @@ interface APAcceptService { @Single class APAcceptServiceImpl( - private val userService: IUserService, + private val userService: UserService, private val userQueryService: UserQueryService ) : APAcceptService { override suspend fun receiveAccept(accept: Accept): ActivityPubResponse { diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt index e8be8ec7..0313acf8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APLikeService.kt @@ -7,7 +7,7 @@ import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException import dev.usbharu.hideout.query.PostQueryService import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.reaction.IReactionService +import dev.usbharu.hideout.service.reaction.ReactionService import io.ktor.http.* import org.koin.core.annotation.Single @@ -17,7 +17,7 @@ interface APLikeService { @Single class APLikeServiceImpl( - private val reactionService: IReactionService, + private val reactionService: ReactionService, private val apUserService: APUserService, private val apNoteService: APNoteService, private val userQueryService: UserQueryService, diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt index f32f7b4e..2cf9d080 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APNoteService.kt @@ -13,7 +13,7 @@ import dev.usbharu.hideout.plugins.postAp import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.PostQueryService import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IPostRepository +import dev.usbharu.hideout.repository.PostRepository import dev.usbharu.hideout.service.job.JobQueueParentService import io.ktor.client.* import io.ktor.client.statement.* @@ -35,7 +35,7 @@ interface APNoteService { class APNoteServiceImpl( private val httpClient: HttpClient, private val jobQueueParentService: JobQueueParentService, - private val postRepository: IPostRepository, + private val postRepository: PostRepository, private val apUserService: APUserService, private val userQueryService: UserQueryService, private val followerQueryService: FollowerQueryService, diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt index e8b21f84..a7ca1533 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReactionService.kt @@ -11,7 +11,7 @@ import dev.usbharu.hideout.plugins.postAp import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.PostQueryService import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IPostRepository +import dev.usbharu.hideout.repository.PostRepository import dev.usbharu.hideout.service.job.JobQueueParentService import io.ktor.client.* import kjob.core.job.JobProps @@ -28,7 +28,7 @@ interface APReactionService { @Single class APReactionServiceImpl( private val jobQueueParentService: JobQueueParentService, - private val iPostRepository: IPostRepository, + private val postRepository: PostRepository, private val httpClient: HttpClient, private val userQueryService: UserQueryService, private val followerQueryService: FollowerQueryService, diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt index 54c0d39d..9156abfd 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowService.kt @@ -11,7 +11,7 @@ import dev.usbharu.hideout.plugins.postAp import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.job.JobQueueParentService -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import io.ktor.client.* import io.ktor.http.* import kjob.core.job.JobProps @@ -26,7 +26,7 @@ interface APReceiveFollowService { class APReceiveFollowServiceImpl( private val jobQueueParentService: JobQueueParentService, private val apUserService: APUserService, - private val userService: IUserService, + private val userService: UserService, private val httpClient: HttpClient, private val userQueryService: UserQueryService, private val transaction: Transaction diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt index a058dbd5..8ae5ab13 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUndoService.kt @@ -6,7 +6,7 @@ import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.ap.Undo import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import io.ktor.http.* import org.koin.core.annotation.Single @@ -17,7 +17,7 @@ interface APUndoService { @Single @Suppress("UnsafeCallOnNullableType") class APUndoServiceImpl( - private val userService: IUserService, + private val userService: UserService, private val apUserService: APUserService, private val userQueryService: UserQueryService, private val transaction: Transaction diff --git a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt index c31803eb..caf9f91b 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/ap/APUserService.kt @@ -10,7 +10,7 @@ import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException import dev.usbharu.hideout.plugins.getAp import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import dev.usbharu.hideout.util.HttpUtil.Activity import io.ktor.client.* import io.ktor.client.request.* @@ -33,7 +33,7 @@ interface APUserService { @Single class APUserServiceImpl( - private val userService: IUserService, + private val userService: UserService, private val httpClient: HttpClient, private val userQueryService: UserQueryService, private val transaction: Transaction diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiService.kt similarity index 92% rename from src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/api/PostApiService.kt index 61715cc0..8edee9a7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/IPostApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/PostApiService.kt @@ -7,16 +7,16 @@ import dev.usbharu.hideout.domain.model.hideout.dto.ReactionResponse import dev.usbharu.hideout.domain.model.hideout.form.Post import dev.usbharu.hideout.query.PostResponseQueryService import dev.usbharu.hideout.query.ReactionQueryService -import dev.usbharu.hideout.repository.IUserRepository +import dev.usbharu.hideout.repository.UserRepository import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.post.IPostService -import dev.usbharu.hideout.service.reaction.IReactionService +import dev.usbharu.hideout.service.post.PostService +import dev.usbharu.hideout.service.reaction.ReactionService import dev.usbharu.hideout.util.AcctUtil import org.koin.core.annotation.Single import java.time.Instant @Suppress("LongParameterList") -interface IPostApiService { +interface PostApiService { suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): PostResponse suspend fun getById(id: Long, userId: Long?): PostResponse suspend fun getAll( @@ -45,13 +45,13 @@ interface IPostApiService { @Single class PostApiServiceImpl( - private val postService: IPostService, - private val userRepository: IUserRepository, + private val postService: PostService, + private val userRepository: UserRepository, private val postResponseQueryService: PostResponseQueryService, private val reactionQueryService: ReactionQueryService, - private val reactionService: IReactionService, + private val reactionService: ReactionService, private val transaction: Transaction -) : IPostApiService { +) : PostApiService { override suspend fun createPost(postForm: Post, userId: Long): PostResponse { return transaction.transaction { val createdPost = postService.createLocal( diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/IUserApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/UserApiService.kt similarity index 95% rename from src/main/kotlin/dev/usbharu/hideout/service/api/IUserApiService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/api/UserApiService.kt index 26135f8a..fb8ce555 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/IUserApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/UserApiService.kt @@ -8,11 +8,11 @@ import dev.usbharu.hideout.exception.UsernameAlreadyExistException import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import org.koin.core.annotation.Single import kotlin.math.min -interface IUserApiService { +interface UserApiService { suspend fun findAll(limit: Int? = 100, offset: Long = 0): List<UserResponse> suspend fun findById(id: Long): UserResponse @@ -36,9 +36,9 @@ interface IUserApiService { class UserApiServiceImpl( private val userQueryService: UserQueryService, private val followerQueryService: FollowerQueryService, - private val userService: IUserService, + private val userService: UserService, private val transaction: Transaction -) : IUserApiService { +) : UserApiService { override suspend fun findAll(limit: Int?, offset: Long): List<UserResponse> = userQueryService.findAll(min(limit ?: 100, 100), offset).map { UserResponse.from(it) } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt b/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt index d56bbc4f..e576f8ef 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/api/UserAuthApiService.kt @@ -5,9 +5,9 @@ import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.service.auth.IJwtService +import dev.usbharu.hideout.service.auth.JwtService import dev.usbharu.hideout.service.core.Transaction -import dev.usbharu.hideout.service.user.UserAuthService +import dev.usbharu.hideout.service.user.UserAuthServiceImpl import org.koin.core.annotation.Single interface UserAuthApiService { @@ -17,9 +17,9 @@ interface UserAuthApiService { @Single class UserAuthApiServiceImpl( - private val userAuthService: UserAuthService, + private val userAuthService: UserAuthServiceImpl, private val userQueryService: UserQueryService, - private val jwtService: IJwtService, + private val jwtService: JwtService, private val transaction: Transaction ) : UserAuthApiService { override suspend fun login(username: String, password: String): JwtToken { diff --git a/src/main/kotlin/dev/usbharu/hideout/service/auth/IJwtService.kt b/src/main/kotlin/dev/usbharu/hideout/service/auth/JwtService.kt similarity index 92% rename from src/main/kotlin/dev/usbharu/hideout/service/auth/IJwtService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/auth/JwtService.kt index 2f74c2fa..462430ac 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/auth/IJwtService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/auth/JwtService.kt @@ -10,8 +10,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken import dev.usbharu.hideout.exception.InvalidRefreshTokenException import dev.usbharu.hideout.query.JwtRefreshTokenQueryService import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository -import dev.usbharu.hideout.service.core.IMetaService +import dev.usbharu.hideout.repository.JwtRefreshTokenRepository +import dev.usbharu.hideout.service.core.MetaService import dev.usbharu.hideout.util.RsaUtil import kotlinx.coroutines.runBlocking import org.koin.core.annotation.Single @@ -19,7 +19,7 @@ import java.time.Instant import java.time.temporal.ChronoUnit import java.util.* -interface IJwtService { +interface JwtService { suspend fun createToken(user: User): JwtToken suspend fun refreshToken(refreshToken: RefreshToken): JwtToken @@ -31,11 +31,11 @@ interface IJwtService { @Suppress("InjectDispatcher") @Single class JwtServiceImpl( - private val metaService: IMetaService, - private val refreshTokenRepository: IJwtRefreshTokenRepository, + private val metaService: MetaService, + private val refreshTokenRepository: JwtRefreshTokenRepository, private val userQueryService: UserQueryService, private val refreshTokenQueryService: JwtRefreshTokenQueryService -) : IJwtService { +) : JwtService { private val privateKey = runBlocking { RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/core/IMetaService.kt b/src/main/kotlin/dev/usbharu/hideout/service/core/MetaService.kt similarity index 91% rename from src/main/kotlin/dev/usbharu/hideout/service/core/IMetaService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/core/MetaService.kt index 763dc96a..91da1a90 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/core/IMetaService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/core/MetaService.kt @@ -3,7 +3,7 @@ package dev.usbharu.hideout.service.core import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Meta -interface IMetaService { +interface MetaService { suspend fun getMeta(): Meta suspend fun updateMeta(meta: Meta) suspend fun getJwtMeta(): Jwt diff --git a/src/main/kotlin/dev/usbharu/hideout/service/core/MetaServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/core/MetaServiceImpl.kt index c971c177..e35ff3f7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/core/MetaServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/core/MetaServiceImpl.kt @@ -3,12 +3,12 @@ package dev.usbharu.hideout.service.core import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.exception.NotInitException -import dev.usbharu.hideout.repository.IMetaRepository +import dev.usbharu.hideout.repository.MetaRepository import org.koin.core.annotation.Single @Single -class MetaServiceImpl(private val metaRepository: IMetaRepository, private val transaction: Transaction) : - IMetaService { +class MetaServiceImpl(private val metaRepository: MetaRepository, private val transaction: Transaction) : + MetaService { override suspend fun getMeta(): Meta = transaction.transaction { metaRepository.get() ?: throw NotInitException("Meta is null") } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/core/IServerInitialiseService.kt b/src/main/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseService.kt similarity index 64% rename from src/main/kotlin/dev/usbharu/hideout/service/core/IServerInitialiseService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseService.kt index c54eaccc..d65f8fa6 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/core/IServerInitialiseService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseService.kt @@ -1,5 +1,5 @@ package dev.usbharu.hideout.service.core -interface IServerInitialiseService { +interface ServerInitialiseService { suspend fun init() } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImpl.kt index 1ca3c25f..4fc950c1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImpl.kt @@ -2,7 +2,7 @@ package dev.usbharu.hideout.service.core import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Meta -import dev.usbharu.hideout.repository.IMetaRepository +import dev.usbharu.hideout.repository.MetaRepository import dev.usbharu.hideout.util.ServerUtil import org.koin.core.annotation.Single import org.slf4j.Logger @@ -12,10 +12,10 @@ import java.util.* @Single class ServerInitialiseServiceImpl( - private val metaRepository: IMetaRepository, + private val metaRepository: MetaRepository, private val transaction: Transaction ) : - IServerInitialiseService { + ServerInitialiseService { val logger: Logger = LoggerFactory.getLogger(ServerInitialiseServiceImpl::class.java) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt b/src/main/kotlin/dev/usbharu/hideout/service/post/PostService.kt similarity index 90% rename from src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/post/PostService.kt index 4459b8d2..28c90710 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/IPostService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/PostService.kt @@ -3,6 +3,6 @@ package dev.usbharu.hideout.service.post import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto import dev.usbharu.hideout.domain.model.hideout.entity.Post -interface IPostService { +interface PostService { suspend fun createLocal(post: PostCreateDto): 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 index 0ca22f77..d184cbae 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/post/PostServiceImpl.kt @@ -3,18 +3,18 @@ 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.repository.PostRepository +import dev.usbharu.hideout.repository.UserRepository import dev.usbharu.hideout.service.ap.APNoteService import org.koin.core.annotation.Single import java.time.Instant @Single class PostServiceImpl( - private val postRepository: IPostRepository, - private val userRepository: IUserRepository, + private val postRepository: PostRepository, + private val userRepository: UserRepository, private val apNoteService: APNoteService -) : IPostService { +) : PostService { override suspend fun createLocal(post: PostCreateDto): Post { val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found") val id = postRepository.generateId() diff --git a/src/main/kotlin/dev/usbharu/hideout/service/reaction/IReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionService.kt similarity index 90% rename from src/main/kotlin/dev/usbharu/hideout/service/reaction/IReactionService.kt rename to src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionService.kt index 28b56673..a7b9ed0d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/reaction/IReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionService.kt @@ -1,6 +1,6 @@ package dev.usbharu.hideout.service.reaction -interface IReactionService { +interface ReactionService { suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) suspend fun sendReaction(name: String, userId: Long, postId: Long) suspend fun removeReaction(userId: Long, postId: Long) diff --git a/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt index 4eb42ea3..f8c24df9 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/reaction/ReactionServiceImpl.kt @@ -11,7 +11,7 @@ class ReactionServiceImpl( private val reactionRepository: ReactionRepository, private val apReactionService: APReactionService, private val reactionQueryService: ReactionQueryService -) : IReactionService { +) : ReactionService { override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) { if (reactionQueryService.reactionAlreadyExist(postId, userId, 0).not()) { reactionRepository.save( diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/IUserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/IUserAuthService.kt deleted file mode 100644 index 35896355..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/user/IUserAuthService.kt +++ /dev/null @@ -1,13 +0,0 @@ -package dev.usbharu.hideout.service.user - -import java.security.KeyPair - -interface IUserAuthService { - fun hash(password: String): String - - suspend fun usernameAlreadyUse(username: String): Boolean - - suspend fun generateKeyPair(): KeyPair - - suspend fun verifyAccount(username: String, password: String): Boolean -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/IUserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/IUserService.kt deleted file mode 100644 index 14c6d8ab..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/service/user/IUserService.kt +++ /dev/null @@ -1,34 +0,0 @@ -package dev.usbharu.hideout.service.user - -import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto -import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto -import dev.usbharu.hideout.domain.model.hideout.entity.User - -@Suppress("TooManyFunctions") -interface IUserService { - - suspend fun usernameAlreadyUse(username: String): Boolean - - suspend fun createLocalUser(user: UserCreateDto): User - - suspend fun createRemoteUser(user: RemoteUserCreateDto): User - - /** - * フォローリクエストを送信する - * - * @param id - * @param followerId - * @return リクエストが成功したか - */ - suspend fun followRequest(id: Long, followerId: Long): Boolean - - /** - * フォローする - * - * @param id - * @param followerId - */ - suspend fun follow(id: Long, followerId: Long) - - suspend fun unfollow(id: Long, followerId: Long): Boolean -} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthService.kt index c32249dc..61853b73 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthService.kt @@ -1,53 +1,13 @@ package dev.usbharu.hideout.service.user -import dev.usbharu.hideout.config.Config -import dev.usbharu.hideout.query.UserQueryService -import io.ktor.util.* -import org.koin.core.annotation.Single -import java.security.* -import java.util.* +import java.security.KeyPair -@Single -class UserAuthService( - val userQueryService: UserQueryService -) : IUserAuthService { +interface UserAuthService { + fun hash(password: String): String - override fun hash(password: String): String { - val digest = sha256.digest(password.toByteArray(Charsets.UTF_8)) - return hex(digest) - } + suspend fun usernameAlreadyUse(username: String): Boolean - override suspend fun usernameAlreadyUse(username: String): Boolean { - userQueryService.findByName(username) - return true - } + suspend fun generateKeyPair(): KeyPair - override suspend fun verifyAccount(username: String, password: String): Boolean { - val userEntity = userQueryService.findByNameAndDomain(username, Config.configData.domain) - return userEntity.password == hash(password) - } - - override suspend fun generateKeyPair(): KeyPair { - val keyPairGenerator = KeyPairGenerator.getInstance("RSA") - keyPairGenerator.initialize(keySize) - return keyPairGenerator.generateKeyPair() - } - - companion object { - val sha256: MessageDigest = MessageDigest.getInstance("SHA-256") - const val keySize = 2048 - const val pemSize = 64 - } -} - -fun PublicKey.toPem(): String { - return "-----BEGIN PUBLIC KEY-----\n" + - Base64.getEncoder().encodeToString(encoded).chunked(UserAuthService.pemSize).joinToString("\n") + - "\n-----END PUBLIC KEY-----\n" -} - -fun PrivateKey.toPem(): String { - return "-----BEGIN PRIVATE KEY-----\n" + - Base64.getEncoder().encodeToString(encoded).chunked(UserAuthService.pemSize).joinToString("\n") + - "\n-----END PRIVATE KEY-----\n" + suspend fun verifyAccount(username: String, password: String): Boolean } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthServiceImpl.kt new file mode 100644 index 00000000..0c234430 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/user/UserAuthServiceImpl.kt @@ -0,0 +1,53 @@ +package dev.usbharu.hideout.service.user + +import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.query.UserQueryService +import io.ktor.util.* +import org.koin.core.annotation.Single +import java.security.* +import java.util.* + +@Single +class UserAuthServiceImpl( + val userQueryService: UserQueryService +) : UserAuthService { + + override fun hash(password: String): String { + val digest = sha256.digest(password.toByteArray(Charsets.UTF_8)) + return hex(digest) + } + + override suspend fun usernameAlreadyUse(username: String): Boolean { + userQueryService.findByName(username) + return true + } + + override suspend fun verifyAccount(username: String, password: String): Boolean { + val userEntity = userQueryService.findByNameAndDomain(username, Config.configData.domain) + return userEntity.password == hash(password) + } + + override suspend fun generateKeyPair(): KeyPair { + val keyPairGenerator = KeyPairGenerator.getInstance("RSA") + keyPairGenerator.initialize(keySize) + return keyPairGenerator.generateKeyPair() + } + + companion object { + val sha256: MessageDigest = MessageDigest.getInstance("SHA-256") + const val keySize = 2048 + const val pemSize = 64 + } +} + +fun PublicKey.toPem(): String { + return "-----BEGIN PUBLIC KEY-----\n" + + Base64.getEncoder().encodeToString(encoded).chunked(UserAuthServiceImpl.pemSize).joinToString("\n") + + "\n-----END PUBLIC KEY-----\n" +} + +fun PrivateKey.toPem(): String { + return "-----BEGIN PRIVATE KEY-----\n" + + Base64.getEncoder().encodeToString(encoded).chunked(UserAuthServiceImpl.pemSize).joinToString("\n") + + "\n-----END PRIVATE KEY-----\n" +} diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt index febc8ac6..a141fa24 100644 --- a/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/service/user/UserService.kt @@ -1,97 +1,34 @@ package dev.usbharu.hideout.service.user -import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto -import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto import dev.usbharu.hideout.domain.model.hideout.entity.User -import dev.usbharu.hideout.exception.UserNotFoundException -import dev.usbharu.hideout.query.FollowerQueryService -import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IUserRepository -import dev.usbharu.hideout.service.ap.APSendFollowService -import org.koin.core.annotation.Single -import java.time.Instant -@Single -class UserService( - private val userRepository: IUserRepository, - private val userAuthService: IUserAuthService, - private val apSendFollowService: APSendFollowService, - private val userQueryService: UserQueryService, - private val followerQueryService: FollowerQueryService -) : - IUserService { +@Suppress("TooManyFunctions") +interface UserService { - override suspend fun usernameAlreadyUse(username: String): Boolean { - val findByNameAndDomain = userQueryService.findByNameAndDomain(username, Config.configData.domain) - return findByNameAndDomain != null - } + suspend fun usernameAlreadyUse(username: String): Boolean - override suspend fun createLocalUser(user: UserCreateDto): User { - val nextId = userRepository.nextId() - val hashedPassword = userAuthService.hash(user.password) - val keyPair = userAuthService.generateKeyPair() - val userEntity = User( - id = nextId, - name = user.name, - domain = Config.configData.domain, - screenName = user.screenName, - description = user.description, - password = hashedPassword, - inbox = "${Config.configData.url}/users/${user.name}/inbox", - outbox = "${Config.configData.url}/users/${user.name}/outbox", - url = "${Config.configData.url}/users/${user.name}", - publicKey = keyPair.public.toPem(), - privateKey = keyPair.private.toPem(), - createdAt = Instant.now() - ) - return userRepository.save(userEntity) - } + suspend fun createLocalUser(user: UserCreateDto): User - override suspend fun createRemoteUser(user: RemoteUserCreateDto): User { - val nextId = userRepository.nextId() - val userEntity = User( - id = nextId, - name = user.name, - domain = user.domain, - screenName = user.screenName, - description = user.description, - inbox = user.inbox, - outbox = user.outbox, - url = user.url, - publicKey = user.publicKey, - createdAt = Instant.now() - ) - return userRepository.save(userEntity) - } + suspend fun createRemoteUser(user: RemoteUserCreateDto): User - // TODO APのフォロー処理を作る - override suspend fun followRequest(id: Long, followerId: Long): Boolean { - val user = userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.") - val follower = userRepository.findById(followerId) ?: throw UserNotFoundException("$followerId was not found.") - return if (user.domain == Config.configData.domain) { - follow(id, followerId) - true - } else { - if (userRepository.findFollowRequestsById(id, followerId)) { - // do-nothing - } else { - apSendFollowService.sendFollow(SendFollowDto(follower, user)) - } - false - } - } + /** + * フォローリクエストを送信する + * + * @param id + * @param followerId + * @return リクエストが成功したか + */ + suspend fun followRequest(id: Long, followerId: Long): Boolean - override suspend fun follow(id: Long, followerId: Long) { - followerQueryService.appendFollower(id, followerId) - if (userRepository.findFollowRequestsById(id, followerId)) { - userRepository.deleteFollowRequest(id, followerId) - } - } + /** + * フォローする + * + * @param id + * @param followerId + */ + suspend fun follow(id: Long, followerId: Long) - override suspend fun unfollow(id: Long, followerId: Long): Boolean { - followerQueryService.removeFollower(id, followerId) - return false - } + suspend fun unfollow(id: Long, followerId: Long): Boolean } diff --git a/src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt new file mode 100644 index 00000000..6558d770 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/service/user/UserServiceImpl.kt @@ -0,0 +1,97 @@ +package dev.usbharu.hideout.service.user + +import dev.usbharu.hideout.config.Config +import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto +import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto +import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto +import dev.usbharu.hideout.domain.model.hideout.entity.User +import dev.usbharu.hideout.exception.UserNotFoundException +import dev.usbharu.hideout.query.FollowerQueryService +import dev.usbharu.hideout.query.UserQueryService +import dev.usbharu.hideout.repository.UserRepository +import dev.usbharu.hideout.service.ap.APSendFollowService +import org.koin.core.annotation.Single +import java.time.Instant + +@Single +class UserServiceImpl( + private val userRepository: UserRepository, + private val userAuthService: UserAuthService, + private val apSendFollowService: APSendFollowService, + private val userQueryService: UserQueryService, + private val followerQueryService: FollowerQueryService +) : + UserService { + + override suspend fun usernameAlreadyUse(username: String): Boolean { + val findByNameAndDomain = userQueryService.findByNameAndDomain(username, Config.configData.domain) + return findByNameAndDomain != null + } + + override suspend fun createLocalUser(user: UserCreateDto): User { + val nextId = userRepository.nextId() + val hashedPassword = userAuthService.hash(user.password) + val keyPair = userAuthService.generateKeyPair() + val userEntity = User( + id = nextId, + name = user.name, + domain = Config.configData.domain, + screenName = user.screenName, + description = user.description, + password = hashedPassword, + inbox = "${Config.configData.url}/users/${user.name}/inbox", + outbox = "${Config.configData.url}/users/${user.name}/outbox", + url = "${Config.configData.url}/users/${user.name}", + publicKey = keyPair.public.toPem(), + privateKey = keyPair.private.toPem(), + createdAt = Instant.now() + ) + return userRepository.save(userEntity) + } + + override suspend fun createRemoteUser(user: RemoteUserCreateDto): User { + val nextId = userRepository.nextId() + val userEntity = User( + id = nextId, + name = user.name, + domain = user.domain, + screenName = user.screenName, + description = user.description, + inbox = user.inbox, + outbox = user.outbox, + url = user.url, + publicKey = user.publicKey, + createdAt = Instant.now() + ) + return userRepository.save(userEntity) + } + + // TODO APのフォロー処理を作る + override suspend fun followRequest(id: Long, followerId: Long): Boolean { + val user = userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.") + val follower = userRepository.findById(followerId) ?: throw UserNotFoundException("$followerId was not found.") + return if (user.domain == Config.configData.domain) { + follow(id, followerId) + true + } else { + if (userRepository.findFollowRequestsById(id, followerId)) { + // do-nothing + } else { + apSendFollowService.sendFollow(SendFollowDto(follower, user)) + } + false + } + } + + override suspend fun follow(id: Long, followerId: Long) { + followerQueryService.appendFollower(id, followerId) + if (userRepository.findFollowRequestsById(id, followerId)) { + userRepository.deleteFollowRequest(id, followerId) + } + } + + override suspend fun unfollow(id: Long, followerId: Long): Boolean { + followerQueryService.removeFollower(id, followerId) + return false + } +} diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/SecurityKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/SecurityKtTest.kt index ff3e89f9..0d91ce6f 100644 --- a/src/test/kotlin/dev/usbharu/hideout/plugins/SecurityKtTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/plugins/SecurityKtTest.kt @@ -18,9 +18,9 @@ import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.routing.api.internal.v1.auth import dev.usbharu.hideout.service.api.UserAuthApiService -import dev.usbharu.hideout.service.auth.IJwtService -import dev.usbharu.hideout.service.core.IMetaService -import dev.usbharu.hideout.service.user.IUserAuthService +import dev.usbharu.hideout.service.auth.JwtService +import dev.usbharu.hideout.service.core.MetaService +import dev.usbharu.hideout.service.user.UserAuthService import dev.usbharu.hideout.util.Base64Util import dev.usbharu.hideout.util.JsonWebKeyUtil import io.ktor.client.request.* @@ -51,7 +51,7 @@ class SecurityKtTest { val userAuthService = mock<UserAuthApiService> { onBlocking { login(eq("testUser"), eq("password")) } doReturn jwtToken } - val metaService = mock<IMetaService>() + val metaService = mock<MetaService>() val userQueryService = mock<UserQueryService> { onBlocking { findByNameAndDomain(eq("testUser"), eq("example.com")) } doReturn User( id = 1L, @@ -93,12 +93,12 @@ class SecurityKtTest { config = ApplicationConfig("empty.conf") } Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper()) - mock<IUserAuthService> { + mock<UserAuthService> { onBlocking { verifyAccount(anyString(), anyString()) }.doReturn(false) } - val metaService = mock<IMetaService>() + val metaService = mock<MetaService>() mock<UserQueryService>() - mock<IJwtService>() + mock<JwtService>() val jwkProvider = mock<JwkProvider>() val userAuthApiService = mock<UserAuthApiService> { onBlocking { login(anyString(), anyString()) } doThrow InvalidUsernameOrPasswordException() @@ -126,7 +126,7 @@ class SecurityKtTest { config = ApplicationConfig("empty.conf") } Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper()) - val metaService = mock<IMetaService>() + val metaService = mock<MetaService>() val jwkProvider = mock<JwkProvider>() val userAuthApiService = mock<UserAuthApiService> { onBlocking { login(anyString(), eq("InvalidPassword")) } doThrow InvalidUsernameOrPasswordException() @@ -247,7 +247,7 @@ class SecurityKtTest { .withClaim("uid", 123456L) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() }.doReturn( Jwt( kid, @@ -308,7 +308,7 @@ class SecurityKtTest { .withClaim("uid", 123345L) .withExpiresAt(now.minus(30, ChronoUnit.MINUTES)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() }.doReturn( Jwt( kid, @@ -367,7 +367,7 @@ class SecurityKtTest { .withClaim("uid", 12345L) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() }.doReturn( Jwt( kid, @@ -426,7 +426,7 @@ class SecurityKtTest { .withClaim("uid", null as Long?) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() }.doReturn( Jwt( kid, @@ -484,7 +484,7 @@ class SecurityKtTest { .withKeyId(kid.toString()) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() }.doReturn( Jwt( kid, diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt index 29f220bf..75a2c335 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt @@ -6,7 +6,7 @@ import dev.usbharu.hideout.plugins.configureStatusPages import dev.usbharu.hideout.service.ap.APService import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import io.ktor.client.request.* import io.ktor.http.* import io.ktor.server.config.* @@ -47,7 +47,7 @@ class InboxRoutingKtTest { val apService = mock<APService> { on { parseActivity(any()) } doThrow JsonParseException() } - mock<IUserService>() + mock<UserService>() mock<APUserService>() application { configureStatusPages() @@ -88,7 +88,7 @@ class InboxRoutingKtTest { val apService = mock<APService> { on { parseActivity(any()) } doThrow JsonParseException() } - mock<IUserService>() + mock<UserService>() mock<APUserService>() application { configureStatusPages() 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 4a8fb0e8..81f9e66c 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.api.IPostApiService +import dev.usbharu.hideout.service.api.PostApiService import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* @@ -60,7 +60,7 @@ class PostsTest { url = "https://example.com/posts/2" ) ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getAll( since = anyOrNull(), @@ -135,7 +135,7 @@ class PostsTest { ) ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getAll( since = anyOrNull(), @@ -191,7 +191,7 @@ class PostsTest { createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/1" ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getById(any(), anyOrNull()) } doReturn post } application { @@ -230,7 +230,7 @@ class PostsTest { createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/1" ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getById(any(), isNotNull()) } doReturn post } val claim = mock<Claim> { @@ -273,7 +273,7 @@ class PostsTest { val payload = mock<Payload> { on { getClaim(eq("uid")) } doReturn claim } - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { createPost(any(), any()) } doAnswer { val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0) val userId = it.getArgument<Long>(1) @@ -360,7 +360,7 @@ class PostsTest { url = "https://example.com/posts/2" ) ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getByUser( nameOrId = any(), @@ -421,7 +421,7 @@ class PostsTest { url = "https://example.com/posts/2" ) ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getByUser( nameOrId = eq("test1"), @@ -482,7 +482,7 @@ class PostsTest { url = "https://example.com/posts/2" ) ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getByUser( nameOrId = eq("test1@example.com"), @@ -543,7 +543,7 @@ class PostsTest { url = "https://example.com/posts/2" ) ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getByUser( nameOrId = eq("@test1@example.com"), @@ -593,7 +593,7 @@ class PostsTest { createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/2" ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post } application { @@ -633,7 +633,7 @@ class PostsTest { createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/2" ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post } application { @@ -673,7 +673,7 @@ class PostsTest { createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/2" ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post } application { @@ -713,7 +713,7 @@ class PostsTest { createdAt = Instant.now().toEpochMilli(), url = "https://example.com/posts/2" ) - val postService = mock<IPostApiService> { + val postService = mock<PostApiService> { onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post } application { diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt index a29245df..18f70364 100644 --- a/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/routing/api/internal/v1/UsersTest.kt @@ -10,8 +10,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.UserCreate import dev.usbharu.hideout.plugins.TOKEN_AUTH import dev.usbharu.hideout.plugins.configureSecurity import dev.usbharu.hideout.plugins.configureSerialization -import dev.usbharu.hideout.service.api.IUserApiService -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.api.UserApiService +import dev.usbharu.hideout.service.user.UserService import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* @@ -53,7 +53,7 @@ class UsersTest { Instant.now().toEpochMilli() ), ) - val userService = mock<IUserApiService> { + val userService = mock<UserApiService> { onBlocking { findAll(anyOrNull(), anyOrNull()) } doReturn users } application { @@ -77,7 +77,7 @@ class UsersTest { config = ApplicationConfig("empty.conf") } val userCreateDto = UserCreate("test", "XXXXXXX") - val userService = mock<IUserService> { + val userService = mock<UserService> { onBlocking { usernameAlreadyUse(any()) } doReturn false onBlocking { createLocalUser(any()) } doReturn User( id = 12345, @@ -122,7 +122,7 @@ class UsersTest { config = ApplicationConfig("empty.conf") } val userCreateDto = UserCreate("test", "XXXXXXX") - val userService = mock<IUserService> { + val userService = mock<UserService> { onBlocking { usernameAlreadyUse(any()) } doReturn true } application { @@ -157,7 +157,7 @@ class UsersTest { "https://example.com/test", Instant.now().toEpochMilli() ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findByAcct(any()) } doReturn userResponse } application { @@ -190,7 +190,7 @@ class UsersTest { "https://example.com/test", Instant.now().toEpochMilli() ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findById(any()) } doReturn userResponse } application { @@ -223,7 +223,7 @@ class UsersTest { "https://example.com/test", Instant.now().toEpochMilli() ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findByAcct(any()) } doReturn userResponse } application { @@ -256,7 +256,7 @@ class UsersTest { "https://example.com/test", Instant.now().toEpochMilli() ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findByAcct(any()) } doReturn userResponse } application { @@ -301,7 +301,7 @@ class UsersTest { Instant.now().toEpochMilli() ) ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findFollowersByAcct(any()) } doReturn followers } application { @@ -346,7 +346,7 @@ class UsersTest { Instant.now().toEpochMilli() ) ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findFollowersByAcct(any()) } doReturn followers } application { @@ -391,7 +391,7 @@ class UsersTest { Instant.now().toEpochMilli() ) ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findFollowers(any()) } doReturn followers } application { @@ -423,7 +423,7 @@ class UsersTest { on { getClaim(eq("uid")) } doReturn claim } - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findByAcct(any()) } doReturn UserResponse( "1235", "follower1", @@ -434,7 +434,7 @@ class UsersTest { Instant.now().toEpochMilli() ) } - val userService = mock<IUserService> { + val userService = mock<UserService> { onBlocking { followRequest(eq(1235), eq(1234)) } doReturn true } application { @@ -473,7 +473,7 @@ class UsersTest { on { getClaim(eq("uid")) } doReturn claim } - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findByAcct(any()) } doReturn UserResponse( "1235", "follower1", @@ -484,7 +484,7 @@ class UsersTest { Instant.now().toEpochMilli() ) } - val userService = mock<IUserService> { + val userService = mock<UserService> { onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false } application { @@ -523,7 +523,7 @@ class UsersTest { on { getClaim(eq("uid")) } doReturn claim } - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findById(any()) } doReturn UserResponse( "1235", "follower1", @@ -534,7 +534,7 @@ class UsersTest { Instant.now().toEpochMilli() ) } - val userService = mock<IUserService> { + val userService = mock<UserService> { onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false } application { @@ -586,7 +586,7 @@ class UsersTest { Instant.now().toEpochMilli() ) ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findFollowingsByAcct(any()) } doReturn followers } application { @@ -631,7 +631,7 @@ class UsersTest { Instant.now().toEpochMilli() ) ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findFollowingsByAcct(any()) } doReturn followers } application { @@ -676,7 +676,7 @@ class UsersTest { Instant.now().toEpochMilli() ) ) - val userApiService = mock<IUserApiService> { + val userApiService = mock<UserApiService> { onBlocking { findFollowings(any()) } doReturn followers } application { diff --git a/src/test/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImplTest.kt index 6e5fbe30..7b7f2c21 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/ap/APReceiveFollowServiceImplTest.kt @@ -11,7 +11,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.job.JobQueueParentService -import dev.usbharu.hideout.service.user.IUserService +import dev.usbharu.hideout.service.user.UserService import io.ktor.client.* import io.ktor.client.engine.mock.* import kjob.core.dsl.ScheduleContext @@ -128,7 +128,7 @@ class APReceiveFollowServiceImplTest { ) } - val userService = mock<IUserService> { + val userService = mock<UserService> { onBlocking { followRequest(any(), any()) } doReturn false } val activityPubFollowService = diff --git a/src/test/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImplTest.kt index e4f37934..44fc2844 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/auth/JwtServiceImplTest.kt @@ -14,8 +14,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken import dev.usbharu.hideout.exception.InvalidRefreshTokenException import dev.usbharu.hideout.query.JwtRefreshTokenQueryService import dev.usbharu.hideout.query.UserQueryService -import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository -import dev.usbharu.hideout.service.core.IMetaService +import dev.usbharu.hideout.repository.JwtRefreshTokenRepository +import dev.usbharu.hideout.service.core.MetaService import dev.usbharu.hideout.util.Base64Util import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -42,14 +42,14 @@ class JwtServiceImplTest { keyPairGenerator.initialize(2048) val generateKeyPair = keyPairGenerator.generateKeyPair() - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() } doReturn Jwt( kid, Base64Util.encode(generateKeyPair.private.encoded), Base64Util.encode(generateKeyPair.public.encoded) ) } - val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { + val refreshTokenRepository = mock<JwtRefreshTokenRepository> { onBlocking { generateId() } doReturn 1L } val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, mock(), mock()) @@ -94,7 +94,7 @@ class JwtServiceImplTest { keyPairGenerator.initialize(2048) val generateKeyPair = keyPairGenerator.generateKeyPair() - val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { + val refreshTokenRepository = mock<JwtRefreshTokenRepository> { onBlocking { generateId() } doReturn 2L } @@ -123,7 +123,7 @@ class JwtServiceImplTest { createdAt = Instant.now() ) } - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() } doReturn Jwt( kid, Base64Util.encode(generateKeyPair.private.encoded), @@ -160,7 +160,7 @@ class JwtServiceImplTest { keyPairGenerator.initialize(2048) val generateKeyPair = keyPairGenerator.generateKeyPair() - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() } doReturn Jwt( kid, Base64Util.encode(generateKeyPair.private.encoded), @@ -187,7 +187,7 @@ class JwtServiceImplTest { keyPairGenerator.initialize(2048) val generateKeyPair = keyPairGenerator.generateKeyPair() - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() } doReturn Jwt( kid, Base64Util.encode(generateKeyPair.private.encoded), @@ -214,7 +214,7 @@ class JwtServiceImplTest { keyPairGenerator.initialize(2048) val generateKeyPair = keyPairGenerator.generateKeyPair() - val metaService = mock<IMetaService> { + val metaService = mock<MetaService> { onBlocking { getJwtMeta() } doReturn Jwt( kid, Base64Util.encode(generateKeyPair.private.encoded), diff --git a/src/test/kotlin/dev/usbharu/hideout/service/core/MetaServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/core/MetaServiceImplTest.kt index 02cf9e7e..546dab35 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/core/MetaServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/core/MetaServiceImplTest.kt @@ -5,7 +5,7 @@ package dev.usbharu.hideout.service.core import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.exception.NotInitException -import dev.usbharu.hideout.repository.IMetaRepository +import dev.usbharu.hideout.repository.MetaRepository import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test @@ -19,7 +19,7 @@ class MetaServiceImplTest { @Test fun `getMeta メタデータを取得できる`() = runTest { val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda")) - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { get() } doReturn meta } val metaService = MetaServiceImpl(metaRepository, TestTransaction) @@ -29,7 +29,7 @@ class MetaServiceImplTest { @Test fun `getMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest { - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { get() } doReturn null } val metaService = MetaServiceImpl(metaRepository, TestTransaction) @@ -39,7 +39,7 @@ class MetaServiceImplTest { @Test fun `updateMeta メタデータを保存できる`() = runTest { val meta = Meta("1.0.1", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda")) - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { save(any()) } doReturn Unit } val metaServiceImpl = MetaServiceImpl(metaRepository, TestTransaction) @@ -53,7 +53,7 @@ class MetaServiceImplTest { @Test fun `getJwtMeta Jwtメタデータを取得できる`() = runTest { val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda")) - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { get() } doReturn meta } val metaService = MetaServiceImpl(metaRepository, TestTransaction) @@ -63,7 +63,7 @@ class MetaServiceImplTest { @Test fun `getJwtMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest { - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { get() } doReturn null } val metaService = MetaServiceImpl(metaRepository, TestTransaction) diff --git a/src/test/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImplTest.kt index c854754f..e7f87517 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/core/ServerInitialiseServiceImplTest.kt @@ -4,7 +4,7 @@ package dev.usbharu.hideout.service.core import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Meta -import dev.usbharu.hideout.repository.IMetaRepository +import dev.usbharu.hideout.repository.MetaRepository import dev.usbharu.hideout.util.ServerUtil import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -17,7 +17,7 @@ import kotlin.test.assertEquals class ServerInitialiseServiceImplTest { @Test fun `init メタデータが無いときに初期化を実行する`() = runTest { - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { get() } doReturn null onBlocking { save(any()) } doReturn Unit } @@ -30,7 +30,7 @@ class ServerInitialiseServiceImplTest { @Test fun `init メタデータが存在して同じバージョンのときは何もしない`() = runTest { val meta = Meta(ServerUtil.getImplementationVersion(), Jwt(UUID.randomUUID(), "aaafafd", "afafasdf")) - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { get() } doReturn meta } val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository, TestTransaction) @@ -41,7 +41,7 @@ class ServerInitialiseServiceImplTest { @Test fun `init メタデータが存在して違うバージョンのときはバージョンを変更する`() = runTest { val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "aaafafd", "afafasdf")) - val metaRepository = mock<IMetaRepository> { + val metaRepository = mock<MetaRepository> { onBlocking { get() } doReturn meta onBlocking { save(any()) } doReturn Unit } diff --git a/src/test/kotlin/dev/usbharu/hideout/service/user/UserServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/user/UserServiceTest.kt index 4aed672e..e32ca6f1 100644 --- a/src/test/kotlin/dev/usbharu/hideout/service/user/UserServiceTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/service/user/UserServiceTest.kt @@ -6,7 +6,7 @@ import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.ConfigData import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto -import dev.usbharu.hideout.repository.IUserRepository +import dev.usbharu.hideout.repository.UserRepository import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test @@ -20,15 +20,15 @@ class UserServiceTest { @Test fun `createLocalUser ローカルユーザーを作成できる`() = runTest { Config.configData = ConfigData(domain = "example.com", url = "https://example.com") - val userRepository = mock<IUserRepository> { + val userRepository = mock<UserRepository> { onBlocking { nextId() } doReturn 110001L } val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair() - val userAuthService = mock<IUserAuthService> { + val userAuthService = mock<UserAuthService> { onBlocking { hash(anyString()) } doReturn "hashedPassword" onBlocking { generateKeyPair() } doReturn generateKeyPair } - val userService = UserService(userRepository, userAuthService, mock(), mock(), mock()) + val userService = UserServiceImpl(userRepository, userAuthService, mock(), mock(), mock()) userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test")) verify(userRepository, times(1)).save(any()) argumentCaptor<dev.usbharu.hideout.domain.model.hideout.entity.User> { @@ -51,10 +51,10 @@ class UserServiceTest { fun `createRemoteUser リモートユーザーを作成できる`() = runTest { Config.configData = ConfigData(domain = "example.com", url = "https://example.com") - val userRepository = mock<IUserRepository> { + val userRepository = mock<UserRepository> { onBlocking { nextId() } doReturn 113345L } - val userService = UserService(userRepository, mock(), mock(), mock(), mock()) + val userService = UserServiceImpl(userRepository, mock(), mock(), mock(), mock()) val user = RemoteUserCreateDto( "test", "example.com",