From bbc91ab9816ab5af670393219dc4e7565607ccd5 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Fri, 8 Dec 2023 12:22:08 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20BlockService=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/core/domain/model/block/Block.kt | 6 ++ .../domain/model/block/BlockRepository.kt | 7 ++ .../exposedrepository/BlockRepositoryImpl.kt | 53 ++++++++++++ .../core/service/block/BlockService.kt | 6 ++ .../core/service/block/BlockServiceImpl.kt | 84 +++++++++++++++++++ 5 files changed, 156 insertions(+) create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/Block.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/BlockRepository.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/BlockRepositoryImpl.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockService.kt create mode 100644 src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockServiceImpl.kt diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/Block.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/Block.kt new file mode 100644 index 00000000..a2ddf940 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/Block.kt @@ -0,0 +1,6 @@ +package dev.usbharu.hideout.core.domain.model.block + +data class Block( + val userId: Long, + val target: Long +) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/BlockRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/BlockRepository.kt new file mode 100644 index 00000000..a847bb4a --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/block/BlockRepository.kt @@ -0,0 +1,7 @@ +package dev.usbharu.hideout.core.domain.model.block + +interface BlockRepository { + suspend fun save(block: Block): Block + suspend fun delete(block: Block) + suspend fun findByUserIdAndTarget(userId: Long, target: Long): Block +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/BlockRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/BlockRepositoryImpl.kt new file mode 100644 index 00000000..c3d60ea9 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/BlockRepositoryImpl.kt @@ -0,0 +1,53 @@ +package dev.usbharu.hideout.core.infrastructure.exposedrepository + +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.util.singleOr +import org.jetbrains.exposed.dao.id.LongIdTable +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.deleteWhere +import org.jetbrains.exposed.sql.insert +import org.jetbrains.exposed.sql.select +import org.springframework.stereotype.Repository + +@Repository +class BlockRepositoryImpl : BlockRepository { + override suspend fun save(block: Block): Block { + Blocks.insert { + it[userId] = block.userId + it[target] = block.target + } + return block + } + + override suspend fun delete(block: Block) { + Blocks.deleteWhere { Blocks.userId eq block.userId and (Blocks.target eq block.target) } + } + + override suspend fun findByUserIdAndTarget(userId: Long, target: Long): Block { + val singleOr = Blocks + .select { Blocks.userId eq userId and (Blocks.target eq target) } + .singleOr { + FailedToGetResourcesException( + "userId: $userId target: $target is duplicate or not exist.", + it + ) + } + + return Block( + singleOr[Blocks.userId], + singleOr[Blocks.target] + ) + } +} + +object Blocks : LongIdTable("blocks") { + val userId = long("user_id").references(Users.id).index() + val target = long("target").references(Users.id) + + init { + uniqueIndex(userId, target) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockService.kt new file mode 100644 index 00000000..8988a15d --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockService.kt @@ -0,0 +1,6 @@ +package dev.usbharu.hideout.core.service.block + +interface BlockService { + suspend fun block(userId: Long, target: Long) + suspend fun unblock(userId: Long, target: Long) +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockServiceImpl.kt new file mode 100644 index 00000000..bc0eef96 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/block/BlockServiceImpl.kt @@ -0,0 +1,84 @@ +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): Unit = transaction.transaction { + logger.debug("Block userId: {} → target: {}", userId, target) + blockRepository.save(Block(userId, target)) + if (followerQueryService.alreadyFollow(userId, target)) { + logger.debug("Unfollow (Block) userId: {} → target: {}", userId, target) + userService.unfollow(userId, target) + } + + val user = userRepository.findById(userId) ?: throw IllegalStateException("Block user was not found.") + + if (user.domain == applicationConfig.url.host) { + return@transaction + } + + val target = userRepository.findById(target) ?: throw IllegalStateException("Block use was not found.") + + if (target.domain == applicationConfig.url.host) { + return@transaction + } + + val blockJobParam = DeliverBlockJobParam( + user.id, + dev.usbharu.hideout.activitypub.domain.model.Block( + user.url, + "${applicationConfig.url}/block/${user.id}/${target.id}", + target.url + ), + Reject( + user.url, + "${applicationConfig.url}/reject/${user.id}/${target.id}", + Follow( + apObject = user.url, + actor = target.url + ) + ), + target.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) + } +}