feat: ドメイン層に認可的なものを追加

This commit is contained in:
usbharu 2024-06-08 16:37:57 +09:00
parent 86daf1041b
commit 54e3af2253
15 changed files with 302 additions and 153 deletions

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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<UpdateLocalNote, Unit>(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)
}
}

View File

@ -19,3 +19,7 @@ package dev.usbharu.hideout.core.application.shared
interface CommandExecutor {
val executor: String
}
interface UserDetailGettableCommandExecutor : CommandExecutor {
val userDetailId: Long
}

View File

@ -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"),

View File

@ -52,8 +52,18 @@ class Actor(
moveTo: ActorId? = null,
emojiIds: Set<EmojiId>,
deleted: Boolean,
roles: Set<Role>,
) : DomainEventStorable() {
var roles = roles
private set
fun setRole(roles: Set<Role>, actor: Actor) {
require(actor.roles.contains(Role.ADMINISTRATOR).not())
this.roles = roles
}
var suspend = suspend
set(value) {
if (field != value && value) {

View File

@ -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
}

View File

@ -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<MediaId>,
visibleActors: Set<ActorId> = emptySet(),
hide: Boolean = false,
moveTo: PostId? = null,
visibleActors: Set<ActorId>,
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<ActorId>, 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<MediaId>) {
fun addMediaIds(mediaIds: List<MediaId>, 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<MediaId>, emojis: List<EmojiId>, visibleActors: Set<ActorId>): 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<ActorId> = 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,
}
}
}

View File

@ -16,8 +16,8 @@
package dev.usbharu.hideout.core.domain.shared.domainevent
abstract class DomainEventBody(val map: Map<String, Any>) {
fun toMap(): Map<String, Any> {
abstract class DomainEventBody(val map: Map<String, Any?>) {
fun toMap(): Map<String, Any?> {
return map
}
}

View File

@ -58,7 +58,8 @@ class ActorResultRowMapper : ResultRowMapper<Actor> {
.filter { it.isNotEmpty() }
.map { EmojiId(it.toLong()) }
.toSet(),
deleted = resultRow[Actors.deleted]
deleted = resultRow[Actors.deleted],
roles = emptySet()
)
}
}

View File

@ -39,26 +39,25 @@ class PostQueryMapper(private val postResultRowMapper: ResultRowMapper<Post>) :
.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()
}
}
}

View File

@ -60,7 +60,8 @@ class ActorFactoryImpl(
lastPostAt = null,
suspend = false,
emojiIds = emptySet(),
deleted = false
deleted = false,
roles = emptySet()
)
}
}

View File

@ -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,
)
}
}

View File

@ -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()
)
}
}

View File

@ -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<IllegalArgumentException> {
post.visibility = Visibility.PUBLIC
post.setVisibility(Visibility.PUBLIC, actor)
}
assertThrows<IllegalArgumentException> {
post.visibility = Visibility.UNLISTED
post.setVisibility(Visibility.UNLISTED, actor)
}
assertThrows<IllegalArgumentException> {
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<IllegalArgumentException> {
post.visibility = Visibility.DIRECT
post.setVisibility(Visibility.DIRECT, actor)
}
assertThrows<IllegalArgumentException> {
post.visibility = Visibility.UNLISTED
post.setVisibility(Visibility.UNLISTED, actor)
}
assertThrows<IllegalArgumentException> {
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<IllegalArgumentException> {
post.visibility = Visibility.DIRECT
post.setVisibility(Visibility.DIRECT, actor)
}
assertThrows<IllegalArgumentException> {
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<IllegalArgumentException> {
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<IllegalArgumentException> {
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<IllegalArgumentException> {
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<IllegalArgumentException> {
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<IllegalArgumentException> {
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<IllegalArgumentException> {
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)
}
}