diff --git a/detekt.yml b/detekt.yml index a74f1251..cb59ca02 100644 --- a/detekt.yml +++ b/detekt.yml @@ -154,6 +154,9 @@ performance: UnnecessaryTemporaryInstantiation: active: true + SpreadOperator: + active: false + potential-bugs: CastToNullableType: active: true diff --git a/src/e2eTest/kotlin/AssertionUtil.kt b/src/e2eTest/kotlin/AssertionUtil.kt index 8083b825..6b82aa59 100644 --- a/src/e2eTest/kotlin/AssertionUtil.kt +++ b/src/e2eTest/kotlin/AssertionUtil.kt @@ -1,4 +1,4 @@ -import dev.usbharu.hideout.core.infrastructure.exposedrepository.Users +import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors import org.jetbrains.exposed.sql.and import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.selectAll @@ -16,13 +16,13 @@ object AssertionUtil { domain } - val selectAll = Users.selectAll() + val selectAll = Actors.selectAll() println(selectAll.fetchSize) println(selectAll.toList().size) - selectAll.map { "@${it[Users.name]}@${it[Users.domain]}" }.forEach { println(it) } + selectAll.map { "@${it[Actors.name]}@${it[Actors.domain]}" }.forEach { println(it) } - return Users.select { Users.name eq username and (Users.domain eq s) }.empty().not() + return Actors.select { Actors.name eq username and (Actors.domain eq s) }.empty().not() } } diff --git a/src/e2eTest/resources/oauth2/user.sql b/src/e2eTest/resources/oauth2/user.sql index 15aa977f..34ac640f 100644 --- a/src/e2eTest/resources/oauth2/user.sql +++ b/src/e2eTest/resources/oauth2/user.sql @@ -1,7 +1,7 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (1730415786666758144, 'test-user', 'localhost', 'Im test user.', 'THis account is test user.', - '$2a$10$/mWC/n7nC7X3l9qCEOKnredxne2zewoqEsJWTOdlKfg2zXKJ0F9Em', 'http://localhost/users/test-user/inbox', + 'http://localhost/users/test-user/inbox', 'http://localhost/users/test-user/outbox', 'http://localhost/users/test-user', '-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi4mifRg6huAIn6DXk3Vn @@ -43,4 +43,8 @@ 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); + 'http://localhost/users/test-users/followers', null, false); + +insert into user_details (actor_id, password, auto_accept_followee_follow_request) +values ( 1730415786666758144 + , '$2a$10$/mWC/n7nC7X3l9qCEOKnredxne2zewoqEsJWTOdlKfg2zXKJ0F9Em', true) diff --git a/src/intTest/kotlin/mastodon/account/AccountApiTest.kt b/src/intTest/kotlin/mastodon/account/AccountApiTest.kt index 0c69e626..cf67b35d 100644 --- a/src/intTest/kotlin/mastodon/account/AccountApiTest.kt +++ b/src/intTest/kotlin/mastodon/account/AccountApiTest.kt @@ -1,8 +1,8 @@ package mastodon.account import dev.usbharu.hideout.SpringApplication +import dev.usbharu.hideout.core.infrastructure.exposedquery.ActorQueryServiceImpl import dev.usbharu.hideout.core.infrastructure.exposedquery.FollowerQueryServiceImpl -import dev.usbharu.hideout.core.infrastructure.exposedquery.UserQueryServiceImpl import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat import org.flywaydb.core.Flyway @@ -39,7 +39,7 @@ class AccountApiTest { private lateinit var followerQueryServiceImpl: FollowerQueryServiceImpl @Autowired - private lateinit var userQueryServiceImpl: UserQueryServiceImpl + private lateinit var userQueryServiceImpl: ActorQueryServiceImpl @Autowired diff --git a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt index 9108e357..faabf58a 100644 --- a/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt +++ b/src/intTest/kotlin/util/WithHttpSignatureSecurityContextFactory.kt @@ -2,7 +2,7 @@ package util import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.httpsignature.common.HttpHeaders import dev.usbharu.httpsignature.common.HttpMethod import dev.usbharu.httpsignature.common.HttpRequest @@ -14,7 +14,7 @@ import org.springframework.security.web.authentication.preauth.PreAuthenticatedA import java.net.URL class WithHttpSignatureSecurityContextFactory( - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val transaction: Transaction ) : WithSecurityContextFactory { @@ -28,7 +28,7 @@ class WithHttpSignatureSecurityContextFactory( ) ) val httpSignatureUser = transaction.transaction { - val findByKeyId = userQueryService.findByKeyId(annotation.keyId) + val findByKeyId = actorQueryService.findByKeyId(annotation.keyId) HttpSignatureUser( findByKeyId.name, findByKeyId.domain, diff --git a/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql b/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql index 53ea2830..a736a29c 100644 --- a/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql +++ b/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql @@ -1,18 +1,16 @@ -insert into "USERS" (id, name, domain, screen_name, description, password, inbox, outbox, url, public_key, private_key, - created_at, key_id, following, followers, instance) +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 (3733363, 'follow-test-user-1', 'example.com', 'follow-test-user-1-name', '', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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), + 'https://example.com/users/follow-test-user-1/followers', null, false), (37335363, 'follow-test-user-2', 'example.com', 'follow-test-user-2-name', '', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); + 'https://example.com/users/follow-test-user-2/followers', null, false); diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql index d3076eb1..74a08848 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql @@ -1,30 +1,25 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (8, 'test-user8', 'example.com', 'Im test-user8.', 'THis account is test-user8.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); - -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) -VALUES (9, 'test-user9', 'follower.example.com', 'Im test-user9.', 'THis account is test-user9.', - null, + 'https://example.com/users/test-user8/followers', null, false), + (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', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', 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); + 'https://follower.example.com/users/test-user9/followers', null, false); -insert into relationships (user_id, target_user_id, following, blocking, muting, follow_request, +insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) VALUES (9, 8, true, false, false, false, false); -insert into POSTS (ID, USER_ID, OVERVIEW, TEXT, CREATED_AT, VISIBILITY, URL, REPLY_ID, REPOST_ID, SENSITIVE, AP_ID) +insert into POSTS (ID, ACTOR_ID, OVERVIEW, TEXT, CREATED_AT, VISIBILITY, URL, REPLY_ID, REPOST_ID, SENSITIVE, AP_ID) VALUES (1239, 8, null, 'test post', 12345680, 2, 'https://example.com/users/test-user8/posts/1239', null, null, false, 'https://example.com/users/test-user8/posts/1239'); diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql index 82d37cc0..f5e41dd3 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql @@ -1,31 +1,26 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (4, 'test-user4', 'example.com', 'Im test user4.', 'THis account is test user4.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); - -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) -VALUES (5, 'test-user5', 'follower.example.com', 'Im test user5.', 'THis account is test user5.', - null, + 'https://example.com/users/test-user4/followers', null, false), + (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', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', 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); + 'https://follower.example.com/users/test-user5/followers', null, false); -insert into relationships (user_id, target_user_id, following, blocking, muting, follow_request, +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, "USER_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 cce85d78..3c40f0ca 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql @@ -1,31 +1,26 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (6, 'test-user6', 'example.com', 'Im test-user6.', 'THis account is test-user6.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); - -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) -VALUES (7, 'test-user7', 'follower.example.com', 'Im test-user7.', 'THis account is test-user7.', - null, + 'https://example.com/users/test-user6/followers', null, false), + (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', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', 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); + 'https://follower.example.com/users/test-user7/followers', null, false); -insert into relationships (user_id, target_user_id, following, blocking, muting, follow_request, +insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) VALUES (7, 6, true, false, false, false, false); -insert into POSTS (ID, "USER_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 (1238, 6, null, 'test post', 12345680, 1, 'https://example.com/users/test-user6/posts/1238', null, null, false, 'https://example.com/users/test-user6/posts/1238'); diff --git a/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql b/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql index efe290a5..edc35707 100644 --- a/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql +++ b/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql @@ -1,15 +1,14 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (11, 'test-user11', 'example.com', 'Im test-user11.', 'THis account is test-user11.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); + 'https://example.com/users/test-user11/followers', null, false); -insert into POSTS (ID, "USER_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 (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'); diff --git a/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql b/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql index 30455c5c..4df7c878 100644 --- a/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql +++ b/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql @@ -1,15 +1,14 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (10, 'test-user10', 'example.com', 'Im test-user10.', 'THis account is test-user10.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); + 'https://example.com/users/test-user10/followers', null, false); -insert into POSTS (ID, "USER_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 (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'), diff --git a/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql b/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql index 9b880740..627372d5 100644 --- a/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql +++ b/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql @@ -1,15 +1,14 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (3, 'test-user3', 'example.com', 'Im test user3.', 'THis account is test user3.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); + 'https://example.com/users/test-user3/followers', null, false); -insert into POSTS (ID, "USER_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 (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') diff --git a/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql b/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql index 14e7b47a..22d44040 100644 --- a/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql @@ -1,14 +1,14 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test user.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', 'https://example.com/users/test-user/inbox', + '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); + 'https://example.com/users/test-users/followers', null, false); -insert into POSTS (ID, "USER_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 (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') diff --git a/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql b/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql index f9bfe549..db8674e5 100644 --- a/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql @@ -1,15 +1,14 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (2, 'test-user2', 'example.com', 'Im test user2.', 'THis account is test user2.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); + 'https://example.com/users/test-user2/followers', null, false); -insert into POSTS (ID, "USER_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 (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') diff --git a/src/intTest/resources/sql/test-post.sql b/src/intTest/resources/sql/test-post.sql index 01bcb2dd..eefb3795 100644 --- a/src/intTest/resources/sql/test-post.sql +++ b/src/intTest/resources/sql/test-post.sql @@ -1,3 +1,3 @@ -insert into posts (id, user_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) VALUES (1, 1, null, 'hello', 1234455, 0, 'https://localhost/users/1/posts/1', null, null, false, 'https://users/1/posts/1'); diff --git a/src/intTest/resources/sql/test-user.sql b/src/intTest/resources/sql/test-user.sql index a21d1795..f8239b21 100644 --- a/src/intTest/resources/sql/test-user.sql +++ b/src/intTest/resources/sql/test-user.sql @@ -1,9 +1,9 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test user.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', 'https://example.com/users/test-user/inbox', + '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); + 'https://example.com/users/test-users/followers', null, false); diff --git a/src/intTest/resources/sql/test-user2.sql b/src/intTest/resources/sql/test-user2.sql index 7b123701..93a466a2 100644 --- a/src/intTest/resources/sql/test-user2.sql +++ b/src/intTest/resources/sql/test-user2.sql @@ -1,10 +1,9 @@ -insert into "USERS" (ID, NAME, DOMAIN, SCREEN_NAME, DESCRIPTION, PASSWORD, INBOX, OUTBOX, URL, PUBLIC_KEY, PRIVATE_KEY, - CREATED_AT, KEY_ID, FOLLOWING, FOLLOWERS, INSTANCE) +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 (2, 'test-user2', 'example.com', 'Im test user.', 'THis account is test user.', - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8', '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); + 'https://example.com/users/test-user2s/followers', null, false); diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/domain/model/Person.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/domain/model/Person.kt index cba9eeaf..f08b161e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/domain/model/Person.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/domain/model/Person.kt @@ -17,7 +17,8 @@ constructor( var publicKey: Key, var endpoints: Map = emptyMap(), var followers: String?, - var following: String? + var following: String?, + val manuallyApprovesFollowers: Boolean? = false ) : Object(add(type, "Person")), HasId, HasName { @Suppress("CyclomaticComplexMethod", "CognitiveComplexMethod") @@ -40,6 +41,7 @@ constructor( if (endpoints != other.endpoints) return false if (followers != other.followers) return false if (following != other.following) return false + if (manuallyApprovesFollowers != other.manuallyApprovesFollowers) return false return true } @@ -59,6 +61,26 @@ constructor( result = 31 * result + endpoints.hashCode() result = 31 * result + (followers?.hashCode() ?: 0) result = 31 * result + (following?.hashCode() ?: 0) + result = 31 * result + manuallyApprovesFollowers.hashCode() return result } + + override fun toString(): String { + return "Person(" + + "name='$name', " + + "id='$id', " + + "preferredUsername=$preferredUsername, " + + "summary=$summary, " + + "inbox='$inbox', " + + "outbox='$outbox', " + + "url='$url', " + + "icon=$icon, " + + "publicKey=$publicKey, " + + "endpoints=$endpoints, " + + "followers=$followers, " + + "following=$following, " + + "manuallyApprovesFollowers=$manuallyApprovesFollowers" + + ")" + + " ${super.toString()}" + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt index 561b8de2..19b217d5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/infrastructure/exposedquery/NoteQueryServiceImpl.kt @@ -23,7 +23,7 @@ class NoteQueryServiceImpl(private val postRepository: PostRepository, private v NoteQueryService { override suspend fun findById(id: Long): Pair { return Posts - .leftJoin(Users) + .leftJoin(Actors) .leftJoin(PostsMedia) .leftJoin(Media) .select { Posts.id eq id } @@ -35,7 +35,7 @@ class NoteQueryServiceImpl(private val postRepository: PostRepository, private v override suspend fun findByApid(apId: String): Pair { return Posts - .leftJoin(Users) + .leftJoin(Actors) .leftJoin(PostsMedia) .leftJoin(Media) .select { Posts.apId eq apId } @@ -61,11 +61,11 @@ class NoteQueryServiceImpl(private val postRepository: PostRepository, private v val visibility1 = visibility( Visibility.values().first { visibility -> visibility.ordinal == this[Posts.visibility] }, - this[Users.followers] + this[Actors.followers] ) return Note( id = this[Posts.apId], - attributedTo = this[Users.url], + attributedTo = this[Actors.url], content = this[Posts.text], published = Instant.ofEpochMilli(this[Posts.createdAt]).toString(), to = visibility1.first, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt index 343dcb50..3a48b5df 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessor.kt @@ -4,20 +4,20 @@ import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.external.job.DeliverAcceptJob import dev.usbharu.hideout.core.external.job.DeliverAcceptJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service @Service class APDeliverAcceptJobProcessor( private val apRequestService: APRequestService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val deliverAcceptJob: DeliverAcceptJob, private val transaction: Transaction ) : JobProcessor { override suspend fun process(param: DeliverAcceptJobParam): Unit = transaction.transaction { - apRequestService.apPost(param.inbox, param.accept, userQueryService.findById(param.signer)) + apRequestService.apPost(param.inbox, param.accept, actorQueryService.findById(param.signer)) } override fun job(): DeliverAcceptJob = deliverAcceptJob diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt index 24a54ef5..1a48f22d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessor.kt @@ -7,14 +7,14 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.springframework.stereotype.Service @Service class ApAcceptProcessor( transaction: Transaction, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val relationshipService: RelationshipService ) : AbstractActivityPubProcessor(transaction) { @@ -32,8 +32,8 @@ class ApAcceptProcessor( val userUrl = follow.apObject val followerUrl = follow.actor - val user = userQueryService.findByUrl(userUrl) - val follower = userQueryService.findByUrl(followerUrl) + val user = actorQueryService.findByUrl(userUrl) + val follower = actorQueryService.findByUrl(followerUrl) relationshipService.acceptFollowRequest(user.id, follower.id) logger.debug("SUCCESS Follow from ${user.url} to ${follower.url}.") diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApSendAcceptService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApSendAcceptService.kt index 35270235..2a52fd1c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApSendAcceptService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApSendAcceptService.kt @@ -2,14 +2,14 @@ package dev.usbharu.hideout.activitypub.service.activity.accept import dev.usbharu.hideout.activitypub.domain.model.Accept import dev.usbharu.hideout.activitypub.domain.model.Follow -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.external.job.DeliverAcceptJob import dev.usbharu.hideout.core.external.job.DeliverAcceptJobParam import dev.usbharu.hideout.core.service.job.JobQueueParentService import org.springframework.stereotype.Service interface ApSendAcceptService { - suspend fun sendAcceptFollow(user: User, target: User) + suspend fun sendAcceptFollow(actor: Actor, target: Actor) } @Service @@ -17,17 +17,17 @@ class ApSendAcceptServiceImpl( private val jobQueueParentService: JobQueueParentService, private val deliverAcceptJob: DeliverAcceptJob ) : ApSendAcceptService { - override suspend fun sendAcceptFollow(user: User, target: User) { + override suspend fun sendAcceptFollow(actor: Actor, target: Actor) { val deliverAcceptJobParam = DeliverAcceptJobParam( Accept( apObject = Follow( - apObject = user.url, + apObject = actor.url, actor = target.url ), - actor = user.url + actor = actor.url ), target.inbox, - user.id + actor.id ) jobQueueParentService.scheduleTypeSafe(deliverAcceptJob, deliverAcceptJobParam) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessor.kt index a97a0f19..bc946419 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessor.kt @@ -2,7 +2,7 @@ package dev.usbharu.hideout.activitypub.service.activity.block import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.model.user.UserRepository +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverBlockJob import dev.usbharu.hideout.core.external.job.DeliverBlockJobParam import dev.usbharu.hideout.core.service.job.JobProcessor @@ -14,12 +14,12 @@ import org.springframework.stereotype.Service @Service class APDeliverBlockJobProcessor( private val apRequestService: APRequestService, - private val userRepository: UserRepository, + private val actorRepository: ActorRepository, private val transaction: Transaction, private val deliverBlockJob: DeliverBlockJob ) : JobProcessor { override suspend fun process(param: DeliverBlockJobParam): Unit = transaction.transaction { - val signer = userRepository.findById(param.signer) + val signer = actorRepository.findById(param.signer) apRequestService.apPost( param.inbox, param.reject, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APSendBlockService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APSendBlockService.kt index f814da7e..8e689d96 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APSendBlockService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APSendBlockService.kt @@ -4,14 +4,14 @@ import dev.usbharu.hideout.activitypub.domain.model.Block import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.domain.model.Reject import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.external.job.DeliverBlockJob import dev.usbharu.hideout.core.external.job.DeliverBlockJobParam import dev.usbharu.hideout.core.service.job.JobQueueParentService import org.springframework.stereotype.Service interface APSendBlockService { - suspend fun sendBlock(user: User, target: User) + suspend fun sendBlock(actor: Actor, target: Actor) } @Service @@ -20,19 +20,19 @@ class ApSendBlockServiceImpl( private val jobQueueParentService: JobQueueParentService, private val deliverBlockJob: DeliverBlockJob ) : APSendBlockService { - override suspend fun sendBlock(user: User, target: User) { + override suspend fun sendBlock(actor: Actor, target: Actor) { val blockJobParam = DeliverBlockJobParam( - user.id, + actor.id, Block( - user.url, - "${applicationConfig.url}/block/${user.id}/${target.id}", + actor.url, + "${applicationConfig.url}/block/${actor.id}/${target.id}", target.url ), Reject( - user.url, - "${applicationConfig.url}/reject/${user.id}/${target.id}", + actor.url, + "${applicationConfig.url}/reject/${actor.id}/${target.id}", Follow( - apObject = user.url, + apObject = actor.url, actor = target.url ) ), diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt index 075bf893..e31f4e6c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/BlockActivityPubProcessor.kt @@ -5,7 +5,7 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.springframework.stereotype.Service @@ -14,14 +14,14 @@ import org.springframework.stereotype.Service */ @Service class BlockActivityPubProcessor( - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val relationshipService: RelationshipService, transaction: Transaction ) : AbstractActivityPubProcessor(transaction) { override suspend fun internalProcess(activity: ActivityPubProcessContext) { - val user = userQueryService.findByUrl(activity.activity.actor) - val target = userQueryService.findByUrl(activity.activity.apObject) + val user = actorQueryService.findByUrl(activity.activity.actor) + val target = actorQueryService.findByUrl(activity.activity.apObject) relationshipService.block(user.id, target.id) } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt index 226f2a63..0ba9413e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImpl.kt @@ -6,8 +6,8 @@ import dev.usbharu.hideout.activitypub.query.NoteQueryService import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.external.job.DeliverPostJob +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService -import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -17,7 +17,7 @@ class ApSendCreateServiceImpl( private val followerQueryService: FollowerQueryService, private val objectMapper: ObjectMapper, private val jobQueueParentService: JobQueueParentService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val noteQueryService: NoteQueryService, private val applicationConfig: ApplicationConfig ) : ApSendCreateService { @@ -25,11 +25,11 @@ class ApSendCreateServiceImpl( logger.info("CREATE Create Local Note ${post.url}") logger.debug("START Create Local Note ${post.url}") logger.trace("{}", post) - val followers = followerQueryService.findFollowersById(post.userId) + val followers = followerQueryService.findFollowersById(post.actorId) logger.debug("DELIVER Deliver Note Create ${followers.size} accounts.") - val userEntity = userQueryService.findById(post.userId) + val userEntity = actorQueryService.findById(post.actorId) val note = noteQueryService.findById(post.id).first val create = Create( name = "Create Note", diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt index 1f79af46..292f0ee2 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APReceiveFollowJobProcessor.kt @@ -7,7 +7,7 @@ import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.external.job.ReceiveFollowJob import dev.usbharu.hideout.core.external.job.ReceiveFollowJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.slf4j.LoggerFactory @@ -16,7 +16,7 @@ import org.springframework.stereotype.Service @Service class APReceiveFollowJobProcessor( private val transaction: Transaction, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val apUserService: APUserService, private val objectMapper: ObjectMapper, private val relationshipService: RelationshipService @@ -28,9 +28,9 @@ class APReceiveFollowJobProcessor( logger.info("START Follow from: {} to {}", param.targetActor, param.actor) - val targetEntity = userQueryService.findByUrl(param.targetActor) + val targetEntity = actorQueryService.findByUrl(param.targetActor) val followActorEntity = - userQueryService.findByUrl(follow.actor) + actorQueryService.findByUrl(follow.actor) relationshipService.followRequest(followActorEntity.id, targetEntity.id) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowService.kt index 825ec198..87ad7cd7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowService.kt @@ -15,10 +15,10 @@ class APSendFollowServiceImpl( ) : APSendFollowService { override suspend fun sendFollow(sendFollowDto: SendFollowDto) { val follow = Follow( - apObject = sendFollowDto.followTargetUserId.url, - actor = sendFollowDto.userId.url + apObject = sendFollowDto.followTargetActorId.url, + actor = sendFollowDto.actorId.url ) - apRequestService.apPost(sendFollowDto.followTargetUserId.inbox, follow, sendFollowDto.userId) + apRequestService.apPost(sendFollowDto.followTargetActorId.inbox, follow, sendFollowDto.actorId) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt index 53063c50..1995cf83 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionService.kt @@ -4,9 +4,9 @@ import com.fasterxml.jackson.databind.ObjectMapper import dev.usbharu.hideout.core.domain.model.reaction.Reaction import dev.usbharu.hideout.core.external.job.DeliverReactionJob import dev.usbharu.hideout.core.external.job.DeliverRemoveReactionJob +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.PostQueryService -import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service @@ -19,14 +19,14 @@ interface APReactionService { @Service class APReactionServiceImpl( private val jobQueueParentService: JobQueueParentService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val followerQueryService: FollowerQueryService, private val postQueryService: PostQueryService, @Qualifier("activitypub") private val objectMapper: ObjectMapper ) : APReactionService { override suspend fun reaction(like: Reaction) { - val followers = followerQueryService.findFollowersById(like.userId) - val user = userQueryService.findById(like.userId) + val followers = followerQueryService.findFollowersById(like.actorId) + val user = actorQueryService.findById(like.actorId) val post = postQueryService.findById(like.postId) followers.forEach { follower -> @@ -41,8 +41,8 @@ class APReactionServiceImpl( } override suspend fun removeReaction(like: Reaction) { - val followers = followerQueryService.findFollowersById(like.userId) - val user = userQueryService.findById(like.userId) + val followers = followerQueryService.findFollowersById(like.actorId) + val user = actorQueryService.findById(like.actorId) val post = postQueryService.findById(like.postId) followers.forEach { follower -> diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt index 1487eb56..e7857e8e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApReactionJobProcessor.kt @@ -6,19 +6,19 @@ import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.external.job.DeliverReactionJob import dev.usbharu.hideout.core.external.job.DeliverReactionJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service @Service class ApReactionJobProcessor( - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val apRequestService: APRequestService, private val applicationConfig: ApplicationConfig, private val transaction: Transaction ) : JobProcessor { override suspend fun process(param: DeliverReactionJobParam): Unit = transaction.transaction { - val signer = userQueryService.findByUrl(param.actor) + val signer = actorQueryService.findByUrl(param.actor) apRequestService.apPost( param.inbox, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt index 0409b9a0..5dd3e6e7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/ApRemoveReactionJobProcessor.kt @@ -9,14 +9,14 @@ import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.external.job.DeliverRemoveReactionJob import dev.usbharu.hideout.core.external.job.DeliverRemoveReactionJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service import java.time.Instant @Service class ApRemoveReactionJobProcessor( - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val transaction: Transaction, private val objectMapper: ObjectMapper, private val apRequestService: APRequestService, @@ -25,7 +25,7 @@ class ApRemoveReactionJobProcessor( override suspend fun process(param: DeliverRemoveReactionJobParam): Unit = transaction.transaction { val like = objectMapper.readValue(param.like) - val signer = userQueryService.findByUrl(param.actor) + val signer = actorQueryService.findByUrl(param.actor) apRequestService.apPost( param.inbox, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt index 575a34de..0ef702d5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/APDeliverRejectJobProcessor.kt @@ -4,20 +4,20 @@ import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.external.job.DeliverRejectJob import dev.usbharu.hideout.core.external.job.DeliverRejectJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Component @Component class APDeliverRejectJobProcessor( private val apRequestService: APRequestService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val deliverRejectJob: DeliverRejectJob, private val transaction: Transaction ) : JobProcessor { override suspend fun process(param: DeliverRejectJobParam): Unit = transaction.transaction { - apRequestService.apPost(param.inbox, param.reject, userQueryService.findById(param.signer)) + apRequestService.apPost(param.inbox, param.reject, actorQueryService.findById(param.signer)) } override fun job(): DeliverRejectJob = deliverRejectJob diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt index d86a583a..29bbd1f9 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApRejectProcessor.kt @@ -6,14 +6,14 @@ import dev.usbharu.hideout.activitypub.service.common.AbstractActivityPubProcess import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.springframework.stereotype.Service @Service class ApRejectProcessor( private val relationshipService: RelationshipService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, transaction: Transaction ) : AbstractActivityPubProcessor(transaction) { @@ -26,13 +26,13 @@ class ApRejectProcessor( } when (activityType) { "Follow" -> { - val user = userQueryService.findByUrl(activity.activity.actor) + val user = actorQueryService.findByUrl(activity.activity.actor) activity.activity.apObject as Follow val actor = activity.activity.apObject.actor - val target = userQueryService.findByUrl(actor) + val target = actorQueryService.findByUrl(actor) logger.debug("REJECT Follow user {} target {}", user.url, target.url) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectService.kt index ecb675c2..2be2e379 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectService.kt @@ -1,7 +1,7 @@ package dev.usbharu.hideout.activitypub.service.activity.reject -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor interface ApSendRejectService { - suspend fun sendRejectFollow(user: User, target: User) + suspend fun sendRejectFollow(actor: Actor, target: Actor) } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectServiceImpl.kt index fb7610bb..a5d8194c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/reject/ApSendRejectServiceImpl.kt @@ -3,7 +3,7 @@ package dev.usbharu.hideout.activitypub.service.activity.reject import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.domain.model.Reject import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.external.job.DeliverRejectJob import dev.usbharu.hideout.core.external.job.DeliverRejectJobParam import dev.usbharu.hideout.core.service.job.JobQueueParentService @@ -15,15 +15,15 @@ class ApSendRejectServiceImpl( private val jobQueueParentService: JobQueueParentService, private val deliverRejectJob: DeliverRejectJob ) : ApSendRejectService { - override suspend fun sendRejectFollow(user: User, target: User) { + override suspend fun sendRejectFollow(actor: Actor, target: Actor) { val deliverRejectJobParam = DeliverRejectJobParam( Reject( - user.url, - "${applicationConfig.url}/reject/${user.id}/${target.id}", - Follow(apObject = user.url, actor = target.url) + actor.url, + "${applicationConfig.url}/reject/${actor.id}/${target.id}", + Follow(apObject = actor.url, actor = target.url) ), target.inbox, - user.id + actor.id ) jobQueueParentService.scheduleTypeSafe(deliverRejectJob, deliverRejectJobParam) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt index d5f1fec2..70e31921 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APDeliverUndoJobProcessor.kt @@ -4,7 +4,7 @@ import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.external.job.DeliverUndoJob import dev.usbharu.hideout.core.external.job.DeliverUndoJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.springframework.stereotype.Service @@ -12,11 +12,11 @@ import org.springframework.stereotype.Service class APDeliverUndoJobProcessor( private val deliverUndoJob: DeliverUndoJob, private val apRequestService: APRequestService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val transaction: Transaction ) : JobProcessor { override suspend fun process(param: DeliverUndoJobParam): Unit = transaction.transaction { - apRequestService.apPost(param.inbox, param.undo, userQueryService.findById(param.signer)) + apRequestService.apPost(param.inbox, param.undo, actorQueryService.findById(param.signer)) } override fun job(): DeliverUndoJob = deliverUndoJob diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoService.kt index 827b186e..95114dd2 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoService.kt @@ -1,8 +1,8 @@ package dev.usbharu.hideout.activitypub.service.activity.undo -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor interface APSendUndoService { - suspend fun sendUndoFollow(user: User, target: User) - suspend fun sendUndoBlock(user: User, target: User) + suspend fun sendUndoFollow(actor: Actor, target: Actor) + suspend fun sendUndoBlock(actor: Actor, target: Actor) } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoServiceImpl.kt index e1d4c6fd..6d0f251a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APSendUndoServiceImpl.kt @@ -4,7 +4,7 @@ import dev.usbharu.hideout.activitypub.domain.model.Block import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.domain.model.Undo import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.external.job.DeliverUndoJob import dev.usbharu.hideout.core.external.job.DeliverUndoJobParam import dev.usbharu.hideout.core.service.job.JobQueueParentService @@ -17,38 +17,38 @@ class APSendUndoServiceImpl( private val deliverUndoJob: DeliverUndoJob, private val applicationConfig: ApplicationConfig ) : APSendUndoService { - override suspend fun sendUndoFollow(user: User, target: User) { + override suspend fun sendUndoFollow(actor: Actor, target: Actor) { val deliverUndoJobParam = DeliverUndoJobParam( Undo( - actor = user.url, - id = "${applicationConfig.url}/undo/follow/${user.id}/${target.url}", + actor = actor.url, + id = "${applicationConfig.url}/undo/follow/${actor.id}/${target.url}", apObject = Follow( - apObject = user.url, + apObject = actor.url, actor = target.url ), published = Instant.now().toString() ), target.inbox, - user.id + actor.id ) jobQueueParentService.scheduleTypeSafe(deliverUndoJob, deliverUndoJobParam) } - override suspend fun sendUndoBlock(user: User, target: User) { + override suspend fun sendUndoBlock(actor: Actor, target: Actor) { val deliverUndoJobParam = DeliverUndoJobParam( Undo( - actor = user.url, - id = "${applicationConfig.url}/undo/block/${user.id}/${target.url}", + actor = actor.url, + id = "${applicationConfig.url}/undo/block/${actor.id}/${target.url}", apObject = Block( - apObject = user.url, + apObject = actor.url, actor = target.url, - id = "${applicationConfig.url}/block/${user.id}/${target.id}" + id = "${applicationConfig.url}/block/${actor.id}/${target.id}" ), published = Instant.now().toString() ), target.inbox, - user.id + actor.id ) jobQueueParentService.scheduleTypeSafe(deliverUndoJob, deliverUndoJobParam) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt index f476ce36..888c31f7 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/activity/undo/APUndoProcessor.kt @@ -10,7 +10,7 @@ import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.activitypub.service.objects.user.APUserService import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.relationship.RelationshipService import org.springframework.stereotype.Service @@ -18,7 +18,7 @@ import org.springframework.stereotype.Service class APUndoProcessor( transaction: Transaction, private val apUserService: APUserService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val relationshipService: RelationshipService ) : AbstractActivityPubProcessor(transaction) { @@ -35,8 +35,8 @@ class APUndoProcessor( val follow = undo.apObject as Follow apUserService.fetchPerson(undo.actor, follow.apObject) - val follower = userQueryService.findByUrl(undo.actor) - val target = userQueryService.findByUrl(follow.apObject) + val follower = actorQueryService.findByUrl(undo.actor) + val target = actorQueryService.findByUrl(follow.apObject) relationshipService.unfollow(follower.id, target.id) return @@ -46,7 +46,7 @@ class APUndoProcessor( val block = undo.apObject as Block val blocker = apUserService.fetchPersonWithEntity(undo.actor, block.apObject).second - val target = userQueryService.findByUrl(block.apObject) + val target = actorQueryService.findByUrl(block.apObject) relationshipService.unblock(blocker.id, target.id) return @@ -65,7 +65,7 @@ class APUndoProcessor( } val accepter = apUserService.fetchPersonWithEntity(undo.actor, acceptObject).second - val target = userQueryService.findByUrl(acceptObject) + val target = actorQueryService.findByUrl(acceptObject) relationshipService.rejectFollowRequest(accepter.id, target.id) } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestService.kt index da3954f7..cbc478be 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestService.kt @@ -1,25 +1,25 @@ package dev.usbharu.hideout.activitypub.service.common import dev.usbharu.hideout.activitypub.domain.model.objects.Object -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor interface APRequestService { - suspend fun apGet(url: String, signer: User? = null, responseClass: Class): R + suspend fun apGet(url: String, signer: Actor? = null, responseClass: Class): R suspend fun apPost( url: String, body: T? = null, - signer: User? = null, + signer: Actor? = null, responseClass: Class ): R - suspend fun apPost(url: String, body: T? = null, signer: User? = null): String + suspend fun apPost(url: String, body: T? = null, signer: Actor? = null): String } -suspend inline fun APRequestService.apGet(url: String, signer: User? = null): R = +suspend inline fun APRequestService.apGet(url: String, signer: Actor? = null): R = apGet(url, signer, R::class.java) suspend inline fun APRequestService.apPost( url: String, body: T? = null, - signer: User? = null + signer: Actor? = null ): R = apPost(url, body, signer, R::class.java) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestServiceImpl.kt index 9721cf38..81bc968e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APRequestServiceImpl.kt @@ -2,7 +2,7 @@ package dev.usbharu.hideout.activitypub.service.common import com.fasterxml.jackson.databind.ObjectMapper import dev.usbharu.hideout.activitypub.domain.model.objects.Object -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.util.Base64Util import dev.usbharu.hideout.util.HttpUtil.Activity import dev.usbharu.hideout.util.RsaUtil @@ -33,7 +33,7 @@ class APRequestServiceImpl( @Qualifier("http") private val dateTimeFormatter: DateTimeFormatter, ) : APRequestService { - override suspend fun apGet(url: String, signer: User?, responseClass: Class): R { + override suspend fun apGet(url: String, signer: Actor?, responseClass: Class): R { logger.debug("START ActivityPub Request GET url: {}, signer: {}", url, signer?.url) val date = dateTimeFormatter.format(ZonedDateTime.now(ZoneId.of("GMT"))) val u = URL(url) @@ -57,7 +57,7 @@ class APRequestServiceImpl( private suspend fun apGetSign( date: String, u: URL, - signer: User, + signer: Actor, url: String ): HttpResponse { val headers = headers { @@ -100,14 +100,14 @@ class APRequestServiceImpl( override suspend fun apPost( url: String, body: T?, - signer: User?, + signer: Actor?, responseClass: Class ): R { val bodyAsText = apPost(url, body, signer) return objectMapper.readValue(bodyAsText, responseClass) } - override suspend fun apPost(url: String, body: T?, signer: User?): String { + override suspend fun apPost(url: String, body: T?, signer: Actor?): String { logger.debug("START ActivityPub Request POST url: {}, signer: {}", url, signer?.url) val requestBody = addContextIfNotNull(body) @@ -166,7 +166,7 @@ class APRequestServiceImpl( date: String, u: URL, digest: String, - signer: User, + signer: Actor, requestBody: String? ): HttpResponse { val headers = headers { diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveService.kt index 203d3159..70eaf063 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveService.kt @@ -1,14 +1,14 @@ package dev.usbharu.hideout.activitypub.service.common import dev.usbharu.hideout.activitypub.domain.model.objects.Object -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor interface APResourceResolveService { - suspend fun resolve(url: String, clazz: Class, singer: User?): T + suspend fun resolve(url: String, clazz: Class, singer: Actor?): T suspend fun resolve(url: String, clazz: Class, singerId: Long?): T } -suspend inline fun APResourceResolveService.resolve(url: String, singer: User?): T = +suspend inline fun APResourceResolveService.resolve(url: String, singer: Actor?): T = resolve(url, T::class.java, singer) suspend inline fun APResourceResolveService.resolve(url: String, singerId: Long?): T = diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt index 85099d84..ad24ec57 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImpl.kt @@ -1,8 +1,8 @@ package dev.usbharu.hideout.activitypub.service.common import dev.usbharu.hideout.activitypub.domain.model.objects.Object -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.domain.model.user.UserRepository +import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.service.resource.CacheManager import dev.usbharu.hideout.core.service.resource.ResolveResponse import org.springframework.stereotype.Service @@ -11,7 +11,7 @@ import java.io.InputStream @Service class APResourceResolveServiceImpl( private val apRequestService: APRequestService, - private val userRepository: UserRepository, + private val actorRepository: ActorRepository, private val cacheManager: CacheManager ) : APResourceResolveService { @@ -19,19 +19,19 @@ class APResourceResolveServiceImpl( override suspend fun resolve(url: String, clazz: Class, singerId: Long?): T = internalResolve(url, singerId, clazz) - override suspend fun resolve(url: String, clazz: Class, singer: User?): T = + override suspend fun resolve(url: String, clazz: Class, singer: Actor?): T = internalResolve(url, singer, clazz) private suspend fun internalResolve(url: String, singerId: Long?, clazz: Class): T { val key = genCacheKey(url, singerId) cacheManager.putCache(key) { - runResolve(url, singerId?.let { userRepository.findById(it) }, clazz) + runResolve(url, singerId?.let { actorRepository.findById(it) }, clazz) } return (cacheManager.getOrWait(key) as APResolveResponse).objects } - private suspend fun internalResolve(url: String, singer: User?, clazz: Class): T { + private suspend fun internalResolve(url: String, singer: Actor?, clazz: Class): T { val key = genCacheKey(url, singer?.id) cacheManager.putCache(key) { runResolve(url, singer, clazz) @@ -39,7 +39,7 @@ class APResourceResolveServiceImpl( return (cacheManager.getOrWait(key) as APResolveResponse).objects } - private suspend fun runResolve(url: String, singer: User?, clazz: Class): ResolveResponse = + private suspend fun runResolve(url: String, singer: Actor?, clazz: Class): ResolveResponse = APResolveResponse(apRequestService.apGet(url, singer, clazz)) private fun genCacheKey(url: String, singerId: Long?): String { diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt index ec25c727..bfaf72f1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/inbox/InboxJobProcessor.kt @@ -10,7 +10,7 @@ import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.external.job.InboxJob import dev.usbharu.hideout.core.external.job.InboxJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.httpsignature.common.HttpHeaders @@ -29,7 +29,7 @@ class InboxJobProcessor( private val objectMapper: ObjectMapper, private val signatureHeaderParser: SignatureHeaderParser, private val signatureVerifier: HttpSignatureVerifier, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val apUserService: APUserService, private val transaction: Transaction ) : JobProcessor { @@ -50,7 +50,7 @@ class InboxJobProcessor( val user = transaction.transaction { try { - userQueryService.findByKeyId(signature.keyId) + actorQueryService.findByKeyId(signature.keyId) } catch (_: FailedToGetResourcesException) { apUserService.fetchPersonWithEntity(signature.keyId).second } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt index 0e5b6e14..32a542d4 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteService.kt @@ -140,7 +140,7 @@ class APNoteServiceImpl( postService.createRemote( postBuilder.of( id = postRepository.generateId(), - userId = person.second.id, + actorId = person.second.id, text = note.content, createdAt = Instant.parse(note.published).toEpochMilli(), visibility = visibility, diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt index 181f869a..a9dbab74 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/ApNoteJobProcessor.kt @@ -7,7 +7,7 @@ import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.external.job.DeliverPostJob import dev.usbharu.hideout.core.external.job.DeliverPostJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.job.JobProcessor import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -16,13 +16,13 @@ import org.springframework.stereotype.Service class ApNoteJobProcessor( private val transaction: Transaction, private val objectMapper: ObjectMapper, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val apRequestService: APRequestService ) : JobProcessor { override suspend fun process(param: DeliverPostJobParam) { val create = objectMapper.readValue(param.create) transaction.transaction { - val signer = userQueryService.findByUrl(param.actor) + val signer = actorQueryService.findByUrl(param.actor) logger.debug("CreateNoteJob: actor: {} create: {} inbox: {}", param.actor, create, param.inbox) diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt index 079cc073..4420ceb0 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/NoteApApiServiceImpl.kt @@ -44,7 +44,7 @@ class NoteApApiServiceImpl( return null } - if (followerQueryService.alreadyFollow(findById.second.userId, userId)) { + if (followerQueryService.alreadyFollow(findById.second.actorId, userId)) { return findById.first } return null diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt index a7efb238..3b540ebb 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/objects/user/APUserService.kt @@ -9,8 +9,8 @@ import dev.usbharu.hideout.activitypub.service.common.resolve import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.user.RemoteUserCreateDto import dev.usbharu.hideout.core.service.user.UserService import org.springframework.stereotype.Service @@ -28,13 +28,13 @@ interface APUserService { */ suspend fun fetchPerson(url: String, targetActor: String? = null): Person - suspend fun fetchPersonWithEntity(url: String, targetActor: String? = null): Pair + suspend fun fetchPersonWithEntity(url: String, targetActor: String? = null): Pair } @Service class APUserServiceImpl( private val userService: UserService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val transaction: Transaction, private val applicationConfig: ApplicationConfig, private val apResourceResolveService: APResourceResolveService @@ -43,7 +43,7 @@ class APUserServiceImpl( override suspend fun getPersonByName(name: String): Person { val userEntity = transaction.transaction { - userQueryService.findByNameAndDomain(name, applicationConfig.url.host) + actorQueryService.findByNameAndDomain(name, applicationConfig.url.host) } // TODO: JOINで書き直し val userUrl = "${applicationConfig.url}/users/$name" @@ -68,7 +68,8 @@ class APUserServiceImpl( ), endpoints = mapOf("sharedInbox" to "${applicationConfig.url}/inbox"), followers = userEntity.followers, - following = userEntity.following + following = userEntity.following, + manuallyApprovesFollowers = userEntity.locked ) } @@ -76,9 +77,9 @@ class APUserServiceImpl( fetchPersonWithEntity(url, targetActor).first @Transactional - override suspend fun fetchPersonWithEntity(url: String, targetActor: String?): Pair { + override suspend fun fetchPersonWithEntity(url: String, targetActor: String?): Pair { return try { - val userEntity = userQueryService.findByUrl(url) + val userEntity = actorQueryService.findByUrl(url) val id = userEntity.url return entityToPerson(userEntity, id) to userEntity } catch (ignore: FailedToGetResourcesException) { @@ -86,7 +87,7 @@ class APUserServiceImpl( val id = person.id try { - val userEntity = userQueryService.findByUrl(id) + val userEntity = actorQueryService.findByUrl(id) return entityToPerson(userEntity, id) to userEntity } catch (_: FailedToGetResourcesException) { } @@ -104,21 +105,22 @@ class APUserServiceImpl( keyId = person.publicKey.id, following = person.following, followers = person.followers, - sharedInbox = person.endpoints["sharedInbox"] + sharedInbox = person.endpoints["sharedInbox"], + locked = person.manuallyApprovesFollowers ) ) } } private fun entityToPerson( - userEntity: User, + actorEntity: Actor, id: String ) = Person( type = emptyList(), - name = userEntity.name, + name = actorEntity.name, id = id, - preferredUsername = userEntity.name, - summary = userEntity.description, + preferredUsername = actorEntity.name, + summary = actorEntity.description, inbox = "$id/inbox", outbox = "$id/outbox", url = id, @@ -128,12 +130,13 @@ class APUserServiceImpl( url = "$id/icon.jpg" ), publicKey = Key( - id = userEntity.keyId, + id = actorEntity.keyId, owner = id, - publicKeyPem = userEntity.publicKey + publicKeyPem = actorEntity.publicKey ), endpoints = mapOf("sharedInbox" to "${applicationConfig.url}/inbox"), - followers = userEntity.followers, - following = userEntity.following + followers = actorEntity.followers, + following = actorEntity.following, + manuallyApprovesFollowers = actorEntity.locked ) } diff --git a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt index d4af15fa..1cdd8230 100644 --- a/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/activitypub/service/webfinger/WebFingerApiService.kt @@ -1,21 +1,21 @@ package dev.usbharu.hideout.activitypub.service.webfinger import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.query.ActorQueryService import org.springframework.stereotype.Service @Service interface WebFingerApiService { - suspend fun findByNameAndDomain(name: String, domain: String): User + suspend fun findByNameAndDomain(name: String, domain: String): Actor } @Service -class WebFingerApiServiceImpl(private val transaction: Transaction, private val userQueryService: UserQueryService) : +class WebFingerApiServiceImpl(private val transaction: Transaction, private val actorQueryService: ActorQueryService) : WebFingerApiService { - override suspend fun findByNameAndDomain(name: String, domain: String): User { + override suspend fun findByNameAndDomain(name: String, domain: String): Actor { return transaction.transaction { - userQueryService.findByNameAndDomain(name, domain) + actorQueryService.findByNameAndDomain(name, domain) } } } diff --git a/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt b/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt index 08059d2d..144379c9 100644 --- a/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt +++ b/src/main/kotlin/dev/usbharu/hideout/application/config/SecurityConfig.kt @@ -12,7 +12,7 @@ import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.Htt import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureVerifierComposite import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.UserDetailsImpl import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.UserDetailsServiceImpl -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.hideout.util.hasAnyScope import dev.usbharu.httpsignature.sign.RsaSha256HttpSignatureSigner @@ -69,7 +69,7 @@ import java.util.* class SecurityConfig { @Autowired - private lateinit var userQueryService: UserQueryService + private lateinit var actorQueryService: ActorQueryService @Bean fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager? = @@ -135,7 +135,7 @@ class SecurityConfig { val signatureHeaderParser = DefaultSignatureHeaderParser() provider.setPreAuthenticatedUserDetailsService( HttpSignatureUserDetailsService( - userQueryService, + actorQueryService, HttpSignatureVerifierComposite( mapOf( "rsa-sha256" to RsaSha256HttpSignatureVerifier( diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/Acct.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Acct.kt similarity index 67% rename from src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/Acct.kt rename to src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Acct.kt index f4ea0cdc..d3777741 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/Acct.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Acct.kt @@ -1,3 +1,3 @@ -package dev.usbharu.hideout.core.domain.model.user +package dev.usbharu.hideout.core.domain.model.actor data class Acct(val username: String, val domain: String? = null, val isRemote: Boolean = domain == null) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/User.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt similarity index 84% rename from src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/User.kt rename to src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt index 4c2ded1c..9f0fba72 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/User.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.core.domain.model.user +package dev.usbharu.hideout.core.domain.model.actor import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.config.CharacterLimit @@ -6,13 +6,12 @@ import org.slf4j.LoggerFactory import org.springframework.stereotype.Component import java.time.Instant -data class User private constructor( +data class Actor private constructor( val id: Long, val name: String, val domain: String, val screenName: String, val description: String, - val password: String? = null, val inbox: String, val outbox: String, val url: String, @@ -22,13 +21,9 @@ data class User private constructor( val keyId: String, val followers: String? = null, val following: String? = null, - val instance: Long? = null + val instance: Long? = null, + val locked: Boolean ) { - override fun toString(): String = - "User(id=$id, name='$name', domain='$domain', screenName='$screenName', description='$description'," + - " password=$password, inbox='$inbox', outbox='$outbox', url='$url', publicKey='$publicKey', " + - "privateKey=$privateKey, createdAt=$createdAt, keyId='$keyId', followers=$followers," + - " following=$following, instance=$instance)" @Component class UserBuilder(private val characterLimit: CharacterLimit, private val applicationConfig: ApplicationConfig) { @@ -42,7 +37,6 @@ data class User private constructor( domain: String, screenName: String, description: String, - password: String? = null, inbox: String, outbox: String, url: String, @@ -52,8 +46,9 @@ data class User private constructor( keyId: String, following: String? = null, followers: String? = null, - instance: Long? = null - ): User { + instance: Long? = null, + locked: Boolean + ): Actor { // idは0未満ではいけない require(id >= 0) { "id must be greater than or equal to 0." } @@ -97,7 +92,6 @@ data class User private constructor( // ローカルユーザーはpasswordとprivateKeyをnullにしてはいけない if (domain == applicationConfig.url.host) { - requireNotNull(password) { "password and privateKey must not be null for local users." } requireNotNull(privateKey) { "password and privateKey must not be null for local users." } } @@ -129,13 +123,12 @@ data class User private constructor( "keyId must contain non-blank characters." } - return User( + return Actor( id = id, name = limitedName, domain = domain, screenName = limitedScreenName, description = limitedDescription, - password = password, inbox = inbox, outbox = outbox, url = url, @@ -145,8 +138,30 @@ data class User private constructor( keyId = keyId, followers = followers, following = following, - instance = instance + instance = instance, + locked ) } } + + 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" + + ")" + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/ActorRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/ActorRepository.kt new file mode 100644 index 00000000..39887a5e --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/ActorRepository.kt @@ -0,0 +1,14 @@ +package dev.usbharu.hideout.core.domain.model.actor + +import org.springframework.stereotype.Repository + +@Repository +interface ActorRepository { + suspend fun save(actor: Actor): Actor + + suspend fun findById(id: Long): Actor? + + suspend fun delete(id: Long) + + suspend fun nextId(): Long +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt index e9e2f043..3a5989ab 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/post/Post.kt @@ -5,7 +5,7 @@ import org.springframework.stereotype.Component data class Post private constructor( val id: Long, - val userId: Long, + val actorId: Long, val overview: String? = null, val text: String, val createdAt: Long, @@ -23,7 +23,7 @@ data class Post private constructor( @Suppress("FunctionMinLength", "LongParameterList") fun of( id: Long, - userId: Long, + actorId: Long, overview: String? = null, text: String, createdAt: Long, @@ -37,7 +37,7 @@ data class Post private constructor( ): Post { require(id >= 0) { "id must be greater than or equal to 0." } - require(userId >= 0) { "userId must be greater than or equal to 0." } + require(actorId >= 0) { "actorId must be greater than or equal to 0." } val limitedOverview = if ((overview?.length ?: 0) >= characterLimit.post.overview) { overview?.substring(0, characterLimit.post.overview) @@ -61,7 +61,7 @@ data class Post private constructor( return Post( id = id, - userId = userId, + actorId = actorId, overview = limitedOverview, text = limitedText, createdAt = createdAt, diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/reaction/Reaction.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/reaction/Reaction.kt index b84c1a2e..02997373 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/reaction/Reaction.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/reaction/Reaction.kt @@ -1,3 +1,3 @@ package dev.usbharu.hideout.core.domain.model.reaction -data class Reaction(val id: Long, val emojiId: Long, val postId: Long, val userId: Long) +data class Reaction(val id: Long, val emojiId: Long, val postId: Long, val actorId: Long) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt index 51a3da60..ad9b9635 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt @@ -3,20 +3,20 @@ package dev.usbharu.hideout.core.domain.model.relationship /** * ユーザーとの関係を表します * - * @property userId ユーザー - * @property targetUserId 相手ユーザー + * @property actorId ユーザー + * @property targetActorId 相手ユーザー * @property following フォローしているか * @property blocking ブロックしているか * @property muting ミュートしているか * @property followRequest フォローリクエストを送っているか - * @property ignoreFollowRequestFromTarget フォローリクエストを無視しているか + * @property ignoreFollowRequestToTarget フォローリクエストを無視しているか */ data class Relationship( - val userId: Long, - val targetUserId: Long, + val actorId: Long, + val targetActorId: Long, val following: Boolean, val blocking: Boolean, val muting: Boolean, val followRequest: Boolean, - val ignoreFollowRequestFromTarget: Boolean + val ignoreFollowRequestToTarget: Boolean ) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt index 4b3fc6bc..75da4e35 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepository.kt @@ -23,9 +23,9 @@ interface RelationshipRepository { /** * userIdとtargetUserIdで[Relationship]を取得します * - * @param userId 取得するユーザーID - * @param targetUserId 対象ユーザーID + * @param actorId 取得するユーザーID + * @param targetActorId 対象ユーザーID * @return 取得された[Relationship] 存在しない場合nullが返ります */ - suspend fun findByUserIdAndTargetUserId(userId: Long, targetUserId: Long): Relationship? + suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship? } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt index c7e6986d..09be85c8 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipRepositoryImpl.kt @@ -1,6 +1,6 @@ package dev.usbharu.hideout.core.domain.model.relationship -import dev.usbharu.hideout.core.infrastructure.exposedrepository.Users +import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors import org.jetbrains.exposed.dao.id.LongIdTable import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq @@ -12,32 +12,32 @@ class RelationshipRepositoryImpl : RelationshipRepository { val singleOrNull = Relationships .select { - (Relationships.userId eq relationship.userId) - .and(Relationships.targetUserId eq relationship.targetUserId) + (Relationships.actorId eq relationship.actorId) + .and(Relationships.targetActorId eq relationship.targetActorId) } .singleOrNull() if (singleOrNull == null) { Relationships.insert { - it[userId] = relationship.userId - it[targetUserId] = relationship.targetUserId + it[actorId] = relationship.actorId + it[targetActorId] = relationship.targetActorId it[following] = relationship.following it[blocking] = relationship.blocking it[muting] = relationship.muting it[followRequest] = relationship.followRequest - it[ignoreFollowRequestFromTarget] = relationship.ignoreFollowRequestFromTarget + it[ignoreFollowRequestFromTarget] = relationship.ignoreFollowRequestToTarget } } else { Relationships .update({ - (Relationships.userId eq relationship.userId) - .and(Relationships.targetUserId eq relationship.targetUserId) + (Relationships.actorId eq relationship.actorId) + .and(Relationships.targetActorId eq relationship.targetActorId) }) { it[following] = relationship.following it[blocking] = relationship.blocking it[muting] = relationship.muting it[followRequest] = relationship.followRequest - it[ignoreFollowRequestFromTarget] = relationship.ignoreFollowRequestFromTarget + it[ignoreFollowRequestFromTarget] = relationship.ignoreFollowRequestToTarget } } return relationship @@ -45,33 +45,33 @@ class RelationshipRepositoryImpl : RelationshipRepository { override suspend fun delete(relationship: Relationship) { Relationships.deleteWhere { - (Relationships.userId eq relationship.userId) - .and(Relationships.targetUserId eq relationship.targetUserId) + (Relationships.actorId eq relationship.actorId) + .and(Relationships.targetActorId eq relationship.targetActorId) } } - override suspend fun findByUserIdAndTargetUserId(userId: Long, targetUserId: Long): Relationship? { + override suspend fun findByUserIdAndTargetUserId(actorId: Long, targetActorId: Long): Relationship? { return Relationships.select { - (Relationships.userId eq userId) - .and(Relationships.targetUserId eq targetUserId) + (Relationships.actorId eq actorId) + .and(Relationships.targetActorId eq targetActorId) }.singleOrNull() ?.toRelationships() } } fun ResultRow.toRelationships(): Relationship = Relationship( - userId = this[Relationships.userId], - targetUserId = this[Relationships.targetUserId], + actorId = this[Relationships.actorId], + targetActorId = this[Relationships.targetActorId], following = this[Relationships.following], blocking = this[Relationships.blocking], muting = this[Relationships.muting], followRequest = this[Relationships.followRequest], - ignoreFollowRequestFromTarget = this[Relationships.ignoreFollowRequestFromTarget] + ignoreFollowRequestToTarget = this[Relationships.ignoreFollowRequestFromTarget] ) object Relationships : LongIdTable("relationships") { - val userId = long("user_id").references(Users.id) - val targetUserId = long("target_user_id").references(Users.id) + val actorId = long("actor_id").references(Actors.id) + val targetActorId = long("target_actor_id").references(Actors.id) val following = bool("following") val blocking = bool("blocking") val muting = bool("muting") @@ -79,6 +79,6 @@ object Relationships : LongIdTable("relationships") { val ignoreFollowRequestFromTarget = bool("ignore_follow_request") init { - uniqueIndex(userId, targetUserId) + uniqueIndex(actorId, targetActorId) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/Timeline.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/Timeline.kt index 5a08816e..cc9b181e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/Timeline.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/timeline/Timeline.kt @@ -13,7 +13,7 @@ data class Timeline( val userId: Long, val timelineId: Long, val postId: Long, - val postUserId: Long, + val postActorId: Long, val createdAt: Long, val replyId: Long?, val repostId: Long?, diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/UserRepository.kt deleted file mode 100644 index f37d45fe..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/user/UserRepository.kt +++ /dev/null @@ -1,14 +0,0 @@ -package dev.usbharu.hideout.core.domain.model.user - -import org.springframework.stereotype.Repository - -@Repository -interface UserRepository { - suspend fun save(user: User): User - - suspend fun findById(id: Long): User? - - suspend fun delete(id: Long) - - suspend fun nextId(): Long -} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/userdetails/UserDetail.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/userdetails/UserDetail.kt new file mode 100644 index 00000000..648ccf7e --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/userdetails/UserDetail.kt @@ -0,0 +1,7 @@ +package dev.usbharu.hideout.core.domain.model.userdetails + +data class UserDetail( + val actorId: Long, + val password: String, + val autoAcceptFolloweeFollowRequest: Boolean +) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/userdetails/UserDetailRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/userdetails/UserDetailRepository.kt new file mode 100644 index 00000000..01041ae2 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/userdetails/UserDetailRepository.kt @@ -0,0 +1,7 @@ +package dev.usbharu.hideout.core.domain.model.userdetails + +interface UserDetailRepository { + suspend fun save(userDetail: UserDetail): UserDetail + suspend fun delete(userDetail: UserDetail) + suspend fun findByActorId(actorId: Long): UserDetail? +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostResultRowMapper.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostResultRowMapper.kt index 8505a44d..88b4e50c 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostResultRowMapper.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/PostResultRowMapper.kt @@ -12,7 +12,7 @@ class PostResultRowMapper(private val postBuilder: Post.PostBuilder) : ResultRow override fun map(resultRow: ResultRow): Post { return postBuilder.of( id = resultRow[Posts.id], - userId = resultRow[Posts.userId], + actorId = resultRow[Posts.actorId], overview = resultRow[Posts.overview], text = resultRow[Posts.text], createdAt = resultRow[Posts.createdAt], diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserQueryMapper.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserQueryMapper.kt index 7361815c..c63239d5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserQueryMapper.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposed/UserQueryMapper.kt @@ -2,11 +2,11 @@ package dev.usbharu.hideout.core.infrastructure.exposed import dev.usbharu.hideout.application.infrastructure.exposed.QueryMapper import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import org.jetbrains.exposed.sql.Query import org.springframework.stereotype.Component @Component -class UserQueryMapper(private val userResultRowMapper: ResultRowMapper) : QueryMapper { - override fun map(query: Query): List = query.map(userResultRowMapper::map) +class UserQueryMapper(private val actorResultRowMapper: ResultRowMapper) : QueryMapper { + override fun map(query: Query): List = query.map(actorResultRowMapper::map) } 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 bad247f3..abf8d880 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 @@ -1,32 +1,32 @@ package dev.usbharu.hideout.core.infrastructure.exposed import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.infrastructure.exposedrepository.Users +import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors import org.jetbrains.exposed.sql.ResultRow import org.springframework.stereotype.Component import java.time.Instant @Component -class UserResultRowMapper(private val userBuilder: User.UserBuilder) : ResultRowMapper { - override fun map(resultRow: ResultRow): User { - return userBuilder.of( - id = resultRow[Users.id], - name = resultRow[Users.name], - domain = resultRow[Users.domain], - screenName = resultRow[Users.screenName], - description = resultRow[Users.description], - password = resultRow[Users.password], - inbox = resultRow[Users.inbox], - outbox = resultRow[Users.outbox], - url = resultRow[Users.url], - publicKey = resultRow[Users.publicKey], - privateKey = resultRow[Users.privateKey], - createdAt = Instant.ofEpochMilli((resultRow[Users.createdAt])), - keyId = resultRow[Users.keyId], - followers = resultRow[Users.followers], - following = resultRow[Users.following], - instance = resultRow[Users.instance] +class UserResultRowMapper(private val actorBuilder: Actor.UserBuilder) : ResultRowMapper { + override fun map(resultRow: ResultRow): Actor { + return actorBuilder.of( + id = resultRow[Actors.id], + name = resultRow[Actors.name], + domain = resultRow[Actors.domain], + screenName = resultRow[Actors.screenName], + description = resultRow[Actors.description], + inbox = resultRow[Actors.inbox], + outbox = resultRow[Actors.outbox], + url = resultRow[Actors.url], + publicKey = resultRow[Actors.publicKey], + privateKey = resultRow[Actors.privateKey], + createdAt = Instant.ofEpochMilli((resultRow[Actors.createdAt])), + keyId = resultRow[Actors.keyId], + followers = resultRow[Actors.followers], + following = resultRow[Actors.following], + instance = resultRow[Actors.instance], + locked = resultRow[Actors.locked] ) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ActorQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ActorQueryServiceImpl.kt new file mode 100644 index 00000000..6dab78c2 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ActorQueryServiceImpl.kt @@ -0,0 +1,60 @@ +package dev.usbharu.hideout.core.infrastructure.exposedquery + +import dev.usbharu.hideout.application.infrastructure.exposed.QueryMapper +import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper +import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.infrastructure.exposedrepository.Actors +import dev.usbharu.hideout.core.query.ActorQueryService +import dev.usbharu.hideout.util.singleOr +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.select +import org.jetbrains.exposed.sql.selectAll +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Repository + +@Repository +class ActorQueryServiceImpl( + private val actorResultRowMapper: ResultRowMapper, + private val actorQueryMapper: QueryMapper +) : ActorQueryService { + + private val logger = LoggerFactory.getLogger(ActorQueryServiceImpl::class.java) + + override suspend fun findAll(limit: Int, offset: Long): List = + Actors.selectAll().limit(limit, offset).let(actorQueryMapper::map) + + override suspend fun findById(id: Long): Actor = Actors.select { Actors.id eq id } + .singleOr { FailedToGetResourcesException("id: $id is duplicate or does not exist.", it) } + .let(actorResultRowMapper::map) + + override suspend fun findByName(name: String): List = + Actors.select { Actors.name eq name }.let(actorQueryMapper::map) + + override suspend fun findByNameAndDomain(name: String, domain: String): Actor = + Actors + .select { Actors.name eq name and (Actors.domain eq domain) } + .singleOr { + FailedToGetResourcesException("name: $name,domain: $domain is duplicate or does not exist.", it) + } + .let(actorResultRowMapper::map) + + override suspend fun findByUrl(url: String): Actor { + logger.trace("findByUrl url: $url") + return Actors.select { Actors.url eq url } + .singleOr { FailedToGetResourcesException("url: $url is duplicate or does not exist.", it) } + .let(actorResultRowMapper::map) + } + + override suspend fun findByIds(ids: List): List = + Actors.select { Actors.id inList ids }.let(actorQueryMapper::map) + + override suspend fun existByNameAndDomain(name: String, domain: String): Boolean = + Actors.select { Actors.name eq name and (Actors.domain eq domain) }.empty().not() + + override suspend fun findByKeyId(keyId: String): Actor { + return Actors.select { Actors.keyId eq keyId } + .singleOr { FailedToGetResourcesException("keyId: $keyId is duplicate or does not exist.", it) } + .let(actorResultRowMapper::map) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt index df5acb77..f7161b2e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/FollowerQueryServiceImpl.kt @@ -1,24 +1,24 @@ package dev.usbharu.hideout.core.infrastructure.exposedquery +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService import dev.usbharu.hideout.core.query.RelationshipQueryService -import dev.usbharu.hideout.core.query.UserQueryService import org.springframework.stereotype.Repository @Repository class FollowerQueryServiceImpl( private val relationshipQueryService: RelationshipQueryService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val relationshipRepository: RelationshipRepository ) : FollowerQueryService { - override suspend fun findFollowersById(id: Long): List { - return userQueryService.findByIds( - relationshipQueryService.findByTargetIdAndFollowing(id, true).map { it.userId } + override suspend fun findFollowersById(id: Long): List { + return actorQueryService.findByIds( + relationshipQueryService.findByTargetIdAndFollowing(id, true).map { it.actorId } ) } - override suspend fun alreadyFollow(userId: Long, followerId: Long): Boolean = - relationshipRepository.findByUserIdAndTargetUserId(followerId, userId)?.following ?: false + override suspend fun alreadyFollow(actorId: Long, followerId: Long): Boolean = + relationshipRepository.findByUserIdAndTargetUserId(followerId, actorId)?.following ?: false } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt index 2f710361..b7bd1642 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ReactionQueryServiceImpl.kt @@ -6,44 +6,46 @@ import dev.usbharu.hideout.core.infrastructure.exposedrepository.Reactions import dev.usbharu.hideout.core.infrastructure.exposedrepository.toReaction import dev.usbharu.hideout.core.query.ReactionQueryService import dev.usbharu.hideout.util.singleOr -import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.deleteWhere +import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Repository @Repository class ReactionQueryServiceImpl : ReactionQueryService { - override suspend fun findByPostId(postId: Long, userId: Long?): List { + override suspend fun findByPostId(postId: Long, actorId: Long?): List { return Reactions.select { Reactions.postId.eq(postId) }.map { it.toReaction() } } @Suppress("FunctionMaxLength") - override suspend fun findByPostIdAndUserIdAndEmojiId(postId: Long, userId: Long, emojiId: Long): Reaction { + override suspend fun findByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Reaction { return Reactions .select { - Reactions.postId.eq(postId).and(Reactions.userId.eq(userId)).and( + Reactions.postId.eq(postId).and(Reactions.actorId.eq(actorId)).and( Reactions.emojiId.eq(emojiId) ) } .singleOr { FailedToGetResourcesException( - "postId: $postId,userId: $userId,emojiId: $emojiId is duplicate or does not exist.", + "postId: $postId,userId: $actorId,emojiId: $emojiId is duplicate or does not exist.", it ) } .toReaction() } - override suspend fun reactionAlreadyExist(postId: Long, userId: Long, emojiId: Long): Boolean { + override suspend fun reactionAlreadyExist(postId: Long, actorId: Long, emojiId: Long): Boolean { return Reactions.select { - Reactions.postId.eq(postId).and(Reactions.userId.eq(userId)).and( + Reactions.postId.eq(postId).and(Reactions.actorId.eq(actorId)).and( Reactions.emojiId.eq(emojiId) ) }.empty().not() } - override suspend fun deleteByPostIdAndUserId(postId: Long, userId: Long) { - Reactions.deleteWhere { Reactions.postId.eq(postId).and(Reactions.userId.eq(userId)) } + override suspend fun deleteByPostIdAndActorId(postId: Long, actorId: Long) { + Reactions.deleteWhere { Reactions.postId.eq(postId).and(Reactions.actorId.eq(actorId)) } } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/RelationshipQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/RelationshipQueryServiceImpl.kt index f1a122c9..43d8206a 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/RelationshipQueryServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/RelationshipQueryServiceImpl.kt @@ -5,12 +5,39 @@ import dev.usbharu.hideout.core.domain.model.relationship.Relationships import dev.usbharu.hideout.core.domain.model.relationship.toRelationships import dev.usbharu.hideout.core.query.RelationshipQueryService import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.select import org.springframework.stereotype.Service @Service class RelationshipQueryServiceImpl : RelationshipQueryService { override suspend fun findByTargetIdAndFollowing(targetId: Long, following: Boolean): List = - Relationships.select { Relationships.targetUserId eq targetId and (Relationships.following eq following) } + Relationships.select { Relationships.targetActorId eq targetId and (Relationships.following eq following) } .map { it.toRelationships() } + + override suspend fun findByTargetIdAndFollowRequestAndIgnoreFollowRequest( + maxId: Long?, + sinceId: Long?, + limit: Int, + targetId: Long, + followRequest: Boolean, + ignoreFollowRequest: Boolean + ): List { + val query = Relationships + .select { + Relationships.targetActorId.eq(targetId) + .and(Relationships.followRequest.eq(followRequest)) + .and(Relationships.ignoreFollowRequestFromTarget.eq(ignoreFollowRequest)) + }.limit(limit) + + if (maxId != null) { + query.andWhere { Relationships.id greater maxId } + } + + if (sinceId != null) { + query.andWhere { Relationships.id less sinceId } + } + + return query.map { it.toRelationships() } + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/UserQueryServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/UserQueryServiceImpl.kt deleted file mode 100644 index e2a580e8..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/UserQueryServiceImpl.kt +++ /dev/null @@ -1,60 +0,0 @@ -package dev.usbharu.hideout.core.infrastructure.exposedquery - -import dev.usbharu.hideout.application.infrastructure.exposed.QueryMapper -import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper -import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.infrastructure.exposedrepository.Users -import dev.usbharu.hideout.core.query.UserQueryService -import dev.usbharu.hideout.util.singleOr -import org.jetbrains.exposed.sql.and -import org.jetbrains.exposed.sql.select -import org.jetbrains.exposed.sql.selectAll -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Repository - -@Repository -class UserQueryServiceImpl( - private val userResultRowMapper: ResultRowMapper, - private val userQueryMapper: QueryMapper -) : UserQueryService { - - private val logger = LoggerFactory.getLogger(UserQueryServiceImpl::class.java) - - override suspend fun findAll(limit: Int, offset: Long): List = - Users.selectAll().limit(limit, offset).let(userQueryMapper::map) - - override suspend fun findById(id: Long): User = Users.select { Users.id eq id } - .singleOr { FailedToGetResourcesException("id: $id is duplicate or does not exist.", it) } - .let(userResultRowMapper::map) - - override suspend fun findByName(name: String): List = - Users.select { Users.name eq name }.let(userQueryMapper::map) - - override suspend fun findByNameAndDomain(name: String, domain: String): User = - Users - .select { Users.name eq name and (Users.domain eq domain) } - .singleOr { - FailedToGetResourcesException("name: $name,domain: $domain is duplicate or does not exist.", it) - } - .let(userResultRowMapper::map) - - override suspend fun findByUrl(url: String): User { - logger.trace("findByUrl url: $url") - return Users.select { Users.url eq url } - .singleOr { FailedToGetResourcesException("url: $url is duplicate or does not exist.", it) } - .let(userResultRowMapper::map) - } - - override suspend fun findByIds(ids: List): List = - Users.select { Users.id inList ids }.let(userQueryMapper::map) - - override suspend fun existByNameAndDomain(name: String, domain: String): Boolean = - Users.select { Users.name eq name and (Users.domain eq domain) }.empty().not() - - override suspend fun findByKeyId(keyId: String): User { - return Users.select { Users.keyId eq keyId } - .singleOr { FailedToGetResourcesException("keyId: $keyId is duplicate or does not exist.", it) } - .let(userResultRowMapper::map) - } -} 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 new file mode 100644 index 00000000..0eb59b59 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt @@ -0,0 +1,100 @@ +package dev.usbharu.hideout.core.infrastructure.exposedrepository + +import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper +import dev.usbharu.hideout.application.service.id.IdGenerateService +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.springframework.stereotype.Repository + +@Repository +class ActorRepositoryImpl( + private val idGenerateService: IdGenerateService, + private val actorResultRowMapper: ResultRowMapper +) : + ActorRepository { + + override suspend fun save(actor: Actor): Actor { + val singleOrNull = Actors.select { Actors.id eq actor.id }.empty() + if (singleOrNull) { + Actors.insert { + it[id] = actor.id + it[name] = actor.name + it[domain] = actor.domain + it[screenName] = actor.screenName + it[description] = actor.description + it[inbox] = actor.inbox + it[outbox] = actor.outbox + it[url] = actor.url + it[createdAt] = actor.createdAt.toEpochMilli() + it[publicKey] = actor.publicKey + it[privateKey] = actor.privateKey + it[keyId] = actor.keyId + it[following] = actor.following + it[followers] = actor.followers + it[instance] = actor.instance + it[locked] = actor.locked + } + } else { + Actors.update({ Actors.id eq actor.id }) { + it[name] = actor.name + it[domain] = actor.domain + it[screenName] = actor.screenName + it[description] = actor.description + it[inbox] = actor.inbox + it[outbox] = actor.outbox + it[url] = actor.url + it[createdAt] = actor.createdAt.toEpochMilli() + it[publicKey] = actor.publicKey + it[privateKey] = actor.privateKey + it[keyId] = actor.keyId + it[following] = actor.following + it[followers] = actor.followers + it[instance] = actor.instance + it[locked] = actor.locked + } + } + return actor + } + + override suspend fun findById(id: Long): Actor? = + Actors.select { Actors.id eq id }.singleOrNull()?.let(actorResultRowMapper::map) + + override suspend fun delete(id: Long) { + Actors.deleteWhere { Actors.id.eq(id) } + } + + override suspend fun nextId(): Long = idGenerateService.generateId() +} + +object Actors : Table("actors") { + val id: Column = long("id") + val name: Column = varchar("name", length = 300) + val domain: Column = varchar("domain", length = 1000) + val screenName: Column = varchar("screen_name", length = 300) + val description: Column = varchar( + "description", + length = 10000 + ) + val inbox: Column = varchar("inbox", length = 1000).uniqueIndex() + val outbox: Column = varchar("outbox", length = 1000).uniqueIndex() + val url: Column = varchar("url", length = 1000).uniqueIndex() + val publicKey: Column = varchar("public_key", length = 10000) + val privateKey: Column = varchar( + "private_key", + length = 10000 + ).nullable() + val createdAt: Column = long("created_at") + val keyId = varchar("key_id", length = 1000) + val following = varchar("following", length = 1000).nullable() + val followers = varchar("followers", length = 1000).nullable() + val instance = long("instance").references(Instance.id).nullable() + val locked = bool("locked") + + override val primaryKey: PrimaryKey = PrimaryKey(id) + + init { + uniqueIndex(name, domain) + } +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt index ee372e1c..f8b36460 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedTimelineRepository.kt @@ -22,7 +22,7 @@ class ExposedTimelineRepository(private val idGenerateService: IdGenerateService it[userId] = timeline.userId it[timelineId] = timeline.timelineId it[postId] = timeline.postId - it[postUserId] = timeline.postUserId + it[postActorId] = timeline.postActorId it[createdAt] = timeline.createdAt it[replyId] = timeline.replyId it[repostId] = timeline.repostId @@ -37,7 +37,7 @@ class ExposedTimelineRepository(private val idGenerateService: IdGenerateService it[userId] = timeline.userId it[timelineId] = timeline.timelineId it[postId] = timeline.postId - it[postUserId] = timeline.postUserId + it[postActorId] = timeline.postActorId it[createdAt] = timeline.createdAt it[replyId] = timeline.replyId it[repostId] = timeline.repostId @@ -57,7 +57,7 @@ class ExposedTimelineRepository(private val idGenerateService: IdGenerateService this[Timelines.userId] = it.userId this[Timelines.timelineId] = it.timelineId this[Timelines.postId] = it.postId - this[Timelines.postUserId] = it.postUserId + this[Timelines.postActorId] = it.postActorId this[Timelines.createdAt] = it.createdAt this[Timelines.replyId] = it.replyId this[Timelines.repostId] = it.repostId @@ -84,7 +84,7 @@ fun ResultRow.toTimeline(): Timeline { userId = this[Timelines.userId], timelineId = this[Timelines.timelineId], postId = this[Timelines.postId], - postUserId = this[Timelines.postUserId], + postActorId = this[Timelines.postActorId], createdAt = this[Timelines.createdAt], replyId = this[Timelines.replyId], repostId = this[Timelines.repostId], @@ -101,7 +101,7 @@ object Timelines : Table("timelines") { val userId = long("user_id") val timelineId = long("timeline_id") val postId = long("post_id") - val postUserId = long("post_user_id") + val postActorId = long("post_actor_id") val createdAt = long("created_at") val replyId = long("reply_id").nullable() val repostId = long("repost_id").nullable() diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/PostRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/PostRepositoryImpl.kt index 1de54ad8..d71f0cab 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/PostRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/PostRepositoryImpl.kt @@ -23,7 +23,7 @@ class PostRepositoryImpl( if (singleOrNull == null) { Posts.insert { it[id] = post.id - it[userId] = post.userId + it[actorId] = post.actorId it[overview] = post.overview it[text] = post.text it[createdAt] = post.createdAt @@ -47,7 +47,7 @@ class PostRepositoryImpl( this[PostsMedia.mediaId] = it } Posts.update({ Posts.id eq post.id }) { - it[userId] = post.userId + it[actorId] = post.actorId it[overview] = post.overview it[text] = post.text it[createdAt] = post.createdAt @@ -75,7 +75,7 @@ class PostRepositoryImpl( object Posts : Table() { val id: Column = long("id") - val userId: Column = long("user_id").references(Users.id) + val actorId: Column = long("actor_id").references(Actors.id) val overview: Column = varchar("overview", 100).nullable() val text: Column = varchar("text", 3000) val createdAt: Column = long("created_at") diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt index e6bcf355..a94abda4 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ReactionRepositoryImpl.kt @@ -21,13 +21,13 @@ class ReactionRepositoryImpl( it[id] = reaction.id it[emojiId] = reaction.emojiId it[postId] = reaction.postId - it[userId] = reaction.userId + it[actorId] = reaction.actorId } } else { Reactions.update({ Reactions.id eq reaction.id }) { it[emojiId] = reaction.emojiId it[postId] = reaction.postId - it[userId] = reaction.userId + it[actorId] = reaction.actorId } } return reaction @@ -37,7 +37,7 @@ class ReactionRepositoryImpl( Reactions.deleteWhere { id.eq(reaction.id) .and(postId.eq(reaction.postId)) - .and(userId.eq(reaction.postId)) + .and(actorId.eq(reaction.postId)) .and(emojiId.eq(reaction.emojiId)) } return reaction @@ -49,16 +49,16 @@ fun ResultRow.toReaction(): Reaction { this[Reactions.id].value, this[Reactions.emojiId], this[Reactions.postId], - this[Reactions.userId] + this[Reactions.actorId] ) } object Reactions : LongIdTable("reactions") { val emojiId: Column = long("emoji_id") val postId: Column = long("post_id").references(Posts.id) - val userId: Column = long("user_id").references(Users.id) + val actorId: Column = long("actor_id").references(Actors.id) init { - uniqueIndex(emojiId, postId, userId) + uniqueIndex(emojiId, postId, actorId) } } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserDetailRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserDetailRepositoryImpl.kt new file mode 100644 index 00000000..4fb7b9c5 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserDetailRepositoryImpl.kt @@ -0,0 +1,54 @@ +package dev.usbharu.hideout.core.infrastructure.exposedrepository + +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetail +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository +import org.jetbrains.exposed.dao.id.LongIdTable +import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.deleteWhere +import org.jetbrains.exposed.sql.insert +import org.jetbrains.exposed.sql.select +import org.jetbrains.exposed.sql.update +import org.springframework.stereotype.Repository + +@Repository +class UserDetailRepositoryImpl : UserDetailRepository { + override suspend fun save(userDetail: UserDetail): UserDetail { + val singleOrNull = UserDetails.select { UserDetails.actorId eq userDetail.actorId }.singleOrNull() + if (singleOrNull == null) { + UserDetails.insert { + it[actorId] = userDetail.actorId + it[password] = userDetail.password + it[autoAcceptFolloweeFollowRequest] = userDetail.autoAcceptFolloweeFollowRequest + } + } else { + UserDetails.update({ UserDetails.actorId eq userDetail.actorId }) { + it[password] = userDetail.password + it[autoAcceptFolloweeFollowRequest] = userDetail.autoAcceptFolloweeFollowRequest + } + } + return userDetail + } + + override suspend fun delete(userDetail: UserDetail) { + UserDetails.deleteWhere { UserDetails.actorId eq userDetail.actorId } + } + + override suspend fun findByActorId(actorId: Long): UserDetail? { + return UserDetails + .select { UserDetails.actorId eq actorId } + .singleOrNull() + ?.let { + UserDetail( + it[UserDetails.actorId], + it[UserDetails.password], + it[UserDetails.autoAcceptFolloweeFollowRequest] + ) + } + } +} + +object UserDetails : LongIdTable("user_details") { + val actorId = long("actor_id").references(Actors.id) + val password = varchar("password", 255) + val autoAcceptFolloweeFollowRequest = bool("auto_accept_followee_follow_request") +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserRepositoryImpl.kt deleted file mode 100644 index b4adbaad..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/UserRepositoryImpl.kt +++ /dev/null @@ -1,100 +0,0 @@ -package dev.usbharu.hideout.core.infrastructure.exposedrepository - -import dev.usbharu.hideout.application.infrastructure.exposed.ResultRowMapper -import dev.usbharu.hideout.application.service.id.IdGenerateService -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.domain.model.user.UserRepository -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq -import org.springframework.stereotype.Repository - -@Repository -class UserRepositoryImpl( - private val idGenerateService: IdGenerateService, - private val userResultRowMapper: ResultRowMapper -) : - UserRepository { - - override suspend fun save(user: User): User { - val singleOrNull = Users.select { Users.id eq user.id }.empty() - if (singleOrNull) { - Users.insert { - it[id] = user.id - it[name] = user.name - it[domain] = user.domain - it[screenName] = user.screenName - it[description] = user.description - it[password] = user.password - it[inbox] = user.inbox - it[outbox] = user.outbox - it[url] = user.url - it[createdAt] = user.createdAt.toEpochMilli() - it[publicKey] = user.publicKey - it[privateKey] = user.privateKey - it[keyId] = user.keyId - it[following] = user.following - it[followers] = user.followers - it[instance] = user.instance - } - } else { - Users.update({ Users.id eq user.id }) { - it[name] = user.name - it[domain] = user.domain - it[screenName] = user.screenName - it[description] = user.description - it[password] = user.password - it[inbox] = user.inbox - it[outbox] = user.outbox - it[url] = user.url - it[createdAt] = user.createdAt.toEpochMilli() - it[publicKey] = user.publicKey - it[privateKey] = user.privateKey - it[keyId] = user.keyId - it[following] = user.following - it[followers] = user.followers - it[instance] = user.instance - } - } - return user - } - - override suspend fun findById(id: Long): User? = - Users.select { Users.id eq id }.singleOrNull()?.let(userResultRowMapper::map) - - override suspend fun delete(id: Long) { - Users.deleteWhere { Users.id.eq(id) } - } - - override suspend fun nextId(): Long = idGenerateService.generateId() -} - -object Users : Table("users") { - val id: Column = long("id") - val name: Column = varchar("name", length = 300) - val domain: Column = varchar("domain", length = 1000) - val screenName: Column = varchar("screen_name", length = 300) - val description: Column = varchar( - "description", - length = 10000 - ) - val password: Column = varchar("password", length = 255).nullable() - val inbox: Column = varchar("inbox", length = 1000).uniqueIndex() - val outbox: Column = varchar("outbox", length = 1000).uniqueIndex() - val url: Column = varchar("url", length = 1000).uniqueIndex() - val publicKey: Column = varchar("public_key", length = 10000) - val privateKey: Column = varchar( - "private_key", - length = 10000 - ).nullable() - val createdAt: Column = long("created_at") - val keyId = varchar("key_id", length = 1000) - val following = varchar("following", length = 1000).nullable() - val followers = varchar("followers", length = 1000).nullable() - val instance = long("instance").references(Instance.id).nullable() - - override val primaryKey: PrimaryKey = PrimaryKey(id) - - init { - uniqueIndex(name, domain) - } -} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt index a75fe934..8c891da3 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/httpsignature/HttpSignatureUserDetailsService.kt @@ -3,7 +3,7 @@ package dev.usbharu.hideout.core.infrastructure.springframework.httpsignature import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.exception.HttpSignatureVerifyException -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.httpsignature.common.HttpMethod import dev.usbharu.httpsignature.common.HttpRequest @@ -20,7 +20,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken class HttpSignatureUserDetailsService( - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val httpSignatureVerifier: HttpSignatureVerifier, private val transaction: Transaction, private val httpSignatureHeaderParser: SignatureHeaderParser @@ -35,7 +35,7 @@ class HttpSignatureUserDetailsService( val keyId = token.principal as String val findByKeyId = transaction.transaction { try { - userQueryService.findByKeyId(keyId) + actorQueryService.findByKeyId(keyId) } catch (e: FailedToGetResourcesException) { throw UsernameNotFoundException("User not found", e) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt index b8ac029c..2e979cea 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt @@ -2,7 +2,9 @@ package dev.usbharu.hideout.core.infrastructure.springframework.oauth2 import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.external.Transaction -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository +import dev.usbharu.hideout.core.query.ActorQueryService import kotlinx.coroutines.runBlocking import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UserDetailsService @@ -11,8 +13,9 @@ import org.springframework.stereotype.Service @Service class UserDetailsServiceImpl( - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val applicationConfig: ApplicationConfig, + private val userDetailRepository: UserDetailRepository, private val transaction: Transaction ) : UserDetailsService { @@ -21,11 +24,17 @@ class UserDetailsServiceImpl( throw UsernameNotFoundException("$username not found") } transaction.transaction { - val findById = userQueryService.findByNameAndDomain(username, applicationConfig.url.host) + val findById = try { + actorQueryService.findByNameAndDomain(username, applicationConfig.url.host) + } catch (e: FailedToGetResourcesException) { + throw UsernameNotFoundException("$username not found", e) + } + val userDetails = userDetailRepository.findByActorId(findById.id) + ?: throw UsernameNotFoundException("${findById.id} not found.") UserDetailsImpl( id = findById.id, username = findById.name, - password = findById.password, + password = userDetails.password, enabled = true, accountNonExpired = true, credentialsNonExpired = true, diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/ActorQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/ActorQueryService.kt new file mode 100644 index 00000000..05b79e25 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/ActorQueryService.kt @@ -0,0 +1,16 @@ +package dev.usbharu.hideout.core.query + +import dev.usbharu.hideout.core.domain.model.actor.Actor +import org.springframework.stereotype.Repository + +@Repository +interface ActorQueryService { + suspend fun findAll(limit: Int, offset: Long): List + suspend fun findById(id: Long): Actor + suspend fun findByName(name: String): List + suspend fun findByNameAndDomain(name: String, domain: String): Actor + suspend fun findByUrl(url: String): Actor + suspend fun findByIds(ids: List): List + suspend fun existByNameAndDomain(name: String, domain: String): Boolean + suspend fun findByKeyId(keyId: String): Actor +} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/FollowerQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/FollowerQueryService.kt index 8d3d5bb4..18b98a47 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/FollowerQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/FollowerQueryService.kt @@ -1,9 +1,9 @@ package dev.usbharu.hideout.core.query -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor @Deprecated("Use RelationshipQueryService") interface FollowerQueryService { - suspend fun findFollowersById(id: Long): List - suspend fun alreadyFollow(userId: Long, followerId: Long): Boolean + suspend fun findFollowersById(id: Long): List + suspend fun alreadyFollow(actorId: Long, followerId: Long): Boolean } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt index 0c378c58..602e0a76 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/ReactionQueryService.kt @@ -5,12 +5,12 @@ import org.springframework.stereotype.Repository @Repository interface ReactionQueryService { - suspend fun findByPostId(postId: Long, userId: Long? = null): List + suspend fun findByPostId(postId: Long, actorId: Long? = null): List @Suppress("FunctionMaxLength") - suspend fun findByPostIdAndUserIdAndEmojiId(postId: Long, userId: Long, emojiId: Long): Reaction + suspend fun findByPostIdAndActorIdAndEmojiId(postId: Long, actorId: Long, emojiId: Long): Reaction - suspend fun reactionAlreadyExist(postId: Long, userId: Long, emojiId: Long): Boolean + suspend fun reactionAlreadyExist(postId: Long, actorId: Long, emojiId: Long): Boolean - suspend fun deleteByPostIdAndUserId(postId: Long, userId: Long) + suspend fun deleteByPostIdAndActorId(postId: Long, actorId: Long) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/RelationshipQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/RelationshipQueryService.kt index 5f051397..c4219711 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/RelationshipQueryService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/query/RelationshipQueryService.kt @@ -5,4 +5,14 @@ import dev.usbharu.hideout.core.domain.model.relationship.Relationship interface RelationshipQueryService { suspend fun findByTargetIdAndFollowing(targetId: Long, following: Boolean): List + + @Suppress("LongParameterList") + suspend fun findByTargetIdAndFollowRequestAndIgnoreFollowRequest( + maxId: Long?, + sinceId: Long?, + limit: Int, + targetId: Long, + followRequest: Boolean, + ignoreFollowRequest: Boolean + ): List } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/query/UserQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/core/query/UserQueryService.kt deleted file mode 100644 index 9b78ae4e..00000000 --- a/src/main/kotlin/dev/usbharu/hideout/core/query/UserQueryService.kt +++ /dev/null @@ -1,16 +0,0 @@ -package dev.usbharu.hideout.core.query - -import dev.usbharu.hideout.core.domain.model.user.User -import org.springframework.stereotype.Repository - -@Repository -interface UserQueryService { - suspend fun findAll(limit: Int, offset: Long): List - suspend fun findById(id: Long): User - suspend fun findByName(name: String): List - suspend fun findByNameAndDomain(name: String, domain: String): User - suspend fun findByUrl(url: String): User - suspend fun findByIds(ids: List): List - suspend fun existByNameAndDomain(name: String, domain: String): Boolean - suspend fun findByKeyId(keyId: String): User -} diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/follow/SendFollowDto.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/follow/SendFollowDto.kt index 53b55c00..c6134b97 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/follow/SendFollowDto.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/follow/SendFollowDto.kt @@ -1,5 +1,5 @@ package dev.usbharu.hideout.core.service.follow -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor -data class SendFollowDto(val userId: User, val followTargetUserId: User) +data class SendFollowDto(val actorId: Actor, val followTargetActorId: Actor) 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 2e2c6c0c..a5bb1d47 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,9 +2,9 @@ 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.ActorRepository import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository -import dev.usbharu.hideout.core.domain.model.user.UserRepository import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.timeline.TimelineService import org.jetbrains.exposed.exceptions.ExposedSQLException @@ -16,7 +16,7 @@ import java.time.Instant @Service class PostServiceImpl( private val postRepository: PostRepository, - private val userRepository: UserRepository, + private val actorRepository: ActorRepository, private val timelineService: TimelineService, private val postQueryService: PostQueryService, private val postBuilder: Post.PostBuilder, @@ -32,7 +32,7 @@ class PostServiceImpl( } override suspend fun createRemote(post: Post): Post { - logger.info("START Create Remote Post user: {}, remote url: {}", post.userId, post.apId) + logger.info("START Create Remote Post user: {}, remote url: {}", post.actorId, post.apId) val createdPost = internalCreate(post, false) logger.info("SUCCESS Create Remote Post url: {}", createdPost.url) return createdPost @@ -55,11 +55,11 @@ class PostServiceImpl( } private suspend fun internalCreate(post: PostCreateDto, isLocal: Boolean): Post { - val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found") + val user = actorRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found") val id = postRepository.generateId() val createPost = postBuilder.of( id = id, - userId = post.userId, + actorId = post.userId, overview = post.overview, text = post.text, createdAt = Instant.now().toEpochMilli(), diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionService.kt index 3e00918a..333deb1d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionService.kt @@ -4,7 +4,7 @@ import org.springframework.stereotype.Service @Service interface ReactionService { - suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) - suspend fun sendReaction(name: String, userId: Long, postId: Long) - suspend fun removeReaction(userId: Long, postId: Long) + suspend fun receiveReaction(name: String, domain: String, actorId: Long, postId: Long) + suspend fun sendReaction(name: String, actorId: Long, postId: Long) + suspend fun removeReaction(actorId: Long, postId: Long) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt index 1ab87448..1e9be539 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImpl.kt @@ -16,34 +16,34 @@ class ReactionServiceImpl( private val apReactionService: APReactionService, private val reactionQueryService: ReactionQueryService ) : ReactionService { - override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) { - if (reactionQueryService.reactionAlreadyExist(postId, userId, 0).not()) { + override suspend fun receiveReaction(name: String, domain: String, actorId: Long, postId: Long) { + if (reactionQueryService.reactionAlreadyExist(postId, actorId, 0).not()) { try { reactionRepository.save( - Reaction(reactionRepository.generateId(), 0, postId, userId) + Reaction(reactionRepository.generateId(), 0, postId, actorId) ) } catch (_: ExposedSQLException) { } } } - override suspend fun sendReaction(name: String, userId: Long, postId: Long) { + override suspend fun sendReaction(name: String, actorId: Long, postId: Long) { try { val findByPostIdAndUserIdAndEmojiId = - reactionQueryService.findByPostIdAndUserIdAndEmojiId(postId, userId, 0) + reactionQueryService.findByPostIdAndActorIdAndEmojiId(postId, actorId, 0) apReactionService.removeReaction(findByPostIdAndUserIdAndEmojiId) reactionRepository.delete(findByPostIdAndUserIdAndEmojiId) } catch (_: FailedToGetResourcesException) { } - val reaction = Reaction(reactionRepository.generateId(), 0, postId, userId) + val reaction = Reaction(reactionRepository.generateId(), 0, postId, actorId) reactionRepository.save(reaction) apReactionService.reaction(reaction) } - override suspend fun removeReaction(userId: Long, postId: Long) { + override suspend fun removeReaction(actorId: Long, postId: Long) { try { val findByPostIdAndUserIdAndEmojiId = - reactionQueryService.findByPostIdAndUserIdAndEmojiId(postId, userId, 0) + reactionQueryService.findByPostIdAndActorIdAndEmojiId(postId, actorId, 0) reactionRepository.delete(findByPostIdAndUserIdAndEmojiId) apReactionService.removeReaction(findByPostIdAndUserIdAndEmojiId) } catch (_: FailedToGetResourcesException) { diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipService.kt index 9032bd2e..9226de60 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/relationship/RelationshipService.kt @@ -1,22 +1,22 @@ package dev.usbharu.hideout.core.service.relationship interface RelationshipService { - suspend fun followRequest(userId: Long, targetId: Long) - suspend fun block(userId: Long, targetId: Long) + suspend fun followRequest(actorId: Long, targetId: Long) + suspend fun block(actorId: Long, targetId: Long) /** * フォローリクエストを承認します - * [userId]が[targetId]からのフォローリクエストを承認します + * [actorId]が[targetId]からのフォローリクエストを承認します * - * @param userId 承認操作をするユーザー + * @param actorId 承認操作をするユーザー * @param targetId 承認するフォローリクエストを送ってきたユーザー * @param force 強制的にAcceptアクティビティを発行する */ - suspend fun acceptFollowRequest(userId: Long, targetId: Long, force: Boolean = false) - suspend fun rejectFollowRequest(userId: Long, targetId: Long) - suspend fun ignoreFollowRequest(userId: Long, targetId: Long) - suspend fun unfollow(userId: Long, targetId: Long) - suspend fun unblock(userId: Long, targetId: Long) - suspend fun mute(userId: Long, targetId: Long) - suspend fun unmute(userId: Long, targetId: Long) + suspend fun acceptFollowRequest(actorId: Long, targetId: Long, force: Boolean = false) + suspend fun rejectFollowRequest(actorId: Long, targetId: Long) + suspend fun ignoreFollowRequest(actorId: Long, targetId: Long) + suspend fun unfollow(actorId: Long, targetId: Long) + suspend fun unblock(actorId: Long, targetId: Long) + suspend fun mute(actorId: Long, targetId: Long) + suspend fun unmute(actorId: Long, targetId: Long) } 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 a94332f9..8b508af0 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 @@ -7,10 +7,10 @@ import dev.usbharu.hideout.activitypub.service.activity.reject.ApSendRejectServi 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.relationship.Relationship import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.follow.SendFollowDto import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -18,7 +18,7 @@ import org.springframework.stereotype.Service @Service class RelationshipServiceImpl( private val applicationConfig: ApplicationConfig, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val relationshipRepository: RelationshipRepository, private val apSendFollowService: APSendFollowService, private val apSendBlockService: APSendBlockService, @@ -26,48 +26,48 @@ class RelationshipServiceImpl( private val apSendRejectService: ApSendRejectService, private val apSendUndoService: APSendUndoService ) : RelationshipService { - override suspend fun followRequest(userId: Long, targetId: Long) { - logger.info("START Follow Request userId: {} targetId: {}", userId, targetId) + override suspend fun followRequest(actorId: Long, targetId: Long) { + logger.info("START Follow Request userId: {} targetId: {}", actorId, targetId) val relationship = - relationshipRepository.findByUserIdAndTargetUserId(userId, targetId)?.copy(followRequest = true) + relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId)?.copy(followRequest = true) ?: Relationship( - userId = userId, - targetUserId = targetId, + actorId = actorId, + targetActorId = targetId, following = false, blocking = false, muting = false, followRequest = true, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) - val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, userId) ?: Relationship( - userId = targetId, - targetUserId = userId, + val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, actorId) ?: Relationship( + actorId = targetId, + targetActorId = actorId, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) if (inverseRelationship.blocking) { - logger.debug("FAILED Blocked by target. userId: {} targetId: {}", userId, targetId) + logger.debug("FAILED Blocked by target. userId: {} targetId: {}", actorId, targetId) return } if (relationship.blocking) { - logger.debug("FAILED Blocking user. userId: {} targetId: {}", userId, targetId) + logger.debug("FAILED Blocking user. userId: {} targetId: {}", actorId, targetId) return } - if (inverseRelationship.ignoreFollowRequestFromTarget) { - logger.debug("SUCCESS Ignore Follow Request. userId: {} targetId: {}", userId, targetId) + if (relationship.ignoreFollowRequestToTarget) { + logger.debug("SUCCESS Ignore Follow Request. userId: {} targetId: {}", actorId, targetId) return } if (relationship.following) { - logger.debug("SUCCESS User already follow. userId: {} targetId: {}", userId, targetId) - acceptFollowRequest(targetId, userId, true) + logger.debug("SUCCESS User already follow. userId: {} targetId: {}", actorId, targetId) + acceptFollowRequest(targetId, actorId, true) return } @@ -76,29 +76,31 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = userQueryService.findById(userId) + val user = actorQueryService.findById(actorId) apSendFollowService.sendFollow(SendFollowDto(user, remoteUser)) } else { - // TODO: フォロー許可制ユーザーを実装したら消す - acceptFollowRequest(targetId, userId) + val target = actorQueryService.findById(targetId) + if (target.locked.not()) { + acceptFollowRequest(targetId, actorId) + } } - logger.info("SUCCESS Follow Request userId: {} targetId: {}", userId, targetId) + logger.info("SUCCESS Follow Request userId: {} targetId: {}", actorId, targetId) } - override suspend fun block(userId: Long, targetId: Long) { - val relationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId) + override suspend fun block(actorId: Long, targetId: Long) { + val relationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId) ?.copy(blocking = true, followRequest = false, following = false) ?: Relationship( - userId = userId, - targetUserId = targetId, + actorId = actorId, + targetActorId = targetId, following = false, blocking = true, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) - val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, userId) + val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, actorId) ?.copy(followRequest = false, following = false) relationshipRepository.save(relationship) @@ -109,47 +111,47 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = userQueryService.findById(userId) + val user = actorQueryService.findById(actorId) apSendBlockService.sendBlock(user, remoteUser) } } - override suspend fun acceptFollowRequest(userId: Long, targetId: Long, force: Boolean) { - logger.info("START Accept follow request userId: {} targetId: {}", userId, targetId) + override suspend fun acceptFollowRequest(actorId: Long, targetId: Long, force: Boolean) { + logger.info("START Accept follow request userId: {} targetId: {}", actorId, targetId) - val relationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, userId) + val relationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, actorId) - val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId) ?: Relationship( - userId = targetId, - targetUserId = userId, + val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId) ?: Relationship( + actorId = targetId, + targetActorId = actorId, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) if (relationship == null) { - logger.warn("FAILED Follow Request Not Found. (Relationship) userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Follow Request Not Found. (Relationship) userId: {} targetId: {}", actorId, targetId) return } if (relationship.followRequest.not() && force.not()) { - logger.warn("FAILED Follow Request Not Found. (Follow Request) userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Follow Request Not Found. (Follow Request) userId: {} targetId: {}", actorId, targetId) return } if (relationship.blocking) { - logger.warn("FAILED Blocking user userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Blocking user userId: {} targetId: {}", actorId, targetId) throw IllegalStateException( - "Cannot accept a follow request from a blocked user. userId: $userId targetId: $targetId" + "Cannot accept a follow request from a blocked user. userId: $actorId targetId: $targetId" ) } if (inverseRelationship.blocking) { - logger.warn("FAILED BLocked by user userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED BLocked by user userId: {} targetId: {}", actorId, targetId) throw IllegalStateException( - "Cannot accept a follow request from a blocking user. userId: $userId targetId: $targetId" + "Cannot accept a follow request from a blocking user. userId: $actorId targetId: $targetId" ) } @@ -160,21 +162,21 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = userQueryService.findById(userId) + val user = actorQueryService.findById(actorId) apSendAcceptService.sendAcceptFollow(user, remoteUser) } } - override suspend fun rejectFollowRequest(userId: Long, targetId: Long) { - val relationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, userId) + override suspend fun rejectFollowRequest(actorId: Long, targetId: Long) { + val relationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, actorId) if (relationship == null) { - logger.warn("FAILED Follow Request Not Found. (Relationship) userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Follow Request Not Found. (Relationship) userId: {} targetId: {}", actorId, targetId) return } if (relationship.followRequest.not() && relationship.following.not()) { - logger.warn("FAILED Follow Request Not Found. (Follow Request) userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Follow Request Not Found. (Follow Request) userId: {} targetId: {}", actorId, targetId) return } @@ -185,37 +187,37 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = userQueryService.findById(userId) + val user = actorQueryService.findById(actorId) apSendRejectService.sendRejectFollow(user, remoteUser) } } - override suspend fun ignoreFollowRequest(userId: Long, targetId: Long) { - val relationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId) - ?.copy(ignoreFollowRequestFromTarget = true) + override suspend fun ignoreFollowRequest(actorId: Long, targetId: Long) { + val relationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, actorId) + ?.copy(ignoreFollowRequestToTarget = true) ?: Relationship( - userId = userId, - targetUserId = targetId, + actorId = targetId, + targetActorId = actorId, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = true + ignoreFollowRequestToTarget = true ) relationshipRepository.save(relationship) } - override suspend fun unfollow(userId: Long, targetId: Long) { - val relationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId) + override suspend fun unfollow(actorId: Long, targetId: Long) { + val relationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId) if (relationship == null) { - logger.warn("FAILED Unfollow. (Relationship) userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Unfollow. (Relationship) userId: {} targetId: {}", actorId, targetId) return } if (relationship.following.not()) { - logger.warn("SUCCESS User already unfollow. userId: {} targetId: {}", userId, targetId) + logger.warn("SUCCESS User already unfollow. userId: {} targetId: {}", actorId, targetId) return } @@ -226,21 +228,21 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = userQueryService.findById(userId) + val user = actorQueryService.findById(actorId) apSendUndoService.sendUndoFollow(user, remoteUser) } } - override suspend fun unblock(userId: Long, targetId: Long) { - val relationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId) + override suspend fun unblock(actorId: Long, targetId: Long) { + val relationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId) if (relationship == null) { - logger.warn("FAILED Unblock. (Relationship) userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Unblock. (Relationship) userId: {} targetId: {}", actorId, targetId) return } if (relationship.blocking.not()) { - logger.warn("SUCCESS User is not blocking. userId: {] targetId: {}", userId, targetId) + logger.warn("SUCCESS User is not blocking. userId: {] targetId: {}", actorId, targetId) return } @@ -249,41 +251,41 @@ class RelationshipServiceImpl( val remoteUser = isRemoteUser(targetId) if (remoteUser != null) { - val user = userQueryService.findById(userId) + val user = actorQueryService.findById(actorId) apSendUndoService.sendUndoBlock(user, remoteUser) } } - override suspend fun mute(userId: Long, targetId: Long) { - val relationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId)?.copy(muting = true) + override suspend fun mute(actorId: Long, targetId: Long) { + val relationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId)?.copy(muting = true) ?: Relationship( - userId = userId, - targetUserId = targetId, + actorId = actorId, + targetActorId = targetId, following = false, blocking = false, muting = true, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) relationshipRepository.save(relationship) } - override suspend fun unmute(userId: Long, targetId: Long) { - val relationship = relationshipRepository.findByUserIdAndTargetUserId(userId, targetId)?.copy(muting = false) + override suspend fun unmute(actorId: Long, targetId: Long) { + val relationship = relationshipRepository.findByUserIdAndTargetUserId(actorId, targetId)?.copy(muting = false) if (relationship == null) { - logger.warn("FAILED Mute. (Relationship) userId: {} targetId: {}", userId, targetId) + logger.warn("FAILED Mute. (Relationship) userId: {} targetId: {}", actorId, targetId) return } relationshipRepository.save(relationship) } - private suspend fun isRemoteUser(userId: Long): User? { + private suspend fun isRemoteUser(userId: Long): Actor? { logger.trace("isRemoteUser({})", userId) val user = try { - userQueryService.findById(userId) + actorQueryService.findById(userId) } catch (e: FailedToGetResourcesException) { logger.warn("User not found.", e) throw IllegalStateException("User not found.", e) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt index 73958fb4..e53e327d 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineService.kt @@ -4,22 +4,22 @@ import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.domain.model.timeline.Timeline import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService -import dev.usbharu.hideout.core.query.UserQueryService import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @Service class TimelineService( private val followerQueryService: FollowerQueryService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val timelineRepository: TimelineRepository ) { suspend fun publishTimeline(post: Post, isLocal: Boolean) { - val findFollowersById = followerQueryService.findFollowersById(post.userId).toMutableList() + val findFollowersById = followerQueryService.findFollowersById(post.actorId).toMutableList() if (isLocal) { // 自分自身も含める必要がある - val user = userQueryService.findById(post.userId) + val user = actorQueryService.findById(post.actorId) findFollowersById.add(user) } val timelines = findFollowersById.map { @@ -28,7 +28,7 @@ class TimelineService( userId = it.id, timelineId = 0, postId = post.id, - postUserId = post.userId, + postActorId = post.actorId, createdAt = post.createdAt, replyId = post.replyId, repostId = post.repostId, @@ -46,7 +46,7 @@ class TimelineService( userId = 0, timelineId = 0, postId = post.id, - postUserId = post.userId, + postActorId = post.actorId, createdAt = post.createdAt, replyId = post.replyId, repostId = post.repostId, diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/RemoteUserCreateDto.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/RemoteUserCreateDto.kt index de85e74d..8260d050 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/RemoteUserCreateDto.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/RemoteUserCreateDto.kt @@ -12,5 +12,6 @@ data class RemoteUserCreateDto( val keyId: String, val followers: String?, val following: String?, - val sharedInbox: String? + val sharedInbox: String?, + val locked: Boolean? ) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UpdateUserDto.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UpdateUserDto.kt new file mode 100644 index 00000000..a02c8d1c --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UpdateUserDto.kt @@ -0,0 +1,12 @@ +package dev.usbharu.hideout.core.service.user + +import dev.usbharu.hideout.core.domain.model.media.Media + +data class UpdateUserDto( + val screenName: String, + val description: String, + val avatarMedia: Media?, + val headerMedia: Media?, + val locked: Boolean, + val autoAcceptFolloweeFollowRequest: Boolean +) diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt index 1bb4599a..5ec5d4be 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserAuthServiceImpl.kt @@ -1,6 +1,6 @@ package dev.usbharu.hideout.core.service.user -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder import org.springframework.stereotype.Service import java.security.* @@ -8,13 +8,13 @@ import java.util.* @Service class UserAuthServiceImpl( - val userQueryService: UserQueryService + val actorQueryService: ActorQueryService ) : UserAuthService { override fun hash(password: String): String = BCryptPasswordEncoder().encode(password) override suspend fun usernameAlreadyUse(username: String): Boolean { - userQueryService.findByName(username) + actorQueryService.findByName(username) return true } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserService.kt index a9c0de2d..06715df5 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserService.kt @@ -1,6 +1,6 @@ package dev.usbharu.hideout.core.service.user -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import org.springframework.stereotype.Service @Service @@ -8,7 +8,9 @@ interface UserService { suspend fun usernameAlreadyUse(username: String): Boolean - suspend fun createLocalUser(user: UserCreateDto): User + suspend fun createLocalUser(user: UserCreateDto): Actor - suspend fun createRemoteUser(user: RemoteUserCreateDto): User + suspend fun createRemoteUser(user: RemoteUserCreateDto): Actor + + suspend fun updateUser(userId: Long, updateUserDto: UpdateUserDto) } diff --git a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt index b7bb12cf..442b676b 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/service/user/UserServiceImpl.kt @@ -1,9 +1,11 @@ package dev.usbharu.hideout.core.service.user import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.domain.model.user.User -import dev.usbharu.hideout.core.domain.model.user.UserRepository -import dev.usbharu.hideout.core.query.UserQueryService +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.userdetails.UserDetail +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.instance.InstanceService import org.jetbrains.exposed.exceptions.ExposedSQLException import org.slf4j.LoggerFactory @@ -13,32 +15,32 @@ import java.time.Instant @Service class UserServiceImpl( - private val userRepository: UserRepository, + private val actorRepository: ActorRepository, private val userAuthService: UserAuthService, - private val userQueryService: UserQueryService, - private val userBuilder: User.UserBuilder, + private val actorQueryService: ActorQueryService, + private val actorBuilder: Actor.UserBuilder, private val applicationConfig: ApplicationConfig, - private val instanceService: InstanceService + private val instanceService: InstanceService, + private val userDetailRepository: UserDetailRepository ) : UserService { override suspend fun usernameAlreadyUse(username: String): Boolean { - val findByNameAndDomain = userQueryService.findByNameAndDomain(username, applicationConfig.url.host) + val findByNameAndDomain = actorQueryService.findByNameAndDomain(username, applicationConfig.url.host) return findByNameAndDomain != null } - override suspend fun createLocalUser(user: UserCreateDto): User { - val nextId = userRepository.nextId() + override suspend fun createLocalUser(user: UserCreateDto): Actor { + val nextId = actorRepository.nextId() val hashedPassword = userAuthService.hash(user.password) val keyPair = userAuthService.generateKeyPair() val userUrl = "${applicationConfig.url}/users/${user.name}" - val userEntity = userBuilder.of( + val userEntity = actorBuilder.of( id = nextId, name = user.name, domain = applicationConfig.url.host, screenName = user.screenName, description = user.description, - password = hashedPassword, inbox = "$userUrl/inbox", outbox = "$userUrl/outbox", url = userUrl, @@ -47,13 +49,16 @@ class UserServiceImpl( createdAt = Instant.now(), following = "$userUrl/following", followers = "$userUrl/followers", - keyId = "$userUrl#pubkey" + keyId = "$userUrl#pubkey", + locked = false ) - return userRepository.save(userEntity) + val save = actorRepository.save(userEntity) + userDetailRepository.save(UserDetail(nextId, hashedPassword, true)) + return save } @Transactional - override suspend fun createRemoteUser(user: RemoteUserCreateDto): User { + override suspend fun createRemoteUser(user: RemoteUserCreateDto): Actor { logger.info("START Create New remote user. name: {} url: {}", user.name, user.url) @Suppress("TooGenericExceptionCaught") val instance = try { @@ -63,8 +68,8 @@ class UserServiceImpl( null } - val nextId = userRepository.nextId() - val userEntity = userBuilder.of( + val nextId = actorRepository.nextId() + val userEntity = actorBuilder.of( id = nextId, name = user.name, domain = user.domain, @@ -78,18 +83,40 @@ class UserServiceImpl( followers = user.followers, following = user.following, keyId = user.keyId, - instance = instance?.id + instance = instance?.id, + locked = user.locked ?: false ) return try { - val save = userRepository.save(userEntity) + val save = actorRepository.save(userEntity) logger.warn("SUCCESS Create New remote user. id: {} name: {} url: {}", userEntity.id, user.name, user.url) save } catch (_: ExposedSQLException) { logger.warn("FAILED User already exists. name: {} url: {}", user.name, user.url) - userQueryService.findByUrl(user.url) + actorQueryService.findByUrl(user.url) } } + override suspend fun updateUser(userId: Long, updateUserDto: UpdateUserDto) { + val userDetail = userDetailRepository.findByActorId(userId) + ?: throw IllegalArgumentException("userId: $userId was not found.") + + val actor = actorRepository.findById(userId) ?: throw IllegalArgumentException("userId $userId was not found.") + + actorRepository.save( + actor.copy( + screenName = updateUserDto.screenName, + description = updateUserDto.description, + locked = updateUserDto.locked + ) + ) + + userDetailRepository.save( + userDetail.copy( + autoAcceptFolloweeFollowRequest = updateUserDto.autoAcceptFolloweeFollowRequest + ) + ) + } + companion object { private val logger = LoggerFactory.getLogger(UserServiceImpl::class.java) } 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 new file mode 100644 index 00000000..916c1333 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/AccountQueryServiceImpl.kt @@ -0,0 +1,107 @@ +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.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) + + return query + .singleOr { FailedToGetResourcesException("accountId: $accountId wad not exist or duplicate", it) } + .let { toAccount(it, followingCount, followersCount, postsCount, lastCreated) } + } + + 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) + + return query + .map { toAccount(it, followingCount, followersCount, postsCount, lastCreated) } + } + + private fun toAccount( + resultRow: ResultRow, + followingCount: ExpressionAlias, + followersCount: ExpressionAlias, + postsCount: ExpressionAlias, + lastCreated: ExpressionAlias + ): Account { + val userUrl = "${applicationConfig.url}/users/${resultRow[Actors.id]}" + + return Account( + id = resultRow[Actors.id].toString(), + username = resultRow[Actors.name], + acct = "${resultRow[Actors.name]}@${resultRow[Actors.domain]}", + url = resultRow[Actors.url], + displayName = resultRow[Actors.screenName], + note = resultRow[Actors.description], + avatar = userUrl + "/icon.jpg", + avatarStatic = userUrl + "/icon.jpg", + header = userUrl + "/header.jpg", + headerStatic = userUrl + "/header.jpg", + locked = resultRow[Actors.locked], + fields = emptyList(), + emojis = emptyList(), + bot = false, + 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(), + ) + } +} 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 9c5b46fe..9f636b34 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 @@ -24,7 +24,7 @@ class StatusQueryServiceImpl : StatusQueryService { val mediaIdSet = mutableSetOf() mediaIdSet.addAll(statusQueries.flatMap { it.mediaIds }) val postMap = Posts - .leftJoin(Users) + .leftJoin(Actors) .select { Posts.id inList postIdSet } .associate { it[Posts.id] to toStatus(it) } val mediaMap = Media.select { Media.id inList mediaIdSet } @@ -57,9 +57,9 @@ class StatusQueryServiceImpl : StatusQueryService { ): List { val query = Posts .leftJoin(PostsMedia) - .leftJoin(Users) + .leftJoin(Actors) .leftJoin(Media) - .select { Posts.userId eq accountId }.limit(20) + .select { Posts.actorId eq accountId }.limit(20) if (maxId != null) { query.andWhere { Posts.id eq maxId } @@ -120,7 +120,7 @@ class StatusQueryServiceImpl : StatusQueryService { private suspend fun findByPostIdsWithMedia(ids: List): List { val pairs = Posts .leftJoin(PostsMedia) - .leftJoin(Users) + .leftJoin(Actors) .leftJoin(Media) .select { Posts.id inList ids } .groupBy { it[Posts.id] } @@ -141,24 +141,24 @@ private fun toStatus(it: ResultRow) = Status( uri = it[Posts.apId], createdAt = Instant.ofEpochMilli(it[Posts.createdAt]).toString(), account = Account( - id = it[Users.id].toString(), - username = it[Users.name], - acct = "${it[Users.name]}@${it[Users.domain]}", - url = it[Users.url], - displayName = it[Users.screenName], - note = it[Users.description], - avatar = it[Users.url] + "/icon.jpg", - avatarStatic = it[Users.url] + "/icon.jpg", - header = it[Users.url] + "/header.jpg", - headerStatic = it[Users.url] + "/header.jpg", + id = it[Actors.id].toString(), + username = it[Actors.name], + acct = "${it[Actors.name]}@${it[Actors.domain]}", + url = it[Actors.url], + displayName = it[Actors.screenName], + note = it[Actors.description], + avatar = it[Actors.url] + "/icon.jpg", + avatarStatic = it[Actors.url] + "/icon.jpg", + header = it[Actors.url] + "/header.jpg", + headerStatic = it[Actors.url] + "/header.jpg", locked = false, fields = emptyList(), emojis = emptyList(), bot = false, group = false, discoverable = true, - createdAt = Instant.ofEpochMilli(it[Users.createdAt]).toString(), - lastStatusAt = Instant.ofEpochMilli(it[Users.createdAt]).toString(), + createdAt = Instant.ofEpochMilli(it[Actors.createdAt]).toString(), + lastStatusAt = Instant.ofEpochMilli(it[Actors.createdAt]).toString(), statusesCount = 0, followersCount = 0, followingCount = 0, diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt index f9af1c7d..e8e65008 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiController.kt @@ -143,4 +143,47 @@ class MastodonAccountApiController( return ResponseEntity.ok(removeFromFollowers) } + + override suspend fun apiV1AccountsUpdateCredentialsPatch(updateCredentials: UpdateCredentials?): + ResponseEntity { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + val userid = principal.getClaim("uid").toLong() + + val removeFromFollowers = accountApiService.updateProfile(userid, updateCredentials) + + return ResponseEntity.ok(removeFromFollowers) + } + + override suspend fun apiV1FollowRequestsAccountIdAuthorizePost(accountId: String): ResponseEntity { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + val userid = principal.getClaim("uid").toLong() + + val acceptFollowRequest = accountApiService.acceptFollowRequest(userid, accountId.toLong()) + + return ResponseEntity.ok(acceptFollowRequest) + } + + override suspend fun apiV1FollowRequestsAccountIdRejectPost(accountId: String): ResponseEntity { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + val userid = principal.getClaim("uid").toLong() + + val rejectFollowRequest = accountApiService.rejectFollowRequest(userid, accountId.toLong()) + + return ResponseEntity.ok(rejectFollowRequest) + } + + override fun apiV1FollowRequestsGet(maxId: String?, sinceId: String?, limit: Int?): ResponseEntity> = + runBlocking { + val principal = SecurityContextHolder.getContext().getAuthentication().principal as Jwt + + val userid = principal.getClaim("uid").toLong() + + val accountFlow = + accountApiService.followRequests(userid, maxId?.toLong(), sinceId?.toLong(), limit ?: 20, false) + .asFlow() + ResponseEntity.ok(accountFlow) + } } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/query/AccountQueryService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/query/AccountQueryService.kt new file mode 100644 index 00000000..37eb2d98 --- /dev/null +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/query/AccountQueryService.kt @@ -0,0 +1,8 @@ +package dev.usbharu.hideout.mastodon.query + +import dev.usbharu.hideout.domain.mastodon.model.generated.Account + +interface AccountQueryService { + suspend fun findById(accountId: Long): Account + suspend fun findByIds(accountIds: List): List +} diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt index f639afc8..98cfdb3e 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiService.kt @@ -2,16 +2,21 @@ package dev.usbharu.hideout.mastodon.service.account import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository +import dev.usbharu.hideout.core.query.RelationshipQueryService +import dev.usbharu.hideout.core.service.media.MediaService import dev.usbharu.hideout.core.service.relationship.RelationshipService +import dev.usbharu.hideout.core.service.user.UpdateUserDto import dev.usbharu.hideout.core.service.user.UserCreateDto import dev.usbharu.hideout.core.service.user.UserService import dev.usbharu.hideout.domain.mastodon.model.generated.* +import dev.usbharu.hideout.mastodon.interfaces.api.media.MediaRequest import dev.usbharu.hideout.mastodon.query.StatusQueryService import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import kotlin.math.min @Service +@Suppress("TooManyFunctions") interface AccountApiService { @Suppress("LongParameterList") suspend fun accountsStatuses( @@ -45,6 +50,17 @@ interface AccountApiService { suspend fun unblock(userid: Long, target: Long): Relationship suspend fun unfollow(userid: Long, target: Long): Relationship suspend fun removeFromFollowers(userid: Long, target: Long): Relationship + suspend fun updateProfile(userid: Long, updateCredentials: UpdateCredentials?): Account + suspend fun followRequests( + loginUser: Long, + maxId: Long?, + sinceId: Long?, + limit: Int = 20, + withIgnore: Boolean + ): List + + suspend fun acceptFollowRequest(loginUser: Long, target: Long): Relationship + suspend fun rejectFollowRequest(loginUser: Long, target: Long): Relationship } @Service @@ -54,7 +70,9 @@ class AccountApiServiceImpl( private val userService: UserService, private val statusQueryService: StatusQueryService, private val relationshipService: RelationshipService, - private val relationshipRepository: RelationshipRepository + private val relationshipRepository: RelationshipRepository, + private val mediaService: MediaService, + private val relationshipQueryService: RelationshipQueryService ) : AccountApiService { override suspend fun accountsStatuses( @@ -153,6 +171,82 @@ class AccountApiServiceImpl( return@transaction fetchRelationship(userid, target) } + override suspend fun updateProfile(userid: Long, updateCredentials: UpdateCredentials?): Account = + transaction.transaction { + val avatarMedia = if (updateCredentials?.avatar != null) { + mediaService.uploadLocalMedia( + MediaRequest( + updateCredentials.avatar, + null, + null, + null + ) + ) + } else { + null + } + + val headerMedia = if (updateCredentials?.header != null) { + mediaService.uploadLocalMedia( + MediaRequest( + updateCredentials.header, + null, + null, + null + ) + ) + } else { + null + } + + val account = accountService.findById(userid) + + val updateUserDto = UpdateUserDto( + screenName = updateCredentials?.displayName ?: account.displayName, + description = updateCredentials?.note ?: account.note, + avatarMedia = avatarMedia, + headerMedia = headerMedia, + locked = updateCredentials?.locked ?: account.locked, + autoAcceptFolloweeFollowRequest = false + ) + userService.updateUser(userid, updateUserDto) + + accountService.findById(userid) + } + + override suspend fun followRequests( + loginUser: Long, + maxId: Long?, + sinceId: Long?, + limit: Int, + withIgnore: Boolean + ): List = transaction.transaction { + val actorIdList = relationshipQueryService + .findByTargetIdAndFollowRequestAndIgnoreFollowRequest( + maxId = maxId, + sinceId = sinceId, + limit = limit, + targetId = loginUser, + followRequest = true, + ignoreFollowRequest = withIgnore + ) + .map { it.actorId } + + return@transaction accountService.findByIds(actorIdList) + } + + override suspend fun acceptFollowRequest(loginUser: Long, target: Long): Relationship = transaction.transaction { + relationshipService.acceptFollowRequest(loginUser, target) + + return@transaction fetchRelationship(loginUser, target) + } + + override suspend fun rejectFollowRequest(loginUser: Long, target: Long): Relationship = transaction.transaction { + relationshipService.rejectFollowRequest(loginUser, target) + + return@transaction fetchRelationship(loginUser, target) + } + private fun from(account: Account): CredentialAccount { return CredentialAccount( id = account.id, @@ -180,10 +274,10 @@ class AccountApiServiceImpl( suspendex = account.suspendex, limited = account.limited, followingCount = account.followingCount, - source = CredentialAccountSource( + source = AccountSource( account.note, account.fields, - CredentialAccountSource.Privacy.public, + AccountSource.Privacy.public, false, 0 ), @@ -194,24 +288,24 @@ class AccountApiServiceImpl( private suspend fun fetchRelationship(userid: Long, targetId: Long): Relationship { val relationship = relationshipRepository.findByUserIdAndTargetUserId(userid, targetId) ?: dev.usbharu.hideout.core.domain.model.relationship.Relationship( - userId = userid, - targetUserId = targetId, + actorId = userid, + targetActorId = targetId, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) val inverseRelationship = relationshipRepository.findByUserIdAndTargetUserId(targetId, userid) ?: dev.usbharu.hideout.core.domain.model.relationship.Relationship( - userId = targetId, - targetUserId = userid, + actorId = targetId, + targetActorId = userid, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) return Relationship( diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt index 72050167..b3f57aaf 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountService.kt @@ -1,45 +1,20 @@ package dev.usbharu.hideout.mastodon.service.account -import dev.usbharu.hideout.application.config.ApplicationConfig -import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.domain.mastodon.model.generated.Account +import dev.usbharu.hideout.mastodon.query.AccountQueryService import org.springframework.stereotype.Service @Service interface AccountService { suspend fun findById(id: Long): Account + suspend fun findByIds(ids: List): List } @Service class AccountServiceImpl( - private val userQueryService: UserQueryService, - private val applicationConfig: ApplicationConfig + private val accountQueryService: AccountQueryService ) : AccountService { - override suspend fun findById(id: Long): Account { - val findById = userQueryService.findById(id) - val userUrl = applicationConfig.url.toString() + "/users/" + findById.id.toString() + override suspend fun findById(id: Long): Account = accountQueryService.findById(id) - return Account( - id = findById.id.toString(), - username = findById.name, - acct = "${findById.name}@${findById.domain}", - url = findById.url, - displayName = findById.screenName, - note = findById.description, - avatar = "$userUrl/icon.jpg", - avatarStatic = "$userUrl/icon.jpg", - header = "$userUrl/header.jpg", - headerStatic = "$userUrl/header.jpg", - locked = false, - fields = emptyList(), - emojis = emptyList(), - bot = false, - group = false, - discoverable = false, - createdAt = findById.createdAt.toString(), - lastStatusAt = findById.createdAt.toString(), - statusesCount = 0, - followersCount = 0, - ) - } + override suspend fun findByIds(ids: List): List = accountQueryService.findByIds(ids) } diff --git a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt index 198681ce..eac73698 100644 --- a/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt +++ b/src/main/kotlin/dev/usbharu/hideout/mastodon/service/status/StatusesApiService.kt @@ -4,8 +4,8 @@ import dev.usbharu.hideout.application.external.Transaction import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.media.MediaRepository import dev.usbharu.hideout.core.domain.model.media.toMediaAttachments +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.PostQueryService -import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.service.post.PostCreateDto import dev.usbharu.hideout.core.service.post.PostService import dev.usbharu.hideout.domain.mastodon.model.generated.Status @@ -30,7 +30,7 @@ class StatsesApiServiceImpl( private val postService: PostService, private val accountService: AccountService, private val postQueryService: PostQueryService, - private val userQueryService: UserQueryService, + private val actorQueryService: ActorQueryService, private val mediaRepository: MediaRepository, private val transaction: Transaction ) : @@ -55,7 +55,7 @@ class StatsesApiServiceImpl( val replyUser = if (post.replyId != null) { try { - userQueryService.findById(postQueryService.findById(post.replyId).userId).id + actorQueryService.findById(postQueryService.findById(post.replyId).actorId).id } catch (ignore: FailedToGetResourcesException) { null } diff --git a/src/main/kotlin/dev/usbharu/hideout/util/AcctUtil.kt b/src/main/kotlin/dev/usbharu/hideout/util/AcctUtil.kt index a0f1a09b..a9043fa1 100644 --- a/src/main/kotlin/dev/usbharu/hideout/util/AcctUtil.kt +++ b/src/main/kotlin/dev/usbharu/hideout/util/AcctUtil.kt @@ -1,6 +1,6 @@ package dev.usbharu.hideout.util -import dev.usbharu.hideout.core.domain.model.user.Acct +import dev.usbharu.hideout.core.domain.model.actor.Acct object AcctUtil { fun parse(string: String): Acct { diff --git a/src/main/resources/db/migration/V1__Init_DB.sql b/src/main/resources/db/migration/V1__Init_DB.sql index 234078e7..48223f60 100644 --- a/src/main/resources/db/migration/V1__Init_DB.sql +++ b/src/main/resources/db/migration/V1__Init_DB.sql @@ -13,14 +13,13 @@ create table if not exists instance moderation_note varchar(10000) not null, created_at timestamp not null ); -create table if not exists users +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, - password varchar(255) null, inbox varchar(1000) not null unique, outbox varchar(1000) not null unique, url varchar(1000) not null unique, @@ -31,8 +30,18 @@ create table if not exists users "following" varchar(1000) null, followers varchar(1000) null, "instance" bigint null, + locked boolean not null, unique ("name", "domain"), - constraint fk_users_instance__id foreign key ("instance") references instance (id) on delete restrict on update restrict + constraint fk_actors_instance__id foreign key ("instance") references instance (id) on delete restrict on update restrict +); + +create table if not exists user_details +( + id bigserial primary key, + actor_id bigint not null unique, + password varchar(255) not null, + auto_accept_followee_follow_request boolean not null, + constraint fk_user_details_actor_id__id foreign key (actor_id) references actors (id) on delete restrict on update restrict ); create table if not exists media @@ -58,7 +67,7 @@ create table if not exists meta_info create table if not exists posts ( id bigint primary key, - user_id bigint not null, + actor_id bigint not null, overview varchar(100) null, text varchar(3000) not null, created_at bigint not null, @@ -67,10 +76,10 @@ create table if not exists posts repost_id bigint null, reply_id bigint null, "sensitive" boolean default false not null, - ap_id varchar(100) not null unique + ap_id varchar(100) not null unique ); alter table posts - add constraint fk_posts_userid__id foreign key (user_id) references users (id) on delete restrict on update restrict; + add constraint fk_posts_actor_id__id foreign key (actor_id) references actors (id) on delete restrict on update restrict; alter table posts add constraint fk_posts_repostid__id foreign key (repost_id) references posts (id) on delete restrict on update restrict; alter table posts @@ -90,19 +99,19 @@ create table if not exists reactions id bigserial primary key, emoji_id bigint not null, post_id bigint not null, - user_id bigint not null + actor_id bigint not null ); alter table reactions add constraint fk_reactions_post_id__id foreign key (post_id) references posts (id) on delete restrict on update restrict; alter table reactions - add constraint fk_reactions_user_id__id foreign key (user_id) references users (id) on delete restrict on update restrict; + add constraint fk_reactions_actor_id__id foreign key (actor_id) references actors (id) on delete restrict on update restrict; create table if not exists timelines ( id bigint primary key, user_id bigint not null, timeline_id bigint not null, post_id bigint not null, - post_user_id bigint not null, + post_actor_id bigint not null, created_at bigint not null, reply_id bigint null, repost_id bigint null, @@ -177,14 +186,14 @@ create table if not exists registered_client create table if not exists relationships ( id bigserial primary key, - user_id bigint not null, - target_user_id bigint not null, + actor_id bigint not null, + target_actor_id bigint not null, following boolean not null, blocking boolean not null, muting boolean not null, follow_request boolean not null, ignore_follow_request boolean not null, - constraint fk_relationships_user_id__id foreign key (user_id) references users (id) on delete restrict on update restrict, - constraint fk_relationships_target_user_id__id foreign key (target_user_id) references users (id) on delete restrict on update restrict, - unique (user_id, target_user_id) + constraint fk_relationships_actor_id__id foreign key (actor_id) references actors (id) on delete restrict on update restrict, + constraint fk_relationships_target_actor_id__id foreign key (target_actor_id) references actors (id) on delete restrict on update restrict, + unique (actor_id, target_actor_id) ) diff --git a/src/main/resources/openapi/mastodon.yaml b/src/main/resources/openapi/mastodon.yaml index a43da7de..15df90d9 100644 --- a/src/main/resources/openapi/mastodon.yaml +++ b/src/main/resources/openapi/mastodon.yaml @@ -237,6 +237,27 @@ paths: items: $ref: "#/components/schemas/Relationship" + /api/v1/accounts/update_credentials: + patch: + tags: + - account + security: + - OAuth2: + - "write:accounts" + requestBody: + required: false + content: + application/json: + schema: + $ref: "#/components/schemas/UpdateCredentials" + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Account" + /api/v1/accounts/{id}: get: tags: @@ -555,6 +576,86 @@ paths: schema: $ref: "#/components/schemas/MediaAttachment" + /api/v1/follow_requests: + get: + tags: + - account + security: + - OAuth2: + - "read:follows" + parameters: + - in: query + name: max_id + schema: + type: string + required: false + - in: query + name: since_id + schema: + type: string + required: false + - in: query + name: limit + schema: + type: integer + required: false + responses: + 200: + description: 成功 + headers: + Link: + schema: + type: string + description: ページネーション + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Account" + + /api/v1/follow_requests/{account_id}/authorize: + post: + tags: + - account + security: + - OAuth2: + - "write:follows" + parameters: + - in: path + name: account_id + schema: + type: string + required: true + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Relationship" + + /api/v1/follow_requests/{account_id}/reject: + post: + tags: + - account + security: + - OAuth2: + - "write:follows" + parameters: + - in: path + name: account_id + schema: + type: string + required: true + responses: + 200: + description: 成功 + content: + application/json: + schema: + $ref: "#/components/schemas/Relationship" + components: schemas: V1MediaRequest: @@ -664,6 +765,9 @@ components: type: integer following_count: type: integer + source: + $ref: "#/components/schemas/AccountSource" + required: - id - username @@ -747,7 +851,7 @@ components: following_count: type: integer source: - $ref: "#/components/schemas/CredentialAccountSource" + $ref: "#/components/schemas/AccountSource" role: $ref: "#/components/schemas/Role" required: @@ -774,7 +878,7 @@ components: - followers_count - source - CredentialAccountSource: + AccountSource: type: object properties: note: @@ -1632,6 +1736,58 @@ components: items: type: string + UpdateCredentials: + type: object + properties: + display_name: + type: string + note: + type: string + avatar: + type: string + format: binary + header: + type: string + format: binary + locked: + type: boolean + bot: + type: boolean + discoverable: + type: boolean + hide_collections: + type: boolean + indexable: + type: boolean + fields_attributes: + type: object + additionalProperties: + $ref: "#/components/schemas/UpdateCredentialsFieldsAttributes" + source: + $ref: "#/components/schemas/UpdateCredentialsSource" + + UpdateCredentialsSource: + type: object + properties: + privacy: + type: string + enum: + - public + - unlisted + - private + sensitive: + type: boolean + language: + type: string + + UpdateCredentialsFieldsAttributes: + type: object + properties: + name: + type: string + value: + type: string + securitySchemes: OAuth2: type: oauth2 diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/UserAPControllerImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/ActorAPControllerImplTest.kt similarity index 97% rename from src/test/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/UserAPControllerImplTest.kt rename to src/test/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/ActorAPControllerImplTest.kt index 5d7bab4d..36cfa4c5 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/UserAPControllerImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/interfaces/api/actor/ActorAPControllerImplTest.kt @@ -23,7 +23,7 @@ import org.springframework.test.web.servlet.post import org.springframework.test.web.servlet.setup.MockMvcBuilders @ExtendWith(MockitoExtension::class) -class UserAPControllerImplTest { +class ActorAPControllerImplTest { private lateinit var mockMvc: MockMvc @@ -59,7 +59,8 @@ class UserAPControllerImplTest { ), endpoints = mapOf("sharedInbox" to "https://example.com/inbox"), followers = "https://example.com/users/hoge/followers", - following = "https://example.com/users/hoge/following" + following = "https://example.com/users/hoge/following", + manuallyApprovesFollowers = false ) whenever(apUserService.getPersonByName(eq("hoge"))).doReturn(person) diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt index 4eeded48..f26cd135 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/APDeliverAcceptJobProcessorTest.kt @@ -5,7 +5,7 @@ import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.service.common.APRequestService import dev.usbharu.hideout.core.external.job.DeliverAcceptJob import dev.usbharu.hideout.core.external.job.DeliverAcceptJobParam -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -25,7 +25,7 @@ class APDeliverAcceptJobProcessorTest { private lateinit var apRequestService: APRequestService @Mock - private lateinit var userQueryService: UserQueryService + private lateinit var actorQueryService: ActorQueryService @Mock private lateinit var deliverAcceptJob: DeliverAcceptJob @@ -40,7 +40,7 @@ class APDeliverAcceptJobProcessorTest { fun `process apPostが発行される`() = runTest { val user = UserBuilder.localUserOf() - whenever(userQueryService.findById(eq(1))).doReturn(user) + whenever(actorQueryService.findById(eq(1))).doReturn(user) val accept = Accept( apObject = Follow( diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt index b9015e1d..793a65b6 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/accept/ApAcceptProcessorTest.kt @@ -7,7 +7,7 @@ import dev.usbharu.hideout.activitypub.domain.model.Like import dev.usbharu.hideout.activitypub.service.common.ActivityPubProcessContext import dev.usbharu.hideout.activitypub.service.common.ActivityType import dev.usbharu.hideout.application.config.ActivityPubConfig -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.relationship.RelationshipService import dev.usbharu.httpsignature.common.HttpHeaders import dev.usbharu.httpsignature.common.HttpMethod @@ -34,7 +34,7 @@ import java.net.URL class ApAcceptProcessorTest { @Mock - private lateinit var userQueryService: UserQueryService + private lateinit var actorQueryService: ActorQueryService @Mock private lateinit var relationshipService: RelationshipService @@ -67,9 +67,9 @@ class ApAcceptProcessorTest { ) val user = UserBuilder.localUserOf() - whenever(userQueryService.findByUrl(eq("https://example.com"))).doReturn(user) + whenever(actorQueryService.findByUrl(eq("https://example.com"))).doReturn(user) val remoteUser = UserBuilder.remoteUserOf() - whenever(userQueryService.findByUrl(eq("https://remote.example.com"))).doReturn(remoteUser) + whenever(actorQueryService.findByUrl(eq("https://remote.example.com"))).doReturn(remoteUser) apAcceptProcessor.internalProcess(activity) diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessorTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessorTest.kt index 55e52ff9..1451ad4b 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessorTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/block/APDeliverBlockJobProcessorTest.kt @@ -4,7 +4,7 @@ import dev.usbharu.hideout.activitypub.domain.model.Block import dev.usbharu.hideout.activitypub.domain.model.Follow import dev.usbharu.hideout.activitypub.domain.model.Reject import dev.usbharu.hideout.activitypub.service.common.APRequestService -import dev.usbharu.hideout.core.domain.model.user.UserRepository +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.external.job.DeliverBlockJob import dev.usbharu.hideout.core.external.job.DeliverBlockJobParam import kotlinx.coroutines.test.runTest @@ -26,7 +26,7 @@ class APDeliverBlockJobProcessorTest { private lateinit var apRequestService: APRequestService @Mock - private lateinit var userRepository: UserRepository + private lateinit var actorRepository: ActorRepository @Spy private val transaction = TestTransaction @@ -40,7 +40,7 @@ class APDeliverBlockJobProcessorTest { @Test fun `process rejectとblockがapPostされる`() = runTest { val user = UserBuilder.localUserOf() - whenever(userRepository.findById(eq(user.id))).doReturn(user) + whenever(actorRepository.findById(eq(user.id))).doReturn(user) val block = Block( diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt index 01975882..c2f4f87e 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/create/ApSendCreateServiceImplTest.kt @@ -7,8 +7,8 @@ import dev.usbharu.hideout.activitypub.service.objects.note.APNoteServiceImpl import dev.usbharu.hideout.application.config.ActivityPubConfig import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.external.job.DeliverPostJob +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService -import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.service.job.JobQueueParentService import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test @@ -36,7 +36,7 @@ class ApSendCreateServiceImplTest { private lateinit var jobQueueParentService: JobQueueParentService @Mock - private lateinit var userQueryService: UserQueryService + private lateinit var actorQueryService: ActorQueryService @Mock private lateinit var noteQueryService: NoteQueryService @@ -50,7 +50,7 @@ class ApSendCreateServiceImplTest { @Test fun `createNote 正常なPostでCreateのジョブを発行できる`() = runTest { val post = PostBuilder.of() - val user = UserBuilder.localUserOf(id = post.userId) + val user = UserBuilder.localUserOf(id = post.actorId) val note = Note( id = post.apId, attributedTo = user.url, @@ -67,8 +67,8 @@ class ApSendCreateServiceImplTest { UserBuilder.remoteUserOf() ) - whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(followers) - whenever(userQueryService.findById(eq(post.userId))).doReturn(user) + whenever(followerQueryService.findFollowersById(eq(post.actorId))).doReturn(followers) + whenever(actorQueryService.findById(eq(post.actorId))).doReturn(user) whenever(noteQueryService.findById(eq(post.id))).doReturn(note to post) apSendCreateServiceImpl.createNote(post) diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowServiceImplTest.kt index 0fe5f689..0c9f266c 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/follow/APSendFollowServiceImplTest.kt @@ -24,13 +24,13 @@ class APSendFollowServiceImplTest { apSendFollowServiceImpl.sendFollow(sendFollowDto) val value = Follow( - apObject = sendFollowDto.followTargetUserId.url, - actor = sendFollowDto.userId.url + apObject = sendFollowDto.followTargetActorId.url, + actor = sendFollowDto.actorId.url ) verify(apRequestService, times(1)).apPost( - eq(sendFollowDto.followTargetUserId.inbox), + eq(sendFollowDto.followTargetActorId.inbox), eq(value), - eq(sendFollowDto.userId) + eq(sendFollowDto.actorId) ) } } diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionServiceImplTest.kt index beffd8e0..0dd3ae9a 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/activity/like/APReactionServiceImplTest.kt @@ -35,7 +35,7 @@ class APReactionServiceImplTest { val jobQueueParentService = mock() val apReactionServiceImpl = APReactionServiceImpl( jobQueueParentService = jobQueueParentService, - userQueryService = mock(), + actorQueryService = mock(), followerQueryService = followerQueryService, postQueryService = postQueryService, objectMapper = objectMapper @@ -46,7 +46,7 @@ class APReactionServiceImplTest { id = TwitterSnowflakeIdGenerateService.generateId(), emojiId = 0, postId = post.id, - userId = user.id + actorId = user.id ) ) @@ -72,7 +72,7 @@ class APReactionServiceImplTest { val jobQueueParentService = mock() val apReactionServiceImpl = APReactionServiceImpl( jobQueueParentService = jobQueueParentService, - userQueryService = mock(), + actorQueryService = mock(), followerQueryService = followerQueryService, postQueryService = postQueryService, objectMapper = objectMapper @@ -83,7 +83,7 @@ class APReactionServiceImplTest { id = TwitterSnowflakeIdGenerateService.generateId(), emojiId = 0, postId = post.id, - userId = user.id + actorId = user.id ) ) diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImplTest.kt index 5f167d6b..37623edd 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/common/APResourceResolveServiceImplTest.kt @@ -1,6 +1,6 @@ package dev.usbharu.hideout.activitypub.service.common -import dev.usbharu.hideout.core.domain.model.user.UserRepository +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.service.resource.InMemoryCacheManager import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -20,10 +20,10 @@ class APResourceResolveServiceImplTest { fun `単純な一回のリクエスト`() = runTest { - val userRepository = mock() + val actorRepository = mock() val user = UserBuilder.localUserOf() - whenever(userRepository.findById(any())) doReturn user + whenever(actorRepository.findById(any())) doReturn user val apRequestService = mock { onBlocking { @@ -37,7 +37,7 @@ class APResourceResolveServiceImplTest { ) } val apResourceResolveService = - APResourceResolveServiceImpl(apRequestService, userRepository, InMemoryCacheManager()) + APResourceResolveServiceImpl(apRequestService, actorRepository, InMemoryCacheManager()) apResourceResolveService.resolve("https", 0) @@ -48,10 +48,10 @@ class APResourceResolveServiceImplTest { fun 複数回の同じリクエストが重複して発行されない() = runTest { - val userRepository = mock() + val actorRepository = mock() val user = UserBuilder.localUserOf() - whenever(userRepository.findById(any())) doReturn user + whenever(actorRepository.findById(any())) doReturn user val apRequestService = mock { onBlocking { @@ -65,7 +65,7 @@ class APResourceResolveServiceImplTest { ) } val apResourceResolveService = - APResourceResolveServiceImpl(apRequestService, userRepository, InMemoryCacheManager()) + APResourceResolveServiceImpl(apRequestService, actorRepository, InMemoryCacheManager()) apResourceResolveService.resolve("https", 0) apResourceResolveService.resolve("https", 0) @@ -83,10 +83,10 @@ class APResourceResolveServiceImplTest { fun 複数回の同じリクエストが同時に発行されても重複して発行されない() = runTest { - val userRepository = mock() + val actorRepository = mock() val user = UserBuilder.localUserOf() - whenever(userRepository.findById(any())) doReturn user + whenever(actorRepository.findById(any())) doReturn user val apRequestService = mock { @@ -101,7 +101,7 @@ class APResourceResolveServiceImplTest { ) } val apResourceResolveService = - APResourceResolveServiceImpl(apRequestService, userRepository, InMemoryCacheManager()) + APResourceResolveServiceImpl(apRequestService, actorRepository, InMemoryCacheManager()) repeat(10) { awaitAll( @@ -129,10 +129,10 @@ class APResourceResolveServiceImplTest { @Test fun 関係のないリクエストは発行する() = runTest { - val userRepository = mock() + val actorRepository = mock() val user = UserBuilder.localUserOf() - whenever(userRepository.findById(any())).doReturn( + whenever(actorRepository.findById(any())).doReturn( user ) @@ -149,7 +149,7 @@ class APResourceResolveServiceImplTest { } val apResourceResolveService = - APResourceResolveServiceImpl(apRequestService, userRepository, InMemoryCacheManager()) + APResourceResolveServiceImpl(apRequestService, actorRepository, InMemoryCacheManager()) apResourceResolveService.resolve("abcd", 0) apResourceResolveService.resolve("1234", 0) diff --git a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt index b8713816..0a709b38 100644 --- a/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/activitypub/service/objects/note/APNoteServiceImplTest.kt @@ -16,8 +16,8 @@ import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateServ import dev.usbharu.hideout.core.domain.exception.FailedToGetResourcesException import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.PostRepository +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.PostQueryService -import dev.usbharu.hideout.core.query.UserQueryService import dev.usbharu.hideout.core.service.post.PostService import io.ktor.client.* import io.ktor.client.call.* @@ -51,9 +51,9 @@ class APNoteServiceImplTest { val url = "https://example.com/note" val post = PostBuilder.of() - val user = UserBuilder.localUserOf(id = post.userId) - val userQueryService = mock { - onBlocking { findById(eq(post.userId)) } doReturn user + val user = UserBuilder.localUserOf(id = post.actorId) + val actorQueryService = mock { + onBlocking { findById(eq(post.actorId)) } doReturn user } val expected = Note( id = post.apId, @@ -92,9 +92,9 @@ class APNoteServiceImplTest { val postQueryService = mock { onBlocking { findByApId(eq(post.apId)) } doReturn post } - val user = UserBuilder.localUserOf(id = post.userId) - val userQueryService = mock { - onBlocking { findById(eq(post.userId)) } doReturn user + val user = UserBuilder.localUserOf(id = post.actorId) + val actorQueryService = mock { + onBlocking { findById(eq(post.actorId)) } doReturn user } val note = Note( id = post.apId, @@ -133,6 +133,7 @@ class APNoteServiceImplTest { endpoints = mapOf("sharedInbox" to "https://example.com/inbox"), followers = user.followers, following = user.following, + manuallyApprovesFollowers = false ) val apUserService = mock { @@ -167,9 +168,9 @@ class APNoteServiceImplTest { val postQueryService = mock { onBlocking { findByApId(eq(post.apId)) } doReturn post } - val user = UserBuilder.localUserOf(id = post.userId) - val userQueryService = mock { - onBlocking { findById(eq(post.userId)) } doReturn user + val user = UserBuilder.localUserOf(id = post.actorId) + val actorQueryService = mock { + onBlocking { findById(eq(post.actorId)) } doReturn user } val note = Note( id = post.apId, @@ -299,7 +300,7 @@ class APNoteServiceImplTest { val user = UserBuilder.localUserOf() val post = PostBuilder.of(userId = user.id) - val userQueryService = mock { + val actorQueryService = mock { onBlocking { findById(eq(user.id)) } doReturn user } val note = Note( 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 e9d17e68..9ebbae81 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 @@ -2,9 +2,9 @@ package dev.usbharu.hideout.core.service.post import dev.usbharu.hideout.activitypub.service.activity.create.ApSendCreateService import dev.usbharu.hideout.application.config.CharacterLimit +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 -import dev.usbharu.hideout.core.domain.model.user.UserRepository import dev.usbharu.hideout.core.query.PostQueryService import dev.usbharu.hideout.core.service.timeline.TimelineService import kotlinx.coroutines.test.runTest @@ -31,7 +31,7 @@ class PostServiceImplTest { private lateinit var postRepository: PostRepository @Mock - private lateinit var userRepository: UserRepository + private lateinit var actorRepository: ActorRepository @Mock private lateinit var timelineService: TimelineService @@ -56,7 +56,7 @@ class PostServiceImplTest { whenever(postRepository.save(eq(post))).doReturn(true) whenever(postRepository.generateId()).doReturn(post.id) - whenever(userRepository.findById(eq(post.userId))).doReturn(UserBuilder.localUserOf(id = post.userId)) + whenever(actorRepository.findById(eq(post.actorId))).doReturn(UserBuilder.localUserOf(id = post.actorId)) whenever(timelineService.publishTimeline(eq(post), eq(true))).doReturn(Unit) mockStatic(Instant::class.java, Mockito.CALLS_REAL_METHODS).use { @@ -69,7 +69,7 @@ class PostServiceImplTest { post.visibility, post.repostId, post.replyId, - post.userId, + post.actorId, post.mediaIds ) ) diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImplTest.kt index e3cf0ddd..89e4feae 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/reaction/ReactionServiceImplTest.kt @@ -37,20 +37,20 @@ class ReactionServiceImplTest { val post = PostBuilder.of() - whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(false) + whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.actorId), eq(0))).doReturn(false) val generateId = TwitterSnowflakeIdGenerateService.generateId() whenever(reactionRepository.generateId()).doReturn(generateId) - reactionServiceImpl.receiveReaction("❤", "example.com", post.userId, post.id) + reactionServiceImpl.receiveReaction("❤", "example.com", post.actorId, post.id) - verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId))) + verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.actorId))) } @Test fun `receiveReaction リアクションが既に作成されていることを検知出来ずに例外が発生した場合は何もしない`() = runTest { val post = PostBuilder.of() - whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(false) + whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.actorId), eq(0))).doReturn(false) val generateId = TwitterSnowflakeIdGenerateService.generateId() whenever( reactionRepository.save( @@ -59,7 +59,7 @@ class ReactionServiceImplTest { id = generateId, emojiId = 0, postId = post.id, - userId = post.userId + actorId = post.actorId ) ) ) @@ -71,17 +71,17 @@ class ReactionServiceImplTest { } whenever(reactionRepository.generateId()).doReturn(generateId) - reactionServiceImpl.receiveReaction("❤", "example.com", post.userId, post.id) + reactionServiceImpl.receiveReaction("❤", "example.com", post.actorId, post.id) - verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId))) + verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.actorId))) } @Test fun `receiveReaction リアクションが既に作成されている場合は何もしない`() = runTest() { val post = PostBuilder.of() - whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.userId), eq(0))).doReturn(true) + whenever(reactionQueryService.reactionAlreadyExist(eq(post.id), eq(post.actorId), eq(0))).doReturn(true) - reactionServiceImpl.receiveReaction("❤", "example.com", post.userId, post.id) + reactionServiceImpl.receiveReaction("❤", "example.com", post.actorId, post.id) verify(reactionRepository, never()).save(any()) } @@ -89,47 +89,47 @@ class ReactionServiceImplTest { @Test fun `sendReaction リアクションが存在しないとき保存して配送する`() = runTest { val post = PostBuilder.of() - whenever(reactionQueryService.findByPostIdAndUserIdAndEmojiId(eq(post.id), eq(post.userId), eq(0))).doThrow( + whenever(reactionQueryService.findByPostIdAndActorIdAndEmojiId(eq(post.id), eq(post.actorId), eq(0))).doThrow( FailedToGetResourcesException::class ) val generateId = TwitterSnowflakeIdGenerateService.generateId() whenever(reactionRepository.generateId()).doReturn(generateId) - reactionServiceImpl.sendReaction("❤", post.userId, post.id) + reactionServiceImpl.sendReaction("❤", post.actorId, post.id) - verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId))) - verify(apReactionService, times(1)).reaction(eq(Reaction(generateId, 0, post.id, post.userId))) + verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.actorId))) + verify(apReactionService, times(1)).reaction(eq(Reaction(generateId, 0, post.id, post.actorId))) } @Test fun `sendReaction リアクションが存在するときは削除して保存して配送する`() = runTest { val post = PostBuilder.of() val id = TwitterSnowflakeIdGenerateService.generateId() - whenever(reactionQueryService.findByPostIdAndUserIdAndEmojiId(eq(post.id), eq(post.userId), eq(0))).doReturn( - Reaction(id, 0, post.id, post.userId) + whenever(reactionQueryService.findByPostIdAndActorIdAndEmojiId(eq(post.id), eq(post.actorId), eq(0))).doReturn( + Reaction(id, 0, post.id, post.actorId) ) val generateId = TwitterSnowflakeIdGenerateService.generateId() whenever(reactionRepository.generateId()).doReturn(generateId) - reactionServiceImpl.sendReaction("❤", post.userId, post.id) + reactionServiceImpl.sendReaction("❤", post.actorId, post.id) - verify(reactionRepository, times(1)).delete(eq(Reaction(id, 0, post.id, post.userId))) - verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.userId))) - verify(apReactionService, times(1)).removeReaction(eq(Reaction(id, 0, post.id, post.userId))) - verify(apReactionService, times(1)).reaction(eq(Reaction(generateId, 0, post.id, post.userId))) + verify(reactionRepository, times(1)).delete(eq(Reaction(id, 0, post.id, post.actorId))) + verify(reactionRepository, times(1)).save(eq(Reaction(generateId, 0, post.id, post.actorId))) + verify(apReactionService, times(1)).removeReaction(eq(Reaction(id, 0, post.id, post.actorId))) + verify(apReactionService, times(1)).reaction(eq(Reaction(generateId, 0, post.id, post.actorId))) } @Test fun `removeReaction リアクションが存在する場合削除して配送`() = runTest { val post = PostBuilder.of() - whenever(reactionQueryService.findByPostIdAndUserIdAndEmojiId(eq(post.id), eq(post.userId), eq(0))).doReturn( - Reaction(0, 0, post.id, post.userId) + whenever(reactionQueryService.findByPostIdAndActorIdAndEmojiId(eq(post.id), eq(post.actorId), eq(0))).doReturn( + Reaction(0, 0, post.id, post.actorId) ) - reactionServiceImpl.removeReaction(post.userId, post.id) + reactionServiceImpl.removeReaction(post.actorId, post.id) - verify(reactionRepository, times(1)).delete(eq(Reaction(0, 0, post.id, post.userId))) - verify(apReactionService, times(1)).removeReaction(eq(Reaction(0, 0, post.id, post.userId))) + verify(reactionRepository, times(1)).delete(eq(Reaction(0, 0, post.id, post.actorId))) + verify(apReactionService, times(1)).removeReaction(eq(Reaction(0, 0, post.id, post.actorId))) } } 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 be2fca26..93c4216d 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 @@ -8,7 +8,7 @@ import dev.usbharu.hideout.activitypub.service.activity.undo.APSendUndoService import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.relationship.Relationship import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository -import dev.usbharu.hideout.core.query.UserQueryService +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.service.follow.SendFollowDto import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test @@ -29,7 +29,7 @@ class RelationshipServiceImplTest { private val applicationConfig = ApplicationConfig(URL("https://example.com")) @Mock - private lateinit var userQueryService: UserQueryService + private lateinit var actorQueryService: ActorQueryService @Mock private lateinit var relationshipRepository: RelationshipRepository @@ -54,20 +54,20 @@ class RelationshipServiceImplTest { @Test fun `followRequest ローカルの場合followRequestフラグがtrueで永続化される`() = runTest { - whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) + whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) relationshipServiceImpl.followRequest(1234, 5678) verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = true, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -76,22 +76,22 @@ class RelationshipServiceImplTest { @Test fun `followRequest リモートの場合Followアクティビティが配送される`() = runTest { val localUser = UserBuilder.localUserOf(domain = "example.com") - whenever(userQueryService.findById(eq(1234))).doReturn(localUser) + whenever(actorQueryService.findById(eq(1234))).doReturn(localUser) val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") - whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) + whenever(actorQueryService.findById(eq(5678))).doReturn(remoteUser) relationshipServiceImpl.followRequest(1234, 5678) verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = true, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -104,13 +104,13 @@ class RelationshipServiceImplTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn(null) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = true, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -123,13 +123,13 @@ class RelationshipServiceImplTest { fun `followRequest ブロックしている場合フォローリクエスト出来ない`() = runTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = true, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -141,18 +141,18 @@ class RelationshipServiceImplTest { @Test fun `followRequest 既にフォローしている場合は念の為フォロー承認を自動で行う`() = runTest { val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") - whenever(userQueryService.findById(eq(1234))).doReturn(remoteUser) + whenever(actorQueryService.findById(eq(1234))).doReturn(remoteUser) val localUser = UserBuilder.localUserOf(domain = "example.com") - whenever(userQueryService.findById(eq(5678))).doReturn(localUser) + whenever(actorQueryService.findById(eq(5678))).doReturn(localUser) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -161,13 +161,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -180,25 +180,25 @@ class RelationshipServiceImplTest { fun `followRequest フォローリクエスト無視の場合は無視する`() = runTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = true ) ) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = true + ignoreFollowRequestToTarget = false ) ) @@ -209,20 +209,20 @@ class RelationshipServiceImplTest { @Test fun `block ローカルユーザーの場合永続化される`() = runTest { - whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) + whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) relationshipServiceImpl.block(1234, 5678) verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = true, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -231,22 +231,22 @@ class RelationshipServiceImplTest { @Test fun `block リモートユーザーの場合永続化されて配送される`() = runTest { val localUser = UserBuilder.localUserOf(domain = "example.com") - whenever(userQueryService.findById(eq(1234))).doReturn(localUser) + whenever(actorQueryService.findById(eq(1234))).doReturn(localUser) val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") - whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) + whenever(actorQueryService.findById(eq(5678))).doReturn(remoteUser) relationshipServiceImpl.block(1234, 5678) verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = true, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -256,17 +256,17 @@ class RelationshipServiceImplTest { @Test fun `acceptFollowRequest ローカルユーザーの場合永続化される`() = runTest { - whenever(userQueryService.findById(eq(5678))).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( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = true, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -274,13 +274,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -290,19 +290,19 @@ class RelationshipServiceImplTest { @Test fun `acceptFollowRequest リモートユーザーの場合永続化されて配送される`() = runTest { val localUser = UserBuilder.localUserOf(domain = "example.com") - whenever(userQueryService.findById(eq(1234))).doReturn(localUser) + whenever(actorQueryService.findById(eq(1234))).doReturn(localUser) val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") - whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) + whenever(actorQueryService.findById(eq(5678))).doReturn(remoteUser) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = true, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -311,13 +311,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -347,7 +347,7 @@ class RelationshipServiceImplTest { @Test fun `acceptFollowRequest フォローリクエストが存在せずforceがtrueのときフォローを承認する`() = runTest { - whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.remoteUserOf(domain = "remote.example.com")) + whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.remoteUserOf(domain = "remote.example.com")) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( Relationship( @@ -360,13 +360,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -410,17 +410,17 @@ class RelationshipServiceImplTest { @Test fun `rejectFollowRequest ローカルユーザーの場合永続化される`() = runTest { - whenever(userQueryService.findById(eq(5678))).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( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = true, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -429,13 +429,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -446,20 +446,20 @@ class RelationshipServiceImplTest { @Test fun `rejectFollowRequest リモートユーザーの場合永続化されて配送される`() = runTest { val localUser = UserBuilder.localUserOf(domain = "example.com") - whenever(userQueryService.findById(eq(1234))).doReturn(localUser) + whenever(actorQueryService.findById(eq(1234))).doReturn(localUser) val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") - whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) + whenever(actorQueryService.findById(eq(5678))).doReturn(remoteUser) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = true, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -468,13 +468,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -494,13 +494,13 @@ class RelationshipServiceImplTest { fun `rejectFollowRequest フォローリクエストが存在しない場合何もしない`() = runTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(5678), eq(1234))).doReturn( Relationship( - userId = 5678, - targetUserId = 1234, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -516,13 +516,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 5678, + targetActorId = 1234, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = true + ignoreFollowRequestToTarget = true ) ) ) @@ -530,16 +530,16 @@ class RelationshipServiceImplTest { @Test fun `unfollow ローカルユーザーの場合永続化される`() = runTest { - whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) + whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -548,13 +548,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -565,20 +565,20 @@ class RelationshipServiceImplTest { @Test fun `unfollow リモートユーザー場合永続化されて配送される`() = runTest { val localUser = UserBuilder.localUserOf(domain = "example.com") - whenever(userQueryService.findById(eq(1234))).doReturn(localUser) + whenever(actorQueryService.findById(eq(1234))).doReturn(localUser) val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") - whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) + whenever(actorQueryService.findById(eq(5678))).doReturn(remoteUser) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -587,13 +587,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -612,13 +612,13 @@ class RelationshipServiceImplTest { fun `unfollow フォローしていなかった場合は何もしない`() = runTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -629,16 +629,16 @@ class RelationshipServiceImplTest { @Test fun `unblock ローカルユーザーの場合永続化される`() = runTest { - whenever(userQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) + whenever(actorQueryService.findById(eq(5678))).doReturn(UserBuilder.localUserOf(domain = "example.com")) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = true, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -647,13 +647,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -664,20 +664,20 @@ class RelationshipServiceImplTest { @Test fun `unblock リモートユーザーの場合永続化されて配送される`() = runTest { val localUser = UserBuilder.localUserOf(domain = "example.com") - whenever(userQueryService.findById(eq(1234))).doReturn(localUser) + whenever(actorQueryService.findById(eq(1234))).doReturn(localUser) val remoteUser = UserBuilder.remoteUserOf(domain = "remote.example.com") - whenever(userQueryService.findById(eq(5678))).doReturn(remoteUser) + whenever(actorQueryService.findById(eq(5678))).doReturn(remoteUser) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = true, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -711,13 +711,13 @@ class RelationshipServiceImplTest { fun `unblock ブロックしていない場合は何もしない`() = runTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -733,13 +733,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = true, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) @@ -750,13 +750,13 @@ class RelationshipServiceImplTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(1234), eq(5678))).doReturn( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = true, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -765,13 +765,13 @@ class RelationshipServiceImplTest { verify(relationshipRepository, times(1)).save( eq( Relationship( - userId = 1234, - targetUserId = 5678, + actorId = 1234, + targetActorId = 5678, following = false, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) ) diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt index 4302a2ad..29b195ae 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/timeline/TimelineServiceTest.kt @@ -1,12 +1,12 @@ package dev.usbharu.hideout.core.service.timeline import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService +import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.domain.model.timeline.Timeline import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.query.ActorQueryService import dev.usbharu.hideout.core.query.FollowerQueryService -import dev.usbharu.hideout.core.query.UserQueryService import kotlinx.coroutines.test.runTest import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -27,7 +27,7 @@ class TimelineServiceTest { private lateinit var followerQueryService: FollowerQueryService @Mock - private lateinit var userQueryService: UserQueryService + private lateinit var actorQueryService: ActorQueryService @Mock private lateinit var timelineRepository: TimelineRepository @@ -41,11 +41,11 @@ class TimelineServiceTest { @Test fun `publishTimeline ローカルの投稿はローカルのフォロワーと投稿者のタイムラインに追加される`() = runTest { val post = PostBuilder.of() - val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) - val localUserOf = UserBuilder.localUserOf(id = post.userId) + val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) + val localUserOf = UserBuilder.localUserOf(id = post.actorId) - whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf) - whenever(userQueryService.findById(eq(post.userId))).doReturn(localUserOf) + whenever(followerQueryService.findFollowersById(eq(post.actorId))).doReturn(listOf) + whenever(actorQueryService.findById(eq(post.actorId))).doReturn(localUserOf) whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId()) @@ -54,15 +54,15 @@ class TimelineServiceTest { verify(timelineRepository).saveAll(capture(captor)) val timelineList = captor.value - assertThat(timelineList).hasSize(4).anyMatch { it.userId == post.userId } + assertThat(timelineList).hasSize(4).anyMatch { it.userId == post.actorId } } @Test fun `publishTimeline リモートの投稿はローカルのフォロワーのタイムラインに追加される`() = runTest { val post = PostBuilder.of() - val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) + val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) - whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf) + whenever(followerQueryService.findFollowersById(eq(post.actorId))).doReturn(listOf) whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId()) @@ -77,9 +77,9 @@ class TimelineServiceTest { @Test fun `publishTimeline パブリック投稿はパブリックタイムラインにも追加される`() = runTest { val post = PostBuilder.of() - val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) + val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) - whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf) + whenever(followerQueryService.findFollowersById(eq(post.actorId))).doReturn(listOf) whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId()) @@ -94,9 +94,9 @@ class TimelineServiceTest { @Test fun `publishTimeline パブリック投稿ではない場合はローカルのフォロワーのみに追加される`() = runTest { val post = PostBuilder.of(visibility = Visibility.UNLISTED) - val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) + val listOf = listOf(UserBuilder.localUserOf(), UserBuilder.localUserOf()) - whenever(followerQueryService.findFollowersById(eq(post.userId))).doReturn(listOf) + whenever(followerQueryService.findFollowersById(eq(post.actorId))).doReturn(listOf) whenever(timelineRepository.generateId()).doReturn(TwitterSnowflakeIdGenerateService.generateId()) diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/user/UserServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt similarity index 79% rename from src/test/kotlin/dev/usbharu/hideout/core/service/user/UserServiceTest.kt rename to src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt index c524a0f5..9d5b6f10 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/user/UserServiceTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt @@ -4,9 +4,9 @@ package dev.usbharu.hideout.core.service.user import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.config.CharacterLimit +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.user.User -import dev.usbharu.hideout.core.domain.model.user.UserRepository import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test @@ -18,13 +18,13 @@ import java.security.KeyPairGenerator import kotlin.test.assertEquals import kotlin.test.assertNull -class UserServiceTest { - val userBuilder = User.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com"))) +class ActorServiceTest { + val actorBuilder = Actor.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com"))) val postBuilder = Post.PostBuilder(CharacterLimit()) @Test fun `createLocalUser ローカルユーザーを作成できる`() = runTest { - val userRepository = mock { + val actorRepository = mock { onBlocking { nextId() } doReturn 110001L } val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair() @@ -34,21 +34,21 @@ class UserServiceTest { } val userService = UserServiceImpl( - userRepository, + actorRepository, userAuthService, mock(), - userBuilder, + actorBuilder, testApplicationConfig, + mock(), mock() ) userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test")) - verify(userRepository, times(1)).save(any()) - argumentCaptor { - verify(userRepository, times(1)).save(capture()) + verify(actorRepository, times(1)).save(any()) + argumentCaptor { + verify(actorRepository, times(1)).save(capture()) assertEquals("test", firstValue.name) assertEquals("testUser", firstValue.screenName) assertEquals("XXXXXXXXXXXXX", firstValue.description) - assertEquals("hashedPassword", firstValue.password) assertEquals(110001L, firstValue.id) assertEquals("https://example.com/users/test", firstValue.url) assertEquals("example.com", firstValue.domain) @@ -62,11 +62,11 @@ class UserServiceTest { @Test fun `createRemoteUser リモートユーザーを作成できる`() = runTest { - val userRepository = mock { + val actorRepository = mock { onBlocking { nextId() } doReturn 113345L } val userService = - UserServiceImpl(userRepository, mock(), mock(), userBuilder, testApplicationConfig, mock()) + UserServiceImpl(actorRepository, mock(), mock(), actorBuilder, testApplicationConfig, mock(), mock()) val user = RemoteUserCreateDto( name = "test", domain = "remote.example.com", @@ -79,16 +79,16 @@ class UserServiceTest { keyId = "a", following = "", followers = "", - sharedInbox = null + sharedInbox = null, + locked = false ) userService.createRemoteUser(user) - verify(userRepository, times(1)).save(any()) - argumentCaptor { - verify(userRepository, times(1)).save(capture()) + verify(actorRepository, times(1)).save(any()) + argumentCaptor { + verify(actorRepository, times(1)).save(capture()) assertEquals("test", firstValue.name) assertEquals("testUser", firstValue.screenName) assertEquals("test user", firstValue.description) - assertNull(firstValue.password) assertEquals(113345L, firstValue.id) assertEquals("https://remote.example.com", firstValue.url) assertEquals("remote.example.com", firstValue.domain) diff --git a/src/test/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiControllerTest.kt b/src/test/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiControllerTest.kt index 895f33a4..8356f17e 100644 --- a/src/test/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiControllerTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/account/MastodonAccountApiControllerTest.kt @@ -1,8 +1,8 @@ package dev.usbharu.hideout.mastodon.interfaces.api.account import dev.usbharu.hideout.application.config.ActivityPubConfig +import dev.usbharu.hideout.domain.mastodon.model.generated.AccountSource import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccount -import dev.usbharu.hideout.domain.mastodon.model.generated.CredentialAccountSource import dev.usbharu.hideout.domain.mastodon.model.generated.Role import dev.usbharu.hideout.mastodon.service.account.AccountApiService import kotlinx.coroutines.test.runTest @@ -74,10 +74,10 @@ class MastodonAccountApiControllerTest { lastStatusAt = "", statusesCount = 0, followersCount = 0, - source = CredentialAccountSource( + source = AccountSource( note = "", fields = emptyList(), - privacy = CredentialAccountSource.Privacy.public, + privacy = AccountSource.Privacy.public, sensitive = false, followRequestsCount = 0 ), diff --git a/src/test/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiServiceImplTest.kt index 19834065..652997c5 100644 --- a/src/test/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiServiceImplTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/mastodon/service/account/AccountApiServiceImplTest.kt @@ -1,9 +1,11 @@ package dev.usbharu.hideout.mastodon.service.account import dev.usbharu.hideout.application.external.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository -import dev.usbharu.hideout.core.domain.model.user.UserRepository import dev.usbharu.hideout.core.query.FollowerQueryService +import dev.usbharu.hideout.core.query.RelationshipQueryService +import dev.usbharu.hideout.core.service.media.MediaService import dev.usbharu.hideout.core.service.relationship.RelationshipService import dev.usbharu.hideout.core.service.user.UserService import dev.usbharu.hideout.domain.mastodon.model.generated.Account @@ -31,7 +33,7 @@ class AccountApiServiceImplTest { private lateinit var userService: UserService @Mock - private lateinit var userRepository: UserRepository + private lateinit var actorRepository: ActorRepository @Mock private lateinit var followerQueryService: FollowerQueryService @@ -48,6 +50,12 @@ class AccountApiServiceImplTest { @Mock private lateinit var relationshipRepository: RelationshipRepository + @Mock + private lateinit var relationshipQueryService: RelationshipQueryService + + @Mock + private lateinit var mediaService: MediaService + @InjectMocks private lateinit var accountApiServiceImpl: AccountApiServiceImpl @@ -204,13 +212,13 @@ class AccountApiServiceImplTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(loginUser), eq(userId))).doReturn( dev.usbharu.hideout.core.domain.model.relationship.Relationship( - userId = loginUser, - targetUserId = userId, + actorId = loginUser, + targetActorId = userId, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) @@ -239,24 +247,24 @@ class AccountApiServiceImplTest { whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(followeeId), eq(userId))).doReturn( dev.usbharu.hideout.core.domain.model.relationship.Relationship( - userId = followeeId, - targetUserId = userId, + actorId = followeeId, + targetActorId = userId, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) whenever(relationshipRepository.findByUserIdAndTargetUserId(eq(userId), eq(followeeId))).doReturn( dev.usbharu.hideout.core.domain.model.relationship.Relationship( - userId = userId, - targetUserId = followeeId, + actorId = userId, + targetActorId = followeeId, following = true, blocking = false, muting = false, followRequest = false, - ignoreFollowRequestFromTarget = false + ignoreFollowRequestToTarget = false ) ) diff --git a/src/test/kotlin/utils/PostBuilder.kt b/src/test/kotlin/utils/PostBuilder.kt index afe32938..d69c9d70 100644 --- a/src/test/kotlin/utils/PostBuilder.kt +++ b/src/test/kotlin/utils/PostBuilder.kt @@ -24,7 +24,7 @@ object PostBuilder { ): Post { return postBuilder.of( id = id, - userId = userId, + actorId = userId, overview = overview, text = text, createdAt = createdAt, diff --git a/src/test/kotlin/utils/UserBuilder.kt b/src/test/kotlin/utils/UserBuilder.kt index b62a3cb5..107a0613 100644 --- a/src/test/kotlin/utils/UserBuilder.kt +++ b/src/test/kotlin/utils/UserBuilder.kt @@ -3,13 +3,13 @@ package utils import dev.usbharu.hideout.application.config.ApplicationConfig import dev.usbharu.hideout.application.config.CharacterLimit import dev.usbharu.hideout.application.service.id.TwitterSnowflakeIdGenerateService -import dev.usbharu.hideout.core.domain.model.user.User +import dev.usbharu.hideout.core.domain.model.actor.Actor import kotlinx.coroutines.runBlocking import java.net.URL import java.time.Instant object UserBuilder { - private val userBuilder = User.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com"))) + private val actorBuilder = Actor.UserBuilder(CharacterLimit(), ApplicationConfig(URL("https://example.com"))) private val idGenerator = TwitterSnowflakeIdGenerateService @@ -19,7 +19,6 @@ object UserBuilder { domain: String = "example.com", screenName: String = name, description: String = "This user is test user.", - password: String = "password-$id", inbox: String = "https://$domain/users/$id/inbox", outbox: String = "https://$domain/users/$id/outbox", url: String = "https://$domain/users/$id", @@ -29,14 +28,13 @@ object UserBuilder { keyId: String = "https://$domain/users/$id#pubkey", followers: String = "https://$domain/users/$id/followers", following: String = "https://$domain/users/$id/following" - ): User { - return userBuilder.of( + ): Actor { + return actorBuilder.of( id = id, name = name, domain = domain, screenName = screenName, description = description, - password = password, inbox = inbox, outbox = outbox, url = url, @@ -45,7 +43,8 @@ object UserBuilder { createdAt = createdAt, keyId = keyId, followers = followers, - following = following + following = following, + locked = false ) } @@ -63,14 +62,13 @@ object UserBuilder { keyId: String = "https://$domain/$id#pubkey", followers: String = "https://$domain/$id/followers", following: String = "https://$domain/$id/following" - ): User { - return userBuilder.of( + ): Actor { + return actorBuilder.of( id = id, name = name, domain = domain, screenName = screenName, description = description, - password = null, inbox = inbox, outbox = outbox, url = url, @@ -79,7 +77,8 @@ object UserBuilder { createdAt = createdAt, keyId = keyId, followers = followers, - following = following + following = following, + locked = false ) }