From 54e3af2253869da49e77743453968ae18da9737c Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 8 Jun 2024 16:37:57 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=83=89=E3=83=A1=E3=82=A4=E3=83=B3?= =?UTF-8?q?=E5=B1=A4=E3=81=AB=E8=AA=8D=E5=8F=AF=E7=9A=84=E3=81=AA=E3=82=82?= =?UTF-8?q?=E3=81=AE=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/DeleteLocalPostApplicationService.kt | 14 +- .../RegisterLocalPostApplicationService.kt | 22 ++- .../post/UpdateLocalNoteApplicationService.kt | 37 ++-- .../application/shared/CommandExecutor.kt | 4 + .../core/domain/event/post/PostEvent.kt | 7 +- .../hideout/core/domain/model/actor/Actor.kt | 10 ++ .../hideout/core/domain/model/actor/Role.kt | 21 +++ .../hideout/core/domain/model/post/Post.kt | 169 +++++++++++++----- .../shared/domainevent/DomainEventBody.kt | 4 +- .../exposed/ActorResultRowMapper.kt | 3 +- .../infrastructure/exposed/PostQueryMapper.kt | 29 ++- .../factory/ActorFactoryImpl.kt | 3 +- .../infrastructure/factory/PostFactoryImpl.kt | 31 ++-- .../domain/model/actor/TestActorFactory.kt | 3 +- .../core/domain/model/post/PostTest.kt | 98 +++++----- 15 files changed, 302 insertions(+), 153 deletions(-) create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Role.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/DeleteLocalPostApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/DeleteLocalPostApplicationService.kt index b470ce4d..971f0f7b 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/DeleteLocalPostApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/DeleteLocalPostApplicationService.kt @@ -16,15 +16,23 @@ package dev.usbharu.hideout.core.application.post +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.post.PostId import dev.usbharu.hideout.core.domain.model.post.PostRepository +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository import org.springframework.stereotype.Service @Service -class DeleteLocalPostApplicationService(private val postRepository: PostRepository) { - suspend fun delete(postId: Long) { +class DeleteLocalPostApplicationService( + private val postRepository: PostRepository, + private val userDetailRepository: UserDetailRepository, + private val actorRepository: ActorRepository, +) { + suspend fun delete(postId: Long, userDetailId: Long) { val findById = postRepository.findById(PostId(postId))!! - findById.delete() + val user = userDetailRepository.findById(userDetailId)!! + val actor = actorRepository.findById(user.actorId)!! + findById.delete(actor) postRepository.save(findById) } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/RegisterLocalPostApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/RegisterLocalPostApplicationService.kt index bb67bad9..88a6e869 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/RegisterLocalPostApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/RegisterLocalPostApplicationService.kt @@ -47,15 +47,19 @@ class RegisterLocalPostApplicationService( val actorId = (userDetailRepository.findById(command.userDetailId) ?: throw IllegalStateException("actor not found")).actorId - val post = postFactory.createLocal(actorId, - actorRepository.findById(actorId)!!.name, - command.overview?.let { PostOverview(it) }, - command.content, - command.visibility, - command.repostId?.let { PostId(it) }, - command.replyId?.let { PostId(it) }, - command.sensitive, - command.mediaIds.map { MediaId(it) }) + val actor = actorRepository.findById(actorId)!! + + val post = postFactory.createLocal( + actor = actor, + actorName = actor.name, + overview = command.overview?.let { PostOverview(it) }, + content = command.content, + visibility = command.visibility, + repostId = command.repostId?.let { PostId(it) }, + replyId = command.replyId?.let { PostId(it) }, + sensitive = command.sensitive, + mediaIds = command.mediaIds.map { MediaId(it) }, + ) postRepository.save(post) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/UpdateLocalNoteApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/UpdateLocalNoteApplicationService.kt index 0348c80f..7a885791 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/UpdateLocalNoteApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/post/UpdateLocalNoteApplicationService.kt @@ -16,30 +16,45 @@ package dev.usbharu.hideout.core.application.post +import dev.usbharu.hideout.core.application.shared.AbstractApplicationService +import dev.usbharu.hideout.core.application.shared.CommandExecutor import dev.usbharu.hideout.core.application.shared.Transaction +import dev.usbharu.hideout.core.application.shared.UserDetailGettableCommandExecutor +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.media.MediaId import dev.usbharu.hideout.core.domain.model.post.PostId import dev.usbharu.hideout.core.domain.model.post.PostOverview import dev.usbharu.hideout.core.domain.model.post.PostRepository +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository import dev.usbharu.hideout.core.infrastructure.factory.PostContentFactoryImpl +import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class UpdateLocalNoteApplicationService( - private val transaction: Transaction, + transaction: Transaction, private val postRepository: PostRepository, private val postContentFactoryImpl: PostContentFactoryImpl, -) { - suspend fun update(updateLocalNote: UpdateLocalNote) { - transaction.transaction { - val post = postRepository.findById(PostId(updateLocalNote.postId))!! + private val userDetailRepository: UserDetailRepository, + private val actorRepository: ActorRepository, +) : AbstractApplicationService(transaction, logger) { - post.content = postContentFactoryImpl.create(updateLocalNote.content) - post.overview = updateLocalNote.overview?.let { PostOverview(it) } - post.addMediaIds(updateLocalNote.mediaIds.map { MediaId(it) }) - post.sensitive = updateLocalNote.sensitive + override suspend fun internalExecute(command: UpdateLocalNote, executor: CommandExecutor) { + require(executor is UserDetailGettableCommandExecutor) - postRepository.save(post) - } + val userDetail = userDetailRepository.findById(executor.userDetailId)!! + val actor = actorRepository.findById(userDetail.actorId)!! + val post = postRepository.findById(PostId(command.postId))!! + + post.setContent(postContentFactoryImpl.create(command.content), actor) + post.setOverview(command.overview?.let { PostOverview(it) }, actor) + post.addMediaIds(command.mediaIds.map { MediaId(it) }, actor) + post.setSensitive(command.sensitive, actor) + + postRepository.save(post) + } + + companion object { + private val logger = LoggerFactory.getLogger(UpdateLocalNoteApplicationService::class.java) } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/shared/CommandExecutor.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/shared/CommandExecutor.kt index d022254f..9d530133 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/shared/CommandExecutor.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/shared/CommandExecutor.kt @@ -18,4 +18,8 @@ package dev.usbharu.hideout.core.application.shared interface CommandExecutor { val executor: String +} + +interface UserDetailGettableCommandExecutor : CommandExecutor { + val userDetailId: Long } \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/post/PostEvent.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/post/PostEvent.kt index 1ae9ddb9..ad0fd36f 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/post/PostEvent.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/event/post/PostEvent.kt @@ -16,20 +16,21 @@ package dev.usbharu.hideout.core.domain.event.post +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEvent import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventBody -class PostDomainEventFactory(private val post: Post) { +class PostDomainEventFactory(private val post: Post, private val actor: Actor? = null) { fun createEvent(postEvent: PostEvent): DomainEvent { return DomainEvent.create( postEvent.eventName, - PostEventBody(post) + PostEventBody(post, actor) ) } } -class PostEventBody(post: Post) : DomainEventBody(mapOf("post" to post)) +class PostEventBody(post: Post, actor: Actor?) : DomainEventBody(mapOf("post" to post, "actor" to actor)) enum class PostEvent(val eventName: String) { delete("PostDelete"), diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt index 8d13c8e6..cbbb29db 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt @@ -52,8 +52,18 @@ class Actor( moveTo: ActorId? = null, emojiIds: Set, deleted: Boolean, + roles: Set, ) : DomainEventStorable() { + var roles = roles + private set + + fun setRole(roles: Set, actor: Actor) { + require(actor.roles.contains(Role.ADMINISTRATOR).not()) + + this.roles = roles + } + var suspend = suspend set(value) { if (field != value && value) { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Role.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Role.kt new file mode 100644 index 00000000..ee12ee08 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Role.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dev.usbharu.hideout.core.domain.model.actor + +enum class Role { + LOCAL, MODERATOR, ADMINISTRATOR, REMOTE +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt index 80099fc8..9f932dbf 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt @@ -18,9 +18,12 @@ package dev.usbharu.hideout.core.domain.model.post import dev.usbharu.hideout.core.domain.event.post.PostDomainEventFactory import dev.usbharu.hideout.core.domain.event.post.PostEvent +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.actor.Role import dev.usbharu.hideout.core.domain.model.emoji.EmojiId import dev.usbharu.hideout.core.domain.model.media.MediaId +import dev.usbharu.hideout.core.domain.model.post.Post.Companion.Action.* import dev.usbharu.hideout.core.domain.shared.domainevent.DomainEventStorable import java.net.URI import java.time.Instant @@ -28,7 +31,7 @@ import java.time.Instant class Post( val id: PostId, actorId: ActorId, - overview: PostOverview? = null, + overview: PostOverview?, content: PostContent, val createdAt: Instant, visibility: Visibility, @@ -39,13 +42,12 @@ class Post( val apId: URI, deleted: Boolean, mediaIds: List, - visibleActors: Set = emptySet(), - hide: Boolean = false, - moveTo: PostId? = null, + visibleActors: Set, + hide: Boolean, + moveTo: PostId?, ) : DomainEventStorable() { - var actorId = actorId - private set + val actorId = actorId get() { if (deleted) { return ActorId.ghost @@ -54,27 +56,35 @@ class Post( } var visibility = visibility - set(value) { - require(visibility != Visibility.DIRECT) - require(value != Visibility.DIRECT) - require(field.ordinal >= value.ordinal) + private set - require(deleted.not()) + fun setVisibility(visibility: Visibility, actor: Actor) { - if (field != value) { - addDomainEvent(PostDomainEventFactory(this).createEvent(PostEvent.update)) - } - field = value + require(isAllow(actor, UPDATE, this)) + require(this.visibility != Visibility.DIRECT) + require(visibility != Visibility.DIRECT) + require(this.visibility.ordinal >= visibility.ordinal) + + require(deleted.not()) + + if (this.visibility != visibility) { + addDomainEvent(PostDomainEventFactory(this, actor).createEvent(PostEvent.update)) } + this.visibility = visibility + } var visibleActors = visibleActors - set(value) { - require(deleted.not()) - if (visibility == Visibility.DIRECT) { - addDomainEvent(PostDomainEventFactory(this).createEvent(PostEvent.update)) - field = field.plus(value) - } + private set + + fun setVisibleActors(visibleActors: Set, actor: Actor) { + + require(isAllow(actor, UPDATE, this)) + require(deleted.not()) + if (visibility == Visibility.DIRECT) { + addDomainEvent(PostDomainEventFactory(this, actor).createEvent(PostEvent.update)) + this.visibleActors = this.visibleActors.plus(visibleActors) } + } var content = content get() { @@ -83,13 +93,16 @@ class Post( } return field } - set(value) { - require(deleted.not()) - if (field != value) { - addDomainEvent(PostDomainEventFactory(this).createEvent(PostEvent.update)) - } - field = value + private set + + fun setContent(content: PostContent, actor: Actor) { + require(isAllow(actor, UPDATE, this)) + require(deleted.not()) + if (this.content != content) { + addDomainEvent(PostDomainEventFactory(this, actor).createEvent(PostEvent.update)) } + this.content = content + } var overview = overview get() { @@ -98,22 +111,28 @@ class Post( } return field } - set(value) { - require(deleted.not()) - if (field != value) { - addDomainEvent(PostDomainEventFactory(this).createEvent(PostEvent.update)) - } - field = value + private set + + fun setOverview(overview: PostOverview?, actor: Actor) { + require(isAllow(actor, UPDATE, this)) + require(deleted.not()) + if (this.overview != overview) { + addDomainEvent(PostDomainEventFactory(this, actor).createEvent(PostEvent.update)) } + this.overview = overview + } var sensitive = sensitive - set(value) { - require(deleted.not()) - if (field != value) { - addDomainEvent(PostDomainEventFactory(this).createEvent(PostEvent.update)) - } - field = value + private set + + fun setSensitive(sensitive: Boolean, actor: Actor) { + isAllow(actor, UPDATE, this) + require(deleted.not()) + if (this.sensitive != sensitive) { + addDomainEvent(PostDomainEventFactory(this, actor).createEvent(PostEvent.update)) } + this.sensitive = sensitive + } val text: String get() { @@ -140,18 +159,20 @@ class Post( } private set - fun addMediaIds(mediaIds: List) { + fun addMediaIds(mediaIds: List, actor: Actor) { + require(isAllow(actor, UPDATE, this)) require(deleted.not()) - addDomainEvent(PostDomainEventFactory(this).createEvent(PostEvent.update)) + addDomainEvent(PostDomainEventFactory(this, actor).createEvent(PostEvent.update)) this.mediaIds = this.mediaIds.plus(mediaIds).distinct() } var deleted = deleted private set - fun delete() { + fun delete(actor: Actor) { + isAllow(actor, DELETE, this) if (deleted.not()) { - addDomainEvent(PostDomainEventFactory(this).createEvent(PostEvent.delete)) + addDomainEvent(PostDomainEventFactory(this, actor).createEvent(PostEvent.delete)) content = PostContent.empty overview = null mediaIds = emptyList() @@ -185,7 +206,8 @@ class Post( var moveTo = moveTo private set - fun moveTo(moveTo: PostId) { + fun moveTo(moveTo: PostId, actor: Actor) { + require(isAllow(actor, MOVE, this)) require(this.moveTo == null) this.moveTo = moveTo } @@ -203,6 +225,27 @@ class Post( return id.hashCode() } + fun reconstructWith(mediaIds: List, emojis: List, visibleActors: Set): Post { + return Post( + id = id, + actorId = actorId, + overview = overview, + content = PostContent(this.content.text, this.content.content, emojis), + createdAt = createdAt, + visibility = visibility, + url = url, + repostId = repostId, + replyId = replyId, + sensitive = sensitive, + apId = apId, + deleted = deleted, + mediaIds = mediaIds, + visibleActors = visibleActors, + hide = hide, + moveTo = moveTo + ) + } + companion object { fun create( id: PostId, @@ -221,14 +264,25 @@ class Post( visibleActors: Set = emptySet(), hide: Boolean = false, moveTo: PostId? = null, + actor: Actor, ): Post { + + require(actor.deleted.not()) + require(actor.moveTo == null) + + val visibility1 = if (actor.suspend && visibility == Visibility.PUBLIC) { + Visibility.UNLISTED + } else { + visibility + } + val post = Post( id, actorId, overview, content, createdAt, - visibility, + visibility1, url, repostId, replyId, @@ -243,5 +297,30 @@ class Post( post.addDomainEvent(PostDomainEventFactory(post).createEvent(PostEvent.create)) return post } + + fun isAllow(actor: Actor, action: Action, resource: Post): Boolean { + return when (action) { + UPDATE -> { + if (actor.deleted) { + return true + } + resource.actorId == actor.id || actor.roles.contains(Role.ADMINISTRATOR) || actor.roles.contains( + Role.MODERATOR + ) + } + + MOVE -> resource.actorId == actor.id && actor.deleted.not() + DELETE -> resource.actorId == actor.id || + actor.roles.contains(Role.ADMINISTRATOR) || + actor.roles.contains(Role.MODERATOR) + + } + } + + enum class Action { + UPDATE, + MOVE, + DELETE, + } } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/shared/domainevent/DomainEventBody.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/shared/domainevent/DomainEventBody.kt index 8a46bb19..808c6bdf 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/shared/domainevent/DomainEventBody.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/shared/domainevent/DomainEventBody.kt @@ -16,8 +16,8 @@ package dev.usbharu.hideout.core.domain.shared.domainevent -abstract class DomainEventBody(val map: Map) { - fun toMap(): Map { +abstract class DomainEventBody(val map: Map) { + fun toMap(): Map { return map } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/ActorResultRowMapper.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/ActorResultRowMapper.kt index 639bd216..3b26139e 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/ActorResultRowMapper.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/ActorResultRowMapper.kt @@ -58,7 +58,8 @@ class ActorResultRowMapper : ResultRowMapper { .filter { it.isNotEmpty() } .map { EmojiId(it.toLong()) } .toSet(), - deleted = resultRow[Actors.deleted] + deleted = resultRow[Actors.deleted], + roles = emptySet() ) } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostQueryMapper.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostQueryMapper.kt index 6a338544..47d72f3c 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostQueryMapper.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostQueryMapper.kt @@ -39,26 +39,25 @@ class PostQueryMapper(private val postResultRowMapper: ResultRowMapper) : .first() .let(postResultRowMapper::map) .apply { - addMediaIds( - it.mapNotNull { resultRow: ResultRow -> + reconstructWith( + mediaIds = it.mapNotNull { resultRow: ResultRow -> resultRow .getOrNull(PostsMedia.mediaId) ?.let { mediaId -> MediaId(mediaId) } - } - ) - content = content.copy(emojiIds = it - .mapNotNull { resultRow: ResultRow -> + }, + emojis = it + .mapNotNull { resultRow: ResultRow -> + resultRow + .getOrNull(PostsEmojis.emojiId) + ?.let { emojiId -> EmojiId(emojiId) } + }, + visibleActors = it.mapNotNull { resultRow: ResultRow -> resultRow - .getOrNull(PostsEmojis.emojiId) - ?.let { emojiId -> EmojiId(emojiId) } - } + .getOrNull(PostsVisibleActors.actorId) + ?.let { actorId -> ActorId(actorId) } + }.toSet() ) - visibleActors = it.mapNotNull { resultRow: ResultRow -> - resultRow - .getOrNull(PostsVisibleActors.actorId) - ?.let { actorId -> ActorId(actorId) } - }.toSet() - clearDomainEvents() + } } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt index b03e208a..09ba2411 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt @@ -60,7 +60,8 @@ class ActorFactoryImpl( lastPostAt = null, suspend = false, emojiIds = emptySet(), - deleted = false + deleted = false, + roles = emptySet() ) } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/PostFactoryImpl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/PostFactoryImpl.kt index 7ee64d0a..4b1d4b29 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/PostFactoryImpl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/PostFactoryImpl.kt @@ -17,7 +17,7 @@ package dev.usbharu.hideout.core.infrastructure.factory import dev.usbharu.hideout.core.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.actor.ActorName import dev.usbharu.hideout.core.domain.model.media.MediaId import dev.usbharu.hideout.core.domain.model.post.Post @@ -36,7 +36,7 @@ class PostFactoryImpl( private val applicationConfig: ApplicationConfig, ) { suspend fun createLocal( - actorId: ActorId, + actor: Actor, actorName: ActorName, overview: PostOverview?, content: String, @@ -49,19 +49,20 @@ class PostFactoryImpl( val id = idGenerateService.generateId() val url = URI.create(applicationConfig.url.toString() + "/users/" + actorName.name + "/posts/" + id) return Post.create( - PostId(id), - actorId, - overview, - postContentFactoryImpl.create(content), - Instant.now(), - visibility, - url, - repostId, - replyId, - sensitive, - url, - false, - mediaIds, + id = PostId(id), + actorId = actor.id, + overview = overview, + content = postContentFactoryImpl.create(content), + createdAt = Instant.now(), + visibility = visibility, + url = url, + repostId = repostId, + replyId = replyId, + sensitive = sensitive, + apId = url, + deleted = false, + mediaIds = mediaIds, + actor = actor, ) } } diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/actor/TestActorFactory.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/actor/TestActorFactory.kt index c0919feb..4bb92910 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/actor/TestActorFactory.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/actor/TestActorFactory.kt @@ -20,7 +20,7 @@ object TestActorFactory { inbox: URI = URI.create("https://example.com/$id/inbox"), outbox: URI = URI.create("https://example.com/$id/outbox"), uri: URI = URI.create("https://example.com/$id"), - publicKey: ActorPublicKey, + publicKey: ActorPublicKey = ActorPublicKey(""), privateKey: ActorPrivateKey? = null, createdAt: Instant = Instant.now(), keyId: String = "https://example.com/$id#key-id", @@ -65,6 +65,7 @@ object TestActorFactory { moveTo = moveTo, emojiIds = emojiIds, deleted = deleted, + roles = emptySet() ) } } diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/post/PostTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/post/PostTest.kt index f0e4cf1f..5c4f0226 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/post/PostTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/post/PostTest.kt @@ -2,6 +2,8 @@ package dev.usbharu.hideout.core.domain.model.post import dev.usbharu.hideout.core.domain.event.post.PostEvent import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.actor.ActorPublicKey +import dev.usbharu.hideout.core.domain.model.actor.TestActorFactory import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows @@ -29,100 +31,102 @@ class PostTest { fun visibilityがDIRECTのとき変更できない() { val post = TestPostFactory.create(visibility = Visibility.DIRECT) + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + assertThrows { - post.visibility = Visibility.PUBLIC + post.setVisibility(Visibility.PUBLIC, actor) } assertThrows { - post.visibility = Visibility.UNLISTED + post.setVisibility(Visibility.UNLISTED, actor) } assertThrows { - post.visibility = Visibility.FOLLOWERS + post.setVisibility(Visibility.FOLLOWERS, actor) } } @Test fun visibilityを小さくすることはできないPUBLIC() { val post = TestPostFactory.create(visibility = Visibility.PUBLIC) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.visibility = Visibility.DIRECT + post.setVisibility(Visibility.DIRECT, actor) } assertThrows { - post.visibility = Visibility.UNLISTED + post.setVisibility(Visibility.UNLISTED, actor) } assertThrows { - post.visibility = Visibility.FOLLOWERS + post.setVisibility(Visibility.FOLLOWERS, actor) } } @Test fun visibilityを小さくすることはできないUNLISTED() { val post = TestPostFactory.create(visibility = Visibility.UNLISTED) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.visibility = Visibility.DIRECT + post.setVisibility(Visibility.DIRECT, actor) } assertThrows { - post.visibility = Visibility.FOLLOWERS + post.setVisibility(Visibility.FOLLOWERS, actor) } } @Test fun visibilityを小さくすることはできないFOLLOWERS() { val post = TestPostFactory.create(visibility = Visibility.FOLLOWERS) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.visibility = Visibility.DIRECT + post.setVisibility(Visibility.DIRECT, actor) } } @Test fun visibilityをDIRECTにあとからすることはできない() { val post = TestPostFactory.create(visibility = Visibility.DIRECT) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.visibility = Visibility.DIRECT + post.setVisibility(Visibility.DIRECT, actor) } } @Test fun visibilityを大きくすることができるFOLLOWERS() { val post = TestPostFactory.create(visibility = Visibility.FOLLOWERS) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertDoesNotThrow { - post.visibility = Visibility.UNLISTED + post.setVisibility(Visibility.UNLISTED, actor) } val post2 = TestPostFactory.create(visibility = Visibility.FOLLOWERS) assertDoesNotThrow { - post2.visibility = Visibility.PUBLIC + post2.setVisibility(Visibility.PUBLIC, actor) } } @Test fun visibilityを大きくすることができるUNLISTED() { val post = TestPostFactory.create(visibility = Visibility.UNLISTED) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertDoesNotThrow { - post.visibility = Visibility.PUBLIC + post.setVisibility(Visibility.PUBLIC, actor) } } @Test fun deletedがtrueのときvisibilityを変更できない() { val post = TestPostFactory.create(visibility = Visibility.UNLISTED, deleted = true) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.visibility = Visibility.PUBLIC + post.setVisibility(Visibility.PUBLIC, actor) } } @Test fun visibilityが変更されない限りドメインイベントは発生しない() { val post = TestPostFactory.create(visibility = Visibility.UNLISTED) - - post.visibility = Visibility.UNLISTED + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setVisibility(Visibility.UNLISTED, actor) assertEmpty(post) } @@ -130,7 +134,8 @@ class PostTest { @Test fun visibilityが変更されるとupdateイベントが発生する() { val post = TestPostFactory.create(visibility = Visibility.UNLISTED) - post.visibility = Visibility.PUBLIC + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setVisibility(Visibility.PUBLIC, actor) assertContainsEvent(post, PostEvent.update.eventName) } @@ -138,51 +143,51 @@ class PostTest { @Test fun deletedがtrueのときvisibleActorsを変更できない() { val post = TestPostFactory.create(deleted = true) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.visibleActors = setOf(ActorId(100)) + post.setVisibleActors(setOf(ActorId(100)), actor) } } @Test fun ゔvisibilityがDIRECT以外の時visibleActorsを変更できない() { val post = TestPostFactory.create(visibility = Visibility.FOLLOWERS) - - post.visibleActors = setOf(ActorId(100)) + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setVisibleActors(setOf(ActorId(100)), actor) assertEmpty(post) val post2 = TestPostFactory.create(visibility = Visibility.UNLISTED) - post2.visibleActors = setOf(ActorId(100)) + post2.setVisibleActors(setOf(ActorId(100)), actor) assertEmpty(post2) val post3 = TestPostFactory.create(visibility = Visibility.PUBLIC) - post3.visibleActors = setOf(ActorId(100)) + post3.setVisibleActors(setOf(ActorId(100)), actor) assertEmpty(post3) } @Test fun visibilityがDIRECTの時visibleActorsを変更できる() { val post = TestPostFactory.create(visibility = Visibility.DIRECT) - - post.visibleActors = setOf(ActorId(100)) + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setVisibleActors(setOf(ActorId(100)), actor) assertEquals(setOf(ActorId(100)), post.visibleActors) } @Test fun visibleActorsから削除されることはない() { val post = TestPostFactory.create(visibility = Visibility.DIRECT, visibleActors = listOf(100)) - - post.visibleActors = setOf(ActorId(200)) + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setVisibleActors(setOf(ActorId(200)), actor) assertEquals(setOf(ActorId(100), ActorId(200)), post.visibleActors) } @Test fun visibleActorsに追加された時updateイベントが発生する() { val post = TestPostFactory.create(visibility = Visibility.DIRECT) - - post.visibleActors = setOf(ActorId(100)) + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setVisibleActors(setOf(ActorId(100)), actor) assertContainsEvent(post, PostEvent.update.eventName) } @@ -197,17 +202,17 @@ class PostTest { @Test fun deletedがtrueの時contentをセットできない() { val post = TestPostFactory.create(deleted = true) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.content = PostContent("test", "test", emptyList()) + post.setContent(PostContent("test", "test", emptyList()), actor) } } @Test fun contentの内容が変更されたらupdateイベントが発生する() { val post = TestPostFactory.create() - - post.content = PostContent("test", "test", emptyList()) + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setContent(PostContent("test", "test", emptyList()), actor) assertContainsEvent(post, PostEvent.update.eventName) } @@ -228,19 +233,19 @@ class PostTest { @Test fun deletedがtrueのときセットできない() { val post = TestPostFactory.create(deleted = true) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) assertThrows { - post.overview = PostOverview("aaaa") + post.setOverview(PostOverview("aaaa"), actor) } } @Test fun deletedがfalseのときセットできる() { val post = TestPostFactory.create(deleted = false) - + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) val overview = PostOverview("aaaa") assertDoesNotThrow { - post.overview = overview + post.setOverview(overview, actor) } assertEquals(overview, post.overview) @@ -250,11 +255,10 @@ class PostTest { @Test fun overviewの内容が更新されなかった時イベントが発生しない() { val post = TestPostFactory.create(overview = "aaaa") - post.overview = PostOverview("aaaa") + val actor = TestActorFactory.create(id = post.actorId.id, publicKey = ActorPublicKey("")) + post.setOverview(PostOverview("aaaa"), actor) assertEmpty(post) } - - } \ No newline at end of file