This commit is contained in:
usbharu 2024-05-28 00:18:44 +09:00
parent ee8c8d4e14
commit c2e8c0ca1f
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) {
update("ActorUpdate"),
delete("ActorDelete"),
checkUpdate("ActorCheckUpdate"),
move("ActorMove"),
actorSuspend("ActorSuspend"),
actorUnsuspend("ActorUnsuspend"),
}

View File

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

View File

@ -18,6 +18,6 @@ package dev.usbharu.hideout.core.domain.model.actor
interface Actor2Repository {
suspend fun save(actor: Actor2): Actor2
suspend fun deleteById(actor: ActorId)
suspend fun delete(actor: 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
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 {
protected suspend fun create(description: String, emojis: List<EmojiId>): ActorDescription =
ActorDescription(description, emojis)

View File

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

View File

@ -17,32 +17,44 @@
package dev.usbharu.hideout.core.domain.model.userdetails
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,
var password: UserDetailHashedPassword,
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 {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as UserDetail
return actorId == other.actorId
return id == other.id
}
override fun hashCode(): Int {
return actorId.hashCode()
}
companion object {
fun create(
actorId: ActorId,
password: UserDetailHashedPassword,
autoAcceptFolloweeFollowRequest: Boolean = false,
): UserDetail {
return UserDetail(actorId, password, autoAcceptFolloweeFollowRequest)
}
return id.hashCode()
}
}

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
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 org.springframework.stereotype.Service
class DeleteLocalActorApplicationService {
suspend fun delete(actorId: ActorId, executor: ActorId) {
@Service
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
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.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.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.instance.InstanceRepository
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.service.actor.local.LocalActorDomainService
import dev.usbharu.hideout.core.domain.service.userdetail.UserDetailDomainService
@ -37,6 +39,7 @@ class RegisterLocalActorApplicationService(
private val applicationConfig: ApplicationConfig,
private val userDetailDomainService: UserDetailDomainService,
private val userDetailRepository: UserDetailRepository,
private val idGenerateService: IdGenerateService,
) {
suspend fun register(registerLocalActor: RegisterLocalActor) {
transaction.transaction {
@ -54,8 +57,9 @@ class RegisterLocalActorApplicationService(
)
actor2Repository.save(actor)
val userDetail = UserDetail.create(
actor.id,
userDetailDomainService.hashPassword(registerLocalActor.password),
id = UserDetailId(idGenerateService.generateId()),
actorId = actor.id,
password = userDetailDomainService.hashPassword(registerLocalActor.password),
)
userDetailRepository.save(userDetail)

View File

@ -16,13 +16,25 @@
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 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) {
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
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 org.springframework.stereotype.Service
interface UnsuspendLocalActorApplicationService {
suspend fun unsuspend(actorId: ActorId, executor: ActorId)
@Service
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
}
}
}