diff --git a/src/e2eTest/resources/oauth2/user.sql b/src/e2eTest/resources/oauth2/user.sql index 351d988d..4184f284 100644 --- a/src/e2eTest/resources/oauth2/user.sql +++ b/src/e2eTest/resources/oauth2/user.sql @@ -44,7 +44,7 @@ Ja15+ZWbOA4vJA9pOh3x4XM= -----END PRIVATE KEY----- ', 1701398248417, 'http://localhost/users/test-user#pubkey', 'http://localhost/users/test-user/following', - 'http://localhost/users/test-users/followers', null, false, 0, 0, 0, null); + 'http://localhost/users/test-users/followers', 0, false, 0, 0, 0, null); insert into user_details (actor_id, password, auto_accept_followee_follow_request) values ( 1730415786666758144 diff --git a/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql b/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql index 2221dfc7..a2b01c22 100644 --- a/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql +++ b/src/intTest/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql @@ -7,11 +7,11 @@ VALUES (3733363, 'follow-test-user-1', 'example.com', 'follow-test-user-1-name', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/follow-test-user-1#pubkey', 'https://example.com/users/follow-test-user-1/following', - 'https://example.com/users/follow-test-user-1/followers', null, false, 0, 0, 0, null), + 'https://example.com/users/follow-test-user-1/followers', 0, false, 0, 0, 0, null), (37335363, 'follow-test-user-2', 'example.com', 'follow-test-user-2-name', '', 'https://example.com/users/follow-test-user-2/inbox', 'https://example.com/users/follow-test-user-2/outbox', 'https://example.com/users/follow-test-user-2', '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/follow-test-user-2#pubkey', 'https://example.com/users/follow-test-user-2/following', - 'https://example.com/users/follow-test-user-2/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/follow-test-user-2/followers', 0, false, 0, 0, 0, null); diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql index f522d4bc..dc2ab9f1 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql @@ -7,7 +7,7 @@ VALUES (8, 'test-user8', 'example.com', 'Im test-user8.', 'THis account is test- '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user8#pubkey', 'https://example.com/users/test-user8/following', - 'https://example.com/users/test-user8/followers', null, false, 0, 0, 0, null), + 'https://example.com/users/test-user8/followers', 0, false, 0, 0, 0, null), (9, 'test-user9', 'follower.example.com', 'Im test-user9.', 'THis account is test-user9.', 'https://follower.example.com/users/test-user9/inbox', 'https://follower.example.com/users/test-user9/outbox', 'https://follower.example.com/users/test-user9', @@ -15,7 +15,7 @@ VALUES (8, 'test-user8', 'example.com', 'Im test-user8.', 'THis account is test- null, 12345678, 'https://follower.example.com/users/test-user9#pubkey', 'https://follower.example.com/users/test-user9/following', - 'https://follower.example.com/users/test-user9/followers', null, false, 0, 0, 0, null); + 'https://follower.example.com/users/test-user9/followers', 0, false, 0, 0, 0, null); insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql index b0f688f2..a44861f4 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql @@ -7,7 +7,7 @@ VALUES (4, 'test-user4', 'example.com', 'Im test user4.', 'THis account is test '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user4#pubkey', 'https://example.com/users/test-user4/following', - 'https://example.com/users/test-user4/followers', null, false, 0, 0, 0, null), + 'https://example.com/users/test-user4/followers', 0, false, 0, 0, 0, null), (5, 'test-user5', 'follower.example.com', 'Im test user5.', 'THis account is test user5.', 'https://follower.example.com/users/test-user5/inbox', 'https://follower.example.com/users/test-user5/outbox', 'https://follower.example.com/users/test-user5', @@ -15,7 +15,7 @@ VALUES (4, 'test-user4', 'example.com', 'Im test user4.', 'THis account is test null, 12345678, 'https://follower.example.com/users/test-user5#pubkey', 'https://follower.example.com/users/test-user5/following', - 'https://follower.example.com/users/test-user5/followers', null, false, 0, 0, 0, null); + 'https://follower.example.com/users/test-user5/followers', 0, false, 0, 0, 0, null); insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) diff --git a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql index 4a271f1f..77cb3395 100644 --- a/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql @@ -7,7 +7,7 @@ VALUES (6, 'test-user6', 'example.com', 'Im test-user6.', 'THis account is test- '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user6#pubkey', 'https://example.com/users/test-user6/following', - 'https://example.com/users/test-user6/followers', null, false, 0, 0, 0, null), + 'https://example.com/users/test-user6/followers', 0, false, 0, 0, 0, null), (7, 'test-user7', 'follower.example.com', 'Im test-user7.', 'THis account is test-user7.', 'https://follower.example.com/users/test-user7/inbox', 'https://follower.example.com/users/test-user7/outbox', 'https://follower.example.com/users/test-user7', @@ -15,7 +15,7 @@ VALUES (6, 'test-user6', 'example.com', 'Im test-user6.', 'THis account is test- null, 12345678, 'https://follower.example.com/users/test-user7#pubkey', 'https://follower.example.com/users/test-user7/following', - 'https://follower.example.com/users/test-user7/followers', null, false, 0, 0, 0, null); + 'https://follower.example.com/users/test-user7/followers', 0, false, 0, 0, 0, null); insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, ignore_follow_request) diff --git a/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql b/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql index b99b289f..6cc9db8c 100644 --- a/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql +++ b/src/intTest/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql @@ -7,7 +7,7 @@ VALUES (11, 'test-user11', 'example.com', 'Im test-user11.', 'THis account is te '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user11#pubkey', 'https://example.com/users/test-user11/following', - 'https://example.com/users/test-user11/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/test-user11/followers', 0, false, 0, 0, 0, null); insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, diff --git a/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql b/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql index 67178345..41ac73a4 100644 --- a/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql +++ b/src/intTest/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql @@ -7,7 +7,7 @@ VALUES (10, 'test-user10', 'example.com', 'Im test-user10.', 'THis account is te '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user10#pubkey', 'https://example.com/users/test-user10/following', - 'https://example.com/users/test-user10/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/test-user10/followers', 0, false, 0, 0, 0, null); insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, diff --git a/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql b/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql index b848530c..250cfb5a 100644 --- a/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql +++ b/src/intTest/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql @@ -7,7 +7,7 @@ VALUES (3, 'test-user3', 'example.com', 'Im test user3.', 'THis account is test '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user3#pubkey', 'https://example.com/users/test-user3/following', - 'https://example.com/users/test-user3/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/test-user3/followers', 0, false, 0, 0, 0, null); insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, diff --git a/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql b/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql index 0a3272b8..777f9244 100644 --- a/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/匿名でpublic投稿を取得できる.sql @@ -7,7 +7,7 @@ VALUES (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test us '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user#pubkey', 'https://example.com/users/test-user/following', - 'https://example.com/users/test-users/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/test-users/followers', 0, false, 0, 0, 0, null); insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, diff --git a/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql b/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql index abeb3150..b132734d 100644 --- a/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql +++ b/src/intTest/resources/sql/note/匿名でunlisted投稿を取得できる.sql @@ -7,7 +7,7 @@ VALUES (2, 'test-user2', 'example.com', 'Im test user2.', 'THis account is test '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user2#pubkey', 'https://example.com/users/test-user2/following', - 'https://example.com/users/test-user2/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/test-user2/followers', 0, false, 0, 0, 0, null); insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, diff --git a/src/intTest/resources/sql/test-user.sql b/src/intTest/resources/sql/test-user.sql index cdcc686d..d46e5280 100644 --- a/src/intTest/resources/sql/test-user.sql +++ b/src/intTest/resources/sql/test-user.sql @@ -7,4 +7,4 @@ VALUES (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test us '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user#pubkey', 'https://example.com/users/test-user/following', - 'https://example.com/users/test-users/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/test-users/followers', 0, false, 0, 0, 0, null); diff --git a/src/intTest/resources/sql/test-user2.sql b/src/intTest/resources/sql/test-user2.sql index ef455c75..0f736704 100644 --- a/src/intTest/resources/sql/test-user2.sql +++ b/src/intTest/resources/sql/test-user2.sql @@ -7,4 +7,4 @@ VALUES (2, 'test-user2', 'example.com', 'Im test user.', 'THis account is test u '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, 'https://example.com/users/test-user2#pubkey', 'https://example.com/users/test-user2/following', - 'https://example.com/users/test-user2s/followers', null, false, 0, 0, 0, null); + 'https://example.com/users/test-user2s/followers', 0, false, 0, 0, 0, null); diff --git a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt index 1bfb4905..eee1e824 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/domain/model/actor/Actor.kt @@ -51,8 +51,8 @@ data class Actor private constructor( val keyId: String, val followers: String? = null, val following: String? = null, - @get:Positive - val instance: Long? = null, + @get:PositiveOrZero + val instance: Long, val locked: Boolean, val followersCount: Int = 0, val followingCount: Int = 0, @@ -86,7 +86,7 @@ data class Actor private constructor( keyId: String, following: String? = null, followers: String? = null, - instance: Long? = null, + instance: Long, locked: Boolean, followersCount: Int = 0, followingCount: Int = 0, diff --git a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt index 67c33051..08bc5de4 100644 --- a/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt +++ b/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ActorRepositoryImpl.kt @@ -167,7 +167,7 @@ object Actors : Table("actors") { 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 instance = long("instance").references(Instance.id) val locked = bool("locked") val followingCount = integer("following_count") val followersCount = integer("followers_count") 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 5a459405..294656ca 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 @@ -78,7 +78,8 @@ class UserServiceImpl( following = "$userUrl/following", followers = "$userUrl/followers", keyId = "$userUrl#pubkey", - locked = false + locked = false, + instance = 0 ) val save = actorRepository.save(userEntity) userDetailRepository.save(UserDetail(nextId, hashedPassword, true)) @@ -95,13 +96,7 @@ class UserServiceImpl( throw IllegalStateException("Cannot create Deleted actor.") } - @Suppress("TooGenericExceptionCaught") - val instance = try { - instanceService.fetchInstance(user.url, user.sharedInbox) - } catch (e: Exception) { - logger.warn("FAILED to fetch instance. url: {}", user.url, e) - null - } + val instance = instanceService.fetchInstance(user.url, user.sharedInbox) val nextId = actorRepository.nextId() val userEntity = actorBuilder.of( @@ -118,7 +113,7 @@ class UserServiceImpl( followers = user.followers, following = user.following, keyId = user.keyId, - instance = instance?.id, + instance = instance.id, locked = user.locked ?: false ) return try { diff --git a/src/main/resources/db/migration/V1__Init_DB.sql b/src/main/resources/db/migration/V1__Init_DB.sql index 4b76304f..09f4f0ca 100644 --- a/src/main/resources/db/migration/V1__Init_DB.sql +++ b/src/main/resources/db/migration/V1__Init_DB.sql @@ -45,7 +45,7 @@ create table if not exists actors key_id varchar(1000) not null, "following" varchar(1000) null, followers varchar(1000) null, - "instance" bigint null, + "instance" bigint not null, locked boolean not null, following_count int not null, followers_count int not null, @@ -240,10 +240,14 @@ create table if not exists relationships unique (actor_id, target_actor_id) ); +insert into instance (id, name, description, url, icon_url, shared_inbox, software, version, is_blocked, is_muted, + moderation_note, created_at) +values (0, 'system', '', '', '', null, '', '', false, false, '', current_timestamp); + insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at, key_id, following, followers, instance, locked, following_count, followers_count, posts_count, last_post_at) -values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', null, true, 0, 0, 0, null); +values (0, 'ghost', '', '', '', '', '', '', '', null, 0, '', '', '', 0, true, 0, 0, 0, null); create table if not exists deleted_actors ( diff --git a/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt index c44479cc..846c0d9e 100644 --- a/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt +++ b/src/test/kotlin/dev/usbharu/hideout/core/service/user/ActorServiceTest.kt @@ -22,6 +22,8 @@ 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.instance.Instance +import dev.usbharu.hideout.core.service.instance.InstanceService import jakarta.validation.Validation import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest @@ -31,6 +33,7 @@ import org.mockito.kotlin.* import utils.TestApplicationConfig.testApplicationConfig import java.net.URL import java.security.KeyPairGenerator +import java.time.Instant import kotlin.test.assertEquals import kotlin.test.assertNull @@ -40,6 +43,7 @@ class ActorServiceTest { ApplicationConfig(URL("https://example.com")), Validation.buildDefaultValidatorFactory().validator ) + @Test fun `createLocalUser ローカルユーザーを作成できる`() = runTest { @@ -90,13 +94,34 @@ class ActorServiceTest { onBlocking { nextId() } doReturn 113345L } + val instanceService = mock { + onBlocking { + fetchInstance( + eq("https://remote.example.com"), + isNull() + ) + } doReturn Instance( + 12345L, + "", + "", + "https://remote.example.com", + "https://remote.example.com/favicon.ico", + null, + "unknown", + "", + false, + false, + "", + Instant.now() + ) + } val userService = UserServiceImpl( actorRepository = actorRepository, userAuthService = mock(), actorBuilder = actorBuilder, applicationConfig = testApplicationConfig, - instanceService = mock(), + instanceService = instanceService, userDetailRepository = mock(), deletedActorRepository = mock(), reactionRepository = mock(), diff --git a/src/test/kotlin/utils/UserBuilder.kt b/src/test/kotlin/utils/UserBuilder.kt index 4f28ea93..0aff8e44 100644 --- a/src/test/kotlin/utils/UserBuilder.kt +++ b/src/test/kotlin/utils/UserBuilder.kt @@ -64,7 +64,8 @@ object UserBuilder { keyId = keyId, followers = followers, following = following, - locked = false + locked = false, + instance = 0 ) } @@ -82,6 +83,7 @@ object UserBuilder { keyId: String = "https://$domain/$id#pubkey", followers: String = "https://$domain/$id/followers", following: String = "https://$domain/$id/following", + instanceId: Long = generateId(), ): Actor { return actorBuilder.of( id = id, @@ -98,7 +100,8 @@ object UserBuilder { keyId = keyId, followers = followers, following = following, - locked = false + locked = false, + instance = instanceId ) }