mirror of https://github.com/usbharu/Hideout.git
feat: アカウント削除に対応
This commit is contained in:
parent
8a7ff91a95
commit
511288f4bb
|
@ -0,0 +1,11 @@
|
||||||
|
package dev.usbharu.hideout.core.domain.model.deletedActor
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
data class DeletedActor(
|
||||||
|
val id: Long,
|
||||||
|
val name: String,
|
||||||
|
val domain: String,
|
||||||
|
val publicKey: String,
|
||||||
|
val deletedAt: Instant
|
||||||
|
)
|
|
@ -0,0 +1,7 @@
|
||||||
|
package dev.usbharu.hideout.core.domain.model.deletedActor
|
||||||
|
|
||||||
|
interface DeletedActorRepository {
|
||||||
|
suspend fun save(deletedActor: DeletedActor): DeletedActor
|
||||||
|
suspend fun delete(deletedActor: DeletedActor)
|
||||||
|
suspend fun findById(id: Long): DeletedActor
|
||||||
|
}
|
|
@ -28,4 +28,6 @@ interface RelationshipRepository {
|
||||||
* @return 取得された[Relationship] 存在しない場合nullが返ります
|
* @return 取得された[Relationship] 存在しない場合nullが返ります
|
||||||
*/
|
*/
|
||||||
suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship?
|
suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship?
|
||||||
|
|
||||||
|
suspend fun deleteByActorIdOrTargetActorId(actorId: Long, targetActorId: Long)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ class RelationshipRepositoryImpl : RelationshipRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship? {
|
override suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship? {
|
||||||
return Relationships.select {
|
return Relationships.select {
|
||||||
(Relationships.actorId eq actorId)
|
(Relationships.actorId eq actorId)
|
||||||
|
@ -57,6 +58,12 @@ class RelationshipRepositoryImpl : RelationshipRepository {
|
||||||
}.singleOrNull()
|
}.singleOrNull()
|
||||||
?.toRelationships()
|
?.toRelationships()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteByActorIdOrTargetActorId(actorId: Long, targetActorId: Long) {
|
||||||
|
Relationships.deleteWhere {
|
||||||
|
Relationships.actorId.eq(actorId).or(Relationships.targetActorId.eq(targetActorId))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ResultRow.toRelationships(): Relationship = Relationship(
|
fun ResultRow.toRelationships(): Relationship = Relationship(
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package dev.usbharu.hideout.core.infrastructure.exposedquery
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
|
||||||
|
import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor
|
||||||
|
import dev.usbharu.hideout.core.infrastructure.exposedrepository.DeletedActors
|
||||||
|
import dev.usbharu.hideout.core.infrastructure.exposedrepository.toDeletedActor
|
||||||
|
import dev.usbharu.hideout.core.query.DeletedActorQueryService
|
||||||
|
import dev.usbharu.hideout.util.singleOr
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.select
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class DeletedActorQueryServiceImpl : DeletedActorQueryService {
|
||||||
|
override suspend fun findByNameAndDomain(name: String, domain: String): DeletedActor {
|
||||||
|
return DeletedActors
|
||||||
|
.select { DeletedActors.name eq name and (DeletedActors.domain eq domain) }
|
||||||
|
.singleOr {
|
||||||
|
FailedToGetResourcesException("name: $name domain: $domain was not exist or duplicate.", it)
|
||||||
|
}
|
||||||
|
.toDeletedActor()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package dev.usbharu.hideout.core.infrastructure.exposedrepository
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
|
||||||
|
import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor
|
||||||
|
import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActorRepository
|
||||||
|
import dev.usbharu.hideout.util.singleOr
|
||||||
|
import org.jetbrains.exposed.sql.*
|
||||||
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
|
import org.jetbrains.exposed.sql.javatime.timestamp
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class DeletedActorRepositoryImpl : DeletedActorRepository {
|
||||||
|
override suspend fun save(deletedActor: DeletedActor): DeletedActor {
|
||||||
|
val singleOrNull = DeletedActors.select { DeletedActors.id eq deletedActor.id }.singleOrNull()
|
||||||
|
|
||||||
|
if (singleOrNull == null) {
|
||||||
|
DeletedActors.insert {
|
||||||
|
it[DeletedActors.id] = deletedActor.id
|
||||||
|
it[DeletedActors.name] = deletedActor.name
|
||||||
|
it[DeletedActors.domain] = deletedActor.domain
|
||||||
|
it[DeletedActors.publicKey] = deletedActor.publicKey
|
||||||
|
it[DeletedActors.deletedAt] = deletedActor.deletedAt
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DeletedActors.update({ DeletedActors.id eq deletedActor.id }) {
|
||||||
|
it[DeletedActors.name] = deletedActor.name
|
||||||
|
it[DeletedActors.domain] = deletedActor.domain
|
||||||
|
it[DeletedActors.publicKey] = deletedActor.publicKey
|
||||||
|
it[DeletedActors.deletedAt] = deletedActor.deletedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deletedActor
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun delete(deletedActor: DeletedActor) {
|
||||||
|
DeletedActors.deleteWhere { DeletedActors.id eq deletedActor.id }
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun findById(id: Long): DeletedActor {
|
||||||
|
val singleOr = DeletedActors.select { DeletedActors.id eq id }
|
||||||
|
.singleOr { FailedToGetResourcesException("id: $id was not exist or duplicate", it) }
|
||||||
|
|
||||||
|
return deletedActor(singleOr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ResultRow.toDeletedActor(): DeletedActor = deletedActor(this)
|
||||||
|
|
||||||
|
private fun deletedActor(singleOr: ResultRow): DeletedActor {
|
||||||
|
return DeletedActor(
|
||||||
|
singleOr[DeletedActors.id],
|
||||||
|
singleOr[DeletedActors.name],
|
||||||
|
singleOr[DeletedActors.domain],
|
||||||
|
singleOr[DeletedActors.publicKey],
|
||||||
|
singleOr[DeletedActors.deletedAt]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
object DeletedActors : Table("deleted_actors") {
|
||||||
|
val id = long("id")
|
||||||
|
val name = varchar("name", 300)
|
||||||
|
val domain = varchar("domain", 255)
|
||||||
|
val publicKey = varchar("public_key", 10000).uniqueIndex()
|
||||||
|
val deletedAt = timestamp("deleted_at")
|
||||||
|
override val primaryKey: PrimaryKey = PrimaryKey(id)
|
||||||
|
|
||||||
|
init {
|
||||||
|
uniqueIndex(name, domain)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package dev.usbharu.hideout.core.query
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor
|
||||||
|
|
||||||
|
interface DeletedActorQueryService {
|
||||||
|
suspend fun findByNameAndDomain(name: String, domain: String): DeletedActor
|
||||||
|
}
|
|
@ -41,11 +41,17 @@ class PostServiceImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteLocal(post: Post) {
|
override suspend fun deleteLocal(post: Post) {
|
||||||
|
if (post.delted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
reactionRepository.deleteByPostId(post.id)
|
reactionRepository.deleteByPostId(post.id)
|
||||||
postRepository.save(post.delete())
|
postRepository.save(post.delete())
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteRemote(post: Post) {
|
override suspend fun deleteRemote(post: Post) {
|
||||||
|
if (post.delted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
reactionRepository.deleteByPostId(post.id)
|
reactionRepository.deleteByPostId(post.id)
|
||||||
postRepository.save(post.delete())
|
postRepository.save(post.delete())
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,8 @@ interface UserService {
|
||||||
suspend fun createRemoteUser(user: RemoteUserCreateDto): Actor
|
suspend fun createRemoteUser(user: RemoteUserCreateDto): Actor
|
||||||
|
|
||||||
suspend fun updateUser(userId: Long, updateUserDto: UpdateUserDto)
|
suspend fun updateUser(userId: Long, updateUserDto: UpdateUserDto)
|
||||||
|
|
||||||
|
suspend fun deleteRemoteActor(actorId: Long)
|
||||||
|
|
||||||
|
suspend fun deleteLocalUser(userId: Long)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
package dev.usbharu.hideout.core.service.user
|
package dev.usbharu.hideout.core.service.user
|
||||||
|
|
||||||
import dev.usbharu.hideout.application.config.ApplicationConfig
|
import dev.usbharu.hideout.application.config.ApplicationConfig
|
||||||
|
import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
import dev.usbharu.hideout.core.domain.model.actor.Actor
|
||||||
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
import dev.usbharu.hideout.core.domain.model.actor.ActorRepository
|
||||||
|
import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActor
|
||||||
|
import dev.usbharu.hideout.core.domain.model.deletedActor.DeletedActorRepository
|
||||||
|
import dev.usbharu.hideout.core.domain.model.reaction.ReactionRepository
|
||||||
|
import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository
|
||||||
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.UserDetailRepository
|
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
|
||||||
import dev.usbharu.hideout.core.query.ActorQueryService
|
import dev.usbharu.hideout.core.query.ActorQueryService
|
||||||
|
import dev.usbharu.hideout.core.query.DeletedActorQueryService
|
||||||
import dev.usbharu.hideout.core.service.instance.InstanceService
|
import dev.usbharu.hideout.core.service.instance.InstanceService
|
||||||
import org.jetbrains.exposed.exceptions.ExposedSQLException
|
import org.jetbrains.exposed.exceptions.ExposedSQLException
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
@ -21,7 +27,12 @@ class UserServiceImpl(
|
||||||
private val actorBuilder: Actor.UserBuilder,
|
private val actorBuilder: Actor.UserBuilder,
|
||||||
private val applicationConfig: ApplicationConfig,
|
private val applicationConfig: ApplicationConfig,
|
||||||
private val instanceService: InstanceService,
|
private val instanceService: InstanceService,
|
||||||
private val userDetailRepository: UserDetailRepository
|
private val userDetailRepository: UserDetailRepository,
|
||||||
|
private val deletedActorRepository: DeletedActorRepository,
|
||||||
|
private val deletedActorQueryService: DeletedActorQueryService,
|
||||||
|
private val reactionRepository: ReactionRepository,
|
||||||
|
private val relationshipRepository: RelationshipRepository
|
||||||
|
|
||||||
) :
|
) :
|
||||||
UserService {
|
UserService {
|
||||||
|
|
||||||
|
@ -60,6 +71,14 @@ class UserServiceImpl(
|
||||||
@Transactional
|
@Transactional
|
||||||
override suspend fun createRemoteUser(user: RemoteUserCreateDto): Actor {
|
override suspend fun createRemoteUser(user: RemoteUserCreateDto): Actor {
|
||||||
logger.info("START Create New remote user. name: {} url: {}", user.name, user.url)
|
logger.info("START Create New remote user. name: {} url: {}", user.name, user.url)
|
||||||
|
|
||||||
|
try {
|
||||||
|
deletedActorQueryService.findByNameAndDomain(user.name, user.domain)
|
||||||
|
logger.warn("FAILED Deleted actor. user: ${user.name} domain: ${user.domain}")
|
||||||
|
throw IllegalStateException("Cannot create Deleted actor.")
|
||||||
|
} catch (_: FailedToGetResourcesException) {
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("TooGenericExceptionCaught")
|
@Suppress("TooGenericExceptionCaught")
|
||||||
val instance = try {
|
val instance = try {
|
||||||
instanceService.fetchInstance(user.url, user.sharedInbox)
|
instanceService.fetchInstance(user.url, user.sharedInbox)
|
||||||
|
@ -117,6 +136,26 @@ class UserServiceImpl(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteRemoteActor(actorId: Long) {
|
||||||
|
val actor = actorQueryService.findById(actorId)
|
||||||
|
val deletedActor = DeletedActor(
|
||||||
|
actor.id,
|
||||||
|
actor.name,
|
||||||
|
actor.domain,
|
||||||
|
actor.publicKey,
|
||||||
|
Instant.now()
|
||||||
|
)
|
||||||
|
relationshipRepository.deleteByActorIdOrTargetActorId(actorId, actorId)
|
||||||
|
|
||||||
|
reactionRepository.deleteByActorId(actorId)
|
||||||
|
|
||||||
|
deletedActorRepository.save(deletedActor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteLocalUser(userId: Long) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val logger = LoggerFactory.getLogger(UserServiceImpl::class.java)
|
private val logger = LoggerFactory.getLogger(UserServiceImpl::class.java)
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,3 +202,13 @@ create table if not exists relationships
|
||||||
insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at,
|
insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at,
|
||||||
key_id, following, followers, instance, locked)
|
key_id, following, followers, instance, locked)
|
||||||
values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', null, true);
|
values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', null, true);
|
||||||
|
|
||||||
|
create table if not exists deleted_actors
|
||||||
|
(
|
||||||
|
id bigint primary key,
|
||||||
|
"name" varchar(300) not null,
|
||||||
|
domain varchar(255) not null,
|
||||||
|
public_key varchar(10000) not null,
|
||||||
|
deleted_at timestamp not null,
|
||||||
|
unique ("name", domain)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue