From 8c5c2abb3f0e1cd421dd4ef7b61bdc4346a2cda5 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 7 Sep 2024 16:04:19 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A9=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=82=92=E5=A4=96=E3=81=97=E3=81=9F=E3=81=A8=E3=81=8D?= =?UTF-8?q?=E3=81=AB=E3=83=9B=E3=83=BC=E3=83=A0=E3=82=BF=E3=82=A4=E3=83=A0?= =?UTF-8?q?=E3=83=A9=E3=82=A4=E3=83=B3=E3=81=8B=E3=82=89=E8=87=AA=E5=8B=95?= =?UTF-8?q?=E3=81=A7=E5=A4=96=E3=82=8C=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimelineRelationshipFollowSubscriber.kt | 15 ++---- .../TimelineRelationshipUnfollowSubscriber.kt | 46 +++++++++++++++++++ .../timeline/AddTimelineRelationship.kt | 8 +++- .../timeline/RemoveTimelineRelationship.kt | 5 ++ ...dTimelineRelationshipApplicationService.kt | 23 +++++++++- ...eTimelineRelationshipApplicationService.kt | 39 ++++++++++++++++ .../event/relationship/RelationshipEvent.kt | 3 +- .../domain/model/relationship/Relationship.kt | 12 ++--- .../TimelineRelationship.kt | 15 +++++- .../TimelineRelationshipRepository.kt | 3 ++ 10 files changed, 146 insertions(+), 23 deletions(-) create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/RemoveTimelineRelationship.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipFollowSubscriber.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipFollowSubscriber.kt index 3b3970bd..0707c496 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipFollowSubscriber.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipFollowSubscriber.kt @@ -5,24 +5,20 @@ import dev.usbharu.hideout.core.application.timeline.AddTimelineRelationship import dev.usbharu.hideout.core.application.timeline.UserAddTimelineRelationshipApplicationService import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEvent import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEventBody -import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationship -import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipId import dev.usbharu.hideout.core.domain.model.timelinerelationship.Visible import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository -import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService import org.slf4j.LoggerFactory import org.springframework.stereotype.Component @Component class TimelineRelationshipFollowSubscriber( private val userAddTimelineRelationshipApplicationService: UserAddTimelineRelationshipApplicationService, - private val idGenerateService: IdGenerateService, private val userDetailRepository: UserDetailRepository, private val domainEventSubscriber: DomainEventSubscriber ) : Subscriber { override fun init() { - domainEventSubscriber.subscribe(RelationshipEvent.FOLLOW.eventName) { + domainEventSubscriber.subscribe(RelationshipEvent.ACCEPT_FOLLOW.eventName) { val relationship = it.body.getRelationship() val userDetail = userDetailRepository.findByActorId(relationship.actorId.id) ?: throw InternalServerException("Userdetail ${relationship.actorId} not found by actorid.") @@ -34,12 +30,9 @@ class TimelineRelationshipFollowSubscriber( @Suppress("UnsafeCallOnNullableType") userAddTimelineRelationshipApplicationService.execute( AddTimelineRelationship( - TimelineRelationship( - TimelineRelationshipId(idGenerateService.generateId()), - userDetail.homeTimelineId!!, - relationship.targetActorId, - Visible.FOLLOWERS - ) + userDetail.homeTimelineId!!, + relationship.targetActorId, + Visible.FOLLOWERS ), it.body.principal ) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt new file mode 100644 index 00000000..018420d8 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt @@ -0,0 +1,46 @@ +package dev.usbharu.hideout.core.application.domainevent.subscribers + +import dev.usbharu.hideout.core.application.timeline.RemoveTimelineRelationship +import dev.usbharu.hideout.core.application.timeline.UserRemoveTimelineRelationshipApplicationService +import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEvent +import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEventBody +import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipRepository +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +@Component +class TimelineRelationshipUnfollowSubscriber( + private val domainEventSubscriber: DomainEventSubscriber, + private val userRemoveTimelineRelationshipApplicationService: UserRemoveTimelineRelationshipApplicationService, + private val userDetailRepository: UserDetailRepository, + private val timelineRelationshipRepository: TimelineRelationshipRepository, +) : Subscriber { + override fun init() { + domainEventSubscriber.subscribe(RelationshipEvent.UNFOLLOW.eventName) { + val relationship = it.body.getRelationship() + val userDetail = userDetailRepository.findByActorId(relationship.actorId.id) ?: throw IllegalStateException( + "UserDetail ${relationship.actorId} not found by actorId." + ) + if (userDetail.homeTimelineId == null) { + logger.warn("HomeTimeline for ${userDetail.id} not found.") + return@subscribe + } + + val timelineRelationship = timelineRelationshipRepository.findByTimelineIdAndActorId( + userDetail.homeTimelineId!!, + relationship.targetActorId + ) + ?: throw IllegalStateException("TimelineRelationship ${userDetail.homeTimelineId} to ${relationship.targetActorId} not found by timelineId and ActorId") + + userRemoveTimelineRelationshipApplicationService.execute( + RemoveTimelineRelationship(timelineRelationship.id), + it.body.principal + ) + } + } + + companion object { + private val logger = LoggerFactory.getLogger(TimelineRelationshipUnfollowSubscriber::class.java) + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/AddTimelineRelationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/AddTimelineRelationship.kt index e8c7bda4..21684dda 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/AddTimelineRelationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/AddTimelineRelationship.kt @@ -1,7 +1,11 @@ package dev.usbharu.hideout.core.application.timeline -import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationship +import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.timeline.TimelineId +import dev.usbharu.hideout.core.domain.model.timelinerelationship.Visible data class AddTimelineRelationship( - val timelineRelationship: TimelineRelationship + val timelineId: TimelineId, + val actorId: ActorId, + val visible: Visible ) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/RemoveTimelineRelationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/RemoveTimelineRelationship.kt new file mode 100644 index 00000000..5565ca22 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/RemoveTimelineRelationship.kt @@ -0,0 +1,5 @@ +package dev.usbharu.hideout.core.application.timeline + +import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipId + +data class RemoveTimelineRelationship(val timelineRelationshipId: TimelineRelationshipId) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserAddTimelineRelationshipApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserAddTimelineRelationshipApplicationService.kt index 3809fb3a..d78f03b2 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserAddTimelineRelationshipApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserAddTimelineRelationshipApplicationService.kt @@ -1,15 +1,22 @@ package dev.usbharu.hideout.core.application.timeline +import dev.usbharu.hideout.core.application.exception.PermissionDeniedException import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService import dev.usbharu.hideout.core.application.shared.Transaction import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser +import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository +import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationship +import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipId import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipRepository +import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class UserAddTimelineRelationshipApplicationService( private val timelineRelationshipRepository: TimelineRelationshipRepository, + private val timelineRepository: TimelineRepository, + private val idGenerateService: IdGenerateService, transaction: Transaction ) : LocalUserAbstractApplicationService( @@ -17,7 +24,21 @@ class UserAddTimelineRelationshipApplicationService( logger ) { override suspend fun internalExecute(command: AddTimelineRelationship, principal: LocalUser) { - timelineRelationshipRepository.save(command.timelineRelationship) + val timeline = timelineRepository.findById(command.timelineId) + ?: throw IllegalArgumentException("Timeline ${command.timelineId} not found.") + + if (timeline.userDetailId != principal.userDetailId) { + throw PermissionDeniedException() + } + + timelineRelationshipRepository.save( + TimelineRelationship( + TimelineRelationshipId(idGenerateService.generateId()), + command.timelineId, + command.actorId, + command.visible + ) + ) } companion object { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt new file mode 100644 index 00000000..cdb434bf --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt @@ -0,0 +1,39 @@ +package dev.usbharu.hideout.core.application.timeline + +import dev.usbharu.hideout.core.application.exception.PermissionDeniedException +import dev.usbharu.hideout.core.application.shared.LocalUserAbstractApplicationService +import dev.usbharu.hideout.core.application.shared.Transaction +import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser +import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository +import dev.usbharu.hideout.core.domain.model.timelinerelationship.TimelineRelationshipRepository +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service + +@Service +class UserRemoveTimelineRelationshipApplicationService( + transaction: Transaction, + private val timelineRelationshipRepository: TimelineRelationshipRepository, + private val timelineRepository: TimelineRepository +) : + LocalUserAbstractApplicationService( + transaction, logger + ) { + + override suspend fun internalExecute(command: RemoveTimelineRelationship, principal: LocalUser) { + val timelineRelationship = (timelineRelationshipRepository.findById(command.timelineRelationshipId) + ?: throw IllegalArgumentException("TimelineRelationship ${command.timelineRelationshipId} not found.")) + + val timeline = (timelineRepository.findById(timelineRelationship.timelineId) + ?: throw IllegalArgumentException("Timeline ${timelineRelationship.timelineId} not found.")) + + if (timeline.userDetailId != principal.userDetailId) { + throw PermissionDeniedException() + } + + timelineRelationshipRepository.delete(timelineRelationship) + } + + companion object { + private val logger = LoggerFactory.getLogger(UserRemoveTimelineRelationshipApplicationService::class.java) + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/relationship/RelationshipEvent.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/relationship/RelationshipEvent.kt index 5e26b130..fdd7f4a1 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/relationship/RelationshipEvent.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/relationship/RelationshipEvent.kt @@ -35,7 +35,8 @@ class RelationshipEventBody( } enum class RelationshipEvent(val eventName: String) { - FOLLOW("RelationshipFollow"), + ACCEPT_FOLLOW("RelationshipFollow"), + REJECT_FOLLOW("RelationshipRejectFollow"), UNFOLLOW("RelationshipUnfollow"), BLOCK("RelationshipBlock"), UNBLOCK("RelationshipUnblock"), diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt index af32b48d..93babff4 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt @@ -44,12 +44,6 @@ class Relationship( var mutingFollowRequest: Boolean = mutingFollowRequest private set - fun follow() { - require(blocking.not()) - following = true - addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.FOLLOW)) - } - fun unfollow() { following = false addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.UNFOLLOW)) @@ -96,11 +90,15 @@ class Relationship( } fun acceptFollowRequest() { - follow() + require(blocking.not()) + following = true + addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.ACCEPT_FOLLOW)) followRequesting = false } fun rejectFollowRequest() { + require(followRequesting) + addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.REJECT_FOLLOW)) followRequesting = false } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationship.kt index df2cf099..592630e0 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationship.kt @@ -8,7 +8,20 @@ class TimelineRelationship( val timelineId: TimelineId, val actorId: ActorId, val visible: Visible -) +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as TimelineRelationship + + return id == other.id + } + + override fun hashCode(): Int { + return id.hashCode() + } +} enum class Visible { PUBLIC, diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationshipRepository.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationshipRepository.kt index ccf1c463..5fd8f176 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationshipRepository.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timelinerelationship/TimelineRelationshipRepository.kt @@ -1,10 +1,13 @@ package dev.usbharu.hideout.core.domain.model.timelinerelationship import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.timeline.TimelineId interface TimelineRelationshipRepository { suspend fun save(timelineRelationship: TimelineRelationship): TimelineRelationship suspend fun delete(timelineRelationship: TimelineRelationship) suspend fun findByActorId(actorId: ActorId): List + suspend fun findById(timelineRelationshipId: TimelineRelationshipId): TimelineRelationship? + suspend fun findByTimelineIdAndActorId(timelineId: TimelineId, actorId: ActorId): TimelineRelationship? } From cf0b0017f6a722af962f60c1ef6c575fb9ef78bb Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 7 Sep 2024 16:44:30 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E6=89=80=E6=9C=89=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=82=8B=E3=82=BF=E3=82=A4=E3=83=A0=E3=83=A9?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=81=AE=E4=B8=80=E8=A6=A7=E3=82=92=E5=8F=96?= =?UTF-8?q?=E5=BE=97=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/application/model/Timeline.kt | 23 ++++++++++++ .../core/application/timeline/GetTimelines.kt | 3 ++ .../UserGetTimelinesApplicationService.kt | 37 +++++++++++++++++++ .../model/timeline/TimelineRepository.kt | 6 +++ 4 files changed, 69 insertions(+) create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/Timeline.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetTimelines.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/Timeline.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/Timeline.kt new file mode 100644 index 00000000..8abc559a --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/Timeline.kt @@ -0,0 +1,23 @@ +package dev.usbharu.hideout.core.application.model + +import dev.usbharu.hideout.core.domain.model.timeline.TimelineVisibility + +data class Timeline( + val id: Long, + val userDetailId: Long, + val name: String, + val visibility: TimelineVisibility, + val isSystem: Boolean +) { + companion object { + fun of(timeline: dev.usbharu.hideout.core.domain.model.timeline.Timeline): Timeline { + return Timeline( + timeline.id.value, + timeline.userDetailId.id, + timeline.name.value, + timeline.visibility, + timeline.isSystem + ) + } + } +} diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetTimelines.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetTimelines.kt new file mode 100644 index 00000000..a4233829 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetTimelines.kt @@ -0,0 +1,3 @@ +package dev.usbharu.hideout.core.application.timeline + +data class GetTimelines(val userDetailId: Long) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt new file mode 100644 index 00000000..f6cf8e5c --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt @@ -0,0 +1,37 @@ +package dev.usbharu.hideout.core.application.timeline + +import dev.usbharu.hideout.core.application.model.Timeline +import dev.usbharu.hideout.core.application.shared.AbstractApplicationService +import dev.usbharu.hideout.core.application.shared.Transaction +import dev.usbharu.hideout.core.domain.model.support.principal.Principal +import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository +import dev.usbharu.hideout.core.domain.model.timeline.TimelineVisibility +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service + +@Service +class UserGetTimelinesApplicationService(transaction: Transaction, private val timelineRepository: TimelineRepository) : + AbstractApplicationService>( + transaction, logger + ) { + override suspend fun internalExecute(command: GetTimelines, principal: Principal): List { + + val userDetailId = UserDetailId(command.userDetailId) + + val timelineVisibility = if (userDetailId == principal.userDetailId) { + listOf(TimelineVisibility.PUBLIC, TimelineVisibility.UNLISTED, TimelineVisibility.PRIVATE) + } else { + listOf(TimelineVisibility.PUBLIC) + } + + val timelineList = + timelineRepository.findAllByUserDetailIdAndVisibilityIn(userDetailId, timelineVisibility) + + return timelineList.map { Timeline.of(it) } + } + + companion object { + private val logger = LoggerFactory.getLogger(UserGetTimelinesApplicationService::class.java) + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/TimelineRepository.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/TimelineRepository.kt index 28fdb0f1..c0d4242f 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/TimelineRepository.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/TimelineRepository.kt @@ -1,5 +1,7 @@ package dev.usbharu.hideout.core.domain.model.timeline +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId + interface TimelineRepository { suspend fun save(timeline: Timeline): Timeline suspend fun delete(timeline: Timeline) @@ -7,4 +9,8 @@ interface TimelineRepository { suspend fun findByIds(ids: List): List suspend fun findById(id: TimelineId): Timeline? + suspend fun findAllByUserDetailIdAndVisibilityIn( + userDetailId: UserDetailId, + visibility: List + ): List } From b3a5749b54778966f9302461c6dc99539a25c4c2 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 7 Sep 2024 18:46:49 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=BC=E8=A9=B3=E7=B4=B0=E3=81=8B=E3=82=89=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=AD=E3=83=BC/=E3=82=A2=E3=83=B3=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExposedTimelineRelationshipRepository.kt | 16 +++++++ .../ExposedTimelineRepository.kt | 11 +++++ .../interfaces/web/user/UserController.kt | 43 ++++++++++++++++++- .../main/resources/templates/userById.html | 11 +++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRelationshipRepository.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRelationshipRepository.kt index 5ea3c74d..1ab6986a 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRelationshipRepository.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRelationshipRepository.kt @@ -45,6 +45,22 @@ class ExposedTimelineRelationshipRepository : AbstractRepository(), TimelineRela } } + override suspend fun findById(timelineRelationshipId: TimelineRelationshipId): TimelineRelationship? { + return query { + TimelineRelationships.selectAll().where { + TimelineRelationships.id eq timelineRelationshipId.value + }.singleOrNull()?.toTimelineRelationship() + } + } + + override suspend fun findByTimelineIdAndActorId(timelineId: TimelineId, actorId: ActorId): TimelineRelationship? { + return query { + TimelineRelationships.selectAll().where { + TimelineRelationships.timelineId eq timelineId.value and (TimelineRelationships.actorId eq actorId.id) + }.singleOrNull()?.toTimelineRelationship() + } + } + companion object { private val logger = LoggerFactory.getLogger(ExposedTimelineRelationshipRepository::class.java) } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt index cd2b3f77..9fe9f694 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt @@ -58,6 +58,17 @@ class ExposedTimelineRepository(override val domainEventPublisher: DomainEventPu } } + override suspend fun findAllByUserDetailIdAndVisibilityIn( + userDetailId: UserDetailId, + visibility: List + ): List { + return query { + Timelines.selectAll().where { + Timelines.userDetailId eq userDetailId.id and (Timelines.visibility inList visibility.map { it.name }) + }.map { it.toTimeline() } + } + } + companion object { private val logger = LoggerFactory.getLogger(ExposedTimelineRepository::class.java.name) } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt index c2691652..c2adad5d 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt @@ -3,16 +3,24 @@ package dev.usbharu.hideout.core.interfaces.web.user import dev.usbharu.hideout.core.application.actor.GetActorDetail import dev.usbharu.hideout.core.application.actor.GetActorDetailApplicationService import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService +import dev.usbharu.hideout.core.application.relationship.followrequest.FollowRequest +import dev.usbharu.hideout.core.application.relationship.followrequest.UserFollowRequestApplicationService +import dev.usbharu.hideout.core.application.relationship.get.GetRelationship +import dev.usbharu.hideout.core.application.relationship.get.GetRelationshipApplicationService +import dev.usbharu.hideout.core.application.relationship.unfollow.Unfollow +import dev.usbharu.hideout.core.application.relationship.unfollow.UserUnfollowApplicationService import dev.usbharu.hideout.core.application.timeline.GetUserTimeline import dev.usbharu.hideout.core.application.timeline.GetUserTimelineApplicationService import dev.usbharu.hideout.core.domain.model.support.acct.Acct import dev.usbharu.hideout.core.domain.model.support.page.Page import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous +import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser import dev.usbharu.hideout.core.infrastructure.springframework.SpringSecurityFormLoginPrincipalContextHolder import org.springframework.stereotype.Controller import org.springframework.ui.Model import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestParam @Controller @@ -20,7 +28,11 @@ class UserController( private val getLocalInstanceApplicationService: GetLocalInstanceApplicationService, private val getUserDetailApplicationService: GetActorDetailApplicationService, private val springSecurityFormLoginPrincipalContextHolder: SpringSecurityFormLoginPrincipalContextHolder, - private val getUserTimelineApplicationService: GetUserTimelineApplicationService + private val getUserTimelineApplicationService: GetUserTimelineApplicationService, + private val userFollowRequestApplicationService: UserFollowRequestApplicationService, + private val getActorDetailApplicationService: GetActorDetailApplicationService, + private val userUnfollowApplicationService: UserUnfollowApplicationService, + private val userGetRelationshipApplicationService: GetRelationshipApplicationService ) { @GetMapping("/users/{name}") suspend fun userById( @@ -38,6 +50,15 @@ class UserController( "user", actorDetail ) + val relationship = + if (principal is LocalUser) { + userGetRelationshipApplicationService.execute(GetRelationship(actorDetail.id), principal) + } else { + null + } + + + model.addAttribute("relationship", relationship) model.addAttribute( "userTimeline", getUserTimelineApplicationService.execute( @@ -50,4 +71,24 @@ class UserController( ) return "userById" } + + @PostMapping("/users/{name}/follow") + suspend fun follow(@PathVariable name: String): String { + val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() + + val actorDetail = getActorDetailApplicationService.execute(GetActorDetail(Acct.of(name), null), principal) + userFollowRequestApplicationService.execute(FollowRequest((actorDetail.id)), principal) + + return "redirect:/users/$name" + } + + @PostMapping("/users/{name}/unfollow") + suspend fun unfollow(@PathVariable name: String): String { + val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() + + val actorDetail = getActorDetailApplicationService.execute(GetActorDetail(Acct.of(name), null), principal) + userUnfollowApplicationService.execute(Unfollow((actorDetail.id)), principal) + + return "redirect:/users/$name" + } } diff --git a/hideout-core/src/main/resources/templates/userById.html b/hideout-core/src/main/resources/templates/userById.html index 822c9a3d..cf45d55f 100644 --- a/hideout-core/src/main/resources/templates/userById.html +++ b/hideout-core/src/main/resources/templates/userById.html @@ -19,6 +19,17 @@

+ +
+ +
+
+ +
+
+

From 0c3e69a7e4e856f3c342a0efd5dfbe3b97a0fd16 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 7 Sep 2024 23:23:57 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20unfollow=E6=99=82=E3=81=AB=E3=83=95?= =?UTF-8?q?=E3=82=A9=E3=83=AD=E3=83=BC=E3=83=AA=E3=82=AF=E3=82=A8=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=82=82=E7=A0=B4=E6=A3=84=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 不整合等の解消を容易にするためのため --- .../hideout/core/domain/model/relationship/Relationship.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt index 93babff4..9f7e4f6f 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt @@ -46,7 +46,11 @@ class Relationship( fun unfollow() { following = false - addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.UNFOLLOW)) + followRequesting = false + val relationshipEventFactory = RelationshipEventFactory(this) + addDomainEvent(relationshipEventFactory.createEvent(RelationshipEvent.UNFOLLOW)) + addDomainEvent(relationshipEventFactory.createEvent(RelationshipEvent.UNFOLLOW_REQUEST)) + } fun block() { From cf1327eae40bf515610aae0bd10a4fee288e7196 Mon Sep 17 00:00:00 2001 From: usbharu Date: Sat, 7 Sep 2024 14:29:44 +0000 Subject: [PATCH 5/5] style: fix lint (CI) --- .../TimelineRelationshipUnfollowSubscriber.kt | 2 +- .../UserGetTimelinesApplicationService.kt | 6 +++--- ...oveTimelineRelationshipApplicationService.kt | 17 +++++++++++------ .../domain/model/relationship/Relationship.kt | 1 - .../core/interfaces/web/user/UserController.kt | 1 - 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt index 018420d8..0430a7a2 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/domainevent/subscribers/TimelineRelationshipUnfollowSubscriber.kt @@ -43,4 +43,4 @@ class TimelineRelationshipUnfollowSubscriber( companion object { private val logger = LoggerFactory.getLogger(TimelineRelationshipUnfollowSubscriber::class.java) } -} \ No newline at end of file +} diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt index f6cf8e5c..2ebced42 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserGetTimelinesApplicationService.kt @@ -13,10 +13,10 @@ import org.springframework.stereotype.Service @Service class UserGetTimelinesApplicationService(transaction: Transaction, private val timelineRepository: TimelineRepository) : AbstractApplicationService>( - transaction, logger + transaction, + logger ) { override suspend fun internalExecute(command: GetTimelines, principal: Principal): List { - val userDetailId = UserDetailId(command.userDetailId) val timelineVisibility = if (userDetailId == principal.userDetailId) { @@ -34,4 +34,4 @@ class UserGetTimelinesApplicationService(transaction: Transaction, private val t companion object { private val logger = LoggerFactory.getLogger(UserGetTimelinesApplicationService::class.java) } -} \ No newline at end of file +} diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt index cdb434bf..ee2819bd 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/UserRemoveTimelineRelationshipApplicationService.kt @@ -16,15 +16,20 @@ class UserRemoveTimelineRelationshipApplicationService( private val timelineRepository: TimelineRepository ) : LocalUserAbstractApplicationService( - transaction, logger + transaction, + logger ) { override suspend fun internalExecute(command: RemoveTimelineRelationship, principal: LocalUser) { - val timelineRelationship = (timelineRelationshipRepository.findById(command.timelineRelationshipId) - ?: throw IllegalArgumentException("TimelineRelationship ${command.timelineRelationshipId} not found.")) + val timelineRelationship = ( + timelineRelationshipRepository.findById(command.timelineRelationshipId) + ?: throw IllegalArgumentException("TimelineRelationship ${command.timelineRelationshipId} not found.") + ) - val timeline = (timelineRepository.findById(timelineRelationship.timelineId) - ?: throw IllegalArgumentException("Timeline ${timelineRelationship.timelineId} not found.")) + val timeline = ( + timelineRepository.findById(timelineRelationship.timelineId) + ?: throw IllegalArgumentException("Timeline ${timelineRelationship.timelineId} not found.") + ) if (timeline.userDetailId != principal.userDetailId) { throw PermissionDeniedException() @@ -36,4 +41,4 @@ class UserRemoveTimelineRelationshipApplicationService( companion object { private val logger = LoggerFactory.getLogger(UserRemoveTimelineRelationshipApplicationService::class.java) } -} \ No newline at end of file +} diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt index 9f7e4f6f..f1f48851 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt @@ -50,7 +50,6 @@ class Relationship( val relationshipEventFactory = RelationshipEventFactory(this) addDomainEvent(relationshipEventFactory.createEvent(RelationshipEvent.UNFOLLOW)) addDomainEvent(relationshipEventFactory.createEvent(RelationshipEvent.UNFOLLOW_REQUEST)) - } fun block() { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt index c2adad5d..a7d8a900 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt @@ -57,7 +57,6 @@ class UserController( null } - model.addAttribute("relationship", relationship) model.addAttribute( "userTimeline",