From f98178b37cf8de611d0c472c95630e0f3db528f9 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sun, 17 Dec 2023 19:08:18 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20actor=E3=81=AEDB=E3=81=8B=E3=82=89?= =?UTF-8?q?=E3=81=AE=E5=8F=96=E5=BE=97=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B?= =?UTF-8?q?=E5=A4=A7=E8=A6=8F=E6=A8=A1=E3=81=AA=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/mastodon/account/AccountApiTest.kt | 8 +- ...WithHttpSignatureSecurityContextFactory.kt | 8 +- .../accept/APDeliverAcceptJobProcessor.kt | 8 +- .../activity/accept/ApAcceptProcessor.kt | 11 +-- .../block/BlockActivityPubProcessor.kt | 12 ++- .../create/ApSendCreateServiceImpl.kt | 9 ++- .../activity/delete/APDeleteProcessor.kt | 15 ++-- .../delete/APDeliverDeleteJobProcessor.kt | 8 +- .../activity/delete/APSendDeleteService.kt | 10 ++- .../follow/APReceiveFollowJobProcessor.kt | 12 +-- .../activity/like/APReactionService.kt | 9 ++- .../activity/like/ApReactionJobProcessor.kt | 8 +- .../like/ApRemoveReactionJobProcessor.kt | 8 +- .../reject/APDeliverRejectJobProcessor.kt | 8 +- .../activity/reject/ApRejectProcessor.kt | 13 ++-- .../undo/APDeliverUndoJobProcessor.kt | 8 +- .../service/activity/undo/APUndoProcessor.kt | 24 +++--- .../service/inbox/InboxJobProcessor.kt | 17 ++--- .../objects/note/ApNoteJobProcessor.kt | 8 +- .../service/objects/user/APUserService.kt | 75 ++++++++++--------- .../service/webfinger/WebFingerApiService.kt | 13 +++- .../application/config/SecurityConfig.kt | 15 ++-- .../exposed/ExposedTransaction.kt | 3 +- .../core/domain/exception/HideoutException.kt | 21 ++++++ .../exception/resource/NotFoundException.kt | 16 ++++ .../resource/UserNotFoundException.kt | 37 +++++++++ .../local/LocalUserNotFoundException.kt | 33 ++++++++ .../domain/model/actor/ActorRepository.kt | 18 +++++ .../exposedquery/ActorQueryServiceImpl.kt | 60 --------------- .../exposedquery/FollowerQueryServiceImpl.kt | 8 +- .../exposedrepository/ActorRepositoryImpl.kt | 41 +++++++++- .../HttpSignatureUserDetailsService.kt | 13 +--- .../oauth2/UserDetailsServiceImpl.kt | 17 ++--- .../hideout/core/query/ActorQueryService.kt | 16 ---- .../relationship/RelationshipServiceImpl.kt | 32 ++++---- .../core/service/timeline/TimelineService.kt | 9 ++- .../core/service/user/UserAuthServiceImpl.kt | 8 +- .../core/service/user/UserServiceImpl.kt | 11 ++- .../service/status/StatusesApiService.kt | 13 +--- src/main/resources/application.yml | 18 ++--- src/main/resources/logback.xml | 15 ++++ .../accept/APDeliverAcceptJobProcessorTest.kt | 1 - .../activity/accept/ApAcceptProcessorTest.kt | 1 - .../create/ApSendCreateServiceImplTest.kt | 1 - .../objects/note/APNoteServiceImplTest.kt | 1 - .../RelationshipServiceImplTest.kt | 1 - .../service/timeline/TimelineServiceTest.kt | 1 - .../core/service/user/ActorServiceTest.kt | 2 - 48 files changed, 403 insertions(+), 301 deletions(-) create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/domain/exception/HideoutException.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/NotFoundException.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/UserNotFoundException.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/local/LocalUserNotFoundException.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ActorQueryServiceImpl.kt delete mode 100644 src/main/kotlin/dev/usbharu/hideout/core/query/ActorQueryService.kt diff --git a/src/intTest/kotlin/mastodon/account/AccountApiTest.kt b/src/intTest/kotlin/mastodon/account/AccountApiTest.kt index cf67b35d..f2f9ffc7 100644 --- a/src/intTest/kotlin/mastodon/account/AccountApiTest.kt +++ b/src/intTest/kotlin/mastodon/account/AccountApiTest.kt @@ -1,7 +1,7 @@ package mastodon.account import dev.usbharu.hideout.SpringApplication -import dev.usbharu.hideout.core.infrastructure.exposedquery.ActorQueryServiceImpl +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.infrastructure.exposedquery.FollowerQueryServiceImpl import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat @@ -39,7 +39,7 @@ class AccountApiTest { private lateinit var followerQueryServiceImpl: FollowerQueryServiceImpl @Autowired - private lateinit var userQueryServiceImpl: ActorQueryServiceImpl + private lateinit var actorRepository: ActorRepository @Autowired @@ -100,7 +100,7 @@ class AccountApiTest { .asyncDispatch() .andExpect { status { isFound() } } - userQueryServiceImpl.findByNameAndDomain("api-test-user-1", "example.com") + actorRepository.findByNameAndDomain("api-test-user-1", "example.com") } @Test @@ -116,7 +116,7 @@ class AccountApiTest { .asyncDispatch() .andExpect { status { isFound() } } - userQueryServiceImpl.findByNameAndDomain("api-test-user-2", "example.com") + actorRepository.findByNameAndDomain("api-test-user-2", "example.com") } @Test diff --git a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt index faabf58a..fc9772f0 100644 --- a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt +++ b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt @@ -1,8 +1,9 @@ package util import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.httpsignature.common.HttpHeaders import dev.usbharu.httpsignature.common.HttpMethod import dev.usbharu.httpsignature.common.HttpRequest @@ -14,7 +15,7 @@ import org.springframework.security.web.authentication.preauth.PreAuthenticatedA import java.net.URL class WithHttpSignatureSecurityContextFactory( - private val actorQueryService: ActorQueryService, + private val actorRepository: ActorRepository, private val transaction: Transaction ) : WithSecurityContextFactory { @@ -28,7 +29,8 @@ class WithHttpSignatureSecurityContextFactory( ) ) val httpSignatureUser = transaction.transaction { - val findByKeyId = actorQueryService.findByKeyId(annotation.keyId) + val findByKeyId = + actorRepository.findByKeyId(annotation.keyId) ?: throw UserNotFoundException.withKeyId(annotation.keyId) HttpSignatureUser( findByKeyId.name, findByKeyId.domain, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt index 3a48b5df..0936d8b7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt @@ -2,22 +2,22 @@ package dev.usbharu.hideout.activitypub.service.activity.accept import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverAcceptJob import dev.usbharu.hideout.core.external.job.DeliverAcceptJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service @Service class APDeliverAcceptJobProcessor( private val apRequestService: APRequestService, - private val actorQueryService: ActorQueryService, private val deliverAcceptJob: DeliverAcceptJob, - private val transaction: Transaction + private val transaction: Transaction, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: DeliverAcceptJobParam): Unit = transaction.transaction { - apRequestService.apPost(param.inbox, param.accept, actorQueryService.findById(param.signer)) + apRequestService.apPost(param.inbox, param.accept, actorRepository.findById(param.signer)) } override fun job(): DeliverAcceptJob = deliverAcceptJob diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt index 1a48f22d..cae83622 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt @@ -7,15 +7,16 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.springframework.stereotype.Service @Service class ApAcceptProcessor( transaction: Transaction, - private val actorQueryService: ActorQueryService, - private val relationshipService: RelationshipService + private val relationshipService: RelationshipService, + private val actorRepository: ActorRepository ) : AbstractActivityPubProcessor(transaction) { @@ -32,8 +33,8 @@ class ApAcceptProcessor( val userUrl = follow.apObject val followerUrl = follow.actor - val user = actorQueryService.findByUrl(userUrl) - val follower = actorQueryService.findByUrl(followerUrl) + val user = actorRepository.findByUrl(userUrl) ?: throw UserNotFoundException.withUrl(userUrl) + val follower = actorRepository.findByUrl(followerUrl) ?: throw UserNotFoundException.withUrl(followerUrl) relationshipService.acceptFollowRequest(user.id, follower.id) logger.debug("SUCCESS Follow from ${user.url} to ${follower.url}.") diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt index e31f4e6c..7262edd4 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt @@ -5,7 +5,8 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.springframework.stereotype.Service @@ -14,14 +15,17 @@ import org.springframework.stereotype.Service */ @Service class BlockActivityPubProcessor( - private val actorQueryService: ActorQueryService, private val relationshipService: RelationshipService, + private val actorRepository: ActorRepository, transaction: Transaction ) : AbstractActivityPubProcessor(transaction) { override suspend fun internalProcess(activity: ActivityPubProcessContext) { - val user = actorQueryService.findByUrl(activity.activity.actor) - val target = actorQueryService.findByUrl(activity.activity.apObject) + val user = actorRepository.findByUrl(activity.activity.actor) + ?: throw UserNotFoundException.withUrl(activity.activity.actor) + val target = actorRepository.findByUrl(activity.activity.apObject) ?: throw UserNotFoundException.withUrl( + activity.activity.apObject + ) relationshipService.block(user.id, target.id) } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt index 0ba9413e..7f6ea823 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt @@ -4,9 +4,10 @@ import com.fasterxml.jackson.databind.ObjectMapper import dev.usbharu.hideout.activitypub.domain.model.Create import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.application.config.ApplicationConfig +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.external.job.DeliverPostJob -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService import org.slf4j.LoggerFactory @@ -17,9 +18,9 @@ class ApSendCreateServiceImpl( private val followerQueryService: FollowerQueryService, private val objectMapper: ObjectMapper, private val jobQueueParentService: JobQueueParentService, - private val actorQueryService: ActorQueryService, private val noteQueryService: NoteQueryService, - private val applicationConfig: ApplicationConfig + private val applicationConfig: ApplicationConfig, + private val actorRepository: ActorRepository ) : ApSendCreateService { override suspend fun createNote(post: Post) { logger.info("CREATE Create Local Note ${post.url}") @@ -29,7 +30,7 @@ class ApSendCreateServiceImpl( logger.debug("DELIVER Deliver Note Create ${followers.size} accounts.") - val userEntity = actorQueryService.findById(post.actorId) + val userEntity = actorRepository.findById(post.actorId) ?: throw UserNotFoundException.withId(post.actorId) val note = noteQueryService.findById(post.id).first val create = Create( name = "Create Note", diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt index 508c3d45..f56f6018 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeleteProcessor.kt @@ -9,7 +9,7 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.post.PostService import dev.usbharu.hideout.core.service.user.UserService @@ -19,9 +19,9 @@ import org.springframework.stereotype.Service class APDeleteProcessor( transaction: Transaction, private val postQueryService: PostQueryService, - private val actorQueryService: ActorQueryService, private val userService: UserService, - private val postService: PostService + private val postService: PostService, + private val actorRepository: ActorRepository ) : AbstractActivityPubProcessor(transaction) { override suspend fun internalProcess(activity: ActivityPubProcessContext) { @@ -34,12 +34,9 @@ class APDeleteProcessor( throw IllegalActivityPubObjectException("object hasn't id or object") } - try { - val actor = actorQueryService.findByUrl(deleteId) - userService.deleteRemoteActor(actor.id) - } catch (e: Exception) { - logger.warn("FAILED delete id: {} is not found.", deleteId, e) - } + val actor = actorRepository.findByUrl(deleteId) + actor?.let { userService.deleteRemoteActor(it.id) } + try { val post = postQueryService.findByApId(deleteId) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeliverDeleteJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeliverDeleteJobProcessor.kt index 5c72c304..9924594f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeliverDeleteJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APDeliverDeleteJobProcessor.kt @@ -2,21 +2,21 @@ package dev.usbharu.hideout.activitypub.service.activity.delete import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverDeleteJob import dev.usbharu.hideout.core.external.job.DeliverDeleteJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service @Service class APDeliverDeleteJobProcessor( private val apRequestService: APRequestService, - private val actorQueryService: ActorQueryService, private val transaction: Transaction, - private val deliverDeleteJob: DeliverDeleteJob + private val deliverDeleteJob: DeliverDeleteJob, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: DeliverDeleteJobParam): Unit = transaction.transaction { - apRequestService.apPost(param.inbox, param.delete, actorQueryService.findById(param.signer)) + apRequestService.apPost(param.inbox, param.delete, actorRepository.findById(param.signer)) } override fun job(): DeliverDeleteJob = deliverDeleteJob diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APSendDeleteService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APSendDeleteService.kt index 2d1dde2a..626418d8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APSendDeleteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/delete/APSendDeleteService.kt @@ -4,11 +4,12 @@ import dev.usbharu.hideout.activitypub.domain.model.Delete import dev.usbharu.hideout.activitypub.domain.model.Tombstone import dev.usbharu.hideout.activitypub.domain.model.objects.ObjectValue import dev.usbharu.hideout.application.config.ApplicationConfig +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.external.job.DeliverDeleteJob import dev.usbharu.hideout.core.external.job.DeliverDeleteJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService import org.springframework.stereotype.Service @@ -24,11 +25,12 @@ class APSendDeleteServiceImpl( private val jobQueueParentService: JobQueueParentService, private val delverDeleteJob: DeliverDeleteJob, private val followerQueryService: FollowerQueryService, - private val actorQueryService: ActorQueryService, - private val applicationConfig: ApplicationConfig + private val applicationConfig: ApplicationConfig, + private val actorRepository: ActorRepository ) : APSendDeleteService { override suspend fun sendDeleteNote(deletedPost: Post) { - val actor = actorQueryService.findById(deletedPost.actorId) + val actor = + actorRepository.findById(deletedPost.actorId) ?: throw UserNotFoundException.withId(deletedPost.actorId) val followersById = followerQueryService.findFollowersById(deletedPost.actorId) val delete = Delete( diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt index 292f0ee2..50641d62 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt @@ -5,9 +5,10 @@ import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.ReceiveFollowJob import dev.usbharu.hideout.core.external.job.ReceiveFollowJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.slf4j.LoggerFactory @@ -16,10 +17,10 @@ import org.springframework.stereotype.Service @Service class APReceiveFollowJobProcessor( private val transaction: Transaction, - private val actorQueryService: ActorQueryService, private val apUserService: APUserService, private val objectMapper: ObjectMapper, - private val relationshipService: RelationshipService + private val relationshipService: RelationshipService, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: ReceiveFollowJobParam) = transaction.transaction { @@ -28,9 +29,10 @@ class APReceiveFollowJobProcessor( logger.info("START Follow from: {} to {}", param.targetActor, param.actor) - val targetEntity = actorQueryService.findByUrl(param.targetActor) + val targetEntity = + actorRepository.findByUrl(param.targetActor) ?: throw UserNotFoundException.withUrl(param.targetActor) val followActorEntity = - actorQueryService.findByUrl(follow.actor) + actorRepository.findByUrl(follow.actor) ?: throw UserNotFoundException.withUrl(follow.actor) relationshipService.followRequest(followActorEntity.id, targetEntity.id) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt index 1995cf83..94f67a4f 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt @@ -1,10 +1,11 @@ package dev.usbharu.hideout.activitypub.service.activity.like import com.fasterxml.jackson.databind.ObjectMapper +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.reaction.Reaction import dev.usbharu.hideout.core.external.job.DeliverReactionJob import dev.usbharu.hideout.core.external.job.DeliverRemoveReactionJob -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService @@ -19,14 +20,14 @@ interface APReactionService { @Service class APReactionServiceImpl( private val jobQueueParentService: JobQueueParentService, - private val actorQueryService: ActorQueryService, private val followerQueryService: FollowerQueryService, private val postQueryService: PostQueryService, + private val actorRepository: ActorRepository, @Qualifier("activitypub") private val objectMapper: ObjectMapper ) : APReactionService { override suspend fun reaction(like: Reaction) { val followers = followerQueryService.findFollowersById(like.actorId) - val user = actorQueryService.findById(like.actorId) + val user = actorRepository.findById(like.actorId) ?: throw UserNotFoundException.withId(like.actorId) val post = postQueryService.findById(like.postId) followers.forEach { follower -> @@ -42,7 +43,7 @@ class APReactionServiceImpl( override suspend fun removeReaction(like: Reaction) { val followers = followerQueryService.findFollowersById(like.actorId) - val user = actorQueryService.findById(like.actorId) + val user = actorRepository.findById(like.actorId) ?: throw UserNotFoundException.withId(like.actorId) val post = postQueryService.findById(like.postId) followers.forEach { follower -> diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt index e7857e8e..ee4f8605 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt @@ -4,21 +4,21 @@ import dev.usbharu.hideout.activitypub.domain.model.Like import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverReactionJob import dev.usbharu.hideout.core.external.job.DeliverReactionJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service @Service class ApReactionJobProcessor( - private val actorQueryService: ActorQueryService, private val apRequestService: APRequestService, private val applicationConfig: ApplicationConfig, - private val transaction: Transaction + private val transaction: Transaction, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: DeliverReactionJobParam): Unit = transaction.transaction { - val signer = actorQueryService.findByUrl(param.actor) + val signer = actorRepository.findByUrl(param.actor) apRequestService.apPost( param.inbox, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt index 5dd3e6e7..0d48c53a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt @@ -7,25 +7,25 @@ import dev.usbharu.hideout.activitypub.domain.model.Undo import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverRemoveReactionJob import dev.usbharu.hideout.core.external.job.DeliverRemoveReactionJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service import java.time.Instant @Service class ApRemoveReactionJobProcessor( - private val actorQueryService: ActorQueryService, private val transaction: Transaction, private val objectMapper: ObjectMapper, private val apRequestService: APRequestService, - private val applicationConfig: ApplicationConfig + private val applicationConfig: ApplicationConfig, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: DeliverRemoveReactionJobParam): Unit = transaction.transaction { val like = objectMapper.readValue(param.like) - val signer = actorQueryService.findByUrl(param.actor) + val signer = actorRepository.findByUrl(param.actor) apRequestService.apPost( param.inbox, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt index 0ef702d5..a7706473 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt @@ -2,22 +2,22 @@ package dev.usbharu.hideout.activitypub.service.activity.reject import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverRejectJob import dev.usbharu.hideout.core.external.job.DeliverRejectJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Component @Component class APDeliverRejectJobProcessor( private val apRequestService: APRequestService, - private val actorQueryService: ActorQueryService, private val deliverRejectJob: DeliverRejectJob, - private val transaction: Transaction + private val transaction: Transaction, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: DeliverRejectJobParam): Unit = transaction.transaction { - apRequestService.apPost(param.inbox, param.reject, actorQueryService.findById(param.signer)) + apRequestService.apPost(param.inbox, param.reject, actorRepository.findById(param.signer)) } override fun job(): DeliverRejectJob = deliverRejectJob diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt index 29bbd1f9..d1c53f0e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt @@ -6,15 +6,16 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.springframework.stereotype.Service @Service class ApRejectProcessor( private val relationshipService: RelationshipService, - private val actorQueryService: ActorQueryService, - transaction: Transaction + transaction: Transaction, + private val actorRepository: ActorRepository ) : AbstractActivityPubProcessor(transaction) { override suspend fun internalProcess(activity: ActivityPubProcessContext) { @@ -26,13 +27,15 @@ class ApRejectProcessor( } when (activityType) { "Follow" -> { - val user = actorQueryService.findByUrl(activity.activity.actor) + val user = actorRepository.findByUrl(activity.activity.actor) ?: throw UserNotFoundException.withUrl( + activity.activity.actor + ) activity.activity.apObject as Follow val actor = activity.activity.apObject.actor - val target = actorQueryService.findByUrl(actor) + val target = actorRepository.findByUrl(actor) ?: throw UserNotFoundException.withUrl(actor) logger.debug("REJECT Follow user {} target {}", user.url, target.url) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt index 70e31921..ebc3257c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt @@ -2,9 +2,9 @@ package dev.usbharu.hideout.activitypub.service.activity.undo import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverUndoJob import dev.usbharu.hideout.core.external.job.DeliverUndoJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service @@ -12,11 +12,11 @@ import org.springframework.stereotype.Service class APDeliverUndoJobProcessor( private val deliverUndoJob: DeliverUndoJob, private val apRequestService: APRequestService, - private val actorQueryService: ActorQueryService, - private val transaction: Transaction + private val transaction: Transaction, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: DeliverUndoJobParam): Unit = transaction.transaction { - apRequestService.apPost(param.inbox, param.undo, actorQueryService.findById(param.signer)) + apRequestService.apPost(param.inbox, param.undo, actorRepository.findById(param.signer)) } override fun job(): DeliverUndoJob = deliverUndoJob diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt index 77388337..afd9a721 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt @@ -7,7 +7,9 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.exception.resource.local.LocalUserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.reaction.ReactionService import dev.usbharu.hideout.core.service.relationship.RelationshipService @@ -17,10 +19,10 @@ import org.springframework.stereotype.Service class APUndoProcessor( transaction: Transaction, private val apUserService: APUserService, - private val actorQueryService: ActorQueryService, private val relationshipService: RelationshipService, private val postQueryService: PostQueryService, - private val reactionService: ReactionService + private val reactionService: ReactionService, + private val actorRepository: ActorRepository ) : AbstractActivityPubProcessor(transaction) { override suspend fun internalProcess(activity: ActivityPubProcessContext) { @@ -35,9 +37,9 @@ class APUndoProcessor( "Follow" -> { val follow = undo.apObject as Follow - apUserService.fetchPerson(undo.actor, follow.apObject) - val follower = actorQueryService.findByUrl(undo.actor) - val target = actorQueryService.findByUrl(follow.apObject) + val follower = apUserService.fetchPersonWithEntity(undo.actor, follow.apObject).second + val target = + actorRepository.findByUrl(follow.apObject) ?: throw UserNotFoundException.withUrl(follow.apObject) relationshipService.unfollow(follower.id, target.id) return @@ -47,7 +49,8 @@ class APUndoProcessor( val block = undo.apObject as Block val blocker = apUserService.fetchPersonWithEntity(undo.actor, block.apObject).second - val target = actorQueryService.findByUrl(block.apObject) + val target = + actorRepository.findByUrl(block.apObject) ?: throw UserNotFoundException.withUrl(block.apObject) relationshipService.unblock(blocker.id, target.id) return @@ -66,7 +69,8 @@ class APUndoProcessor( } val accepter = apUserService.fetchPersonWithEntity(undo.actor, acceptObject).second - val target = actorQueryService.findByUrl(acceptObject) + val target = + actorRepository.findByUrl(acceptObject) ?: throw UserNotFoundException.withUrl(acceptObject) relationshipService.rejectFollowRequest(accepter.id, target.id) return @@ -77,7 +81,9 @@ class APUndoProcessor( val post = postQueryService.findByUrl(like.apObject) - val actor = actorQueryService.findByUrl(like.actor) + val signer = + actorRepository.findById(post.actorId) ?: throw LocalUserNotFoundException.withId(post.actorId) + val actor = apUserService.fetchPersonWithEntity(like.actor, signer.url).second reactionService.receiveRemoveReaction(actor.id, post.id) return diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt index bfaf72f1..660f5958 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt @@ -7,10 +7,8 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessor import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.external.job.InboxJob import dev.usbharu.hideout.core.external.job.InboxJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.httpsignature.common.HttpHeaders @@ -29,7 +27,6 @@ class InboxJobProcessor( private val objectMapper: ObjectMapper, private val signatureHeaderParser: SignatureHeaderParser, private val signatureVerifier: HttpSignatureVerifier, - private val actorQueryService: ActorQueryService, private val apUserService: APUserService, private val transaction: Transaction ) : JobProcessor { @@ -37,7 +34,8 @@ class InboxJobProcessor( private suspend fun verifyHttpSignature( httpRequest: HttpRequest, signature: Signature, - transaction: Transaction + transaction: Transaction, + actor: String ): Boolean { val requiredHeaders = when (httpRequest.method) { HttpMethod.GET -> getRequiredHeaders @@ -49,11 +47,7 @@ class InboxJobProcessor( } val user = transaction.transaction { - try { - actorQueryService.findByKeyId(signature.keyId) - } catch (_: FailedToGetResourcesException) { - apUserService.fetchPersonWithEntity(signature.keyId).second - } + apUserService.fetchPersonWithEntity(actor).second } @Suppress("TooGenericExceptionCaught") @@ -97,7 +91,10 @@ class InboxJobProcessor( logger.debug("Has signature? {}", signature != null) - val verify = signature?.let { verifyHttpSignature(httpRequest, it, transaction) } ?: false + + //todo 不正なactorを取得してしまわないようにする + val verify = + signature?.let { verifyHttpSignature(httpRequest, it, transaction, jsonNode["actor"].textValue()) } ?: false logger.debug("Is verifying success? {}", verify) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt index a9dbab74..921eaddf 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt @@ -5,9 +5,9 @@ import com.fasterxml.jackson.module.kotlin.readValue import dev.usbharu.hideout.activitypub.domain.model.Create import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverPostJob import dev.usbharu.hideout.core.external.job.DeliverPostJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -16,13 +16,13 @@ import org.springframework.stereotype.Service class ApNoteJobProcessor( private val transaction: Transaction, private val objectMapper: ObjectMapper, - private val actorQueryService: ActorQueryService, - private val apRequestService: APRequestService + private val apRequestService: APRequestService, + private val actorRepository: ActorRepository ) : JobProcessor { override suspend fun process(param: DeliverPostJobParam) { val create = objectMapper.readValue(param.create) transaction.transaction { - val signer = actorQueryService.findByUrl(param.actor) + val signer = actorRepository.findByUrl(param.actor) logger.debug("CreateNoteJob: actor: {} create: {} inbox: {}", param.actor, create, param.inbox) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt index 009c6821..886ecb42 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt @@ -1,6 +1,5 @@ package dev.usbharu.hideout.activitypub.service.objects.user -import dev.usbharu.hideout.activitypub.domain.exception.IllegalActivityPubObjectException import dev.usbharu.hideout.activitypub.domain.model.Image import dev.usbharu.hideout.activitypub.domain.model.Key import dev.usbharu.hideout.activitypub.domain.model.Person @@ -8,9 +7,9 @@ import dev.usbharu.hideout.activitypub.service.common.APResourceResolveService import dev.usbharu.hideout.activitypub.service.common.resolve import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.Actor -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.service.user.RemoteUserCreateDto import dev.usbharu.hideout.core.service.user.UserService import org.springframework.stereotype.Service @@ -34,16 +33,17 @@ interface APUserService { @Service class APUserServiceImpl( private val userService: UserService, - private val actorQueryService: ActorQueryService, private val transaction: Transaction, private val applicationConfig: ApplicationConfig, - private val apResourceResolveService: APResourceResolveService + private val apResourceResolveService: APResourceResolveService, + private val actorRepository: ActorRepository ) : APUserService { override suspend fun getPersonByName(name: String): Person { val userEntity = transaction.transaction { - actorQueryService.findByNameAndDomain(name, applicationConfig.url.host) + actorRepository.findByNameAndDomain(name, applicationConfig.url.host) + ?: throw UserNotFoundException.withNameAndDomain(name, applicationConfig.url.host) } // TODO: JOINで書き直し val userUrl = "${applicationConfig.url}/users/$name" @@ -78,38 +78,41 @@ class APUserServiceImpl( @Transactional override suspend fun fetchPersonWithEntity(url: String, targetActor: String?): Pair { - return try { - val userEntity = actorQueryService.findByUrl(url) - val id = userEntity.url - return entityToPerson(userEntity, id) to userEntity - } catch (ignore: FailedToGetResourcesException) { - val person = apResourceResolveService.resolve(url, null as Long?) + val userEntity = actorRepository.findByUrl(url) - val id = person.id - try { - val userEntity = actorQueryService.findByUrl(id) - return entityToPerson(userEntity, id) to userEntity - } catch (_: FailedToGetResourcesException) { - } - person to userService.createRemoteUser( - RemoteUserCreateDto( - name = person.preferredUsername - ?: throw IllegalActivityPubObjectException("preferredUsername is null"), - domain = id.substringAfter("://").substringBefore("/"), - screenName = person.name ?: person.preferredUsername, - description = person.summary.orEmpty(), - inbox = person.inbox, - outbox = person.outbox, - url = id, - publicKey = person.publicKey.publicKeyPem, - keyId = person.publicKey.id, - following = person.following, - followers = person.followers, - sharedInbox = person.endpoints["sharedInbox"], - locked = person.manuallyApprovesFollowers - ) - ) + if (userEntity != null) { + return entityToPerson(userEntity, userEntity.url) to userEntity } + + + val person = apResourceResolveService.resolve(url, null as Long?) + + val id = person.id + + val actor = actorRepository.findByUrlWithLock(id) + + if (actor != null) { + return person to actor + } + + return person to userService.createRemoteUser( + RemoteUserCreateDto( + name = person.preferredUsername, + domain = id.substringAfter("://").substringBefore("/"), + screenName = person.name ?: person.preferredUsername, + description = person.summary.orEmpty(), + inbox = person.inbox, + outbox = person.outbox, + url = id, + publicKey = person.publicKey.publicKeyPem, + keyId = person.publicKey.id, + following = person.following, + followers = person.followers, + sharedInbox = person.endpoints["sharedInbox"], + locked = person.manuallyApprovesFollowers + ) + ) + } private fun entityToPerson( diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt index 1cdd8230..25b774a0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt @@ -1,8 +1,9 @@ package dev.usbharu.hideout.activitypub.service.webfinger import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.Actor -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import org.springframework.stereotype.Service @Service @@ -11,11 +12,17 @@ interface WebFingerApiService { } @Service -class WebFingerApiServiceImpl(private val transaction: Transaction, private val actorQueryService: ActorQueryService) : +class WebFingerApiServiceImpl( + private val transaction: Transaction, + private val actorRepository: ActorRepository +) : WebFingerApiService { override suspend fun findByNameAndDomain(name: String, domain: String): Actor { return transaction.transaction { - actorQueryService.findByNameAndDomain(name, domain) + actorRepository.findByNameAndDomain(name, domain) ?: throw UserNotFoundException.withNameAndDomain( + name, + domain + ) } } } diff --git a/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt b/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt index 144379c9..966be809 100644 --- a/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt +++ b/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt @@ -7,19 +7,18 @@ import com.nimbusds.jose.jwk.source.ImmutableJWKSet import com.nimbusds.jose.jwk.source.JWKSource import com.nimbusds.jose.proc.SecurityContext import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureFilter import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUserDetailsService import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureVerifierComposite import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.UserDetailsImpl import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.UserDetailsServiceImpl -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.hideout.util.hasAnyScope import dev.usbharu.httpsignature.sign.RsaSha256HttpSignatureSigner import dev.usbharu.httpsignature.verify.DefaultSignatureHeaderParser import dev.usbharu.httpsignature.verify.RsaSha256HttpSignatureVerifier import jakarta.annotation.PostConstruct -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer import org.springframework.boot.context.properties.ConfigurationProperties @@ -68,9 +67,6 @@ import java.util.* @Suppress("FunctionMaxLength", "TooManyFunctions") class SecurityConfig { - @Autowired - private lateinit var actorQueryService: ActorQueryService - @Bean fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager? = authenticationConfiguration.authenticationManager @@ -130,12 +126,14 @@ class SecurityConfig { @Bean @Order(1) - fun httpSignatureAuthenticationProvider(transaction: Transaction): PreAuthenticatedAuthenticationProvider { + fun httpSignatureAuthenticationProvider( + transaction: Transaction, + actorRepository: ActorRepository + ): PreAuthenticatedAuthenticationProvider { val provider = PreAuthenticatedAuthenticationProvider() val signatureHeaderParser = DefaultSignatureHeaderParser() provider.setPreAuthenticatedUserDetailsService( HttpSignatureUserDetailsService( - actorQueryService, HttpSignatureVerifierComposite( mapOf( "rsa-sha256" to RsaSha256HttpSignatureVerifier( @@ -145,7 +143,8 @@ class SecurityConfig { signatureHeaderParser ), transaction, - signatureHeaderParser + signatureHeaderParser, + actorRepository ) ) provider.setUserDetailsChecker(AccountStatusUserDetailsChecker()) diff --git a/src/main/kotlin/dev/usbharu/hideout/application/infrastructure/exposed/ExposedTransaction.kt b/src/main/kotlin/dev/usbharu/hideout/application/infrastructure/exposed/ExposedTransaction.kt index 74be00ff..097c551a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/application/infrastructure/exposed/ExposedTransaction.kt +++ b/src/main/kotlin/dev/usbharu/hideout/application/infrastructure/exposed/ExposedTransaction.kt @@ -6,12 +6,11 @@ import org.jetbrains.exposed.sql.StdOutSqlLogger import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction import org.springframework.stereotype.Service -import java.sql.Connection @Service class ExposedTransaction : Transaction { override suspend fun transaction(block: suspend () -> T): T { - return newSuspendedTransaction(MDCContext(), transactionIsolation = Connection.TRANSACTION_SERIALIZABLE) { + return newSuspendedTransaction(MDCContext()) { addLogger(StdOutSqlLogger) block() } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/HideoutException.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/HideoutException.kt new file mode 100644 index 00000000..0307e24d --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/HideoutException.kt @@ -0,0 +1,21 @@ +package dev.usbharu.hideout.core.domain.exception + +import java.io.Serial + +open class HideoutException : RuntimeException { + constructor() : super() + constructor(message: String?) : super(message) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) + constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super( + message, + cause, + enableSuppression, + writableStackTrace + ) + + companion object { + @Serial + private const val serialVersionUID: Long = 8506638570017469956L + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/NotFoundException.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/NotFoundException.kt new file mode 100644 index 00000000..1a1e0d0d --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/NotFoundException.kt @@ -0,0 +1,16 @@ +package dev.usbharu.hideout.core.domain.exception.resource + +import dev.usbharu.hideout.core.domain.exception.HideoutException + +open class NotFoundException : HideoutException { + constructor() : super() + constructor(message: String?) : super(message) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) + constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super( + message, + cause, + enableSuppression, + writableStackTrace + ) +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/UserNotFoundException.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/UserNotFoundException.kt new file mode 100644 index 00000000..0560be92 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/UserNotFoundException.kt @@ -0,0 +1,37 @@ +package dev.usbharu.hideout.core.domain.exception.resource + +import java.io.Serial + +open class UserNotFoundException : NotFoundException { + constructor() : super() + constructor(message: String?) : super(message) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) + constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super( + message, + cause, + enableSuppression, + writableStackTrace + ) + + companion object { + @Serial + private const val serialVersionUID: Long = 3219433672235626200L + + + fun withName(string: String, throwable: Throwable? = null): UserNotFoundException = + UserNotFoundException("name: $string was not found.", throwable) + + fun withId(id: Long, throwable: Throwable? = null): UserNotFoundException = + UserNotFoundException("id: $id was not found.", throwable) + + fun withUrl(url: String, throwable: Throwable? = null): UserNotFoundException = + UserNotFoundException("url: $url was not found.", throwable) + + fun withNameAndDomain(name: String, domain: String, throwable: Throwable? = null): UserNotFoundException = + UserNotFoundException("name: $name domain: $domain (@$name@$domain) was not found.", throwable) + + fun withKeyId(keyId: String, throwable: Throwable? = null) = + UserNotFoundException("keyId: $keyId was not found.", throwable) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/local/LocalUserNotFoundException.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/local/LocalUserNotFoundException.kt new file mode 100644 index 00000000..b2cdb0ae --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/exception/resource/local/LocalUserNotFoundException.kt @@ -0,0 +1,33 @@ +package dev.usbharu.hideout.core.domain.exception.resource.local + +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import java.io.Serial + +class LocalUserNotFoundException : UserNotFoundException { + constructor() : super() + constructor(message: String?) : super(message) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) + constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super( + message, + cause, + enableSuppression, + writableStackTrace + ) + + + companion object { + @Serial + private const val serialVersionUID: Long = -4742548128672528145L + + fun withName(string: String, throwable: Throwable? = null): LocalUserNotFoundException = + LocalUserNotFoundException("name: $string was not found.", throwable) + + fun withId(id: Long, throwable: Throwable? = null): LocalUserNotFoundException = + LocalUserNotFoundException("id: $id was not found.", throwable) + + fun withUrl(url: String, throwable: Throwable? = null): LocalUserNotFoundException = + LocalUserNotFoundException("url: $url was not found.", throwable) + } + +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/ActorRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/ActorRepository.kt index 39887a5e..ae39290a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/ActorRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/ActorRepository.kt @@ -8,6 +8,24 @@ interface ActorRepository { suspend fun findById(id: Long): Actor? + suspend fun findByIdWithLock(id: Long): Actor? + + suspend fun findAll(limit: Int, offset: Long): List + + suspend fun findByName(name: String): List + + suspend fun findByNameAndDomain(name: String, domain: String): Actor? + + suspend fun findByNameAndDomainWithLock(name: String, domain: String): Actor? + + suspend fun findByUrl(url: String): Actor? + + suspend fun findByUrlWithLock(url: String): Actor? + + suspend fun findByIds(ids: List): List + + suspend fun findByKeyId(keyId: String): Actor? + suspend fun delete(id: Long) suspend fun nextId(): Long diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ActorQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ActorQueryServiceImpl.kt deleted file mode 100644 index 6dab78c2..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ActorQueryServiceImpl.kt +++ /dev/null @@ -1,60 +0,0 @@ -package dev.usbharu.hideout.core.infrastructure.exposedquery - -import dev.usbharu.hideout.application.infrastructure.exposed.QueryMapper -import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException -import dev.usbharu.hideout.core.domain.model.actor.Actor -import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors -import dev.usbharu.hideout.core.query.ActorQueryService -import dev.usbharu.hideout.util.singleOr -import org.jetbrains.exposed.sql.and -import org.jetbrains.exposed.sql.select -import org.jetbrains.exposed.sql.selectAll -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Repository - -@Repository -class ActorQueryServiceImpl( - private val actorResultRowMapper: ResultRowMapper, - private val actorQueryMapper: QueryMapper -) : ActorQueryService { - - private val logger = LoggerFactory.getLogger(ActorQueryServiceImpl::class.java) - - override suspend fun findAll(limit: Int, offset: Long): List = - Actors.selectAll().limit(limit, offset).let(actorQueryMapper::map) - - override suspend fun findById(id: Long): Actor = Actors.select { Actors.id eq id } - .singleOr { FailedToGetResourcesException("id: $id is duplicate or does not exist.", it) } - .let(actorResultRowMapper::map) - - override suspend fun findByName(name: String): List = - Actors.select { Actors.name eq name }.let(actorQueryMapper::map) - - override suspend fun findByNameAndDomain(name: String, domain: String): Actor = - Actors - .select { Actors.name eq name and (Actors.domain eq domain) } - .singleOr { - FailedToGetResourcesException("name: $name,domain: $domain is duplicate or does not exist.", it) - } - .let(actorResultRowMapper::map) - - override suspend fun findByUrl(url: String): Actor { - logger.trace("findByUrl url: $url") - return Actors.select { Actors.url eq url } - .singleOr { FailedToGetResourcesException("url: $url is duplicate or does not exist.", it) } - .let(actorResultRowMapper::map) - } - - override suspend fun findByIds(ids: List): List = - Actors.select { Actors.id inList ids }.let(actorQueryMapper::map) - - override suspend fun existByNameAndDomain(name: String, domain: String): Boolean = - Actors.select { Actors.name eq name and (Actors.domain eq domain) }.empty().not() - - override suspend fun findByKeyId(keyId: String): Actor { - return Actors.select { Actors.keyId eq keyId } - .singleOr { FailedToGetResourcesException("keyId: $keyId is duplicate or does not exist.", it) } - .let(actorResultRowMapper::map) - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt index f7161b2e..9c841f15 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt @@ -1,8 +1,8 @@ package dev.usbharu.hideout.core.infrastructure.exposedquery import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.RelationshipQueryService import org.springframework.stereotype.Repository @@ -10,11 +10,11 @@ import org.springframework.stereotype.Repository @Repository class FollowerQueryServiceImpl( private val relationshipQueryService: RelationshipQueryService, - private val actorQueryService: ActorQueryService, - private val relationshipRepository: RelationshipRepository + private val relationshipRepository: RelationshipRepository, + private val actorRepository: ActorRepository ) : FollowerQueryService { override suspend fun findFollowersById(id: Long): List { - return actorQueryService.findByIds( + return actorRepository.findByIds( relationshipQueryService.findByTargetIdAndFollowing(id, true).map { it.actorId } ) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt index 96ce6409..fa0f395d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt @@ -1,5 +1,6 @@ package dev.usbharu.hideout.core.infrastructure.exposedrepository +import dev.usbharu.hideout.application.infrastructure.exposed.QueryMapper import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper import dev.usbharu.hideout.application.service.id.IdGenerateService import dev.usbharu.hideout.core.domain.model.actor.Actor @@ -12,12 +13,13 @@ import org.springframework.stereotype.Repository @Repository class ActorRepositoryImpl( private val idGenerateService: IdGenerateService, - private val actorResultRowMapper: ResultRowMapper + private val actorResultRowMapper: ResultRowMapper, + private val actorQueryMapper: QueryMapper ) : ActorRepository { override suspend fun save(actor: Actor): Actor { - val singleOrNull = Actors.select { Actors.id eq actor.id }.empty() + val singleOrNull = Actors.select { Actors.id eq actor.id }.forUpdate().empty() if (singleOrNull) { Actors.insert { it[id] = actor.id @@ -70,6 +72,41 @@ class ActorRepositoryImpl( override suspend fun findById(id: Long): Actor? = Actors.select { Actors.id eq id }.singleOrNull()?.let(actorResultRowMapper::map) + override suspend fun findByIdWithLock(id: Long): Actor? = + Actors.select { Actors.id eq id }.forUpdate().singleOrNull()?.let(actorResultRowMapper::map) + + override suspend fun findAll(limit: Int, offset: Long): List = + Actors.selectAll().limit(limit, offset).let(actorQueryMapper::map) + + override suspend fun findByName(name: String): List = + Actors.select { Actors.name eq name }.let(actorQueryMapper::map) + + override suspend fun findByNameAndDomain(name: String, domain: String): Actor? = Actors + .select { Actors.name eq name and (Actors.domain eq domain) } + .singleOrNull() + ?.let(actorResultRowMapper::map) + + override suspend fun findByNameAndDomainWithLock(name: String, domain: String): Actor? = Actors + .select { Actors.name eq name and (Actors.domain eq domain) } + .forUpdate() + .singleOrNull() + ?.let(actorResultRowMapper::map) + + override suspend fun findByUrl(url: String): Actor? = Actors.select { Actors.url eq url } + .singleOrNull() + ?.let(actorResultRowMapper::map) + + override suspend fun findByUrlWithLock(url: String): Actor? = Actors.select { Actors.url eq url }.forUpdate() + .singleOrNull() + ?.let(actorResultRowMapper::map) + + override suspend fun findByIds(ids: List): List = + Actors.select { Actors.id inList ids }.let(actorQueryMapper::map) + + override suspend fun findByKeyId(keyId: String): Actor? = Actors.select { Actors.keyId eq keyId } + .singleOrNull() + ?.let(actorResultRowMapper::map) + override suspend fun delete(id: Long) { Actors.deleteWhere { Actors.id.eq(id) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt index 8c891da3..17552026 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt @@ -1,9 +1,8 @@ package dev.usbharu.hideout.core.infrastructure.springframework.httpsignature import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.exception.HttpSignatureVerifyException -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.httpsignature.common.HttpMethod import dev.usbharu.httpsignature.common.HttpRequest @@ -20,10 +19,10 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken class HttpSignatureUserDetailsService( - private val actorQueryService: ActorQueryService, private val httpSignatureVerifier: HttpSignatureVerifier, private val transaction: Transaction, - private val httpSignatureHeaderParser: SignatureHeaderParser + private val httpSignatureHeaderParser: SignatureHeaderParser, + private val actorRepository: ActorRepository ) : AuthenticationUserDetailsService { override fun loadUserDetails(token: PreAuthenticatedAuthenticationToken): UserDetails = runBlocking { @@ -34,11 +33,7 @@ class HttpSignatureUserDetailsService( val keyId = token.principal as String val findByKeyId = transaction.transaction { - try { - actorQueryService.findByKeyId(keyId) - } catch (e: FailedToGetResourcesException) { - throw UsernameNotFoundException("User not found", e) - } + actorRepository.findByKeyId(keyId) ?: throw UsernameNotFoundException("keyId: $keyId not found.") } val signature = httpSignatureHeaderParser.parse(credentials.headers) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt index 2e979cea..6da7e79a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt @@ -2,9 +2,9 @@ package dev.usbharu.hideout.core.infrastructure.springframework.oauth2 import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository -import dev.usbharu.hideout.core.query.ActorQueryService import kotlinx.coroutines.runBlocking import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UserDetailsService @@ -13,10 +13,10 @@ import org.springframework.stereotype.Service @Service class UserDetailsServiceImpl( - private val actorQueryService: ActorQueryService, private val applicationConfig: ApplicationConfig, private val userDetailRepository: UserDetailRepository, - private val transaction: Transaction + private val transaction: Transaction, + private val actorRepository: ActorRepository ) : UserDetailsService { override fun loadUserByUsername(username: String?): UserDetails = runBlocking { @@ -24,11 +24,10 @@ class UserDetailsServiceImpl( throw UsernameNotFoundException("$username not found") } transaction.transaction { - val findById = try { - actorQueryService.findByNameAndDomain(username, applicationConfig.url.host) - } catch (e: FailedToGetResourcesException) { - throw UsernameNotFoundException("$username not found", e) - } + val findById = + actorRepository.findByNameAndDomain(username, applicationConfig.url.host) + ?: throw UserNotFoundException.withNameAndDomain(username, applicationConfig.url.host) + val userDetails = userDetailRepository.findByActorId(findById.id) ?: throw UsernameNotFoundException("${findById.id} not found.") UserDetailsImpl( diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/ActorQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/ActorQueryService.kt deleted file mode 100644 index 05b79e25..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/ActorQueryService.kt +++ /dev/null @@ -1,16 +0,0 @@ -package dev.usbharu.hideout.core.query - -import dev.usbharu.hideout.core.domain.model.actor.Actor -import org.springframework.stereotype.Repository - -@Repository -interface ActorQueryService { - suspend fun findAll(limit: Int, offset: Long): List - suspend fun findById(id: Long): Actor - suspend fun findByName(name: String): List - suspend fun findByNameAndDomain(name: String, domain: String): Actor - suspend fun findByUrl(url: String): Actor - suspend fun findByIds(ids: List): List - suspend fun existByNameAndDomain(name: String, domain: String): Boolean - suspend fun findByKeyId(keyId: String): Actor -} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt index 69082c3e..cd83150e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt @@ -6,12 +6,11 @@ import dev.usbharu.hideout.activitypub.service.activity.follow.APSendFollowServi import dev.usbharu.hideout.activitypub.service.activity.reject.ApSendRejectService import dev.usbharu.hideout.activitypub.service.activity.undo.APSendUndoService import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.relationship.Relationship import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.follow.SendFollowDto import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -19,7 +18,6 @@ import org.springframework.stereotype.Service @Service class RelationshipServiceImpl( private val applicationConfig: ApplicationConfig, - private val actorQueryService: ActorQueryService, private val relationshipRepository: RelationshipRepository, private val apSendFollowService: APSendFollowService, private val apSendBlockService: APSendBlockService, @@ -78,10 +76,10 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = actorQueryService.findById(actorId) + val user = actorRepository.findById(actorId) ?: throw UserNotFoundException.withId(actorId) apSendFollowService.sendFollow(SendFollowDto(user, remoteUser)) } else { - val target = actorQueryService.findById(targetId) + val target = actorRepository.findById(targetId) ?: throw UserNotFoundException.withId(targetId) if (target.locked.not()) { acceptFollowRequest(targetId, actorId) } @@ -93,8 +91,8 @@ class RelationshipServiceImpl( override suspend fun block(actorId: Long, targetId: Long) { val relationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId) - val user = actorQueryService.findById(actorId) - val targetActor = actorQueryService.findById(targetId) + val user = actorRepository.findById(actorId) ?: throw UserNotFoundException.withId(actorId) + val targetActor = actorRepository.findById(targetId) ?: throw UserNotFoundException.withId(targetId) if (relationship?.following == true) { actorRepository.save(user.decrementFollowing()) actorRepository.save(targetActor.decrementFollowers()) @@ -174,13 +172,13 @@ class RelationshipServiceImpl( val copy = relationship.copy(followRequest = false, following = true, blocking = false) - val user = actorQueryService.findById(actorId) + val user = actorRepository.findById(actorId) ?: throw UserNotFoundException.withId(actorId) actorRepository.save(user.incrementFollowers()) relationshipRepository.save(copy) - val remoteActor = actorQueryService.findById(targetId) + val remoteActor = actorRepository.findById(targetId) ?: throw UserNotFoundException.withId(targetId) actorRepository.save(remoteActor.incrementFollowing()) @@ -209,7 +207,7 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = actorQueryService.findById(actorId) + val user = actorRepository.findById(actorId) ?: throw UserNotFoundException.withId(actorId) apSendRejectService.sendRejectFollow(user, remoteUser) } } @@ -238,8 +236,8 @@ class RelationshipServiceImpl( return } - val user = actorQueryService.findById(actorId) - val targetActor = actorQueryService.findById(targetId) + val user = actorRepository.findById(actorId) ?: throw UserNotFoundException.withId(actorId) + val targetActor = actorRepository.findById(targetId) ?: throw UserNotFoundException.withId(targetId) if (relationship.following) { actorRepository.save(user.decrementFollowing()) @@ -280,7 +278,7 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = actorQueryService.findById(actorId) + val user = actorRepository.findById(actorId) ?: throw UserNotFoundException.withId(actorId) apSendUndoService.sendUndoBlock(user, remoteUser) } } @@ -315,12 +313,8 @@ class RelationshipServiceImpl( private suspend fun isRemoteUser(userId: Long): Actor? { logger.trace("isRemoteUser({})", userId) - val user = try { - actorQueryService.findById(userId) - } catch (e: FailedToGetResourcesException) { - logger.warn("User not found.", e) - throw IllegalStateException("User not found.", e) - } + val user = + actorRepository.findById(userId) ?: throw UserNotFoundException.withId(userId) logger.trace("user info {}", user) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt index e53e327d..a6d8b185 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt @@ -1,10 +1,11 @@ package dev.usbharu.hideout.core.service.timeline +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.domain.model.timeline.Timeline import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -12,14 +13,14 @@ import org.springframework.stereotype.Service @Service class TimelineService( private val followerQueryService: FollowerQueryService, - private val actorQueryService: ActorQueryService, - private val timelineRepository: TimelineRepository + private val timelineRepository: TimelineRepository, + private val actorRepository: ActorRepository ) { suspend fun publishTimeline(post: Post, isLocal: Boolean) { val findFollowersById = followerQueryService.findFollowersById(post.actorId).toMutableList() if (isLocal) { // 自分自身も含める必要がある - val user = actorQueryService.findById(post.actorId) + val user = actorRepository.findById(post.actorId) ?: throw UserNotFoundException.withId(post.actorId) findFollowersById.add(user) } val timelines = findFollowersById.map { diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt index 5ec5d4be..dd8f8669 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt @@ -1,6 +1,7 @@ package dev.usbharu.hideout.core.service.user -import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.application.config.ApplicationConfig +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.stereotype.Service import java.security.* @@ -8,13 +9,14 @@ import java.util.* @Service class UserAuthServiceImpl( - val actorQueryService: ActorQueryService + private val actorRepository: ActorRepository, + private val applicationConfig: ApplicationConfig ) : UserAuthService { override fun hash(password: String): String = BCryptPasswordEncoder().encode(password) override suspend fun usernameAlreadyUse(username: String): Boolean { - actorQueryService.findByName(username) + actorRepository.findByNameAndDomain(username, applicationConfig.url.host) ?: return false return true } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt index 36259740..d8b97c32 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt @@ -3,6 +3,7 @@ package dev.usbharu.hideout.core.service.user import dev.usbharu.hideout.activitypub.service.activity.delete.APSendDeleteService import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.exception.resource.UserNotFoundException import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor @@ -11,7 +12,6 @@ import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository import dev.usbharu.hideout.core.domain.model.userdetails.UserDetail import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.DeletedActorQueryService import dev.usbharu.hideout.core.service.instance.InstanceService import dev.usbharu.hideout.core.service.post.PostService @@ -26,7 +26,6 @@ import java.time.Instant class UserServiceImpl( private val actorRepository: ActorRepository, private val userAuthService: UserAuthService, - private val actorQueryService: ActorQueryService, private val actorBuilder: Actor.UserBuilder, private val applicationConfig: ApplicationConfig, private val instanceService: InstanceService, @@ -42,7 +41,7 @@ class UserServiceImpl( UserService { override suspend fun usernameAlreadyUse(username: String): Boolean { - val findByNameAndDomain = actorQueryService.findByNameAndDomain(username, applicationConfig.url.host) + val findByNameAndDomain = actorRepository.findByNameAndDomain(username, applicationConfig.url.host) return findByNameAndDomain != null } @@ -116,7 +115,7 @@ class UserServiceImpl( save } catch (_: ExposedSQLException) { logger.warn("FAILED User already exists. name: {} url: {}", user.name, user.url) - actorQueryService.findByUrl(user.url) + actorRepository.findByUrl(user.url)!! } } @@ -142,7 +141,7 @@ class UserServiceImpl( } override suspend fun deleteRemoteActor(actorId: Long) { - val actor = actorQueryService.findById(actorId) + val actor = actorRepository.findByIdWithLock(actorId) ?: throw UserNotFoundException.withId(actorId) val deletedActor = DeletedActor( actor.id, actor.name, @@ -161,7 +160,7 @@ class UserServiceImpl( } override suspend fun deleteLocalUser(userId: Long) { - val actor = actorQueryService.findById(userId) + val actor = actorRepository.findByIdWithLock(userId) ?: throw UserNotFoundException.withId(userId) apSendDeleteService.sendDeleteActor(actor) val deletedActor = DeletedActor( actor.id, diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt index eac73698..53c4326b 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt @@ -1,10 +1,9 @@ package dev.usbharu.hideout.mastodon.service.status import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.media.MediaRepository import dev.usbharu.hideout.core.domain.model.media.toMediaAttachments -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.post.PostCreateDto import dev.usbharu.hideout.core.service.post.PostService @@ -30,9 +29,9 @@ class StatsesApiServiceImpl( private val postService: PostService, private val accountService: AccountService, private val postQueryService: PostQueryService, - private val actorQueryService: ActorQueryService, private val mediaRepository: MediaRepository, - private val transaction: Transaction + private val transaction: Transaction, + private val actorRepository: ActorRepository ) : StatusesApiService { override suspend fun postStatus( @@ -54,11 +53,7 @@ class StatsesApiServiceImpl( val account = accountService.findById(userId) val replyUser = if (post.replyId != null) { - try { - actorQueryService.findById(postQueryService.findById(post.replyId).actorId).id - } catch (ignore: FailedToGetResourcesException) { - null - } + actorRepository.findById(postQueryService.findById(post.replyId).actorId)?.id } else { null } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index daff34db..2208876e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,6 +1,6 @@ hideout: url: "https://test-hideout.usbharu.dev" - use-mongodb: false + use-mongodb: true security: jwt: generate: true @@ -22,14 +22,14 @@ spring: url: "jdbc:postgresql:hideout2" username: "postgres" password: "" - # data: - # mongodb: - # auto-index-creation: true - # host: localhost - # port: 27017 - # database: hideout - # username: hideoutuser - # password: hideoutpass + data: + mongodb: + auto-index-creation: true + host: localhost + port: 27017 + database: hideout + # username: hideoutuser + # password: hideoutpass servlet: multipart: max-file-size: 40MB diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 26a50765..41b1f895 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,4 +1,18 @@ + + logFile.log + + UTF-8 + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{x-request-id}] %logger{36} - %msg%n + + + + logFile.%d{yyyy-MM-dd_HH}.log + + + 30 + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{x-request-id}] [%X{x-job-id}] %logger{36} - @@ -8,6 +22,7 @@ + diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt index f26cd135..d89fbe6d 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt @@ -5,7 +5,6 @@ import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.core.external.job.DeliverAcceptJob import dev.usbharu.hideout.core.external.job.DeliverAcceptJobParam -import dev.usbharu.hideout.core.query.ActorQueryService import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt index 793a65b6..d9b8f24e 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt @@ -7,7 +7,6 @@ import dev.usbharu.hideout.activitypub.domain.model.Like import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.config.ActivityPubConfig -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.relationship.RelationshipService import dev.usbharu.httpsignature.common.HttpHeaders import dev.usbharu.httpsignature.common.HttpMethod diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt index c2f4f87e..0f5ec6f8 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt @@ -7,7 +7,6 @@ import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl import dev.usbharu.hideout.application.config.ActivityPubConfig import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.external.job.DeliverPostJob -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService import kotlinx.coroutines.test.runTest diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt index 0a709b38..59978164 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt @@ -16,7 +16,6 @@ import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateServ import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.post.PostService import io.ktor.client.* diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt index 4f6fa718..b21bd0a5 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt @@ -9,7 +9,6 @@ import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.relationship.Relationship import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.follow.SendFollowDto import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt index 29b195ae..22583888 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt @@ -5,7 +5,6 @@ import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.domain.model.timeline.Timeline import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository -import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt index d41e7e32..fa1f438d 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt @@ -38,7 +38,6 @@ class ActorServiceTest { UserServiceImpl( actorRepository = actorRepository, userAuthService = userAuthService, - actorQueryService = mock(), actorBuilder = actorBuilder, applicationConfig = testApplicationConfig, instanceService = mock(), @@ -85,7 +84,6 @@ class ActorServiceTest { UserServiceImpl( actorRepository = actorRepository, userAuthService = mock(), - actorQueryService = mock(), actorBuilder = actorBuilder, applicationConfig = testApplicationConfig, instanceService = mock(),