refactor: その他の部分でRelationshipServiceに置き換え

This commit is contained in:
usbharu 2023-12-10 15:42:59 +09:00
parent 0f65f242b6
commit fb1022aa41
10 changed files with 21 additions and 211 deletions

View File

@ -7,8 +7,8 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess
import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext
import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.activitypub.service.common.ActivityType
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.query.FollowerQueryService
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.relationship.RelationshipService
import dev.usbharu.hideout.core.service.user.UserService import dev.usbharu.hideout.core.service.user.UserService
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -16,13 +16,13 @@ import org.springframework.stereotype.Service
class ApAcceptProcessor( class ApAcceptProcessor(
transaction: Transaction, transaction: Transaction,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService, private val userService: UserService,
private val userService: UserService private val relationshipService: RelationshipService
) : ) :
AbstractActivityPubProcessor<Accept>(transaction) { AbstractActivityPubProcessor<Accept>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Accept>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Accept>) {
val value = activity.activity.apObject ?: throw IllegalActivityPubObjectException("object is null") val value = activity.activity.apObject
if (value.type.contains("Follow").not()) { if (value.type.contains("Follow").not()) {
logger.warn("FAILED Activity type isn't Follow.") logger.warn("FAILED Activity type isn't Follow.")
@ -37,12 +37,7 @@ class ApAcceptProcessor(
val user = userQueryService.findByUrl(userUrl) val user = userQueryService.findByUrl(userUrl)
val follower = userQueryService.findByUrl(followerUrl) val follower = userQueryService.findByUrl(followerUrl)
if (followerQueryService.alreadyFollow(user.id, follower.id)) { relationshipService.acceptFollowRequest(follower.id, user.id)
logger.debug("END User already follow from ${follower.url} to ${user.url}.")
return
}
userService.follow(user.id, follower.id)
logger.debug("SUCCESS Follow from ${follower.url} to ${user.url}.") logger.debug("SUCCESS Follow from ${follower.url} to ${user.url}.")
} }

View File

@ -6,7 +6,7 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext
import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.activitypub.service.common.ActivityType
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.block.BlockService import dev.usbharu.hideout.core.service.relationship.RelationshipService
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -15,15 +15,15 @@ import org.springframework.stereotype.Service
*/ */
@Service @Service
class BlockActivityPubProcessor( class BlockActivityPubProcessor(
private val blockService: BlockService,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val relationshipService: RelationshipService,
transaction: Transaction transaction: Transaction
) : ) :
AbstractActivityPubProcessor<Block>(transaction) { AbstractActivityPubProcessor<Block>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Block>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Block>) {
val user = userQueryService.findByUrl(activity.activity.actor) val user = userQueryService.findByUrl(activity.activity.actor)
val target = userQueryService.findByUrl(activity.activity.apObject) val target = userQueryService.findByUrl(activity.activity.apObject)
blockService.block(user.id, target.id) relationshipService.block(user.id, target.id)
} }
override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Block override fun isSupported(activityType: ActivityType): Boolean = activityType == ActivityType.Block

View File

@ -2,16 +2,14 @@ package dev.usbharu.hideout.activitypub.service.activity.follow
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import dev.usbharu.hideout.activitypub.domain.model.Accept
import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.domain.model.Follow
import dev.usbharu.hideout.activitypub.service.common.APRequestService
import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.activitypub.service.objects.user.APUserService
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.external.job.ReceiveFollowJob import dev.usbharu.hideout.core.external.job.ReceiveFollowJob
import dev.usbharu.hideout.core.external.job.ReceiveFollowJobParam import dev.usbharu.hideout.core.external.job.ReceiveFollowJobParam
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.job.JobProcessor import dev.usbharu.hideout.core.service.job.JobProcessor
import dev.usbharu.hideout.core.service.user.UserService import dev.usbharu.hideout.core.service.relationship.RelationshipService
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -21,35 +19,21 @@ class APReceiveFollowJobProcessor(
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val apUserService: APUserService, private val apUserService: APUserService,
private val objectMapper: ObjectMapper, private val objectMapper: ObjectMapper,
private val apRequestService: APRequestService, private val relationshipService: RelationshipService
private val userService: UserService
) : ) :
JobProcessor<ReceiveFollowJobParam, ReceiveFollowJob> { JobProcessor<ReceiveFollowJobParam, ReceiveFollowJob> {
override suspend fun process(param: ReceiveFollowJobParam) = transaction.transaction { override suspend fun process(param: ReceiveFollowJobParam) = transaction.transaction {
val person = apUserService.fetchPerson(param.actor, param.targetActor) apUserService.fetchPerson(param.actor, param.targetActor)
val follow = objectMapper.readValue<Follow>(param.follow) val follow = objectMapper.readValue<Follow>(param.follow)
logger.info("START Follow from: {} to {}", param.targetActor, param.actor) logger.info("START Follow from: {} to {}", param.targetActor, param.actor)
val signer = userQueryService.findByUrl(param.targetActor)
val urlString = person.inbox
apRequestService.apPost(
url = urlString,
body = Accept(
name = "Follow",
apObject = follow,
actor = param.targetActor
),
signer = signer
)
val targetEntity = userQueryService.findByUrl(param.targetActor) val targetEntity = userQueryService.findByUrl(param.targetActor)
val followActorEntity = val followActorEntity =
userQueryService.findByUrl(follow.actor) userQueryService.findByUrl(follow.actor)
userService.followRequest(targetEntity.id, followActorEntity.id) relationshipService.followRequest(followActorEntity.id, targetEntity.id)
logger.info("SUCCESS Follow from: {} to: {}", param.targetActor, param.actor) logger.info("SUCCESS Follow from: {} to: {}", param.targetActor, param.actor)
} }

View File

@ -8,6 +8,7 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityType
import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.activitypub.service.objects.user.APUserService
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.relationship.RelationshipService
import dev.usbharu.hideout.core.service.user.UserService import dev.usbharu.hideout.core.service.user.UserService
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -16,7 +17,8 @@ class APUndoProcessor(
transaction: Transaction, transaction: Transaction,
private val apUserService: APUserService, private val apUserService: APUserService,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val userService: UserService private val userService: UserService,
private val relationshipService: RelationshipService
) : ) :
AbstractActivityPubProcessor<Undo>(transaction) { AbstractActivityPubProcessor<Undo>(transaction) {
override suspend fun internalProcess(activity: ActivityPubProcessContext<Undo>) { override suspend fun internalProcess(activity: ActivityPubProcessContext<Undo>) {
@ -34,13 +36,11 @@ class APUndoProcessor(
"Follow" -> { "Follow" -> {
val follow = undo.`object` as Follow val follow = undo.`object` as Follow
if (follow.apObject == null) {
return
}
apUserService.fetchPerson(undo.actor, follow.apObject) apUserService.fetchPerson(undo.actor, follow.apObject)
val follower = userQueryService.findByUrl(undo.actor) val follower = userQueryService.findByUrl(undo.actor)
val target = userQueryService.findByUrl(follow.apObject) val target = userQueryService.findByUrl(follow.apObject)
userService.unfollow(target.id, follower.id)
relationshipService.unfollow(follower.id, target.id)
return return
} }

View File

@ -1,25 +0,0 @@
package dev.usbharu.hideout.core.service.block
/**
* ブロックに関する処理を行います
*
*/
interface BlockService {
/**
* ブロックします
* 実装はリモートユーザーへのブロックの場合ブロックアクティビティを配送するべきです
*
* @param userId ブロックの動作を行ったユーザーid
* @param target ブロック対象のユーザーid
*/
suspend fun block(userId: Long, target: Long)
/**
* ブロックを解除します
* 実装はリモートユーザーへのブロック解除の場合Undo Blockアクティビティを配送するべきです
*
* @param userId ブロック解除の動作を行ったユーザーid
* @param target ブロック解除の対象のユーザーid
*/
suspend fun unblock(userId: Long, target: Long)
}

View File

@ -1,91 +0,0 @@
package dev.usbharu.hideout.core.service.block
import dev.usbharu.hideout.activitypub.domain.model.Follow
import dev.usbharu.hideout.activitypub.domain.model.Reject
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.model.block.Block
import dev.usbharu.hideout.core.domain.model.block.BlockRepository
import dev.usbharu.hideout.core.domain.model.user.UserRepository
import dev.usbharu.hideout.core.external.job.DeliverBlockJob
import dev.usbharu.hideout.core.external.job.DeliverBlockJobParam
import dev.usbharu.hideout.core.query.FollowerQueryService
import dev.usbharu.hideout.core.service.job.JobQueueParentService
import dev.usbharu.hideout.core.service.user.UserService
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
@Service
class BlockServiceImpl(
private val transaction: Transaction,
private val blockRepository: BlockRepository,
private val followerQueryService: FollowerQueryService,
private val userService: UserService,
private val jobQueueParentService: JobQueueParentService,
private val deliverBlockJob: DeliverBlockJob,
private val userRepository: UserRepository,
private val applicationConfig: ApplicationConfig
) :
BlockService {
override suspend fun block(userId: Long, target: Long) {
logger.debug("Block userId: {} → target: {}", userId, target)
val user = userRepository.findById(userId) ?: throw IllegalStateException("Block user was not found.")
val targetEntity = userRepository.findById(target) ?: throw IllegalStateException("Block use was not found.")
if (user.domain != applicationConfig.url.host && targetEntity.domain != applicationConfig.url.host) {
logger.warn("Invalid Block activity. Both user and target are remote users.")
return
}
blockRepository.save(Block(userId, target))
if (followerQueryService.alreadyFollow(userId, target)) {
logger.debug("Unfollow (Block) userId: {} → target: {}", userId, target)
userService.unfollow(userId, target)
}
if (user.domain == applicationConfig.url.host) {
return
}
if (targetEntity.domain == applicationConfig.url.host) {
return
}
val blockJobParam = DeliverBlockJobParam(
user.id,
dev.usbharu.hideout.activitypub.domain.model.Block(
user.url,
"${applicationConfig.url}/block/${user.id}/${targetEntity.id}",
targetEntity.url
),
Reject(
user.url,
"${applicationConfig.url}/reject/${user.id}/${targetEntity.id}",
Follow(
apObject = user.url,
actor = targetEntity.url
)
),
targetEntity.inbox
)
jobQueueParentService.scheduleTypeSafe(deliverBlockJob, blockJobParam)
}
override suspend fun unblock(userId: Long, target: Long) = transaction.transaction {
logger.debug("Unblock userId: {} → target: {}", userId, target)
try {
val block = blockRepository.findByUserIdAndTarget(userId, target)
blockRepository.delete(block)
} catch (e: FailedToGetResourcesException) {
logger.warn("FAILED Unblock userId: {} target: {}", userId, target, e)
}
}
companion object {
private val logger = LoggerFactory.getLogger(BlockServiceImpl::class.java)
}
}

View File

@ -11,23 +11,4 @@ interface UserService {
suspend fun createLocalUser(user: UserCreateDto): User suspend fun createLocalUser(user: UserCreateDto): User
suspend fun createRemoteUser(user: RemoteUserCreateDto): User suspend fun createRemoteUser(user: RemoteUserCreateDto): User
/**
* フォローリクエストを送信する
*
* @param id
* @param followerId
* @return リクエストが成功したか
*/
suspend fun followRequest(id: Long, followerId: Long): Boolean
/**
* フォローする
*
* @param id
* @param followerId
*/
suspend fun follow(id: Long, followerId: Long)
suspend fun unfollow(id: Long, followerId: Long): Boolean
} }

View File

@ -2,12 +2,10 @@ package dev.usbharu.hideout.core.service.user
import dev.usbharu.hideout.activitypub.service.activity.follow.APSendFollowService import dev.usbharu.hideout.activitypub.service.activity.follow.APSendFollowService
import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.config.ApplicationConfig
import dev.usbharu.hideout.core.domain.exception.UserNotFoundException
import dev.usbharu.hideout.core.domain.model.user.User import dev.usbharu.hideout.core.domain.model.user.User
import dev.usbharu.hideout.core.domain.model.user.UserRepository import dev.usbharu.hideout.core.domain.model.user.UserRepository
import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.FollowerQueryService
import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.query.UserQueryService
import dev.usbharu.hideout.core.service.follow.SendFollowDto
import dev.usbharu.hideout.core.service.instance.InstanceService import dev.usbharu.hideout.core.service.instance.InstanceService
import org.jetbrains.exposed.exceptions.ExposedSQLException import org.jetbrains.exposed.exceptions.ExposedSQLException
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -96,38 +94,6 @@ class UserServiceImpl(
} }
} }
// TODO APのフォロー処理を作る
override suspend fun followRequest(id: Long, followerId: Long): Boolean {
val user = userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
val follower = userRepository.findById(followerId) ?: throw UserNotFoundException("$followerId was not found.")
return if (user.domain == applicationConfig.url.host) {
follow(id, followerId)
true
} else {
if (userRepository.findFollowRequestsById(id, followerId)) {
// do-nothing
} else {
apSendFollowService.sendFollow(SendFollowDto(follower, user))
}
false
}
}
override suspend fun follow(id: Long, followerId: Long) {
logger.debug("START Follow id: {} → target: {}", followerId, id)
followerQueryService.appendFollower(id, followerId)
if (userRepository.findFollowRequestsById(id, followerId)) {
logger.debug("Follow request is accepted! ")
userRepository.deleteFollowRequest(id, followerId)
}
logger.debug("SUCCESS Follow id: {} → target: {}", followerId, id)
}
override suspend fun unfollow(id: Long, followerId: Long): Boolean {
followerQueryService.removeFollower(id, followerId)
return false
}
companion object { companion object {
private val logger = LoggerFactory.getLogger(UserServiceImpl::class.java) private val logger = LoggerFactory.getLogger(UserServiceImpl::class.java)
} }

View File

@ -28,7 +28,7 @@ class MastodonAccountApiController(
): ResponseEntity<Relationship> { ): ResponseEntity<Relationship> {
val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt
return ResponseEntity.ok(accountApiService.follow2(principal.getClaim<String>("uid").toLong(), id.toLong())) return ResponseEntity.ok(accountApiService.follow(principal.getClaim<String>("uid").toLong(), id.toLong()))
} }
override suspend fun apiV1AccountsIdGet(id: String): ResponseEntity<Account> = override suspend fun apiV1AccountsIdGet(id: String): ResponseEntity<Account> =

View File

@ -29,7 +29,7 @@ interface AccountApiService {
suspend fun verifyCredentials(userid: Long): CredentialAccount suspend fun verifyCredentials(userid: Long): CredentialAccount
suspend fun registerAccount(userCreateDto: UserCreateDto): Unit suspend fun registerAccount(userCreateDto: UserCreateDto): Unit
suspend fun follow2(loginUser: Long, followTargetUserId: Long): Relationship suspend fun follow(loginUser: Long, followTargetUserId: Long): Relationship
suspend fun account(id: Long): Account suspend fun account(id: Long): Account
suspend fun relationships(userid: Long, id: List<Long>, withSuspended: Boolean): List<Relationship> suspend fun relationships(userid: Long, id: List<Long>, withSuspended: Boolean): List<Relationship>
@ -100,7 +100,7 @@ class AccountApiServiceImpl(
userService.createLocalUser(UserCreateDto(userCreateDto.name, userCreateDto.name, "", userCreateDto.password)) userService.createLocalUser(UserCreateDto(userCreateDto.name, userCreateDto.name, "", userCreateDto.password))
} }
override suspend fun follow2(loginUser: Long, followTargetUserId: Long): Relationship { override suspend fun follow(loginUser: Long, followTargetUserId: Long): Relationship {
relationshipService.followRequest(loginUser, followTargetUserId) relationshipService.followRequest(loginUser, followTargetUserId)
return fetchRelationship(loginUser, followTargetUserId) return fetchRelationship(loginUser, followTargetUserId)