fix: フォロー承認に失敗するのを修正

This commit is contained in:
usbharu 2023-12-11 01:22:17 +09:00
parent 8038232334
commit 55783fefa2
14 changed files with 80 additions and 38 deletions

View File

@ -1,6 +1,7 @@
package dev.usbharu.hideout.activitypub.service.activity.accept package dev.usbharu.hideout.activitypub.service.activity.accept
import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.activitypub.service.common.APRequestService
import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.external.job.DeliverAcceptJob import dev.usbharu.hideout.core.external.job.DeliverAcceptJob
import dev.usbharu.hideout.core.external.job.DeliverAcceptJobParam import dev.usbharu.hideout.core.external.job.DeliverAcceptJobParam
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
@ -11,10 +12,11 @@ import org.springframework.stereotype.Service
class APDeliverAcceptJobProcessor( class APDeliverAcceptJobProcessor(
private val apRequestService: APRequestService, private val apRequestService: APRequestService,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val deliverAcceptJob: DeliverAcceptJob private val deliverAcceptJob: DeliverAcceptJob,
private val transaction: Transaction
) : ) :
JobProcessor<DeliverAcceptJobParam, DeliverAcceptJob> { JobProcessor<DeliverAcceptJobParam, DeliverAcceptJob> {
override suspend fun process(param: DeliverAcceptJobParam) { override suspend fun process(param: DeliverAcceptJobParam): Unit = transaction.transaction {
apRequestService.apPost(param.inbox, param.accept, userQueryService.findById(param.signer)) apRequestService.apPost(param.inbox, param.accept, userQueryService.findById(param.signer))
} }

View File

@ -21,8 +21,8 @@ class ApSendAcceptServiceImpl(
val deliverAcceptJobParam = DeliverAcceptJobParam( val deliverAcceptJobParam = DeliverAcceptJobParam(
Accept( Accept(
apObject = Follow( apObject = Follow(
apObject = target.url, apObject = user.url,
actor = user.url actor = target.url
), ),
actor = user.url actor = user.url
), ),

View File

@ -1,6 +1,7 @@
package dev.usbharu.hideout.activitypub.service.activity.reject package dev.usbharu.hideout.activitypub.service.activity.reject
import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.activitypub.service.common.APRequestService
import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.external.job.DeliverRejectJob import dev.usbharu.hideout.core.external.job.DeliverRejectJob
import dev.usbharu.hideout.core.external.job.DeliverRejectJobParam import dev.usbharu.hideout.core.external.job.DeliverRejectJobParam
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
@ -11,10 +12,11 @@ import org.springframework.stereotype.Component
class APDeliverRejectJobProcessor( class APDeliverRejectJobProcessor(
private val apRequestService: APRequestService, private val apRequestService: APRequestService,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val deliverRejectJob: DeliverRejectJob private val deliverRejectJob: DeliverRejectJob,
private val transaction: Transaction
) : ) :
JobProcessor<DeliverRejectJobParam, DeliverRejectJob> { JobProcessor<DeliverRejectJobParam, DeliverRejectJob> {
override suspend fun process(param: DeliverRejectJobParam) { override suspend fun process(param: DeliverRejectJobParam): Unit = transaction.transaction {
apRequestService.apPost(param.inbox, param.reject, userQueryService.findById(param.signer)) apRequestService.apPost(param.inbox, param.reject, userQueryService.findById(param.signer))
} }

View File

@ -1,6 +1,7 @@
package dev.usbharu.hideout.activitypub.service.activity.undo package dev.usbharu.hideout.activitypub.service.activity.undo
import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.activitypub.service.common.APRequestService
import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.external.job.DeliverUndoJob import dev.usbharu.hideout.core.external.job.DeliverUndoJob
import dev.usbharu.hideout.core.external.job.DeliverUndoJobParam import dev.usbharu.hideout.core.external.job.DeliverUndoJobParam
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
@ -11,9 +12,10 @@ import org.springframework.stereotype.Service
class APDeliverUndoJobProcessor( class APDeliverUndoJobProcessor(
private val deliverUndoJob: DeliverUndoJob, private val deliverUndoJob: DeliverUndoJob,
private val apRequestService: APRequestService, private val apRequestService: APRequestService,
private val userQueryService: UserQueryService private val userQueryService: UserQueryService,
private val transaction: Transaction
) : JobProcessor<DeliverUndoJobParam, DeliverUndoJob> { ) : JobProcessor<DeliverUndoJobParam, DeliverUndoJob> {
override suspend fun process(param: DeliverUndoJobParam) { override suspend fun process(param: DeliverUndoJobParam): Unit = transaction.transaction {
apRequestService.apPost(param.inbox, param.undo, userQueryService.findById(param.signer)) apRequestService.apPost(param.inbox, param.undo, userQueryService.findById(param.signer))
} }

View File

@ -1,5 +1,6 @@
package dev.usbharu.hideout.activitypub.service.activity.undo package dev.usbharu.hideout.activitypub.service.activity.undo
import dev.usbharu.hideout.activitypub.domain.model.Block
import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.domain.model.Follow
import dev.usbharu.hideout.activitypub.domain.model.Undo import dev.usbharu.hideout.activitypub.domain.model.Undo
import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcessor
@ -44,6 +45,16 @@ class APUndoProcessor(
return return
} }
"Block" -> {
val block = undo.apObject as Block
val blocker = apUserService.fetchPersonWithEntity(undo.actor, block.apObject).second
val target = userQueryService.findByUrl(block.apObject)
relationshipService.unblock(blocker.id, target.id)
return
}
else -> {} else -> {}
} }
TODO() TODO()

View File

@ -14,7 +14,8 @@ data class DeliverAcceptJobParam(
) )
@Component @Component
class DeliverAcceptJob(private val objectMapper: ObjectMapper) : HideoutJob<DeliverAcceptJobParam, DeliverAcceptJob>() { class DeliverAcceptJob(private val objectMapper: ObjectMapper) :
HideoutJob<DeliverAcceptJobParam, DeliverAcceptJob>("DeliverAcceptJob") {
val accept = string("accept") val accept = string("accept")
val inbox = string("inbox") val inbox = string("inbox")

View File

@ -16,7 +16,7 @@ data class DeliverRejectJobParam(
@Component @Component
class DeliverRejectJob(@Qualifier("activitypub") private val objectMapper: ObjectMapper) : class DeliverRejectJob(@Qualifier("activitypub") private val objectMapper: ObjectMapper) :
HideoutJob<DeliverRejectJobParam, DeliverRejectJob>() { HideoutJob<DeliverRejectJobParam, DeliverRejectJob>("DeliverRejectJob") {
val reject = string("reject") val reject = string("reject")
val inbox = string("inbox") val inbox = string("inbox")
val signer = long("signer") val signer = long("signer")

View File

@ -16,7 +16,7 @@ data class DeliverUndoJobParam(
@Component @Component
class DeliverUndoJob(@Qualifier("activitypub") private val objectMapper: ObjectMapper) : class DeliverUndoJob(@Qualifier("activitypub") private val objectMapper: ObjectMapper) :
HideoutJob<DeliverUndoJobParam, DeliverUndoJob>() { HideoutJob<DeliverUndoJobParam, DeliverUndoJob>("DeliverUndoJob") {
val undo = string("undo") val undo = string("undo")
val inbox = string("inbox") val inbox = string("inbox")

View File

@ -7,7 +7,7 @@ import kjob.core.dsl.ScheduleContext
import kjob.core.job.JobProps import kjob.core.job.JobProps
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
abstract class HideoutJob<out T, out R : HideoutJob<T, R>>(name: String = "") : Job(name) { abstract class HideoutJob<out T, out R : HideoutJob<T, R>>(name: String) : Job(name) {
abstract fun convert(value: @UnsafeVariance T): ScheduleContext<@UnsafeVariance R>.(@UnsafeVariance R) -> Unit abstract fun convert(value: @UnsafeVariance T): ScheduleContext<@UnsafeVariance R>.(@UnsafeVariance R) -> Unit
fun convertUnsafe(props: JobProps<*>): T = convert(props as JobProps<R>) fun convertUnsafe(props: JobProps<*>): T = convert(props as JobProps<R>)
abstract fun convert(props: JobProps<@UnsafeVariance R>): T abstract fun convert(props: JobProps<@UnsafeVariance R>): T

View File

@ -40,6 +40,9 @@ class KJobJobQueueWorkerService(private val jobQueueProcessorList: List<JobProce
MDC.put("x-job-id", this.jobId) MDC.put("x-job-id", this.jobId)
val param = it.convertUnsafe(props) val param = it.convertUnsafe(props)
jobProcessor.process(param) jobProcessor.process(param)
} catch (e: Exception) {
logger.warn("FAILED Execute Job. job name: {} job id: {}", it.name, this.jobId, e)
throw e
} finally { } finally {
MDC.remove("x-job-id") MDC.remove("x-job-id")
} }

View File

@ -3,6 +3,15 @@ package dev.usbharu.hideout.core.service.relationship
interface RelationshipService { interface RelationshipService {
suspend fun followRequest(userId: Long, targetId: Long) suspend fun followRequest(userId: Long, targetId: Long)
suspend fun block(userId: Long, targetId: Long) suspend fun block(userId: Long, targetId: Long)
/**
* フォローリクエストを承認します
* [userId][targetId]からのフォローリクエストを承認します
*
* @param userId 承認操作をするユーザー
* @param targetId 承認するフォローリクエストを送ってきたユーザー
* @param force 強制的にAcceptアクティビティを発行する
*/
suspend fun acceptFollowRequest(userId: Long, targetId: Long, force: Boolean = false) suspend fun acceptFollowRequest(userId: Long, targetId: Long, force: Boolean = false)
suspend fun rejectFollowRequest(userId: Long, targetId: Long) suspend fun rejectFollowRequest(userId: Long, targetId: Long)
suspend fun ignoreFollowRequest(userId: Long, targetId: Long) suspend fun ignoreFollowRequest(userId: Long, targetId: Long)

View File

@ -27,6 +27,8 @@ class RelationshipServiceImpl(
private val apSendUndoService: APSendUndoService private val apSendUndoService: APSendUndoService
) : RelationshipService { ) : RelationshipService {
override suspend fun followRequest(userId: Long, targetId: Long) { override suspend fun followRequest(userId: Long, targetId: Long) {
logger.info("START Follow Request userId: {} targetId: {}", userId, targetId)
val relationship = val relationship =
relationshipRepository.findByUserIdAndTargetUserId(userId, targetId)?.copy(followRequest = true) relationshipRepository.findByUserIdAndTargetUserId(userId, targetId)?.copy(followRequest = true)
?: Relationship( ?: Relationship(
@ -65,7 +67,7 @@ class RelationshipServiceImpl(
if (relationship.following) { if (relationship.following) {
logger.debug("SUCCESS User already follow. userId: {} targetId: {}", userId, targetId) logger.debug("SUCCESS User already follow. userId: {} targetId: {}", userId, targetId)
acceptFollowRequest(userId, targetId, true) acceptFollowRequest(targetId, userId, true)
return return
} }
@ -78,9 +80,10 @@ class RelationshipServiceImpl(
apSendFollowService.sendFollow(SendFollowDto(user, remoteUser)) apSendFollowService.sendFollow(SendFollowDto(user, remoteUser))
} else { } else {
//TODO: フォロー許可制ユーザーを実装したら消す //TODO: フォロー許可制ユーザーを実装したら消す
acceptFollowRequest(userId, targetId) acceptFollowRequest(targetId, userId)
} }
logger.info("SUCCESS Follow Request userId: {} targetId: {}", userId, targetId)
} }
override suspend fun block(userId: Long, targetId: Long) { override suspend fun block(userId: Long, targetId: Long) {
@ -106,9 +109,11 @@ class RelationshipServiceImpl(
} }
override suspend fun acceptFollowRequest(userId: Long, targetId: Long, force: Boolean) { override suspend fun acceptFollowRequest(userId: Long, targetId: Long, force: Boolean) {
val relationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId) logger.info("START Accept follow request userId: {} targetId: {}", userId, targetId)
val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, userId) ?: Relationship( val relationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, userId)
val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId) ?: Relationship(
userId = targetId, userId = targetId,
targetUserId = userId, targetUserId = userId,
following = false, following = false,
@ -267,6 +272,7 @@ class RelationshipServiceImpl(
} }
private suspend fun isRemoteUser(userId: Long): User? { private suspend fun isRemoteUser(userId: Long): User? {
logger.trace("isRemoteUser({})", userId)
val user = try { val user = try {
userQueryService.findById(userId) userQueryService.findById(userId)
} catch (e: FailedToGetResourcesException) { } catch (e: FailedToGetResourcesException) {
@ -274,9 +280,13 @@ class RelationshipServiceImpl(
throw IllegalStateException("User not found.", e) throw IllegalStateException("User not found.", e)
} }
logger.trace("user info {}", user)
if (user.domain == applicationConfig.url.host) { if (user.domain == applicationConfig.url.host) {
logger.trace("user: {} is local user", userId)
return null return null
} }
logger.trace("user: {} is remote user", userId)
return user return user
} }

View File

@ -1,7 +1,9 @@
<configuration> <configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{x-request-id}] %logger{36} - %msg%n</pattern> <pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{x-request-id}] [%X{x-job-id}] %logger{36} -
%msg%n
</pattern>
</encoder> </encoder>
</appender> </appender>
<root level="DEBUG"> <root level="DEBUG">

View File

@ -140,10 +140,10 @@ class RelationshipServiceImplTest {
@Test @Test
fun `followRequest 既にフォローしている場合は念の為フォロー承認を自動で行う`() = runTest { fun `followRequest 既にフォローしている場合は念の為フォロー承認を自動で行う`() = runTest {
val localUser = UserBuilder.localUserOf(domain = "example.com")
whenever(userQueryService.findById(eq(1234))).doReturn(localUser)
val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com")
whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) whenever(userQueryService.findById(eq(1234))).doReturn(remoteUser)
val localUser = UserBuilder.localUserOf(domain = "example.com")
whenever(userQueryService.findById(eq(5678))).doReturn(localUser)
whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn(
Relationship( Relationship(
userId = 1234, userId = 1234,
@ -258,10 +258,10 @@ class RelationshipServiceImplTest {
fun `acceptFollowRequest ローカルユーザーの場合永続化される`() = runTest { fun `acceptFollowRequest ローカルユーザーの場合永続化される`() = runTest {
whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com"))
whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn(
Relationship( Relationship(
userId = 1234, userId = 5678,
targetUserId = 5678, targetUserId = 1234,
following = false, following = false,
blocking = false, blocking = false,
muting = false, muting = false,
@ -274,8 +274,8 @@ class RelationshipServiceImplTest {
verify(relationshipRepository, times(1)).save( verify(relationshipRepository, times(1)).save(
Relationship( Relationship(
userId = 1234, userId = 5678,
targetUserId = 5678, targetUserId = 1234,
following = true, following = true,
blocking = false, blocking = false,
muting = false, muting = false,
@ -294,10 +294,10 @@ class RelationshipServiceImplTest {
val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com")
whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser)
whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn(
Relationship( Relationship(
userId = 1234, userId = 5678,
targetUserId = 5678, targetUserId = 1234,
following = false, following = false,
blocking = false, blocking = false,
muting = false, muting = false,
@ -311,8 +311,8 @@ class RelationshipServiceImplTest {
verify(relationshipRepository, times(1)).save( verify(relationshipRepository, times(1)).save(
eq( eq(
Relationship( Relationship(
userId = 1234, userId = 5678,
targetUserId = 5678, targetUserId = 1234,
following = true, following = true,
blocking = false, blocking = false,
muting = false, muting = false,
@ -334,9 +334,9 @@ class RelationshipServiceImplTest {
@Test @Test
fun `acceptFollowRequest フォローリクエストが存在せずforceがfalseのとき何もしない`() = runTest { fun `acceptFollowRequest フォローリクエストが存在せずforceがfalseのとき何もしない`() = runTest {
whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn(
Relationship( Relationship(
1234, 5678, false, false, false, false, false 5678, 1234, false, false, false, false, false
) )
) )
@ -349,9 +349,9 @@ class RelationshipServiceImplTest {
fun `acceptFollowRequest フォローリクエストが存在せずforceがtrueのときフォローを承認する`() = runTest { fun `acceptFollowRequest フォローリクエストが存在せずforceがtrueのときフォローを承認する`() = runTest {
whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.remoteUserOf(domain = "remote.example.com")) whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.remoteUserOf(domain = "remote.example.com"))
whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn(
Relationship( Relationship(
1234, 5678, false, false, false, false, false 5678, 1234, false, false, false, false, false
) )
) )
@ -360,8 +360,8 @@ class RelationshipServiceImplTest {
verify(relationshipRepository, times(1)).save( verify(relationshipRepository, times(1)).save(
eq( eq(
Relationship( Relationship(
userId = 1234, userId = 5678,
targetUserId = 5678, targetUserId = 1234,
following = true, following = true,
blocking = false, blocking = false,
muting = false, muting = false,
@ -374,9 +374,9 @@ class RelationshipServiceImplTest {
@Test @Test
fun `acceptFollowRequest ブロックしている場合は何もしない`() = runTest { fun `acceptFollowRequest ブロックしている場合は何もしない`() = runTest {
whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn(
Relationship( Relationship(
1234, 5678, false, true, false, true, false 5678, 1234, false, true, false, true, false
) )
) )