This commit is contained in:
usbharu 2024-05-28 00:18:44 +09:00
parent 99c27e45c2
commit 6b80d81410
13 changed files with 211 additions and 34 deletions

View File

@ -38,4 +38,8 @@ class ActorEventBody(actor: Actor2) : DomainEventBody(
enum class ActorEvent(val eventName: String) { enum class ActorEvent(val eventName: String) {
update("ActorUpdate"), update("ActorUpdate"),
delete("ActorDelete"), delete("ActorDelete"),
checkUpdate("ActorCheckUpdate"),
move("ActorMove"),
actorSuspend("ActorSuspend"),
actorUnsuspend("ActorUnsuspend"),
} }

View File

@ -17,8 +17,7 @@
package dev.usbharu.hideout.core.domain.model.actor package dev.usbharu.hideout.core.domain.model.actor
import dev.usbharu.hideout.core.domain.event.actor.ActorDomainEventFactory import dev.usbharu.hideout.core.domain.event.actor.ActorDomainEventFactory
import dev.usbharu.hideout.core.domain.event.actor.ActorEvent.delete import dev.usbharu.hideout.core.domain.event.actor.ActorEvent.*
import dev.usbharu.hideout.core.domain.event.actor.ActorEvent.update
import dev.usbharu.hideout.core.domain.model.instance.InstanceId import dev.usbharu.hideout.core.domain.model.instance.InstanceId
import dev.usbharu.hideout.core.domain.model.shared.Domain import dev.usbharu.hideout.core.domain.model.shared.Domain
import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventStorable import dev.usbharu.hideout.core.domain.model.shared.domainevent.DomainEventStorable
@ -38,20 +37,46 @@ class Actor2 private constructor(
val privateKey: ActorPrivateKey? = null, val privateKey: ActorPrivateKey? = null,
val createdAt: Instant, val createdAt: Instant,
val keyId: ActorKeyId, val keyId: ActorKeyId,
val followersEndpoint: URI, val followersEndpoint: URI?,
val followingEndpoint: URI, val followingEndpoint: URI?,
val instance: InstanceId, val instance: InstanceId,
var locked: Boolean, var locked: Boolean,
var followersCount: ActorRelationshipCount?, var followersCount: ActorRelationshipCount?,
var followingCount: ActorRelationshipCount?, var followingCount: ActorRelationshipCount?,
var postsCount: ActorPostsCount, var postsCount: ActorPostsCount,
var lastPostDate: Instant? = null, var lastPostDate: Instant? = null,
var suspend: Boolean, suspend: Boolean,
var lastUpdate: Instant = createdAt,
alsoKnownAs: List<ActorId> = emptyList(),
moveTo: ActorId? = null,
) : DomainEventStorable() { ) : DomainEventStorable() {
val emojis var suspend = suspend
get() = screenName.emojis set(value) {
if (field != value && value) {
addDomainEvent(ActorDomainEventFactory(this).createEvent(actorSuspend))
} else if (field != value && !value) {
addDomainEvent(ActorDomainEventFactory(this).createEvent(actorUnsuspend))
}
field = value
}
var alsoKnownAs = alsoKnownAs
set(value) {
require(value.find { it == id } == null)
field = value.distinct()
}
var moveTo = moveTo
set(value) {
require(moveTo != id)
addDomainEvent(ActorDomainEventFactory(this).createEvent(move))
field = value
}
val emojis
get() = screenName.emojis + description.emojis
var description = description var description = description
set(value) { set(value) {
@ -69,6 +94,10 @@ class Actor2 private constructor(
addDomainEvent(ActorDomainEventFactory(this).createEvent(delete)) addDomainEvent(ActorDomainEventFactory(this).createEvent(delete))
} }
fun checkUpdate() {
addDomainEvent(ActorDomainEventFactory(this).createEvent(checkUpdate))
}
abstract class Actor2Factory { abstract class Actor2Factory {
protected suspend fun create( protected suspend fun create(
id: ActorId, id: ActorId,

View File

@ -18,6 +18,6 @@ package dev.usbharu.hideout.core.domain.model.actor
interface Actor2Repository { interface Actor2Repository {
suspend fun save(actor: Actor2): Actor2 suspend fun save(actor: Actor2): Actor2
suspend fun deleteById(actor: ActorId) suspend fun delete(actor: Actor2)
suspend fun findById(id: ActorId): Actor2? suspend fun findById(id: ActorId): Actor2?
} }

View File

@ -19,7 +19,7 @@ package dev.usbharu.hideout.core.domain.model.actor
import dev.usbharu.hideout.core.domain.model.emoji.EmojiId import dev.usbharu.hideout.core.domain.model.emoji.EmojiId
class ActorDescription private constructor(private val description: String, private val emojis: List<EmojiId>) { class ActorDescription private constructor(val description: String, val emojis: List<EmojiId>) {
abstract class ActorDescriptionFactory { abstract class ActorDescriptionFactory {
protected suspend fun create(description: String, emojis: List<EmojiId>): ActorDescription = protected suspend fun create(description: String, emojis: List<EmojiId>): ActorDescription =
ActorDescription(description, emojis) ActorDescription(description, emojis)

View File

@ -16,8 +16,12 @@
package dev.usbharu.hideout.core.domain.model.post package dev.usbharu.hideout.core.domain.model.post
import dev.usbharu.hideout.core.domain.model.actor.ActorId
interface Post2Repository { interface Post2Repository {
suspend fun save(post: Post2): Post2 suspend fun save(post: Post2): Post2
suspend fun saveAll(posts: List<Post2>): List<Post2>
suspend fun findById(id: PostId): Post2? suspend fun findById(id: PostId): Post2?
suspend fun findByActorId(id: ActorId): List<Post2>
suspend fun deleteById(id: PostId) suspend fun deleteById(id: PostId)
} }

View File

@ -17,32 +17,44 @@
package dev.usbharu.hideout.core.domain.model.userdetails package dev.usbharu.hideout.core.domain.model.userdetails
import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.actor.ActorId
import java.time.Instant
class UserDetail( class UserDetail private constructor(
val id: UserDetailId,
val actorId: ActorId, val actorId: ActorId,
var password: UserDetailHashedPassword, var password: UserDetailHashedPassword,
var autoAcceptFolloweeFollowRequest: Boolean, var autoAcceptFolloweeFollowRequest: Boolean,
var lastMigration: Instant? = null,
) { ) {
companion object {
fun create(
id: UserDetailId,
actorId: ActorId,
password: UserDetailHashedPassword,
autoAcceptFolloweeFollowRequest: Boolean = false,
lastMigration: Instant? = null,
): UserDetail {
return UserDetail(
id,
actorId,
password,
autoAcceptFolloweeFollowRequest,
lastMigration
)
}
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (javaClass != other?.javaClass) return false if (javaClass != other?.javaClass) return false
other as UserDetail other as UserDetail
return actorId == other.actorId return id == other.id
} }
override fun hashCode(): Int { override fun hashCode(): Int {
return actorId.hashCode() return id.hashCode()
}
companion object {
fun create(
actorId: ActorId,
password: UserDetailHashedPassword,
autoAcceptFolloweeFollowRequest: Boolean = false,
): UserDetail {
return UserDetail(actorId, password, autoAcceptFolloweeFollowRequest)
}
} }
} }

View File

@ -0,0 +1,20 @@
/*
* 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.userdetails
@JvmInline
value class UserDetailId(val id: Long)

View File

@ -0,0 +1,35 @@
/*
* 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.service.actor.local
import dev.usbharu.hideout.core.domain.model.actor.Actor2
interface LocalActorMigrationCheckDomainService {
suspend fun canAccountMigration(from: Actor2, to: Actor2): AccountMigrationCheck
}
sealed class AccountMigrationCheck(
val canMigration: Boolean,
) {
class CanAccountMigration : AccountMigrationCheck(true)
class CircularReferences(val message: String) : AccountMigrationCheck(false)
class SelfReferences : AccountMigrationCheck(false)
class AlreadyMoved(val message: String) : AccountMigrationCheck(false)
}

View File

@ -16,10 +16,23 @@
package dev.usbharu.hideout.core.usecase.actor package dev.usbharu.hideout.core.usecase.actor
import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository
import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.actor.ActorId
import org.springframework.stereotype.Service
class DeleteLocalActorApplicationService { @Service
suspend fun delete(actorId: ActorId, executor: ActorId) { class DeleteLocalActorApplicationService(
private val transaction: Transaction,
private val actor2Repository: Actor2Repository,
) {
suspend fun delete(actorId: Long, executor: ActorId) {
transaction.transaction {
val id = ActorId(actorId)
val findById = actor2Repository.findById(id)!!
findById.delete()
actor2Repository.delete(findById)
}
} }
} }

View File

@ -16,10 +16,40 @@
package dev.usbharu.hideout.core.usecase.actor package dev.usbharu.hideout.core.usecase.actor
import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository
import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.actor.ActorId
import dev.usbharu.hideout.core.domain.service.actor.local.AccountMigrationCheck.*
import dev.usbharu.hideout.core.domain.service.actor.local.LocalActorMigrationCheckDomainService
import org.springframework.stereotype.Service
@Service
class MigrationLocalActorApplicationService(
private val transaction: Transaction,
private val actor2Repository: Actor2Repository,
private val localActorMigrationCheckDomainService: LocalActorMigrationCheckDomainService,
) {
suspend fun migration(from: Long, to: Long, executor: ActorId) {
transaction.transaction {
val fromActorId = ActorId(from)
val toActorId = ActorId(to)
val fromActor = actor2Repository.findById(fromActorId)!!
val toActor = actor2Repository.findById(toActorId)!!
val canAccountMigration = localActorMigrationCheckDomainService.canAccountMigration(fromActor, toActor)
when (canAccountMigration) {
is AlreadyMoved -> TODO()
is CanAccountMigration -> {
fromActor.moveTo = toActorId
actor2Repository.save(fromActor)
}
is CircularReferences -> TODO()
is SelfReferences -> TODO()
}
}
class MigrationLocalActorApplicationService {
suspend fun migration(from: ActorId, to: ActorId, executor: ActorId) {
TODO()
} }
} }

View File

@ -18,9 +18,11 @@ package dev.usbharu.hideout.core.usecase.actor
import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.config.ApplicationConfig
import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.application.service.id.IdGenerateService
import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository
import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository import dev.usbharu.hideout.core.domain.model.instance.InstanceRepository
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetail import dev.usbharu.hideout.core.domain.model.userdetails.UserDetail
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
import dev.usbharu.hideout.core.domain.service.actor.local.LocalActorDomainService import dev.usbharu.hideout.core.domain.service.actor.local.LocalActorDomainService
import dev.usbharu.hideout.core.domain.service.userdetail.UserDetailDomainService import dev.usbharu.hideout.core.domain.service.userdetail.UserDetailDomainService
@ -37,6 +39,7 @@ class RegisterLocalActorApplicationService(
private val applicationConfig: ApplicationConfig, private val applicationConfig: ApplicationConfig,
private val userDetailDomainService: UserDetailDomainService, private val userDetailDomainService: UserDetailDomainService,
private val userDetailRepository: UserDetailRepository, private val userDetailRepository: UserDetailRepository,
private val idGenerateService: IdGenerateService,
) { ) {
suspend fun register(registerLocalActor: RegisterLocalActor) { suspend fun register(registerLocalActor: RegisterLocalActor) {
transaction.transaction { transaction.transaction {
@ -54,8 +57,9 @@ class RegisterLocalActorApplicationService(
) )
actor2Repository.save(actor) actor2Repository.save(actor)
val userDetail = UserDetail.create( val userDetail = UserDetail.create(
actor.id, id = UserDetailId(idGenerateService.generateId()),
userDetailDomainService.hashPassword(registerLocalActor.password), actorId = actor.id,
password = userDetailDomainService.hashPassword(registerLocalActor.password),
) )
userDetailRepository.save(userDetail) userDetailRepository.save(userDetail)

View File

@ -16,13 +16,25 @@
package dev.usbharu.hideout.core.usecase.actor package dev.usbharu.hideout.core.usecase.actor
import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository
import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.actor.ActorId
import org.springframework.stereotype.Service
class SuspendLocalActorApplicationService(private val actor2Repository: Actor2Repository) { @Service
class SuspendLocalActorApplicationService(
private val transaction: Transaction,
private val actor2Repository: Actor2Repository,
) {
suspend fun suspend(actorId: Long, executor: ActorId) { suspend fun suspend(actorId: Long, executor: ActorId) {
val findById = actor2Repository.findById(ActorId(actorId))!! transaction.transaction {
val id = ActorId(actorId)
val findById = actor2Repository.findById(id)!!
findById.suspend = true
}
findById.suspend = true
} }
} }

View File

@ -16,8 +16,22 @@
package dev.usbharu.hideout.core.usecase.actor package dev.usbharu.hideout.core.usecase.actor
import dev.usbharu.hideout.application.external.Transaction
import dev.usbharu.hideout.core.domain.model.actor.Actor2Repository
import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.actor.ActorId
import org.springframework.stereotype.Service
interface UnsuspendLocalActorApplicationService { @Service
suspend fun unsuspend(actorId: ActorId, executor: ActorId) class UnsuspendLocalActorApplicationService(
private val transaction: Transaction,
private val actor2Repository: Actor2Repository,
) {
suspend fun unsuspend(actorId: Long, executor: Long) {
transaction.transaction {
val findById = actor2Repository.findById(ActorId(actorId))!!
findById.suspend = false
}
}
} }