From 6eb10b5bd7504ea36067d1228cb3210724d5a971 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:16:45 +0900 Subject: [PATCH 1/4] =?UTF-8?q?refactor:=20Actors=E3=83=86=E3=83=BC?= =?UTF-8?q?=E3=83=96=E3=83=AB=E3=81=AB=E3=83=95=E3=82=A9=E3=83=AD=E3=83=AF?= =?UTF-8?q?=E3=83=BC=E6=95=B0=E6=83=85=E5=A0=B1=E3=81=A8=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E6=95=B0=E6=83=85=E5=A0=B1=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/core/domain/model/actor/Actor.kt | 78 ++++++++++++++----- .../exposed/UserResultRowMapper.kt | 6 +- .../exposedrepository/ActorRepositoryImpl.kt | 13 ++++ .../relationship/RelationshipServiceImpl.kt | 55 ++++++++++--- 4 files changed, 121 insertions(+), 31 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt index 9f0fba72..6c645c45 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt @@ -22,7 +22,11 @@ data class Actor private constructor( val followers: String? = null, val following: String? = null, val instance: Long? = null, - val locked: Boolean + val locked: Boolean, + val followersCount: Int = 0, + val followingCount: Int = 0, + val postsCount: Int = 0, + val lastPostDate: Instant? = null ) { @Component @@ -47,7 +51,11 @@ data class Actor private constructor( following: String? = null, followers: String? = null, instance: Long? = null, - locked: Boolean + locked: Boolean, + followersCount: Int, + followingCount: Int, + postsCount: Int, + lastPostDate: Instant? ): Actor { // idは0未満ではいけない require(id >= 0) { "id must be greater than or equal to 0." } @@ -123,6 +131,18 @@ data class Actor private constructor( "keyId must contain non-blank characters." } + require(postsCount >= 0) { + "postsCount must be greater than or equal to 0" + } + + require(followersCount >= 0) { + "followersCount must be greater than or equal to 0" + } + + require(followingCount >= 0) { + "followingCount must be greater than or equal to 0" + } + return Actor( id = id, name = limitedName, @@ -139,29 +159,47 @@ data class Actor private constructor( followers = followers, following = following, instance = instance, - locked + locked = locked, + followersCount = followersCount, + followingCount = followingCount, + postsCount = postsCount, + lastPostDate = lastPostDate ) } } + fun incrementFollowing(): Actor = this.copy(followingCount = this.followingCount + 1) + + fun decrementFollowing(): Actor = this.copy(followingCount = this.followingCount - 1) + + fun incrementFollowers(): Actor = this.copy(followersCount = this.followersCount + 1) + + fun decrementFollowers(): Actor = this.copy(followersCount = this.followersCount - 1) + + fun incrementPostsCount(): Actor = this.copy(postsCount = this.postsCount + 1) + + fun decrementPostsCount(): Actor = this.copy(postsCount = this.postsCount - 1) + + fun withLastPostAt(lastPostDate: Instant): Actor = this.copy(lastPostDate = lastPostDate) + override fun toString(): String { return "Actor(" + - "id=$id, " + - "name='$name', " + - "domain='$domain', " + - "screenName='$screenName', " + - "description='$description', " + - "inbox='$inbox', " + - "outbox='$outbox', " + - "url='$url', " + - "publicKey='$publicKey', " + - "privateKey=$privateKey, " + - "createdAt=$createdAt, " + - "keyId='$keyId', " + - "followers=$followers, " + - "following=$following, " + - "instance=$instance, " + - "locked=$locked" + - ")" + "id=$id, " + + "name='$name', " + + "domain='$domain', " + + "screenName='$screenName', " + + "description='$description', " + + "inbox='$inbox', " + + "outbox='$outbox', " + + "url='$url', " + + "publicKey='$publicKey', " + + "privateKey=$privateKey, " + + "createdAt=$createdAt, " + + "keyId='$keyId', " + + "followers=$followers, " + + "following=$following, " + + "instance=$instance, " + + "locked=$locked" + + ")" } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserResultRowMapper.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserResultRowMapper.kt index abf8d880..a5b58c60 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserResultRowMapper.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserResultRowMapper.kt @@ -26,7 +26,11 @@ class UserResultRowMapper(private val actorBuilder: Actor.UserBuilder) : ResultR followers = resultRow[Actors.followers], following = resultRow[Actors.following], instance = resultRow[Actors.instance], - locked = resultRow[Actors.locked] + locked = resultRow[Actors.locked], + followingCount = resultRow[Actors.followingCount], + followersCount = resultRow[Actors.followersCount], + postsCount = resultRow[Actors.postsCount], + lastPostDate = resultRow[Actors.lastPostAt], ) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt index 0eb59b59..96ce6409 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt @@ -6,6 +6,7 @@ import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.actor.ActorRepository 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 @@ -35,6 +36,10 @@ class ActorRepositoryImpl( it[followers] = actor.followers it[instance] = actor.instance it[locked] = actor.locked + it[followersCount] = actor.followersCount + it[followingCount] = actor.followingCount + it[postsCount] = actor.postsCount + it[lastPostAt] = actor.lastPostDate } } else { Actors.update({ Actors.id eq actor.id }) { @@ -53,6 +58,10 @@ class ActorRepositoryImpl( it[followers] = actor.followers it[instance] = actor.instance it[locked] = actor.locked + it[followersCount] = actor.followersCount + it[followingCount] = actor.followingCount + it[postsCount] = actor.postsCount + it[lastPostAt] = actor.lastPostDate } } return actor @@ -91,6 +100,10 @@ object Actors : Table("actors") { val followers = varchar("followers", length = 1000).nullable() val instance = long("instance").references(Instance.id).nullable() val locked = bool("locked") + val followingCount = integer("following_count") + val followersCount = integer("followers_count") + val postsCount = integer("posts_count") + val lastPostAt = timestamp("last_post_at").nullable() override val primaryKey: PrimaryKey = PrimaryKey(id) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt index 8b508af0..92e47772 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt @@ -8,6 +8,7 @@ import dev.usbharu.hideout.activitypub.service.activity.undo.APSendUndoService 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.ActorRepository import dev.usbharu.hideout.core.domain.model.relationship.Relationship import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository import dev.usbharu.hideout.core.query.ActorQueryService @@ -24,7 +25,8 @@ class RelationshipServiceImpl( private val apSendBlockService: APSendBlockService, private val apSendAcceptService: ApSendAcceptService, private val apSendRejectService: ApSendRejectService, - private val apSendUndoService: APSendUndoService + private val apSendUndoService: APSendUndoService, + private val actorRepository: ActorRepository ) : RelationshipService { override suspend fun followRequest(actorId: Long, targetId: Long) { logger.info("START Follow Request userId: {} targetId: {}", actorId, targetId) @@ -90,6 +92,15 @@ class RelationshipServiceImpl( override suspend fun block(actorId: Long, targetId: Long) { val relationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId) + + val user = actorQueryService.findById(actorId) + val targetActor = actorQueryService.findById(targetId) + if (relationship?.following == true) { + actorRepository.save(user.decrementFollowing()) + actorRepository.save(targetActor.decrementFollowers()) + } + + val blockedRelationship = relationship ?.copy(blocking = true, followRequest = false, following = false) ?: Relationship( actorId = actorId, targetActorId = targetId, @@ -101,17 +112,26 @@ class RelationshipServiceImpl( ) val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, actorId) + + + + if (inverseRelationship?.following == true) { + actorRepository.save(targetActor.decrementFollowing()) + actorRepository.save(user.decrementFollowers()) + } + + val blockedInverseRelationship = inverseRelationship ?.copy(followRequest = false, following = false) - relationshipRepository.save(relationship) - if (inverseRelationship != null) { - relationshipRepository.save(inverseRelationship) + relationshipRepository.save(blockedRelationship) + if (blockedInverseRelationship != null) { + relationshipRepository.save(blockedInverseRelationship) } val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = actorQueryService.findById(actorId) + apSendBlockService.sendBlock(user, remoteUser) } } @@ -157,13 +177,18 @@ class RelationshipServiceImpl( val copy = relationship.copy(followRequest = false, following = true, blocking = false) + val user = actorQueryService.findById(actorId) + + actorRepository.save(user.incrementFollowers()) + relationshipRepository.save(copy) - val remoteUser = isRemoteUser(targetId) + val remoteActor = actorQueryService.findById(targetId) - if (remoteUser != null) { - val user = actorQueryService.findById(actorId) - apSendAcceptService.sendAcceptFollow(user, remoteUser) + actorRepository.save(remoteActor.incrementFollowing()) + + if (isRemoteActor(remoteActor)) { + apSendAcceptService.sendAcceptFollow(user, remoteActor) } } @@ -216,6 +241,14 @@ class RelationshipServiceImpl( return } + val user = actorQueryService.findById(actorId) + val targetActor = actorQueryService.findById(targetId) + + if (relationship.following) { + actorRepository.save(user.decrementFollowing()) + actorRepository.save(targetActor.decrementFollowers()) + } + if (relationship.following.not()) { logger.warn("SUCCESS User already unfollow. userId: {} targetId: {}", actorId, targetId) return @@ -228,7 +261,7 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = actorQueryService.findById(actorId) + apSendUndoService.sendUndoFollow(user, remoteUser) } } @@ -282,6 +315,8 @@ class RelationshipServiceImpl( relationshipRepository.save(relationship) } + private fun isRemoteActor(actor: Actor): Boolean = actor.domain != applicationConfig.url.host + private suspend fun isRemoteUser(userId: Long): Actor? { logger.trace("isRemoteUser({})", userId) val user = try { From 7f04aec7bfae814de84af1525d92eded4420c9e0 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Thu, 14 Dec 2023 00:55:40 +0900 Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20Mastodon=20API=E3=81=A7Account?= =?UTF-8?q?=E3=81=AE=E7=AE=87=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout/core/domain/model/actor/Actor.kt | 8 +-- .../core/service/post/PostServiceImpl.kt | 24 ++++++- .../exposedquery/AccountQueryServiceImpl.kt | 70 ++++--------------- .../exposedquery/StatusQueryServiceImpl.kt | 10 +-- .../resources/db/migration/V1__Init_DB.sql | 41 ++++++----- 5 files changed, 65 insertions(+), 88 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt index 6c645c45..166f9647 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt @@ -52,10 +52,10 @@ data class Actor private constructor( followers: String? = null, instance: Long? = null, locked: Boolean, - followersCount: Int, - followingCount: Int, - postsCount: Int, - lastPostDate: Instant? + followersCount: Int = 0, + followingCount: Int = 0, + postsCount: Int = 0, + lastPostDate: Instant? = null ): Actor { // idは0未満ではいけない require(id >= 0) { "id must be greater than or equal to 0." } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt index 54a4ae1b..96304642 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt @@ -2,6 +2,7 @@ package dev.usbharu.hideout.core.service.post import dev.usbharu.hideout.activitypub.service.activity.create.ApSendCreateService import dev.usbharu.hideout.core.domain.exception.UserNotFoundException +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.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository @@ -35,7 +36,9 @@ class PostServiceImpl( override suspend fun createRemote(post: Post): Post { logger.info("START Create Remote Post user: {}, remote url: {}", post.actorId, post.apId) - val createdPost = internalCreate(post, false) + val actor = + actorRepository.findById(post.actorId) ?: throw UserNotFoundException("${post.actorId} was not found.") + val createdPost = internalCreate(post, false, actor) logger.info("SUCCESS Create Remote Post url: {}", createdPost.url) return createdPost } @@ -46,6 +49,10 @@ class PostServiceImpl( } reactionRepository.deleteByPostId(post.id) postRepository.save(post.delete()) + val actor = actorRepository.findById(post.actorId) + ?: throw IllegalStateException("actor: ${post.actorId} was not found.") + + actorRepository.save(actor.decrementPostsCount()) } override suspend fun deleteRemote(post: Post) { @@ -54,17 +61,28 @@ class PostServiceImpl( } reactionRepository.deleteByPostId(post.id) postRepository.save(post.delete()) + + val actor = actorRepository.findById(post.actorId) + ?: throw IllegalStateException("actor: ${post.actorId} was not found.") + + actorRepository.save(actor.decrementPostsCount()) } override suspend fun deleteByActor(actorId: Long) { postQueryService.findByActorId(actorId).filterNot { it.delted }.forEach { postRepository.save(it.delete()) } + + val actor = actorRepository.findById(actorId) + ?: throw IllegalStateException("actor: ${actorId} was not found.") + + actorRepository.save(actor.copy(postsCount = 0, lastPostDate = null)) } - private suspend fun internalCreate(post: Post, isLocal: Boolean): Post { + private suspend fun internalCreate(post: Post, isLocal: Boolean, actor: Actor): Post { return try { if (postRepository.save(post)) { try { timelineService.publishTimeline(post, isLocal) + actorRepository.save(actor.incrementPostsCount()) } catch (e: DuplicateKeyException) { logger.trace("Timeline already exists.", e) } @@ -91,7 +109,7 @@ class PostServiceImpl( replyId = post.repolyId, repostId = post.repostId, ) - return internalCreate(createPost, isLocal) + return internalCreate(createPost, isLocal, user) } companion object { diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt index 916c1333..8827612b 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt @@ -2,81 +2,35 @@ package dev.usbharu.hideout.mastodon.infrastructure.exposedquery import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException -import dev.usbharu.hideout.core.domain.model.relationship.Relationships import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors -import dev.usbharu.hideout.core.infrastructure.exposedrepository.Posts import dev.usbharu.hideout.domain.mastodon.model.generated.Account import dev.usbharu.hideout.mastodon.query.AccountQueryService import dev.usbharu.hideout.util.singleOr -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.ResultRow +import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository import java.time.Instant @Repository class AccountQueryServiceImpl(private val applicationConfig: ApplicationConfig) : AccountQueryService { override suspend fun findById(accountId: Long): Account { - val followingCount = Count(Relationships.actorId.eq(Actors.id), true).alias("following_count") - val followersCount = Count(Relationships.targetActorId.eq(Actors.id), true).alias("followers_count") - val postsCount = Posts.id.countDistinct().alias("posts_count") - val lastCreated = Posts.createdAt.max().alias("last_created") - val query = Actors - .join(Relationships, JoinType.LEFT) { - Actors.id eq Relationships.actorId or (Actors.id eq Relationships.targetActorId) - } - .leftJoin(Posts) - .slice( - followingCount, - followersCount, - *(Actors.realFields.toTypedArray()), - lastCreated, - postsCount - ) - .select { - (Actors.id.eq(accountId)).and( - Relationships.following.eq(true).or(Relationships.following.isNull()) - ) - } - .groupBy(Actors.id) + + val query = Actors.select { Actors.id eq accountId } return query .singleOr { FailedToGetResourcesException("accountId: $accountId wad not exist or duplicate", it) } - .let { toAccount(it, followingCount, followersCount, postsCount, lastCreated) } + .let { toAccount(it) } } override suspend fun findByIds(accountIds: List): List { - val followingCount = Count(Relationships.actorId.eq(Actors.id), true).alias("following_count") - val followersCount = Count(Relationships.targetActorId.eq(Actors.id), true).alias("followers_count") - val postsCount = Posts.id.countDistinct().alias("posts_count") - val lastCreated = Posts.createdAt.max().alias("last_created") - val query = Actors - .join(Relationships, JoinType.LEFT) { - Actors.id eq Relationships.actorId or (Actors.id eq Relationships.targetActorId) - } - .leftJoin(Posts) - .slice( - followingCount, - followersCount, - *(Actors.realFields.toTypedArray()), - lastCreated, - postsCount - ) - .select { - Actors.id.inList(accountIds) - .and(Relationships.following.eq(true).or(Relationships.following.isNull())) - } - .groupBy(Actors.id) + val query = Actors.select { Actors.id inList accountIds } return query - .map { toAccount(it, followingCount, followersCount, postsCount, lastCreated) } + .map { toAccount(it) } } private fun toAccount( - resultRow: ResultRow, - followingCount: ExpressionAlias, - followersCount: ExpressionAlias, - postsCount: ExpressionAlias, - lastCreated: ExpressionAlias + resultRow: ResultRow ): Account { val userUrl = "${applicationConfig.url}/users/${resultRow[Actors.id]}" @@ -98,10 +52,10 @@ class AccountQueryServiceImpl(private val applicationConfig: ApplicationConfig) group = false, discoverable = true, createdAt = Instant.ofEpochMilli(resultRow[Actors.createdAt]).toString(), - lastStatusAt = resultRow[lastCreated]?.let { Instant.ofEpochMilli(it).toString() }, - statusesCount = resultRow[postsCount].toInt(), - followersCount = resultRow[followersCount].toInt(), - followingCount = resultRow[followingCount].toInt(), + lastStatusAt = resultRow[Actors.lastPostAt]?.toString(), + statusesCount = resultRow[Actors.postsCount], + followersCount = resultRow[Actors.followersCount], + followingCount = resultRow[Actors.followingCount], ) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt index 9f636b34..831c693a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImpl.kt @@ -151,17 +151,17 @@ private fun toStatus(it: ResultRow) = Status( avatarStatic = it[Actors.url] + "/icon.jpg", header = it[Actors.url] + "/header.jpg", headerStatic = it[Actors.url] + "/header.jpg", - locked = false, + locked = it[Actors.locked], fields = emptyList(), emojis = emptyList(), bot = false, group = false, discoverable = true, createdAt = Instant.ofEpochMilli(it[Actors.createdAt]).toString(), - lastStatusAt = Instant.ofEpochMilli(it[Actors.createdAt]).toString(), - statusesCount = 0, - followersCount = 0, - followingCount = 0, + lastStatusAt = it[Actors.lastPostAt]?.toString(), + statusesCount = it[Actors.postsCount], + followersCount = it[Actors.followersCount], + followingCount = it[Actors.followingCount], noindex = false, moved = false, suspendex = false, diff --git a/src/main/resources/db/migration/V1__Init_DB.sql b/src/main/resources/db/migration/V1__Init_DB.sql index 741844d4..1badf0ae 100644 --- a/src/main/resources/db/migration/V1__Init_DB.sql +++ b/src/main/resources/db/migration/V1__Init_DB.sql @@ -15,22 +15,26 @@ create table if not exists instance ); create table if not exists actors ( - id bigint primary key, - "name" varchar(300) not null, - "domain" varchar(1000) not null, - screen_name varchar(300) not null, - description varchar(10000) not null, - inbox varchar(1000) not null unique, - outbox varchar(1000) not null unique, - url varchar(1000) not null unique, - public_key varchar(10000) not null, - private_key varchar(10000) null, - created_at bigint not null, - key_id varchar(1000) not null, - "following" varchar(1000) null, - followers varchar(1000) null, - "instance" bigint null, - locked boolean not null, + id bigint primary key, + "name" varchar(300) not null, + "domain" varchar(1000) not null, + screen_name varchar(300) not null, + description varchar(10000) not null, + inbox varchar(1000) not null unique, + outbox varchar(1000) not null unique, + url varchar(1000) not null unique, + public_key varchar(10000) not null, + private_key varchar(10000) null, + created_at bigint not null, + key_id varchar(1000) not null, + "following" varchar(1000) null, + followers varchar(1000) null, + "instance" bigint null, + locked boolean not null, + following_count int not null, + followers_count int not null, + posts_count int not null, + last_post_at timestamp null default null, unique ("name", "domain"), constraint fk_actors_instance__id foreign key ("instance") references instance (id) on delete restrict on update restrict ); @@ -200,8 +204,9 @@ create table if not exists relationships ); insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at, - key_id, following, followers, instance, locked) -values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', null, true); + key_id, following, followers, instance, locked, following_count, followers_count, posts_count, + last_post_at) +values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', null, true, 0, 0, 0, null); create table if not exists deleted_actors ( From b158ad8ce007915d800dbc91a19629c5ca16dd98 Mon Sep 17 00:00:00 2001 From: usbharu Date: Thu, 14 Dec 2023 01:13:16 +0900 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../hideout/core/domain/model/actor/Actor.kt | 34 +++++++++---------- .../core/service/post/PostServiceImpl.kt | 2 +- .../relationship/RelationshipServiceImpl.kt | 4 --- .../exposedquery/AccountQueryServiceImpl.kt | 1 - 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt index 166f9647..3833e71a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt @@ -184,22 +184,22 @@ data class Actor private constructor( override fun toString(): String { return "Actor(" + - "id=$id, " + - "name='$name', " + - "domain='$domain', " + - "screenName='$screenName', " + - "description='$description', " + - "inbox='$inbox', " + - "outbox='$outbox', " + - "url='$url', " + - "publicKey='$publicKey', " + - "privateKey=$privateKey, " + - "createdAt=$createdAt, " + - "keyId='$keyId', " + - "followers=$followers, " + - "following=$following, " + - "instance=$instance, " + - "locked=$locked" + - ")" + "id=$id, " + + "name='$name', " + + "domain='$domain', " + + "screenName='$screenName', " + + "description='$description', " + + "inbox='$inbox', " + + "outbox='$outbox', " + + "url='$url', " + + "publicKey='$publicKey', " + + "privateKey=$privateKey, " + + "createdAt=$createdAt, " + + "keyId='$keyId', " + + "followers=$followers, " + + "following=$following, " + + "instance=$instance, " + + "locked=$locked" + + ")" } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt index 96304642..63cfb4ef 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImpl.kt @@ -72,7 +72,7 @@ class PostServiceImpl( postQueryService.findByActorId(actorId).filterNot { it.delted }.forEach { postRepository.save(it.delete()) } val actor = actorRepository.findById(actorId) - ?: throw IllegalStateException("actor: ${actorId} was not found.") + ?: throw IllegalStateException("actor: $actorId was not found.") actorRepository.save(actor.copy(postsCount = 0, lastPostDate = null)) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt index 92e47772..69082c3e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImpl.kt @@ -113,8 +113,6 @@ class RelationshipServiceImpl( val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, actorId) - - if (inverseRelationship?.following == true) { actorRepository.save(targetActor.decrementFollowing()) actorRepository.save(user.decrementFollowers()) @@ -131,7 +129,6 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - apSendBlockService.sendBlock(user, remoteUser) } } @@ -261,7 +258,6 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - apSendUndoService.sendUndoFollow(user, remoteUser) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt index 8827612b..92f38f09 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt @@ -14,7 +14,6 @@ import java.time.Instant @Repository class AccountQueryServiceImpl(private val applicationConfig: ApplicationConfig) : AccountQueryService { override suspend fun findById(accountId: Long): Account { - val query = Actors.select { Actors.id eq accountId } return query From f65277b102ac9bc60f7083d7c49ef514b859c14f Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Thu, 14 Dec 2023 12:07:47 +0900 Subject: [PATCH 4/4] =?UTF-8?q?test:=20=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/e2eTest/resources/oauth2/user.sql | 7 ++++--- .../apiV1AccountsIdFollowPost フォローできる.sql | 7 ++++--- ...証でフォロワーがfollowers投稿を取得できる.sql | 9 +++++---- ...re認証でフォロワーがpublic投稿を取得できる.sql | 11 ++++++----- ...認証でフォロワーがunlisted投稿を取得できる.sql | 9 +++++---- ...投稿はattachmentにDocumentとして画像が存在する.sql | 13 +++++++------ ...プライになっている投稿はinReplyToが存在する.sql | 15 ++++++++------- ...匿名でfollowers投稿を取得しようとすると404.sql | 13 +++++++------ .../sql/note/匿名でpublic投稿を取得できる.sql | 13 +++++++------ .../sql/note/匿名でunlisted投稿を取得できる.sql | 13 +++++++------ src/intTest/resources/sql/test-user.sql | 7 ++++--- src/intTest/resources/sql/test-user2.sql | 7 ++++--- .../core/service/post/PostServiceImplTest.kt | 5 +++++ .../relationship/RelationshipServiceImplTest.kt | 8 ++++++++ 14 files changed, 81 insertions(+), 56 deletions(-) diff --git a/src/e2eTest/resources/oauth2/user.sql b/src/e2eTest/resources/oauth2/user.sql index 34ac640f..351d988d 100644 --- a/src/e2eTest/resources/oauth2/user.sql +++ b/src/e2eTest/resources/oauth2/user.sql @@ -1,5 +1,6 @@ -insert into actors (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at, + key_id, following, followers, instance, locked, following_count, followers_count, posts_count, + last_post_at) VALUES (1730415786666758144, 'test-user', 'localhost', 'Im test user.', 'THis account is test user.', 'http://localhost/users/test-user/inbox', 'http://localhost/users/test-user/outbox', 'http://localhost/users/test-user', @@ -43,7 +44,7 @@ Ja15+ZWbOA4vJA9pOh3x4XM= -----END PRIVATE KEY----- ', 1701398248417, 'http://localhost/users/test-user#pubkey', 'http://localhost/users/test-user/following', - 'http://localhost/users/test-users/followers', null, false); + 'http://localhost/users/test-users/followers', null, false, 0, 0, 0, null); insert into user_details (actor_id, password, auto_accept_followee_follow_request) values ( 1730415786666758144 diff --git a/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql b/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql index a736a29c..2221dfc7 100644 --- a/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql +++ b/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql @@ -1,16 +1,17 @@ insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, - created_at, key_id, following, followers, instance, locked) + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (3733363, 'follow-test-user-1', 'example.com', 'follow-test-user-1-name', '', 'https://example.com/users/follow-test-user-1/inbox', 'https://example.com/users/follow-test-user-1/outbox', 'https://example.com/users/follow-test-user-1', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/follow-test-user-1#pubkey', 'https://example.com/users/follow-test-user-1/following', - 'https://example.com/users/follow-test-user-1/followers', null, false), + 'https://example.com/users/follow-test-user-1/followers', null, false, 0, 0, 0, null), (37335363, 'follow-test-user-2', 'example.com', 'follow-test-user-2-name', '', 'https://example.com/users/follow-test-user-2/inbox', 'https://example.com/users/follow-test-user-2/outbox', 'https://example.com/users/follow-test-user-2', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/follow-test-user-2#pubkey', 'https://example.com/users/follow-test-user-2/following', - 'https://example.com/users/follow-test-user-2/followers', null, false); + 'https://example.com/users/follow-test-user-2/followers', null, false, 0, 0, 0, null); diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql index 74a08848..4402e2a8 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql @@ -1,12 +1,13 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (8, 'test-user8', 'example.com', 'Im test-user8.', 'THis account is test-user8.', 'https://example.com/users/test-user8/inbox', 'https://example.com/users/test-user8/outbox', 'https://example.com/users/test-user8', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user8#pubkey', 'https://example.com/users/test-user8/following', - 'https://example.com/users/test-user8/followers', null, false), + 'https://example.com/users/test-user8/followers', null, false, 0, 0, 0, null), (9, 'test-user9', 'follower.example.com', 'Im test-user9.', 'THis account is test-user9.', 'https://follower.example.com/users/test-user9/inbox', 'https://follower.example.com/users/test-user9/outbox', 'https://follower.example.com/users/test-user9', @@ -14,7 +15,7 @@ VALUES (8, 'test-user8', 'example.com', 'Im test-user8.', 'THis account is test- null, 12345678, 'https://follower.example.com/users/test-user9#pubkey', 'https://follower.example.com/users/test-user9/following', - 'https://follower.example.com/users/test-user9/followers', null, false); + 'https://follower.example.com/users/test-user9/followers', null, false, 0, 0, 0, null); insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql index f5e41dd3..bcd8c504 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql @@ -1,12 +1,13 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (4, 'test-user4', 'example.com', 'Im test user4.', 'THis account is test user4.', 'https://example.com/users/test-user4/inbox', 'https://example.com/users/test-user4/outbox', 'https://example.com/users/test-user4', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user4#pubkey', 'https://example.com/users/test-user4/following', - 'https://example.com/users/test-user4/followers', null, false), + 'https://example.com/users/test-user4/followers', null, false, 0, 0, 0, null), (5, 'test-user5', 'follower.example.com', 'Im test user5.', 'THis account is test user5.', 'https://follower.example.com/users/test-user5/inbox', 'https://follower.example.com/users/test-user5/outbox', 'https://follower.example.com/users/test-user5', @@ -14,13 +15,13 @@ VALUES (4, 'test-user4', 'example.com', 'Im test user4.', 'THis account is test null, 12345678, 'https://follower.example.com/users/test-user5#pubkey', 'https://follower.example.com/users/test-user5/following', - 'https://follower.example.com/users/test-user5/followers', null, false); + 'https://follower.example.com/users/test-user5/followers', null, false, 0, 0, 0, null); insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) VALUES (5, 4, true, false, false, false, false); -insert into POSTS (ID, "actor_ID", OVERVIEW, TEXT, "CREATED_AT", VISIBILITY, URL, "REPOST_ID", "REPLY_ID", SENSITIVE, +insert into POSTS (ID, "actor_id", OVERVIEW, TEXT, "created_at", VISIBILITY, URL, "repost_id", "reply_id", SENSITIVE, AP_ID) VALUES (1237, 4, null, 'test post', 12345680, 0, 'https://example.com/users/test-user4/posts/1237', null, null, false, 'https://example.com/users/test-user4/posts/1237'); diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql index 3c40f0ca..147ef378 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql @@ -1,12 +1,13 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (6, 'test-user6', 'example.com', 'Im test-user6.', 'THis account is test-user6.', 'https://example.com/users/test-user6/inbox', 'https://example.com/users/test-user6/outbox', 'https://example.com/users/test-user6', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user6#pubkey', 'https://example.com/users/test-user6/following', - 'https://example.com/users/test-user6/followers', null, false), + 'https://example.com/users/test-user6/followers', null, false, 0, 0, 0, null), (7, 'test-user7', 'follower.example.com', 'Im test-user7.', 'THis account is test-user7.', 'https://follower.example.com/users/test-user7/inbox', 'https://follower.example.com/users/test-user7/outbox', 'https://follower.example.com/users/test-user7', @@ -14,7 +15,7 @@ VALUES (6, 'test-user6', 'example.com', 'Im test-user6.', 'THis account is test- null, 12345678, 'https://follower.example.com/users/test-user7#pubkey', 'https://follower.example.com/users/test-user7/following', - 'https://follower.example.com/users/test-user7/followers', null, false); + 'https://follower.example.com/users/test-user7/followers', null, false, 0, 0, 0, null); insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) diff --git a/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql b/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql index edc35707..8db9ac9e 100644 --- a/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql +++ b/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql @@ -1,17 +1,18 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (11, 'test-user11', 'example.com', 'Im test-user11.', 'THis account is test-user11.', 'https://example.com/users/test-user11/inbox', 'https://example.com/users/test-user11/outbox', 'https://example.com/users/test-user11', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user11#pubkey', 'https://example.com/users/test-user11/following', - 'https://example.com/users/test-user11/followers', null, false); + 'https://example.com/users/test-user11/followers', null, false, 0, 0, 0, null); -insert into POSTS (ID, actor_id, OVERVIEW, TEXT, "CREATED_AT", VISIBILITY, URL, "REPOST_ID", "REPLY_ID", SENSITIVE, - AP_ID) +insert into POSTS (id, actor_id, overview, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, + deleted) VALUES (1242, 11, null, 'test post', 12345680, 0, 'https://example.com/users/test-user11/posts/1242', null, null, false, - 'https://example.com/users/test-user11/posts/1242'); + 'https://example.com/users/test-user11/posts/1242', false); insert into MEDIA (ID, NAME, URL, REMOTE_URL, THUMBNAIL_URL, TYPE, BLURHASH, MIME_TYPE, DESCRIPTION) VALUES (1, 'test-media', 'https://example.com/media/test-media.png', null, null, 0, null, 'image/png', null), diff --git a/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql b/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql index 4df7c878..cfc6da58 100644 --- a/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql +++ b/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql @@ -1,16 +1,17 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (10, 'test-user10', 'example.com', 'Im test-user10.', 'THis account is test-user10.', 'https://example.com/users/test-user10/inbox', 'https://example.com/users/test-user10/outbox', 'https://example.com/users/test-user10', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user10#pubkey', 'https://example.com/users/test-user10/following', - 'https://example.com/users/test-user10/followers', null, false); + 'https://example.com/users/test-user10/followers', null, false, 0, 0, 0, null); -insert into POSTS (ID, actor_id, OVERVIEW, TEXT, "CREATED_AT", VISIBILITY, URL, "REPOST_ID", "REPLY_ID", SENSITIVE, - AP_ID) +insert into POSTS (id, actor_id, overview, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, + deleted) VALUES (1240, 10, null, 'test post', 12345680, 0, 'https://example.com/users/test-user10/posts/1240', null, null, false, - 'https://example.com/users/test-user10/posts/1240'), + 'https://example.com/users/test-user10/posts/1240', false), (1241, 10, null, 'test post', 12345680, 0, 'https://example.com/users/test-user10/posts/1241', null, 1240, false, - 'https://example.com/users/test-user10/posts/1241'); + 'https://example.com/users/test-user10/posts/1241', false); diff --git a/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql b/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql index 627372d5..efae7a76 100644 --- a/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql +++ b/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql @@ -1,14 +1,15 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (3, 'test-user3', 'example.com', 'Im test user3.', 'THis account is test user3.', 'https://example.com/users/test-user3/inbox', 'https://example.com/users/test-user3/outbox', 'https://example.com/users/test-user3', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user3#pubkey', 'https://example.com/users/test-user3/following', - 'https://example.com/users/test-user3/followers', null, false); + 'https://example.com/users/test-user3/followers', null, false, 0, 0, 0, null); -insert into POSTS (ID, actor_id, OVERVIEW, TEXT, "CREATED_AT", VISIBILITY, URL, "REPOST_ID", "REPLY_ID", SENSITIVE, - AP_ID) +insert into POSTS (id, actor_id, overview, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, + deleted) VALUES (1236, 3, null, 'test post', 12345680, 2, 'https://example.com/users/test-user3/posts/1236', null, null, false, - 'https://example.com/users/test-user3/posts/1236') + 'https://example.com/users/test-user3/posts/1236', false) diff --git a/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql b/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql index 22d44040..a9f3839e 100644 --- a/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql @@ -1,14 +1,15 @@ -insert into actors (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at, + key_id, following, followers, instance, locked, following_count, followers_count, posts_count, + last_post_at) VALUES (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test user.', 'https://example.com/users/test-user/inbox', 'https://example.com/users/test-user/outbox', 'https://example.com/users/test-user', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user#pubkey', 'https://example.com/users/test-user/following', - 'https://example.com/users/test-users/followers', null, false); + 'https://example.com/users/test-users/followers', null, false, 0, 0, 0, null); -insert into POSTS (ID, actor_id, OVERVIEW, TEXT, "CREATED_AT", VISIBILITY, URL, "REPOST_ID", "REPLY_ID", SENSITIVE, - AP_ID) +insert into POSTS (id, actor_id, overview, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, + deleted) VALUES (1234, 1, null, 'test post', 12345680, 0, 'https://example.com/users/test-user/posts/1234', null, null, false, - 'https://example.com/users/test-user/posts/1234') + 'https://example.com/users/test-user/posts/1234', false) diff --git a/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql b/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql index db8674e5..6e2a63ff 100644 --- a/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql @@ -1,14 +1,15 @@ -insert into actors (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at, + key_id, following, followers, instance, locked, following_count, followers_count, posts_count, + last_post_at) VALUES (2, 'test-user2', 'example.com', 'Im test user2.', 'THis account is test user2.', 'https://example.com/users/test-user2/inbox', 'https://example.com/users/test-user2/outbox', 'https://example.com/users/test-user2', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user2#pubkey', 'https://example.com/users/test-user2/following', - 'https://example.com/users/test-user2/followers', null, false); + 'https://example.com/users/test-user2/followers', null, false, 0, 0, 0, null); -insert into POSTS (ID, actor_id, OVERVIEW, TEXT, "CREATED_AT", VISIBILITY, URL, "REPOST_ID", "REPLY_ID", SENSITIVE, - AP_ID) +insert into POSTS (id, actor_id, overview, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, + deleted) VALUES (1235, 2, null, 'test post', 12345680, 1, 'https://example.com/users/test-user2/posts/1235', null, null, false, - 'https://example.com/users/test-user2/posts/1235') + 'https://example.com/users/test-user2/posts/1235', false) diff --git a/src/intTest/resources/sql/test-user.sql b/src/intTest/resources/sql/test-user.sql index f8239b21..cdcc686d 100644 --- a/src/intTest/resources/sql/test-user.sql +++ b/src/intTest/resources/sql/test-user.sql @@ -1,9 +1,10 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test user.', 'https://example.com/users/test-user/inbox', 'https://example.com/users/test-user/outbox', 'https://example.com/users/test-user', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user#pubkey', 'https://example.com/users/test-user/following', - 'https://example.com/users/test-users/followers', null, false); + 'https://example.com/users/test-users/followers', null, false, 0, 0, 0, null); diff --git a/src/intTest/resources/sql/test-user2.sql b/src/intTest/resources/sql/test-user2.sql index 93a466a2..ef455c75 100644 --- a/src/intTest/resources/sql/test-user2.sql +++ b/src/intTest/resources/sql/test-user2.sql @@ -1,9 +1,10 @@ -insert into "actors" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE, LOCKED) +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) VALUES (2, 'test-user2', 'example.com', 'Im test user.', 'THis account is test user.', 'https://example.com/users/test-user2/inbox', 'https://example.com/users/test-user2/outbox', 'https://example.com/users/test-user2', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user2#pubkey', 'https://example.com/users/test-user2/following', - 'https://example.com/users/test-user2s/followers', null, false); + 'https://example.com/users/test-user2s/followers', null, false, 0, 0, 0, null); diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImplTest.kt index 8efae4ec..cd43fd90 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/post/PostServiceImplTest.kt @@ -90,9 +90,11 @@ class PostServiceImplTest { fun `createRemote 正常にリモートのpostを作成できる`() = runTest { val post = PostBuilder.of() + whenever(actorRepository.findById(eq(post.actorId))).doReturn(UserBuilder.remoteUserOf(id = post.actorId)) whenever(postRepository.save(eq(post))).doReturn(true) whenever(timelineService.publishTimeline(eq(post), eq(false))).doReturn(Unit) + val createLocal = postServiceImpl.createRemote(post) assertThat(createLocal).isEqualTo(post) @@ -106,6 +108,7 @@ class PostServiceImplTest { fun `createRemote 既に作成されていた場合はそのまま帰す`() = runTest { val post = PostBuilder.of() + whenever(actorRepository.findById(eq(post.actorId))).doReturn(UserBuilder.remoteUserOf(id = post.actorId)) whenever(postRepository.save(eq(post))).doReturn(false) val createLocal = postServiceImpl.createRemote(post) @@ -120,6 +123,7 @@ class PostServiceImplTest { fun `createRemote 既に作成されていることを検知できず例外が発生した場合はDBから取得して返す`() = runTest { val post = PostBuilder.of() + whenever(actorRepository.findById(eq(post.actorId))).doReturn(UserBuilder.remoteUserOf(id = post.actorId)) whenever(postRepository.save(eq(post))).doAnswer { throw ExposedSQLException(null, emptyList(), mock()) } whenever(postQueryService.findByApId(eq(post.apId))).doReturn(post) @@ -135,6 +139,7 @@ class PostServiceImplTest { fun `createRemote 既に作成されていることを検知出来ずタイムラインにpush出来なかった場合何もしない`() = runTest { val post = PostBuilder.of() + whenever(actorRepository.findById(eq(post.actorId))).doReturn(UserBuilder.remoteUserOf(id = post.actorId)) whenever(postRepository.save(eq(post))).doReturn(true) whenever(timelineService.publishTimeline(eq(post), eq(false))).doThrow(DuplicateKeyException::class) diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt index 93c4216d..4f6fa718 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipServiceImplTest.kt @@ -6,6 +6,7 @@ import dev.usbharu.hideout.activitypub.service.activity.follow.APSendFollowServi import dev.usbharu.hideout.activitypub.service.activity.reject.ApSendRejectService import dev.usbharu.hideout.activitypub.service.activity.undo.APSendUndoService import dev.usbharu.hideout.application.config.ApplicationConfig +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.relationship.Relationship import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository import dev.usbharu.hideout.core.query.ActorQueryService @@ -49,6 +50,9 @@ class RelationshipServiceImplTest { @Mock private lateinit var apSendUndoService: APSendUndoService + @Mock + private lateinit var actorRepository: ActorRepository + @InjectMocks private lateinit var relationshipServiceImpl: RelationshipServiceImpl @@ -209,6 +213,7 @@ class RelationshipServiceImplTest { @Test fun `block ローカルユーザーの場合永続化される`() = runTest { + whenever(actorQueryService.findById(eq(1234))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) relationshipServiceImpl.block(1234, 5678) @@ -256,6 +261,7 @@ class RelationshipServiceImplTest { @Test fun `acceptFollowRequest ローカルユーザーの場合永続化される`() = runTest { + whenever(actorQueryService.findById(eq(1234))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( @@ -347,6 +353,7 @@ class RelationshipServiceImplTest { @Test fun `acceptFollowRequest フォローリクエストが存在せずforceがtrueのときフォローを承認する`() = runTest { + whenever(actorQueryService.findById(eq(1234))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.remoteUserOf(domain = "remote.example.com")) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( @@ -530,6 +537,7 @@ class RelationshipServiceImplTest { @Test fun `unfollow ローカルユーザーの場合永続化される`() = runTest { + whenever(actorQueryService.findById(eq(1234))).doReturn(UserBuilder.remoteUserOf(domain = "remote.example.com")) whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship(