From 50b9e3178ca1bf689c39782ca66e783e7737662c Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Wed, 26 Apr 2023 16:52:05 +0900
Subject: [PATCH 01/45] =?UTF-8?q?refactor:=20UserAuthentication=E3=82=92?=
 =?UTF-8?q?=E9=9D=9E=E6=8E=A8=E5=A5=A8=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/domain/model/User.kt  | 27 ++++++++++++++++---
 .../domain/model/UserAuthentication.kt        |  5 ++--
 .../hideout/repository/UserRepository.kt      | 23 +++-------------
 .../activitypub/ActivityPubUserServiceImpl.kt |  6 ++++-
 .../hideout/service/impl/UserAuthService.kt   |  6 ++++-
 5 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
index 7239465e..62c8fa47 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
@@ -1,16 +1,26 @@
 package dev.usbharu.hideout.domain.model
 
+import org.h2.mvstore.type.LongDataType
 import org.jetbrains.exposed.dao.id.LongIdTable
 import org.jetbrains.exposed.sql.ResultRow
+import org.jetbrains.exposed.sql.Table
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.ZoneId
 
 data class User(
+    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
+    val url: String,
+    val publicKey:String,
+    val privateKey:String? = null,
+    val createdAt:LocalDateTime
 )
 
 data class UserEntity(
@@ -35,15 +45,21 @@ data class UserEntity(
     )
 }
 
-object Users : LongIdTable("users") {
+object Users : Table("users") {
+    val id = long("id").uniqueIndex()
     val name = varchar("name", length = 64)
     val domain = varchar("domain", length = 255)
     val screenName = varchar("screen_name", length = 64)
     val description = varchar("description", length = 600)
+    val password = varchar("password", length = 255).nullable()
     val inbox = varchar("inbox", length = 255).uniqueIndex()
     val outbox = varchar("outbox", length = 255).uniqueIndex()
     val url = varchar("url", length = 255).uniqueIndex()
+    val publicKey = varchar("public_key", length = 10000)
+    val privateKey = varchar("private_key", length = 10000)
+    val createdAt = long("created_at")
 
+    override val primaryKey: PrimaryKey = PrimaryKey(id)
     init {
         uniqueIndex(name, domain)
     }
@@ -52,12 +68,17 @@ object Users : LongIdTable("users") {
 
 fun ResultRow.toUser(): User {
     return User(
+        this[Users.id],
         this[Users.name],
         this[Users.domain],
         this[Users.screenName],
         this[Users.description],
+        this[Users.password],
         this[Users.inbox],
         this[Users.outbox],
-        this[Users.url]
+        this[Users.url],
+        this[Users.publicKey],
+        this[Users.privateKey],
+        LocalDateTime.ofInstant(Instant.ofEpochMilli((this[Users.createdAt])), ZoneId.systemDefault())
     )
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
index d1cd3d82..c1f02961 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
@@ -3,13 +3,14 @@ package dev.usbharu.hideout.domain.model
 import org.jetbrains.exposed.dao.id.LongIdTable
 import org.jetbrains.exposed.sql.ReferenceOption
 
+@Deprecated("")
 data class UserAuthentication(
     val userId: Long,
     val hash: String?,
     val publicKey: String,
     val privateKey: String?
 )
-
+@Deprecated("")
 data class UserAuthenticationEntity(
     val id: Long,
     val userId: Long,
@@ -25,7 +26,7 @@ data class UserAuthenticationEntity(
         userAuthentication.privateKey
     )
 }
-
+@Deprecated("")
 object UsersAuthentication : LongIdTable("users_auth") {
     val userId = long("user_id").references(Users.id, onUpdate = ReferenceOption.CASCADE)
     val hash = varchar("hash", length = 64).nullable()
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index dfaf32aa..c0382755 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -1,9 +1,6 @@
 package dev.usbharu.hideout.repository
 
-import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UserEntity
-import dev.usbharu.hideout.domain.model.Users
-import dev.usbharu.hideout.domain.model.UsersFollowers
+import dev.usbharu.hideout.domain.model.*
 import kotlinx.coroutines.Dispatchers
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
@@ -20,21 +17,9 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    private fun ResultRow.toUser(): User {
-        return User(
-            this[Users.name],
-            this[Users.domain],
-            this[Users.screenName],
-            this[Users.description],
-            this[Users.inbox],
-            this[Users.outbox],
-            this[Users.url]
-        )
-    }
-
     private fun ResultRow.toUserEntity(): UserEntity {
         return UserEntity(
-            this[Users.id].value,
+            this[Users.id],
             this[Users.name],
             this[Users.domain],
             this[Users.screenName],
@@ -58,7 +43,7 @@ class UserRepository(private val database: Database) : IUserRepository {
                 it[inbox] = user.inbox
                 it[outbox] = user.outbox
                 it[url] = user.url
-            }[Users.id].value, user)
+            }[Users.id], user)
         }
     }
 
@@ -143,7 +128,7 @@ class UserRepository(private val database: Database) : IUserRepository {
                 .select { Users.id eq id }
                 .map {
                     UserEntity(
-                        id = it[followers[Users.id]].value,
+                        id = it[followers[Users.id]],
                         name = it[followers[Users.name]],
                         domain = it[followers[Users.domain]],
                         screenName = it[followers[Users.screenName]],
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 88272bdf..f4dd9fec 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -17,6 +17,7 @@ import io.ktor.client.request.*
 import io.ktor.client.statement.*
 import io.ktor.http.*
 import org.slf4j.LoggerFactory
+import java.time.LocalDateTime
 
 class ActivityPubUserServiceImpl(
     private val userService: UserService,
@@ -91,6 +92,7 @@ class ActivityPubUserServiceImpl(
             val person = Config.configData.objectMapper.readValue<Person>(httpResponse.bodyAsText())
             val userEntity = userService.create(
                 User(
+                    id = 0L,
                     name = person.preferredUsername
                         ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
                     domain = url.substringAfter(":").substringBeforeLast("/"),
@@ -98,7 +100,9 @@ class ActivityPubUserServiceImpl(
                     description = person.summary ?: "",
                     inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"),
                     outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"),
-                    url = url
+                    url = url,
+                    publicKey = "",
+                    createdAt = LocalDateTime.now()
                 )
             )
             userAuthService.createAccount(
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index 5542d1ee..5166082a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -13,6 +13,7 @@ import io.ktor.util.*
 import java.security.*
 import java.security.interfaces.RSAPrivateKey
 import java.security.interfaces.RSAPublicKey
+import java.time.LocalDateTime
 import java.util.*
 
 class UserAuthService(
@@ -34,13 +35,16 @@ class UserAuthService(
     override suspend fun registerAccount(username: String, hash: String) {
         val url = "${Config.configData.url}/users/$username"
         val registerUser = User(
+            id = 0L,
             name = username,
             domain = Config.configData.domain,
             screenName = username,
             description = "",
             inbox = "$url/inbox",
             outbox = "$url/outbox",
-            url = url
+            url = url,
+            publicKey = "",
+            createdAt = LocalDateTime.now(),
         )
         val createdUser = userRepository.create(registerUser)
 

From 07cf2c7c9d107f49dc8309d4285a7dbeb0756c8b Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Wed, 26 Apr 2023 17:08:27 +0900
Subject: [PATCH 02/45] =?UTF-8?q?refactor:=20UserEntity=E3=82=92=E5=89=8A?=
 =?UTF-8?q?=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/domain/model/Posts.kt |  1 +
 .../dev/usbharu/hideout/domain/model/User.kt  | 66 ---------------
 .../domain/model/UserAuthentication.kt        |  1 +
 .../hideout/domain/model/UsersFollowers.kt    |  1 +
 .../hideout/repository/IUserRepository.kt     | 21 +++--
 .../hideout/repository/UserRepository.kt      | 84 +++++++++++++------
 .../hideout/service/impl/UserAuthService.kt   |  1 -
 .../hideout/service/impl/UserService.kt       | 19 ++---
 .../hideout/plugins/ActivityPubKtTest.kt      | 39 ++++++---
 .../usbharu/hideout/plugins/KtorKeyMapTest.kt | 36 +++++---
 .../hideout/repository/UserRepositoryTest.kt  |  1 -
 .../ActivityPubFollowServiceImplTest.kt       | 15 ++--
 .../ActivityPubNoteServiceImplTest.kt         | 26 ++++--
 13 files changed, 159 insertions(+), 152 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt
index 3a6867db..d9e13915 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt
@@ -1,5 +1,6 @@
 package dev.usbharu.hideout.domain.model
 
+import dev.usbharu.hideout.repository.Users
 import org.jetbrains.exposed.sql.ResultRow
 import org.jetbrains.exposed.sql.Table
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
index 62c8fa47..ee46667a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
@@ -1,12 +1,6 @@
 package dev.usbharu.hideout.domain.model
 
-import org.h2.mvstore.type.LongDataType
-import org.jetbrains.exposed.dao.id.LongIdTable
-import org.jetbrains.exposed.sql.ResultRow
-import org.jetbrains.exposed.sql.Table
-import java.time.Instant
 import java.time.LocalDateTime
-import java.time.ZoneId
 
 data class User(
     val id:Long,
@@ -22,63 +16,3 @@ data class User(
     val privateKey:String? = null,
     val createdAt:LocalDateTime
 )
-
-data class UserEntity(
-    val id: Long,
-    val name: String,
-    val domain: String,
-    val screenName: String,
-    val description: String,
-    val inbox: String,
-    val outbox: String,
-    val url: String
-) {
-    constructor(id: Long, user: User) : this(
-        id,
-        user.name,
-        user.domain,
-        user.screenName,
-        user.description,
-        user.inbox,
-        user.outbox,
-        user.url
-    )
-}
-
-object Users : Table("users") {
-    val id = long("id").uniqueIndex()
-    val name = varchar("name", length = 64)
-    val domain = varchar("domain", length = 255)
-    val screenName = varchar("screen_name", length = 64)
-    val description = varchar("description", length = 600)
-    val password = varchar("password", length = 255).nullable()
-    val inbox = varchar("inbox", length = 255).uniqueIndex()
-    val outbox = varchar("outbox", length = 255).uniqueIndex()
-    val url = varchar("url", length = 255).uniqueIndex()
-    val publicKey = varchar("public_key", length = 10000)
-    val privateKey = varchar("private_key", length = 10000)
-    val createdAt = long("created_at")
-
-    override val primaryKey: PrimaryKey = PrimaryKey(id)
-    init {
-        uniqueIndex(name, domain)
-    }
-}
-
-
-fun ResultRow.toUser(): User {
-    return User(
-        this[Users.id],
-        this[Users.name],
-        this[Users.domain],
-        this[Users.screenName],
-        this[Users.description],
-        this[Users.password],
-        this[Users.inbox],
-        this[Users.outbox],
-        this[Users.url],
-        this[Users.publicKey],
-        this[Users.privateKey],
-        LocalDateTime.ofInstant(Instant.ofEpochMilli((this[Users.createdAt])), ZoneId.systemDefault())
-    )
-}
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
index c1f02961..5754021a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
@@ -1,5 +1,6 @@
 package dev.usbharu.hideout.domain.model
 
+import dev.usbharu.hideout.repository.Users
 import org.jetbrains.exposed.dao.id.LongIdTable
 import org.jetbrains.exposed.sql.ReferenceOption
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
index 1f5de8ce..b5078c53 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
@@ -1,5 +1,6 @@
 package dev.usbharu.hideout.domain.model
 
+import dev.usbharu.hideout.repository.Users
 import org.jetbrains.exposed.dao.id.LongIdTable
 
 object UsersFollowers : LongIdTable("users_followers") {
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
index dd89dbd9..73ac26a4 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
@@ -1,32 +1,31 @@
 package dev.usbharu.hideout.repository
 
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UserEntity
 
 interface IUserRepository {
-    suspend fun create(user: User): UserEntity
+    suspend fun create(user: User): User
 
-    suspend fun findById(id: Long): UserEntity?
+    suspend fun findById(id: Long): User?
 
-    suspend fun findByIds(ids: List<Long>): List<UserEntity>
+    suspend fun findByIds(ids: List<Long>): List<User>
 
-    suspend fun findByName(name: String): UserEntity?
+    suspend fun findByName(name: String): User?
 
-    suspend fun findByNameAndDomains(names: List<Pair<String,String>>): List<UserEntity>
+    suspend fun findByNameAndDomains(names: List<Pair<String,String>>): List<User>
 
-    suspend fun findByUrl(url:String):UserEntity?
+    suspend fun findByUrl(url:String): User?
 
-    suspend fun findByUrls(urls: List<String>): List<UserEntity>
+    suspend fun findByUrls(urls: List<String>): List<User>
 
-    suspend fun update(userEntity: UserEntity)
+    suspend fun update(userEntity: User)
 
     suspend fun delete(id: Long)
 
     suspend fun findAll(): List<User>
 
-    suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long = 0): List<UserEntity>
+    suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long = 0): List<User>
 
     suspend fun createFollower(id: Long, follower: Long)
     suspend fun deleteFollower(id: Long, follower: Long)
-    suspend fun findFollowersById(id: Long): List<UserEntity>
+    suspend fun findFollowersById(id: Long): List<User>
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index c0382755..051ceff0 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -6,6 +6,9 @@ import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
 import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
 import org.jetbrains.exposed.sql.transactions.transaction
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.ZoneId
 
 class UserRepository(private val database: Database) : IUserRepository {
     init {
@@ -17,25 +20,14 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    private fun ResultRow.toUserEntity(): UserEntity {
-        return UserEntity(
-            this[Users.id],
-            this[Users.name],
-            this[Users.domain],
-            this[Users.screenName],
-            this[Users.description],
-            this[Users.inbox],
-            this[Users.outbox],
-            this[Users.url],
-        )
-    }
+    private fun ResultRow.toUserEntity(): User = toUser()
 
     suspend fun <T> query(block: suspend () -> T): T =
         newSuspendedTransaction(Dispatchers.IO) { block() }
 
-    override suspend fun create(user: User): UserEntity {
+    override suspend fun create(user: User): User {
         return query {
-            UserEntity(Users.insert {
+            Users.insert {
                 it[name] = user.name
                 it[domain] = user.domain
                 it[screenName] = user.screenName
@@ -43,7 +35,8 @@ class UserRepository(private val database: Database) : IUserRepository {
                 it[inbox] = user.inbox
                 it[outbox] = user.outbox
                 it[url] = user.url
-            }[Users.id], user)
+            }
+            return@query user
         }
     }
 
@@ -56,7 +49,7 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    override suspend fun findById(id: Long): UserEntity? {
+    override suspend fun findById(id: Long): User? {
         return query {
             Users.select { Users.id eq id }.map {
                 it.toUserEntity()
@@ -64,7 +57,7 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    override suspend fun findByIds(ids: List<Long>): List<UserEntity> {
+    override suspend fun findByIds(ids: List<Long>): List<User> {
         return query {
             Users.select { Users.id inList ids }.map {
                 it.toUserEntity()
@@ -72,7 +65,7 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    override suspend fun findByName(name: String): UserEntity? {
+    override suspend fun findByName(name: String): User? {
         return query {
             Users.select { Users.name eq name }.map {
                 it.toUserEntity()
@@ -80,7 +73,7 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<UserEntity> {
+    override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
         return query {
             val selectAll = Users.selectAll()
             names.forEach { (name, domain) ->
@@ -90,19 +83,19 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    override suspend fun findByUrl(url: String): UserEntity? {
+    override suspend fun findByUrl(url: String): User? {
         return query {
             Users.select { Users.url eq url }.singleOrNull()?.toUserEntity()
         }
     }
 
-    override suspend fun findByUrls(urls: List<String>): List<UserEntity> {
+    override suspend fun findByUrls(urls: List<String>): List<User> {
         return query {
             Users.select { Users.url inList urls }.map { it.toUserEntity() }
         }
     }
 
-    override suspend fun findFollowersById(id: Long): List<UserEntity> {
+    override suspend fun findFollowersById(id: Long): List<User> {
         return query {
             val followers = Users.alias("FOLLOWERS")
             Users.innerJoin(
@@ -127,22 +120,26 @@ class UserRepository(private val database: Database) : IUserRepository {
                 )
                 .select { Users.id eq id }
                 .map {
-                    UserEntity(
+                    User(
                         id = it[followers[Users.id]],
                         name = it[followers[Users.name]],
                         domain = it[followers[Users.domain]],
                         screenName = it[followers[Users.screenName]],
                         description = it[followers[Users.description]],
+                        password = it[followers[Users.password]],
                         inbox = it[followers[Users.inbox]],
                         outbox = it[followers[Users.outbox]],
                         url = it[followers[Users.url]],
+                        publicKey = it[followers[Users.publicKey]],
+                        privateKey = it[followers[Users.privateKey]],
+                        createdAt = LocalDateTime.ofInstant(Instant.ofEpochMilli(it[followers[Users.createdAt]]), ZoneId.systemDefault())
                     )
                 }
         }
     }
 
 
-    override suspend fun update(userEntity: UserEntity) {
+    override suspend fun update(userEntity: User) {
         return query {
             Users.update({ Users.id eq userEntity.id }) {
                 it[name] = userEntity.name
@@ -174,9 +171,46 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List<UserEntity> {
+    override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List<User> {
         return query {
             Users.selectAll().limit(limit, offset).map { it.toUserEntity() }
         }
     }
 }
+
+object Users : Table("users") {
+    val id = long("id").uniqueIndex()
+    val name = varchar("name", length = 64)
+    val domain = varchar("domain", length = 255)
+    val screenName = varchar("screen_name", length = 64)
+    val description = varchar("description", length = 600)
+    val password = varchar("password", length = 255).nullable()
+    val inbox = varchar("inbox", length = 255).uniqueIndex()
+    val outbox = varchar("outbox", length = 255).uniqueIndex()
+    val url = varchar("url", length = 255).uniqueIndex()
+    val publicKey = varchar("public_key", length = 10000)
+    val privateKey = varchar("private_key", length = 10000)
+    val createdAt = long("created_at")
+
+    override val primaryKey: PrimaryKey = PrimaryKey(id)
+    init {
+        uniqueIndex(name, domain)
+    }
+}
+
+fun ResultRow.toUser(): User {
+    return User(
+        this[Users.id],
+        this[Users.name],
+        this[Users.domain],
+        this[Users.screenName],
+        this[Users.description],
+        this[Users.password],
+        this[Users.inbox],
+        this[Users.outbox],
+        this[Users.url],
+        this[Users.publicKey],
+        this[Users.privateKey],
+        LocalDateTime.ofInstant(Instant.ofEpochMilli((this[Users.createdAt])), ZoneId.systemDefault())
+    )
+}
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index 5166082a..a0cdfabc 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -4,7 +4,6 @@ import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.UserAuthentication
 import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
-import dev.usbharu.hideout.domain.model.UserEntity
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.repository.IUserAuthRepository
 import dev.usbharu.hideout.repository.IUserRepository
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index a64ccd04..fcbc60cb 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -1,7 +1,6 @@
 package dev.usbharu.hideout.service.impl
 
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UserEntity
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.repository.IUserRepository
 import java.lang.Integer.min
@@ -9,7 +8,7 @@ import java.lang.Integer.min
 class UserService(private val userRepository: IUserRepository) {
 
     private val maxLimit = 100
-    suspend fun findAll(limit: Int? = maxLimit, offset: Long? = 0): List<UserEntity> {
+    suspend fun findAll(limit: Int? = maxLimit, offset: Long? = 0): List<User> {
 
         return userRepository.findAllByLimitAndByOffset(
             min(limit ?: maxLimit, maxLimit),
@@ -17,36 +16,36 @@ class UserService(private val userRepository: IUserRepository) {
         )
     }
 
-    suspend fun findById(id: Long): UserEntity {
+    suspend fun findById(id: Long): User {
         return userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
     }
 
-    suspend fun findByIds(ids: List<Long>): List<UserEntity> {
+    suspend fun findByIds(ids: List<Long>): List<User> {
         return userRepository.findByIds(ids)
     }
 
-    suspend fun findByName(name: String): UserEntity {
+    suspend fun findByName(name: String): User {
         return userRepository.findByName(name)
             ?: throw UserNotFoundException("$name was not found.")
     }
 
-    suspend fun findByNameAndDomains(names: List<Pair<String,String>>): List<UserEntity> {
+    suspend fun findByNameAndDomains(names: List<Pair<String,String>>): List<User> {
         return userRepository.findByNameAndDomains(names)
     }
 
-    suspend fun findByUrl(url: String): UserEntity {
+    suspend fun findByUrl(url: String): User {
         return userRepository.findByUrl(url) ?: throw UserNotFoundException("$url was not found.")
     }
 
-    suspend fun findByUrls(urls: List<String>): List<UserEntity> {
+    suspend fun findByUrls(urls: List<String>): List<User> {
         return userRepository.findByUrls(urls)
     }
 
-    suspend fun create(user: User): UserEntity {
+    suspend fun create(user: User): User {
         return userRepository.create(user)
     }
 
-    suspend fun findFollowersById(id: Long): List<UserEntity> {
+    suspend fun findFollowersById(id: Long): List<User> {
         return userRepository.findFollowersById(id)
     }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
index b5690c99..035f3143 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
@@ -1,10 +1,9 @@
 package dev.usbharu.hideout.plugins
 
-import dev.usbharu.hideout.domain.model.ap.JsonLd
 import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.UserAuthentication
 import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
-import dev.usbharu.hideout.domain.model.UserEntity
+import dev.usbharu.hideout.domain.model.ap.JsonLd
 import dev.usbharu.hideout.repository.IUserAuthRepository
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.impl.UserAuthService
@@ -17,41 +16,55 @@ import org.junit.jupiter.api.Test
 import java.security.KeyPairGenerator
 import java.security.interfaces.RSAPrivateKey
 import java.security.interfaces.RSAPublicKey
+import java.time.LocalDateTime
 
 class ActivityPubKtTest {
     @Test
     fun HttpSignTest(): Unit = runBlocking {
 
         val ktorKeyMap = KtorKeyMap(UserAuthService(object : IUserRepository {
-            override suspend fun create(user: User): UserEntity {
+            override suspend fun create(user: User): User {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findById(id: Long): UserEntity? {
+            override suspend fun findById(id: Long): User? {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByIds(ids: List<Long>): List<UserEntity> {
+            override suspend fun findByIds(ids: List<Long>): List<User> {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByName(name: String): UserEntity? {
-                return UserEntity(1, "test", "localhost", "test", "","","","")
+            override suspend fun findByName(name: String): User? {
+                return User(
+                    1,
+                    "test",
+                    "localhost",
+                    "test",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    null,
+                    LocalDateTime.now()
+                )
             }
 
-            override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<UserEntity> {
+            override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByUrl(url: String): UserEntity? {
+            override suspend fun findByUrl(url: String): User? {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByUrls(urls: List<String>): List<UserEntity> {
+            override suspend fun findByUrls(urls: List<String>): List<User> {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun update(userEntity: UserEntity) {
+            override suspend fun update(userEntity: User) {
                 TODO("Not yet implemented")
             }
 
@@ -63,7 +76,7 @@ class ActivityPubKtTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List<UserEntity> {
+            override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List<User> {
                 TODO("Not yet implemented")
             }
 
@@ -75,7 +88,7 @@ class ActivityPubKtTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findFollowersById(id: Long): List<UserEntity> {
+            override suspend fun findFollowersById(id: Long): List<User> {
                 TODO("Not yet implemented")
             }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index 02cfb9b4..edaeaff3 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -3,7 +3,6 @@ package dev.usbharu.hideout.plugins
 import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.UserAuthentication
 import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
-import dev.usbharu.hideout.domain.model.UserEntity
 import dev.usbharu.hideout.repository.IUserAuthRepository
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.impl.UserAuthService
@@ -12,41 +11,54 @@ import org.junit.jupiter.api.Test
 import java.security.KeyPairGenerator
 import java.security.interfaces.RSAPrivateKey
 import java.security.interfaces.RSAPublicKey
+import java.time.LocalDateTime
 
 class KtorKeyMapTest {
 
     @Test
     fun getPrivateKey() {
         val ktorKeyMap = KtorKeyMap(UserAuthService(object : IUserRepository {
-            override suspend fun create(user: User): UserEntity {
+            override suspend fun create(user: User): User {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findById(id: Long): UserEntity? {
+            override suspend fun findById(id: Long): User? {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByIds(ids: List<Long>): List<UserEntity> {
+            override suspend fun findByIds(ids: List<Long>): List<User> {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByName(name: String): UserEntity? {
-                return UserEntity(1, "test", "localhost", "test", "","","","")
+            override suspend fun findByName(name: String): User? {
+                return User(
+                    1,
+                    "test",
+                    "localhost",
+                    "test",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    "",
+                    createdAt = LocalDateTime.now()
+                )
             }
 
-            override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<UserEntity> {
+            override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByUrl(url: String): UserEntity? {
+            override suspend fun findByUrl(url: String): User? {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByUrls(urls: List<String>): List<UserEntity> {
+            override suspend fun findByUrls(urls: List<String>): List<User> {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun update(userEntity: UserEntity) {
+            override suspend fun update(userEntity: User) {
                 TODO("Not yet implemented")
             }
 
@@ -58,7 +70,7 @@ class KtorKeyMapTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List<UserEntity> {
+            override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List<User> {
                 TODO("Not yet implemented")
             }
 
@@ -70,7 +82,7 @@ class KtorKeyMapTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findFollowersById(id: Long): List<UserEntity> {
+            override suspend fun findFollowersById(id: Long): List<User> {
                 TODO("Not yet implemented")
             }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
index 740bc90e..54b6dc69 100644
--- a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
@@ -3,7 +3,6 @@
 package dev.usbharu.hideout.repository
 
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.Users
 import dev.usbharu.hideout.domain.model.UsersFollowers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
index c5a0bb5f..3de7494d 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
@@ -6,7 +6,7 @@ package dev.usbharu.hideout.service.activitypub
 import com.fasterxml.jackson.module.kotlin.readValue
 import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.config.ConfigData
-import dev.usbharu.hideout.domain.model.UserEntity
+import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.ap.*
 import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
 import dev.usbharu.hideout.service.impl.UserService
@@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.kotlin.*
 import utils.JsonObjectMapper
+import java.time.LocalDateTime
 
 class ActivityPubFollowServiceImplTest {
     @Test
@@ -88,7 +89,7 @@ class ActivityPubFollowServiceImplTest {
         }
         val userService = mock<UserService> {
             onBlocking { findByUrls(any()) } doReturn listOf(
-                UserEntity(
+                User(
                     id = 1L,
                     name = "test",
                     domain = "example.com",
@@ -96,9 +97,11 @@ class ActivityPubFollowServiceImplTest {
                     description = "This user is test user.",
                     inbox = "https://example.com/inbox",
                     outbox = "https://example.com/outbox",
-                    url = "https://example.com"
+                    url = "https://example.com",
+                    publicKey = "",
+                    createdAt = LocalDateTime.now()
                 ),
-                UserEntity(
+                User(
                     id = 2L,
                     name = "follower",
                     domain = "follower.example.com",
@@ -106,7 +109,9 @@ class ActivityPubFollowServiceImplTest {
                     description = "This user is test follower user.",
                     inbox = "https://follower.example.com/inbox",
                     outbox = "https://follower.example.com/outbox",
-                    url = "https://follower.example.com"
+                    url = "https://follower.example.com",
+                    publicKey = "",
+                    createdAt = LocalDateTime.now()
                 )
             )
             onBlocking { addFollowers(any(), any()) } doReturn Unit
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
index 8d820be6..a9445572 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
@@ -6,7 +6,7 @@ package dev.usbharu.hideout.service.activitypub
 import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.config.ConfigData
 import dev.usbharu.hideout.domain.model.PostEntity
-import dev.usbharu.hideout.domain.model.UserEntity
+import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.job.DeliverPostJob
 import dev.usbharu.hideout.service.impl.UserService
 import dev.usbharu.hideout.service.job.JobQueueParentService
@@ -20,13 +20,14 @@ import org.junit.jupiter.api.Test
 import org.mockito.Mockito.eq
 import org.mockito.kotlin.*
 import utils.JsonObjectMapper
+import java.time.LocalDateTime
 import kotlin.test.assertEquals
 
 class ActivityPubNoteServiceImplTest {
     @Test
     fun `createPost 新しい投稿`() = runTest {
-        val followers = listOf<UserEntity>(
-            UserEntity(
+        val followers = listOf<User>(
+            User(
                 2L,
                 "follower",
                 "follower.example.com",
@@ -34,9 +35,12 @@ class ActivityPubNoteServiceImplTest {
                 "test follower user",
                 "https://follower.example.com/inbox",
                 "https://follower.example.com/outbox",
-                "https://follower.example.com"
+                "https://follower.example.com",
+                "",
+                publicKey = "",
+                createdAt = LocalDateTime.now()
             ),
-            UserEntity(
+            User(
                 3L,
                 "follower2",
                 "follower2.example.com",
@@ -44,11 +48,14 @@ class ActivityPubNoteServiceImplTest {
                 "test follower2 user",
                 "https://follower2.example.com/inbox",
                 "https://follower2.example.com/outbox",
-                "https:.//follower2.example.com"
+                "https://follower2.example.com",
+                "",
+                publicKey = "",
+                createdAt = LocalDateTime.now()
             )
         )
         val userService = mock<UserService> {
-            onBlocking { findById(eq(1L)) } doReturn UserEntity(
+            onBlocking { findById(eq(1L)) } doReturn User(
                 1L,
                 "test",
                 "example.com",
@@ -56,7 +63,10 @@ class ActivityPubNoteServiceImplTest {
                 "test user",
                 "https://example.com/inbox",
                 "https://example.com/outbox",
-                "https:.//example.com"
+                "https:.//example.com",
+                "",
+                publicKey = "",
+                createdAt = LocalDateTime.now()
             )
             onBlocking { findFollowersById(eq(1L)) } doReturn followers
         }

From 4442022f9781575aae36c23f45db5157f912a653 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Wed, 26 Apr 2023 17:10:19 +0900
Subject: [PATCH 03/45] =?UTF-8?q?fix:=20=E9=87=8D=E8=A4=87=E3=81=97?=
 =?UTF-8?q?=E3=81=9Findex=E3=82=92=E5=89=8A=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/repository/UserRepository.kt     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index 051ceff0..dd224212 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -179,7 +179,7 @@ class UserRepository(private val database: Database) : IUserRepository {
 }
 
 object Users : Table("users") {
-    val id = long("id").uniqueIndex()
+    val id = long("id")
     val name = varchar("name", length = 64)
     val domain = varchar("domain", length = 255)
     val screenName = varchar("screen_name", length = 64)

From d417245d9291470c8ddca2a99dd507180593ac47 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Wed, 26 Apr 2023 17:28:59 +0900
Subject: [PATCH 04/45] =?UTF-8?q?refactor:=20UserAuth=E9=96=A2=E9=80=A3?=
 =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/Application.kt |  3 +-
 .../domain/model/UserAuthentication.kt        | 17 +----
 .../usbharu/hideout/plugins/ActivityPub.kt    | 14 ++---
 .../hideout/repository/IUserAuthRepository.kt | 15 -----
 .../hideout/repository/UserAuthRepository.kt  | 63 -------------------
 .../hideout/service/IUserAuthService.kt       |  7 ---
 .../activitypub/ActivityPubUserServiceImpl.kt | 23 ++-----
 .../hideout/service/impl/UserAuthService.kt   | 35 ++---------
 .../HttpSignatureVerifyServiceImpl.kt         |  3 +-
 .../hideout/plugins/ActivityPubKtTest.kt      | 38 +----------
 .../usbharu/hideout/plugins/KtorKeyMapTest.kt | 38 +----------
 11 files changed, 25 insertions(+), 231 deletions(-)
 delete mode 100644 src/main/kotlin/dev/usbharu/hideout/repository/IUserAuthRepository.kt
 delete mode 100644 src/main/kotlin/dev/usbharu/hideout/repository/UserAuthRepository.kt

diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt
index e4bca1fe..149a839e 100644
--- a/src/main/kotlin/dev/usbharu/hideout/Application.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt
@@ -58,8 +58,7 @@ fun Application.parent() {
         }
 
         single<IUserRepository> { UserRepository(get()) }
-        single<IUserAuthRepository> { UserAuthRepository(get()) }
-        single<IUserAuthService> { UserAuthService(get(), get()) }
+        single<IUserAuthService> { UserAuthService(get()) }
         single<HttpSignatureVerifyService> { HttpSignatureVerifyServiceImpl(get()) }
         single<JobQueueParentService> {
             val kJobJobQueueService = KJobJobQueueParentService(get())
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
index 5754021a..9dbd767f 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
@@ -11,22 +11,7 @@ data class UserAuthentication(
     val publicKey: String,
     val privateKey: String?
 )
-@Deprecated("")
-data class UserAuthenticationEntity(
-    val id: Long,
-    val userId: Long,
-    val hash: String?,
-    val publicKey: String,
-    val privateKey: String?
-) {
-    constructor(id: Long, userAuthentication: UserAuthentication) : this(
-        id,
-        userAuthentication.userId,
-        userAuthentication.hash,
-        userAuthentication.publicKey,
-        userAuthentication.privateKey
-    )
-}
+
 @Deprecated("")
 object UsersAuthentication : LongIdTable("users_auth") {
     val userId = long("user_id").references(Users.id, onUpdate = ReferenceOption.CASCADE)
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index db0e6a1f..50d4faaa 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -1,8 +1,8 @@
 package dev.usbharu.hideout.plugins
 
-import dev.usbharu.hideout.domain.model.ap.JsonLd
 import dev.usbharu.hideout.config.Config
-import dev.usbharu.hideout.service.IUserAuthService
+import dev.usbharu.hideout.domain.model.ap.JsonLd
+import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.impl.UserAuthService
 import dev.usbharu.hideout.util.HttpUtil.Activity
 import io.ktor.client.*
@@ -144,14 +144,14 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
     }
 }
 
-class KtorKeyMap(private val userAuthRepository: IUserAuthService) : KeyMap {
+class KtorKeyMap(private val userAuthRepository: IUserRepository) : KeyMap {
     override fun getPublicKey(keyId: String?): PublicKey = runBlocking {
         val username = (keyId ?: throw IllegalArgumentException("keyId is null")).substringBeforeLast("#pubkey")
             .substringAfterLast("/")
         val publicBytes = Base64.getDecoder().decode(
-            userAuthRepository.findByUsername(
+            userAuthRepository.findByName(
                 username
-            ).publicKey?.replace("-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----")?.replace("", "")
+            )?.publicKey?.replace("-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----")?.replace("", "")
                 ?.replace("\n", "")
         )
         val x509EncodedKeySpec = X509EncodedKeySpec(publicBytes)
@@ -162,9 +162,9 @@ class KtorKeyMap(private val userAuthRepository: IUserAuthService) : KeyMap {
         val username = (keyId ?: throw IllegalArgumentException("keyId is null")).substringBeforeLast("#pubkey")
             .substringAfterLast("/")
         val publicBytes = Base64.getDecoder().decode(
-            userAuthRepository.findByUsername(
+            userAuthRepository.findByName(
                 username
-            ).privateKey?.replace("-----BEGIN PRIVATE KEY-----", "")?.replace("-----END PRIVATE KEY-----", "")
+            )?.privateKey?.replace("-----BEGIN PRIVATE KEY-----", "")?.replace("-----END PRIVATE KEY-----", "")
                 ?.replace("\n", "")
         )
         val x509EncodedKeySpec = PKCS8EncodedKeySpec(publicBytes)
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserAuthRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserAuthRepository.kt
deleted file mode 100644
index 2f6f46ba..00000000
--- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserAuthRepository.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package dev.usbharu.hideout.repository
-
-import dev.usbharu.hideout.domain.model.UserAuthentication
-import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
-
-interface IUserAuthRepository {
-    suspend fun create(userAuthentication: UserAuthentication):UserAuthenticationEntity
-
-    suspend fun findById(id:Long):UserAuthenticationEntity?
-
-    suspend fun update(userAuthenticationEntity: UserAuthenticationEntity)
-
-    suspend fun delete(id:Long)
-    suspend fun findByUserId(id: Long): UserAuthenticationEntity?
-}
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserAuthRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserAuthRepository.kt
deleted file mode 100644
index 0bb5543c..00000000
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserAuthRepository.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-package dev.usbharu.hideout.repository
-
-import dev.usbharu.hideout.domain.model.UserAuthentication
-import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
-import dev.usbharu.hideout.domain.model.UsersAuthentication
-import kotlinx.coroutines.Dispatchers
-import org.jetbrains.exposed.sql.*
-import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
-import org.jetbrains.exposed.sql.transactions.transaction
-
-class UserAuthRepository(private val database: Database) : IUserAuthRepository {
-
-    init {
-        transaction(database) {
-            SchemaUtils.create(UsersAuthentication)
-            SchemaUtils.createMissingTablesAndColumns(UsersAuthentication)
-        }
-    }
-
-    private fun ResultRow.toUserAuth():UserAuthenticationEntity{
-        return UserAuthenticationEntity(
-            id = this[UsersAuthentication.id].value,
-            userId = this[UsersAuthentication.userId],
-            hash = this[UsersAuthentication.hash],
-            publicKey = this[UsersAuthentication.publicKey],
-            privateKey = this[UsersAuthentication.privateKey]
-        )
-    }
-
-
-    suspend fun <T> query(block: suspend () -> T): T =
-        newSuspendedTransaction(Dispatchers.IO) {block()}
-    override suspend fun create(userAuthentication: UserAuthentication): UserAuthenticationEntity {
-        return query {
-            UserAuthenticationEntity(
-                UsersAuthentication.insert {
-                    it[userId] = userAuthentication.userId
-                    it[hash] = userAuthentication.hash
-                    it[publicKey] = userAuthentication.publicKey
-                    it[privateKey] = userAuthentication.privateKey
-                }[UsersAuthentication.id].value,userAuthentication
-            )
-        }
-    }
-
-    override suspend fun findById(id: Long): UserAuthenticationEntity? {
-        TODO("Not yet implemented")
-    }
-
-    override suspend fun findByUserId(id:Long):UserAuthenticationEntity? {
-        return query {
-            UsersAuthentication.select { UsersAuthentication.userId eq id }.map { it.toUserAuth() }.singleOrNull()
-        }
-    }
-
-    override suspend fun update(userAuthenticationEntity: UserAuthenticationEntity) {
-        TODO("Not yet implemented")
-    }
-
-    override suspend fun delete(id: Long) {
-        TODO("Not yet implemented")
-    }
-}
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt
index d2096d37..1702c41b 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt
@@ -1,8 +1,5 @@
 package dev.usbharu.hideout.service
 
-import dev.usbharu.hideout.domain.model.UserAuthentication
-import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
-
 interface IUserAuthService {
     fun hash(password: String): String
 
@@ -11,8 +8,4 @@ interface IUserAuthService {
 
     suspend fun verifyAccount(username: String, password: String): Boolean
 
-    suspend fun findByUserId(userId: Long): UserAuthenticationEntity
-
-    suspend fun findByUsername(username: String): UserAuthenticationEntity
-    suspend fun createAccount(userEntity: UserAuthentication): UserAuthenticationEntity
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index f4dd9fec..14d4cd11 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -1,12 +1,11 @@
 package dev.usbharu.hideout.service.activitypub
 
 import com.fasterxml.jackson.module.kotlin.readValue
+import dev.usbharu.hideout.config.Config
+import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.ap.Image
 import dev.usbharu.hideout.domain.model.ap.Key
 import dev.usbharu.hideout.domain.model.ap.Person
-import dev.usbharu.hideout.config.Config
-import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UserAuthentication
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
 import dev.usbharu.hideout.service.IUserAuthService
@@ -30,7 +29,6 @@ class ActivityPubUserServiceImpl(
     override suspend fun getPersonByName(name: String): Person {
         // TODO: JOINで書き直し
         val userEntity = userService.findByName(name)
-        val userAuthEntity = userAuthService.findByUserId(userEntity.id)
         val userUrl = "${Config.configData.url}/users/$name"
         return Person(
             type = emptyList(),
@@ -52,7 +50,7 @@ class ActivityPubUserServiceImpl(
                 name = "Public Key",
                 id = "$userUrl#pubkey",
                 owner = userUrl,
-                publicKeyPem = userAuthEntity.publicKey
+                publicKeyPem = userEntity.publicKey
             )
         )
     }
@@ -60,7 +58,6 @@ class ActivityPubUserServiceImpl(
     override suspend fun fetchPerson(url: String): Person {
         return try {
             val userEntity = userService.findByUrl(url)
-            val userAuthEntity = userAuthService.findByUsername(userEntity.name)
             return Person(
                 type = emptyList(),
                 name = userEntity.name,
@@ -81,7 +78,7 @@ class ActivityPubUserServiceImpl(
                     name = "Public Key",
                     id = "$url#pubkey",
                     owner = url,
-                    publicKeyPem = userAuthEntity.publicKey
+                    publicKeyPem = userEntity.publicKey
                 )
             )
 
@@ -90,7 +87,7 @@ class ActivityPubUserServiceImpl(
                 accept(ContentType.Application.Activity)
             }
             val person = Config.configData.objectMapper.readValue<Person>(httpResponse.bodyAsText())
-            val userEntity = userService.create(
+            userService.create(
                 User(
                     id = 0L,
                     name = person.preferredUsername
@@ -101,18 +98,10 @@ class ActivityPubUserServiceImpl(
                     inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"),
                     outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"),
                     url = url,
-                    publicKey = "",
+                    publicKey = person.publicKey?.publicKeyPem ?: throw IllegalActivityPubObjectException("publicKey is null"),
                     createdAt = LocalDateTime.now()
                 )
             )
-            userAuthService.createAccount(
-                UserAuthentication(
-                    userEntity.id,
-                    null,
-                    person.publicKey?.publicKeyPem ?: throw IllegalActivityPubObjectException("publicKey is null"),
-                    null
-                )
-            )
             person
         }
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index a0cdfabc..db6dccf7 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -2,10 +2,7 @@ package dev.usbharu.hideout.service.impl
 
 import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UserAuthentication
-import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
 import dev.usbharu.hideout.exception.UserNotFoundException
-import dev.usbharu.hideout.repository.IUserAuthRepository
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.IUserAuthService
 import io.ktor.util.*
@@ -16,8 +13,7 @@ import java.time.LocalDateTime
 import java.util.*
 
 class UserAuthService(
-    val userRepository: IUserRepository,
-    val userAuthRepository: IUserAuthRepository
+    val userRepository: IUserRepository
 ) : IUserAuthService {
 
 
@@ -31,6 +27,7 @@ class UserAuthService(
         return true
     }
 
+    @Deprecated("")
     override suspend fun registerAccount(username: String, hash: String) {
         val url = "${Config.configData.url}/users/$username"
         val registerUser = User(
@@ -51,37 +48,13 @@ class UserAuthService(
         val privateKey = keyPair.private as RSAPrivateKey
         val publicKey = keyPair.public as RSAPublicKey
 
-
-        val userAuthentication = UserAuthentication(
-            createdUser.id,
-            hash,
-            publicKey.toPem(),
-            privateKey.toPem()
-        )
-
-        userAuthRepository.create(userAuthentication)
+        TODO()
     }
 
     override suspend fun verifyAccount(username: String, password: String): Boolean {
         val userEntity = userRepository.findByName(username)
             ?: throw UserNotFoundException("$username was not found")
-        val userAuthEntity = userAuthRepository.findByUserId(userEntity.id)
-            ?: throw UserNotFoundException("$username auth data was not found")
-        return userAuthEntity.hash == hash(password)
-    }
-
-    override suspend fun findByUserId(userId: Long): UserAuthenticationEntity {
-        return userAuthRepository.findByUserId(userId) ?: throw UserNotFoundException("$userId was not found")
-    }
-
-    override suspend fun findByUsername(username: String): UserAuthenticationEntity {
-        val userEntity = userRepository.findByName(username) ?: throw UserNotFoundException("$username was not found")
-        return userAuthRepository.findByUserId(userEntity.id)
-            ?: throw UserNotFoundException("$username auth data was not found")
-    }
-
-    override suspend fun createAccount(userEntity: UserAuthentication): UserAuthenticationEntity {
-        return userAuthRepository.create(userEntity)
+        return userEntity.password == hash(password)
     }
 
     private fun generateKeyPair(): KeyPair {
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt
index 74525981..488b82cf 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt
@@ -1,12 +1,13 @@
 package dev.usbharu.hideout.service.signature
 
 import dev.usbharu.hideout.plugins.KtorKeyMap
+import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.IUserAuthService
 import io.ktor.http.*
 import tech.barbero.http.message.signing.HttpMessage
 import tech.barbero.http.message.signing.SignatureHeaderVerifier
 
-class HttpSignatureVerifyServiceImpl(private val userAuthService: IUserAuthService) : HttpSignatureVerifyService {
+class HttpSignatureVerifyServiceImpl(private val userAuthService: IUserRepository) : HttpSignatureVerifyService {
     override fun verify(headers: Headers): Boolean {
         val build = SignatureHeaderVerifier.builder().keyMap(KtorKeyMap(userAuthService)).build()
         return true;
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
index 035f3143..757c6ec7 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
@@ -1,28 +1,20 @@
 package dev.usbharu.hideout.plugins
 
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UserAuthentication
-import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
 import dev.usbharu.hideout.domain.model.ap.JsonLd
-import dev.usbharu.hideout.repository.IUserAuthRepository
 import dev.usbharu.hideout.repository.IUserRepository
-import dev.usbharu.hideout.service.impl.UserAuthService
-import dev.usbharu.hideout.service.impl.toPem
 import io.ktor.client.*
 import io.ktor.client.engine.mock.*
 import io.ktor.client.plugins.logging.*
 import kotlinx.coroutines.runBlocking
 import org.junit.jupiter.api.Test
-import java.security.KeyPairGenerator
-import java.security.interfaces.RSAPrivateKey
-import java.security.interfaces.RSAPublicKey
 import java.time.LocalDateTime
 
 class ActivityPubKtTest {
     @Test
     fun HttpSignTest(): Unit = runBlocking {
 
-        val ktorKeyMap = KtorKeyMap(UserAuthService(object : IUserRepository {
+        val ktorKeyMap = KtorKeyMap(object : IUserRepository {
             override suspend fun create(user: User): User {
                 TODO("Not yet implemented")
             }
@@ -92,33 +84,7 @@ class ActivityPubKtTest {
                 TODO("Not yet implemented")
             }
 
-        }, object : IUserAuthRepository {
-            override suspend fun create(userAuthentication: UserAuthentication): UserAuthenticationEntity {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun findById(id: Long): UserAuthenticationEntity? {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun update(userAuthenticationEntity: UserAuthenticationEntity) {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun delete(id: Long) {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun findByUserId(id: Long): UserAuthenticationEntity? {
-                val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
-                keyPairGenerator.initialize(1024)
-                val generateKeyPair = keyPairGenerator.generateKeyPair()
-                return UserAuthenticationEntity(
-                    1, 1, "test", (generateKeyPair.public as RSAPublicKey).toPem(),
-                    (generateKeyPair.private as RSAPrivateKey).toPem()
-                )
-            }
-        }))
+        })
 
         val httpClient = HttpClient(MockEngine { httpRequestData ->
             respondOk()
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index edaeaff3..9da97821 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -1,23 +1,15 @@
 package dev.usbharu.hideout.plugins
 
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UserAuthentication
-import dev.usbharu.hideout.domain.model.UserAuthenticationEntity
-import dev.usbharu.hideout.repository.IUserAuthRepository
 import dev.usbharu.hideout.repository.IUserRepository
-import dev.usbharu.hideout.service.impl.UserAuthService
-import dev.usbharu.hideout.service.impl.toPem
 import org.junit.jupiter.api.Test
-import java.security.KeyPairGenerator
-import java.security.interfaces.RSAPrivateKey
-import java.security.interfaces.RSAPublicKey
 import java.time.LocalDateTime
 
 class KtorKeyMapTest {
 
     @Test
     fun getPrivateKey() {
-        val ktorKeyMap = KtorKeyMap(UserAuthService(object : IUserRepository {
+        val ktorKeyMap = KtorKeyMap(object : IUserRepository {
             override suspend fun create(user: User): User {
                 TODO("Not yet implemented")
             }
@@ -86,33 +78,7 @@ class KtorKeyMapTest {
                 TODO("Not yet implemented")
             }
 
-        }, object : IUserAuthRepository {
-            override suspend fun create(userAuthentication: UserAuthentication): UserAuthenticationEntity {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun findById(id: Long): UserAuthenticationEntity? {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun update(userAuthenticationEntity: UserAuthenticationEntity) {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun delete(id: Long) {
-                TODO("Not yet implemented")
-            }
-
-            override suspend fun findByUserId(id: Long): UserAuthenticationEntity? {
-                val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
-                keyPairGenerator.initialize(1024)
-                val generateKeyPair = keyPairGenerator.generateKeyPair()
-                return UserAuthenticationEntity(
-                    1, 1, "test", (generateKeyPair.public as RSAPublicKey).toPem(),
-                    (generateKeyPair.private as RSAPrivateKey).toPem()
-                )
-            }
-        }))
+        })
 
         ktorKeyMap.getPrivateKey("test")
     }

From cb36a388b154f5e040ea1bfe9b1eea1f251d029c Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Wed, 26 Apr 2023 17:55:24 +0900
Subject: [PATCH 05/45] =?UTF-8?q?feat:=20LocalDateTime=E3=81=8B=E3=82=89In?=
 =?UTF-8?q?stant=E3=81=AB=E5=A4=89=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/domain/model/User.kt  | 12 ++--
 .../hideout/repository/UserRepository.kt      | 20 ++++--
 .../activitypub/ActivityPubUserServiceImpl.kt |  3 +-
 .../hideout/service/impl/UserAuthService.kt   |  7 +-
 .../hideout/plugins/ActivityPubKtTest.kt      | 12 +++-
 .../usbharu/hideout/plugins/KtorKeyMapTest.kt | 11 ++-
 .../hideout/repository/UserRepositoryTest.kt  | 72 ++++++++++++-------
 .../ActivityPubFollowServiceImplTest.kt       |  5 +-
 .../ActivityPubNoteServiceImplTest.kt         |  8 +--
 9 files changed, 99 insertions(+), 51 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
index ee46667a..3f54f7bb 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
@@ -1,18 +1,18 @@
 package dev.usbharu.hideout.domain.model
 
-import java.time.LocalDateTime
+import java.time.Instant
 
 data class User(
-    val id:Long,
+    val id: Long,
     val name: String,
     val domain: String,
     val screenName: String,
     val description: String,
-    val password:String? = null,
+    val password: String? = null,
     val inbox: String,
     val outbox: String,
     val url: String,
-    val publicKey:String,
-    val privateKey:String? = null,
-    val createdAt:LocalDateTime
+    val publicKey: String,
+    val privateKey: String? = null,
+    val createdAt: Instant
 )
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index dd224212..7e0487b1 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -9,6 +9,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
 import java.time.Instant
 import java.time.LocalDateTime
 import java.time.ZoneId
+import java.time.ZoneOffset
 
 class UserRepository(private val database: Database) : IUserRepository {
     init {
@@ -28,13 +29,18 @@ class UserRepository(private val database: Database) : IUserRepository {
     override suspend fun create(user: User): User {
         return query {
             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
             }
             return@query user
         }
@@ -101,7 +107,7 @@ class UserRepository(private val database: Database) : IUserRepository {
             Users.innerJoin(
                 otherTable = UsersFollowers,
                 onColumn = { Users.id },
-                otherColumn = { UsersFollowers.userId })
+                otherColumn = { userId })
 
                 .innerJoin(
                     otherTable = followers,
@@ -114,9 +120,13 @@ class UserRepository(private val database: Database) : IUserRepository {
                     followers.get(Users.domain),
                     followers.get(Users.screenName),
                     followers.get(Users.description),
+                    followers.get(Users.password),
                     followers.get(Users.inbox),
                     followers.get(Users.outbox),
-                    followers.get(Users.url)
+                    followers.get(Users.url),
+                    followers.get(Users.publicKey),
+                    followers.get(Users.privateKey),
+                    followers.get(Users.createdAt)
                 )
                 .select { Users.id eq id }
                 .map {
@@ -132,7 +142,7 @@ class UserRepository(private val database: Database) : IUserRepository {
                         url = it[followers[Users.url]],
                         publicKey = it[followers[Users.publicKey]],
                         privateKey = it[followers[Users.privateKey]],
-                        createdAt = LocalDateTime.ofInstant(Instant.ofEpochMilli(it[followers[Users.createdAt]]), ZoneId.systemDefault())
+                        createdAt = Instant.ofEpochMilli(it[followers[Users.createdAt]])
                     )
                 }
         }
@@ -189,7 +199,7 @@ object Users : Table("users") {
     val outbox = varchar("outbox", length = 255).uniqueIndex()
     val url = varchar("url", length = 255).uniqueIndex()
     val publicKey = varchar("public_key", length = 10000)
-    val privateKey = varchar("private_key", length = 10000)
+    val privateKey = varchar("private_key", length = 10000).nullable()
     val createdAt = long("created_at")
 
     override val primaryKey: PrimaryKey = PrimaryKey(id)
@@ -211,6 +221,6 @@ fun ResultRow.toUser(): User {
         this[Users.url],
         this[Users.publicKey],
         this[Users.privateKey],
-        LocalDateTime.ofInstant(Instant.ofEpochMilli((this[Users.createdAt])), ZoneId.systemDefault())
+        Instant.ofEpochMilli((this[Users.createdAt]))
     )
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 14d4cd11..11e855c0 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -16,6 +16,7 @@ import io.ktor.client.request.*
 import io.ktor.client.statement.*
 import io.ktor.http.*
 import org.slf4j.LoggerFactory
+import java.time.Instant
 import java.time.LocalDateTime
 
 class ActivityPubUserServiceImpl(
@@ -99,7 +100,7 @@ class ActivityPubUserServiceImpl(
                     outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"),
                     url = url,
                     publicKey = person.publicKey?.publicKeyPem ?: throw IllegalActivityPubObjectException("publicKey is null"),
-                    createdAt = LocalDateTime.now()
+                    createdAt = Instant.now()
                 )
             )
             person
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index db6dccf7..08235238 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -9,6 +9,7 @@ import io.ktor.util.*
 import java.security.*
 import java.security.interfaces.RSAPrivateKey
 import java.security.interfaces.RSAPublicKey
+import java.time.Instant
 import java.time.LocalDateTime
 import java.util.*
 
@@ -40,7 +41,7 @@ class UserAuthService(
             outbox = "$url/outbox",
             url = url,
             publicKey = "",
-            createdAt = LocalDateTime.now(),
+            createdAt = Instant.now(),
         )
         val createdUser = userRepository.create(registerUser)
 
@@ -69,13 +70,13 @@ class UserAuthService(
     }
 }
 
-public fun PublicKey.toPem(): String {
+fun PublicKey.toPem(): String {
     return "-----BEGIN PUBLIC KEY-----\n" +
             Base64.getEncoder().encodeToString(encoded).chunked(64).joinToString("\n") +
             "\n-----END PUBLIC KEY-----\n"
 }
 
-public fun PrivateKey.toPem(): String {
+fun PrivateKey.toPem(): String {
     return "-----BEGIN PRIVATE KEY-----" +
             Base64.getEncoder().encodeToString(encoded).chunked(64).joinToString("\n") +
             "\n-----END PRIVATE KEY-----\n"
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
index 757c6ec7..87d91ca0 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
@@ -3,11 +3,14 @@ package dev.usbharu.hideout.plugins
 import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.ap.JsonLd
 import dev.usbharu.hideout.repository.IUserRepository
+import dev.usbharu.hideout.service.impl.toPem
 import io.ktor.client.*
 import io.ktor.client.engine.mock.*
 import io.ktor.client.plugins.logging.*
 import kotlinx.coroutines.runBlocking
 import org.junit.jupiter.api.Test
+import java.security.KeyPairGenerator
+import java.time.Instant
 import java.time.LocalDateTime
 
 class ActivityPubKtTest {
@@ -27,7 +30,10 @@ class ActivityPubKtTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByName(name: String): User? {
+            override suspend fun findByName(name: String): User {
+                val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
+                keyPairGenerator.initialize(1024)
+                val generateKeyPair = keyPairGenerator.generateKeyPair()
                 return User(
                     1,
                     "test",
@@ -39,8 +45,8 @@ class ActivityPubKtTest {
                     "",
                     "",
                     "",
-                    null,
-                    LocalDateTime.now()
+                    generateKeyPair.private.toPem(),
+                    Instant.now()
                 )
             }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index 9da97821..204f6c8c 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -2,7 +2,10 @@ package dev.usbharu.hideout.plugins
 
 import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.repository.IUserRepository
+import dev.usbharu.hideout.service.impl.toPem
 import org.junit.jupiter.api.Test
+import java.security.KeyPairGenerator
+import java.time.Instant
 import java.time.LocalDateTime
 
 class KtorKeyMapTest {
@@ -22,7 +25,10 @@ class KtorKeyMapTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByName(name: String): User? {
+            override suspend fun findByName(name: String): User {
+                val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
+                keyPairGenerator.initialize(1024)
+                val generateKeyPair = keyPairGenerator.generateKeyPair()
                 return User(
                     1,
                     "test",
@@ -34,7 +40,8 @@ class KtorKeyMapTest {
                     "",
                     "",
                     "",
-                    createdAt = LocalDateTime.now()
+                    generateKeyPair.private.toPem(),
+                    createdAt = Instant.now()
                 )
             }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
index 54b6dc69..12f9162e 100644
--- a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
@@ -14,6 +14,10 @@ import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.Assertions.assertIterableEquals
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
+import java.time.Clock
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.ZoneId
 
 
 class UserRepositoryTest {
@@ -43,35 +47,47 @@ class UserRepositoryTest {
         val userRepository = UserRepository(db)
         val user = userRepository.create(
             User(
-                "test",
-                "example.com",
-                "testUser",
-                "This user is test user.",
-                "https://example.com/inbox",
-                "https://example.com/outbox",
-                "https://example.com"
+                id = 0L,
+                name = "test",
+                domain = "example.com",
+                screenName = "testUser",
+                description = "This user is test user.",
+                password = "https://example.com/inbox",
+                inbox = "",
+                outbox = "https://example.com/outbox",
+                url = "https://example.com",
+                publicKey = "",
+                createdAt = Instant.now(Clock.tickMillis(ZoneId.systemDefault()))
             )
         )
         val follower = userRepository.create(
             User(
-                "follower",
-                "follower.example.com",
-                "followerUser",
-                "This user is follower user.",
-                "https://follower.example.com/inbox",
-                "https://follower.example.com/outbox",
-                "https://follower.example.com"
+                id = 1L,
+                name = "follower",
+                domain = "follower.example.com",
+                screenName = "followerUser",
+                description = "This user is follower user.",
+                password = "",
+                inbox = "https://follower.example.com/inbox",
+                outbox = "https://follower.example.com/outbox",
+                url = "https://follower.example.com",
+                publicKey = "",
+                createdAt = Instant.now(Clock.tickMillis(ZoneId.systemDefault()))
             )
         )
         val follower2 = userRepository.create(
             User(
-                "follower2",
-                "follower2.example.com",
-                "followerUser2",
-                "This user is follower user 2.",
-                "https://follower2.example.com/inbox",
-                "https://follower2.example.com/outbox",
-                "https://follower2.example.com"
+                id = 3L,
+                name = "follower2",
+                domain = "follower2.example.com",
+                screenName = "followerUser2",
+                description = "This user is follower user 2.",
+                password = "",
+                inbox = "https://follower2.example.com/inbox",
+                outbox = "https://follower2.example.com/outbox",
+                url = "https://follower2.example.com",
+                publicKey = "",
+                createdAt = Instant.now(Clock.tickMillis(ZoneId.systemDefault()))
             )
         )
         userRepository.createFollower(user.id, follower.id)
@@ -86,25 +102,31 @@ class UserRepositoryTest {
     fun `createFollower フォロワー追加`() = runTest {
         val userRepository = UserRepository(db)
         val user = userRepository.create(
-            User(
+            User(0L,
                 "test",
                 "example.com",
                 "testUser",
                 "This user is test user.",
                 "https://example.com/inbox",
+                "",
                 "https://example.com/outbox",
-                "https://example.com"
+                "https://example.com",
+                publicKey = "",
+                createdAt = Instant.now()
             )
         )
         val follower = userRepository.create(
-            User(
+            User(1L,
                 "follower",
                 "follower.example.com",
                 "followerUser",
                 "This user is follower user.",
+                "",
                 "https://follower.example.com/inbox",
                 "https://follower.example.com/outbox",
-                "https://follower.example.com"
+                "https://follower.example.com",
+                publicKey = "",
+                createdAt = Instant.now()
             )
         )
         userRepository.createFollower(user.id, follower.id)
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
index 3de7494d..cb012e10 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
@@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.kotlin.*
 import utils.JsonObjectMapper
+import java.time.Instant
 import java.time.LocalDateTime
 
 class ActivityPubFollowServiceImplTest {
@@ -99,7 +100,7 @@ class ActivityPubFollowServiceImplTest {
                     outbox = "https://example.com/outbox",
                     url = "https://example.com",
                     publicKey = "",
-                    createdAt = LocalDateTime.now()
+                    createdAt = Instant.now()
                 ),
                 User(
                     id = 2L,
@@ -111,7 +112,7 @@ class ActivityPubFollowServiceImplTest {
                     outbox = "https://follower.example.com/outbox",
                     url = "https://follower.example.com",
                     publicKey = "",
-                    createdAt = LocalDateTime.now()
+                    createdAt = Instant.now()
                 )
             )
             onBlocking { addFollowers(any(), any()) } doReturn Unit
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
index a9445572..ec1fa5ee 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
@@ -20,7 +20,7 @@ import org.junit.jupiter.api.Test
 import org.mockito.Mockito.eq
 import org.mockito.kotlin.*
 import utils.JsonObjectMapper
-import java.time.LocalDateTime
+import java.time.Instant
 import kotlin.test.assertEquals
 
 class ActivityPubNoteServiceImplTest {
@@ -38,7 +38,7 @@ class ActivityPubNoteServiceImplTest {
                 "https://follower.example.com",
                 "",
                 publicKey = "",
-                createdAt = LocalDateTime.now()
+                createdAt = Instant.now()
             ),
             User(
                 3L,
@@ -51,7 +51,7 @@ class ActivityPubNoteServiceImplTest {
                 "https://follower2.example.com",
                 "",
                 publicKey = "",
-                createdAt = LocalDateTime.now()
+                createdAt = Instant.now()
             )
         )
         val userService = mock<UserService> {
@@ -66,7 +66,7 @@ class ActivityPubNoteServiceImplTest {
                 "https:.//example.com",
                 "",
                 publicKey = "",
-                createdAt = LocalDateTime.now()
+                createdAt = Instant.now()
             )
             onBlocking { findFollowersById(eq(1L)) } doReturn followers
         }

From e5c353bc46efcd37f7e631aa6f75acaca492b70a Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Wed, 26 Apr 2023 17:55:45 +0900
Subject: [PATCH 06/45] =?UTF-8?q?style:=20=E3=82=B3=E3=83=BC=E3=83=89?=
 =?UTF-8?q?=E3=82=92=E6=95=B4=E5=BD=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/domain/model/Posts.kt |  4 ++--
 .../hideout/domain/model/UsersFollowers.kt    |  1 +
 .../usbharu/hideout/domain/model/ap/Accept.kt |  7 ++++---
 .../usbharu/hideout/domain/model/ap/Create.kt |  4 ++--
 .../usbharu/hideout/domain/model/ap/Follow.kt |  7 ++++---
 .../usbharu/hideout/domain/model/ap/Image.kt  |  2 +-
 .../usbharu/hideout/domain/model/ap/JsonLd.kt | 19 +++++++++++--------
 .../usbharu/hideout/domain/model/ap/Key.kt    |  9 +++++----
 .../usbharu/hideout/domain/model/ap/Note.kt   | 13 +++++++------
 .../usbharu/hideout/domain/model/ap/Object.kt |  4 ++--
 .../usbharu/hideout/domain/model/ap/Person.kt | 17 +++++++++--------
 .../hideout/domain/model/api/Status.kt        |  4 ++--
 .../hideout/domain/model/job/HideoutJob.kt    |  4 ++--
 .../domain/model/wellknown/WebFinger.kt       |  4 ++--
 .../usbharu/hideout/plugins/ActivityPub.kt    |  6 +++---
 .../dev/usbharu/hideout/plugins/HTTP.kt       |  2 +-
 .../dev/usbharu/hideout/plugins/Monitoring.kt |  5 ++---
 .../dev/usbharu/hideout/plugins/Routing.kt    |  2 +-
 .../dev/usbharu/hideout/plugins/Security.kt   |  2 --
 .../usbharu/hideout/plugins/Serialization.kt  |  4 ----
 .../activitypub/ActivityPubServiceImpl.kt     |  2 +-
 .../HttpSignatureVerifyServiceImpl.kt         |  2 +-
 .../dev/usbharu/hideout/util/HttpUtil.kt      |  6 +++++-
 .../kjob/exposed/ExposedJobRepository.kt      |  1 -
 src/main/web/App.tsx                          |  2 +-
 src/main/web/index.html                       |  8 ++++----
 26 files changed, 73 insertions(+), 68 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt
index d9e13915..56ae54a3 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/Posts.kt
@@ -29,7 +29,7 @@ data class Post(
 
 data class PostEntity(
     val id: Long,
-    val userId:Long,
+    val userId: Long,
     val overview: String? = null,
     val text: String,
     val createdAt: Long,
@@ -39,7 +39,7 @@ data class PostEntity(
     val replyId: Long? = null
 )
 
-fun ResultRow.toPost():PostEntity{
+fun ResultRow.toPost(): PostEntity {
     return PostEntity(
         id = this[Posts.id],
         userId = this[Posts.userId],
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
index b5078c53..ede23ade 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
@@ -6,6 +6,7 @@ import org.jetbrains.exposed.dao.id.LongIdTable
 object UsersFollowers : LongIdTable("users_followers") {
     val userId = long("user_id").references(Users.id).index()
     val followerId = long("follower_id").references(Users.id)
+
     init {
         uniqueIndex(userId, followerId)
     }
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt
index 58889069..7b6d397a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt
@@ -1,15 +1,16 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Accept : Object {
-    public var `object`: Object? = null
-    public var actor:String? = null
+    var `object`: Object? = null
+    var actor: String? = null
+
     protected constructor() : super()
     constructor(
         type: List<String> = emptyList(),
         name: String,
         `object`: Object?,
         actor: String?
-    ) : super(add(type,"Accept"), name) {
+    ) : super(add(type, "Accept"), name) {
         this.`object` = `object`
         this.actor = actor
     }
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
index a0766fd6..46f89ec4 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
@@ -1,10 +1,10 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Create : Object {
-    var `object` : Object? = null
+    var `object`: Object? = null
 
     protected constructor() : super()
-    constructor(type: List<String> = emptyList(), name: String, `object`: Object?) : super(add(type,"Create"), name) {
+    constructor(type: List<String> = emptyList(), name: String, `object`: Object?) : super(add(type, "Create"), name) {
         this.`object` = `object`
     }
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt
index c73c85a3..9ed6e67a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt
@@ -1,15 +1,16 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Follow : Object {
-    public var `object`:String? = null
-    public var actor:String? = null
+    var `object`: String? = null
+    var actor: String? = null
+
     protected constructor() : super()
     constructor(
         type: List<String> = emptyList(),
         name: String,
         `object`: String?,
         actor: String?
-    ) : super(add(type,"Follow"), name) {
+    ) : super(add(type, "Follow"), name) {
         this.`object` = `object`
         this.actor = actor
     }
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Image.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Image.kt
index 5767e7b7..5763366b 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Image.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Image.kt
@@ -6,7 +6,7 @@ open class Image : Object {
 
     protected constructor() : super()
     constructor(type: List<String> = emptyList(), name: String, mediaType: String?, url: String?) : super(
-        add(type,"Image"),
+        add(type, "Image"),
         name
     ) {
         this.mediaType = mediaType
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt
index 4965814a..9700c9d0 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt
@@ -16,10 +16,10 @@ open class JsonLd {
     @JsonProperty("@context")
     @JsonDeserialize(contentUsing = ContextDeserializer::class)
     @JsonSerialize(using = ContextSerializer::class)
-    var context:List<String> = emptyList()
+    var context: List<String> = emptyList()
 
     @JsonCreator
-    constructor(context:List<String>){
+    constructor(context: List<String>) {
         this.context = context
     }
 
@@ -43,9 +43,12 @@ open class JsonLd {
 
 }
 
-public class ContextDeserializer : JsonDeserializer<String>() {
-    override fun deserialize(p0: com.fasterxml.jackson.core.JsonParser?, p1: com.fasterxml.jackson.databind.DeserializationContext?): String {
-        val readTree : JsonNode  = p0?.codec?.readTree(p0) ?: return ""
+class ContextDeserializer : JsonDeserializer<String>() {
+    override fun deserialize(
+        p0: com.fasterxml.jackson.core.JsonParser?,
+        p1: com.fasterxml.jackson.databind.DeserializationContext?
+    ): String {
+        val readTree: JsonNode = p0?.codec?.readTree(p0) ?: return ""
         if (readTree.isObject) {
             return ""
         }
@@ -53,17 +56,17 @@ public class ContextDeserializer : JsonDeserializer<String>() {
     }
 }
 
-public class ContextSerializer : JsonSerializer<List<String>>() {
+class ContextSerializer : JsonSerializer<List<String>>() {
     override fun serialize(value: List<String>?, gen: JsonGenerator?, serializers: SerializerProvider?) {
         if (value.isNullOrEmpty()) {
             gen?.writeNull()
             return
         }
-        if (value?.size == 1) {
+        if (value.size == 1) {
             gen?.writeString(value[0])
         } else {
             gen?.writeStartArray()
-            value?.forEach {
+            value.forEach {
                 gen?.writeString(it)
             }
             gen?.writeEndArray()
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt
index ec79ace0..3b1f168a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt
@@ -1,9 +1,10 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Key : Object {
-    var id:String? = null
-    var owner:String? = null
-    var publicKeyPem:String? = null
+    var id: String? = null
+    var owner: String? = null
+    var publicKeyPem: String? = null
+
     protected constructor() : super()
     constructor(
         type: List<String>,
@@ -11,7 +12,7 @@ open class Key : Object {
         id: String?,
         owner: String?,
         publicKeyPem: String?
-    ) : super(add(type,"Key"), name) {
+    ) : super(add(type, "Key"), name) {
         this.id = id
         this.owner = owner
         this.publicKeyPem = publicKeyPem
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt
index caced1da..0250301c 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt
@@ -1,11 +1,12 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Note : Object {
-    var id:String? = null
-    var attributedTo:String? = null
-    var content:String? = null
-    var published:String? = null
-    var to:List<String> = emptyList()
+    var id: String? = null
+    var attributedTo: String? = null
+    var content: String? = null
+    var published: String? = null
+    var to: List<String> = emptyList()
+
     protected constructor() : super()
     constructor(
         type: List<String> = emptyList(),
@@ -15,7 +16,7 @@ open class Note : Object {
         content: String?,
         published: String?,
         to: List<String> = emptyList()
-    ) : super(add(type,"Note"), name) {
+    ) : super(add(type, "Note"), name) {
         this.id = id
         this.attributedTo = attributedTo
         this.content = content
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
index faca1cd4..e13d3eb5 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
@@ -18,7 +18,7 @@ open class Object : JsonLd {
 
     companion object {
         @JvmStatic
-        protected fun add(list:List<String>,type:String):List<String> {
+        protected fun add(list: List<String>, type: String): List<String> {
             val toMutableList = list.toMutableList()
             toMutableList.add(type)
             return toMutableList.distinct()
@@ -46,7 +46,7 @@ open class Object : JsonLd {
 
 }
 
-public class TypeSerializer : JsonSerializer<List<String>>() {
+class TypeSerializer : JsonSerializer<List<String>>() {
     override fun serialize(value: List<String>?, gen: JsonGenerator?, serializers: SerializerProvider?) {
         println(value)
         if (value?.size == 1) {
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt
index cc04bceb..6fecebc6 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt
@@ -1,14 +1,15 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Person : Object {
-    private var id:String? = null
-    var preferredUsername:String? = null
-    var summary:String? = null
-    var inbox:String? = null
-    var outbox:String? = null
-    private var url:String? = null
+    private var id: String? = null
+    var preferredUsername: String? = null
+    var summary: String? = null
+    var inbox: String? = null
+    var outbox: String? = null
+    private var url: String? = null
     private var icon: Image? = null
     var publicKey: Key? = null
+
     protected constructor() : super()
     constructor(
         type: List<String> = emptyList(),
@@ -21,7 +22,7 @@ open class Person : Object {
         url: String?,
         icon: Image?,
         publicKey: Key?
-    ) : super(add(type,"Person"), name) {
+    ) : super(add(type, "Person"), name) {
         this.id = id
         this.preferredUsername = preferredUsername
         this.summary = summary
@@ -29,7 +30,7 @@ open class Person : Object {
         this.outbox = outbox
         this.url = url
         this.icon = icon
-        this.publicKey =  publicKey
+        this.publicKey = publicKey
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt
index e8e9bfe0..b89a0516 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/api/Status.kt
@@ -1,6 +1,6 @@
 package dev.usbharu.hideout.domain.model.api
 
 data class StatusForPost(
-    val status:String,
-    val userId:Long
+    val status: String,
+    val userId: Long
 )
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/job/HideoutJob.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/job/HideoutJob.kt
index 6bce8a95..e2d124ad 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/job/HideoutJob.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/job/HideoutJob.kt
@@ -4,13 +4,13 @@ import kjob.core.Job
 
 sealed class HideoutJob(name: String = "") : Job(name)
 
-object ReceiveFollowJob : HideoutJob("ReceiveFollowJob"){
+object ReceiveFollowJob : HideoutJob("ReceiveFollowJob") {
     val actor = string("actor")
     val follow = string("follow")
     val targetActor = string("targetActor")
 }
 
-object DeliverPostJob : HideoutJob("DeliverPostJob"){
+object DeliverPostJob : HideoutJob("DeliverPostJob") {
     val post = string("post")
     val actor = string("actor")
     val inbox = string("inbox")
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/wellknown/WebFinger.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/wellknown/WebFinger.kt
index b8542f23..01f0e645 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/wellknown/WebFinger.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/wellknown/WebFinger.kt
@@ -1,5 +1,5 @@
 package dev.usbharu.hideout.domain.model.wellknown
 
-data class WebFinger(val subject:String,val links:List<Link>){
-    data class Link(val rel:String,val type:String,val href:String)
+data class WebFinger(val subject: String, val links: List<Link>) {
+    data class Link(val rel: String, val type: String, val href: String)
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 50d4faaa..50313a58 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -63,8 +63,8 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
             println("Digest !!")
 //            UserAuthService.sha256.reset()
             val digest =
-            Base64.getEncoder().encodeToString(UserAuthService.sha256.digest(body.toByteArray(Charsets.UTF_8)))
-            request.headers.append("Digest", "sha-256="+digest)
+                Base64.getEncoder().encodeToString(UserAuthService.sha256.digest(body.toByteArray(Charsets.UTF_8)))
+            request.headers.append("Digest", "sha-256=" + digest)
         }
 
         if (request.headers.contains("Signature")) {
@@ -126,7 +126,7 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
 
                 override fun addHeader(name: String?, value: String?) {
                     val split = value?.split("=").orEmpty()
-                    name?.let { request.header(it, split.get(0)+"=\""+split.get(1).trim('"')+"\"") }
+                    name?.let { request.header(it, split.get(0) + "=\"" + split.get(1).trim('"') + "\"") }
                 }
 
                 override fun method(): String {
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/HTTP.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/HTTP.kt
index c89f9289..234130ad 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/HTTP.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/HTTP.kt
@@ -1,10 +1,10 @@
 package dev.usbharu.hideout.plugins
 
 import io.ktor.http.*
+import io.ktor.server.application.*
 import io.ktor.server.plugins.cors.routing.*
 import io.ktor.server.plugins.defaultheaders.*
 import io.ktor.server.plugins.forwardedheaders.*
-import io.ktor.server.application.*
 
 fun Application.configureHTTP() {
     install(CORS) {
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Monitoring.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Monitoring.kt
index 3ce065b7..2f33df7a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/Monitoring.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Monitoring.kt
@@ -1,9 +1,8 @@
 package dev.usbharu.hideout.plugins
 
-import io.ktor.server.plugins.callloging.*
-import org.slf4j.event.*
-import io.ktor.server.request.*
 import io.ktor.server.application.*
+import io.ktor.server.plugins.callloging.*
+import org.slf4j.event.Level
 
 fun Application.configureMonitoring() {
     install(CallLogging) {
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
index fc4f0742..8ae17d25 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
@@ -25,7 +25,7 @@ fun Application.configureRouting(
     routing {
         inbox(httpSignatureVerifyService, activityPubService)
         outbox()
-        usersAP(activityPubUserService,userService)
+        usersAP(activityPubUserService, userService)
         webfinger(userService)
 
         route("/api/v1") {
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt
index 94485569..f8a9e2b3 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Security.kt
@@ -3,8 +3,6 @@ package dev.usbharu.hideout.plugins
 import dev.usbharu.hideout.service.IUserAuthService
 import io.ktor.server.application.*
 import io.ktor.server.auth.*
-import io.ktor.server.sessions.*
-import kotlin.collections.set
 
 data class UserSession(val username: String) : Principal
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Serialization.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Serialization.kt
index c8b71a7d..09edfe72 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/Serialization.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Serialization.kt
@@ -4,13 +4,9 @@ import com.fasterxml.jackson.annotation.JsonInclude
 import com.fasterxml.jackson.annotation.JsonSetter
 import com.fasterxml.jackson.annotation.Nulls
 import com.fasterxml.jackson.databind.DeserializationFeature
-import dev.usbharu.hideout.util.HttpUtil.Activity
-import io.ktor.http.*
 import io.ktor.serialization.jackson.*
 import io.ktor.server.application.*
 import io.ktor.server.plugins.contentnegotiation.*
-import io.ktor.server.response.*
-import io.ktor.server.routing.*
 
 fun Application.configureSerialization() {
     install(ContentNegotiation) {
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt
index e86f967f..320359d3 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubServiceImpl.kt
@@ -33,7 +33,7 @@ class ActivityPubServiceImpl(
         return ActivityType.values().first { it.name.equals(type.asText(), true) }
     }
 
-    override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse? {
+    override suspend fun processActivity(json: String, type: ActivityType): ActivityPubResponse {
         return when (type) {
             ActivityType.Accept -> TODO()
             ActivityType.Add -> TODO()
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt
index 488b82cf..5c74f11d 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/signature/HttpSignatureVerifyServiceImpl.kt
@@ -10,7 +10,7 @@ import tech.barbero.http.message.signing.SignatureHeaderVerifier
 class HttpSignatureVerifyServiceImpl(private val userAuthService: IUserRepository) : HttpSignatureVerifyService {
     override fun verify(headers: Headers): Boolean {
         val build = SignatureHeaderVerifier.builder().keyMap(KtorKeyMap(userAuthService)).build()
-        return true;
+        return true
         build.verify(object : HttpMessage {
             override fun headerValues(name: String?): MutableList<String> {
                 return name?.let { headers.getAll(it) }?.toMutableList() ?: mutableListOf()
diff --git a/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt b/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt
index 979b8302..90773182 100644
--- a/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/util/HttpUtil.kt
@@ -30,6 +30,10 @@ object HttpUtil {
         get() = ContentType("application", "activity+json")
 
     val ContentType.Application.JsonLd: ContentType
-        get() = ContentType("application", "ld+json", listOf(HeaderValueParam("profile", "https://www.w3.org/ns/activitystreams")))
+        get() = ContentType(
+            "application",
+            "ld+json",
+            listOf(HeaderValueParam("profile", "https://www.w3.org/ns/activitystreams"))
+        )
 //    fun
 }
diff --git a/src/main/kotlin/dev/usbharu/kjob/exposed/ExposedJobRepository.kt b/src/main/kotlin/dev/usbharu/kjob/exposed/ExposedJobRepository.kt
index 6533358a..0c7f66dd 100644
--- a/src/main/kotlin/dev/usbharu/kjob/exposed/ExposedJobRepository.kt
+++ b/src/main/kotlin/dev/usbharu/kjob/exposed/ExposedJobRepository.kt
@@ -14,7 +14,6 @@ import org.jetbrains.exposed.dao.id.LongIdTable
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList
-import org.jetbrains.exposed.sql.SqlExpressionBuilder.isNull
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.plus
 import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
 import org.jetbrains.exposed.sql.transactions.transaction
diff --git a/src/main/web/App.tsx b/src/main/web/App.tsx
index 32a849b2..d1b57e50 100644
--- a/src/main/web/App.tsx
+++ b/src/main/web/App.tsx
@@ -1,5 +1,5 @@
 import {Component} from "solid-js";
 
-export const App:Component = () => {
+export const App: Component = () => {
     return (<p>aaa</p>)
 }
diff --git a/src/main/web/index.html b/src/main/web/index.html
index 856bb5e6..46837b9c 100644
--- a/src/main/web/index.html
+++ b/src/main/web/index.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width, initial-scale=1" />
-  <meta name="theme-color" content="#000000" />
-  <title>Solid App</title>
+    <meta charset="utf-8"/>
+    <meta content="width=device-width, initial-scale=1" name="viewport"/>
+    <meta content="#000000" name="theme-color"/>
+    <title>Solid App</title>
 </head>
 <body>
 <noscript>You need to enable JavaScript to run this app.</noscript>

From 71a608882992d080d3c2b3065e439f02b97d8b1e Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 11:00:58 +0900
Subject: [PATCH 07/45] =?UTF-8?q?refactor:=20update=E3=82=92=E9=9D=9E?=
 =?UTF-8?q?=E6=8E=A8=E5=A5=A8=E3=81=AB=E3=81=97=E3=81=A6create=E3=82=92sav?=
 =?UTF-8?q?e=E3=81=AB=E5=A4=89=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/repository/IUserRepository.kt |  5 +++--
 .../dev/usbharu/hideout/repository/UserRepository.kt  |  9 ++++-----
 .../usbharu/hideout/service/impl/UserAuthService.kt   |  3 +--
 .../dev/usbharu/hideout/service/impl/UserService.kt   |  2 +-
 .../dev/usbharu/hideout/plugins/ActivityPubKtTest.kt  |  2 +-
 .../dev/usbharu/hideout/plugins/KtorKeyMapTest.kt     |  2 +-
 .../usbharu/hideout/repository/UserRepositoryTest.kt  | 11 +++++------
 7 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
index 73ac26a4..c8a0b1a3 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
@@ -3,7 +3,7 @@ package dev.usbharu.hideout.repository
 import dev.usbharu.hideout.domain.model.User
 
 interface IUserRepository {
-    suspend fun create(user: User): User
+    suspend fun save(user: User): User
 
     suspend fun findById(id: Long): User?
 
@@ -17,7 +17,8 @@ interface IUserRepository {
 
     suspend fun findByUrls(urls: List<String>): List<User>
 
-    suspend fun update(userEntity: User)
+    @Deprecated("", ReplaceWith("save(userEntity)"))
+    suspend fun update(userEntity: User) = save(userEntity)
 
     suspend fun delete(id: Long)
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index 7e0487b1..a416ff5d 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -1,15 +1,13 @@
 package dev.usbharu.hideout.repository
 
-import dev.usbharu.hideout.domain.model.*
+import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.UsersFollowers
 import kotlinx.coroutines.Dispatchers
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
 import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
 import org.jetbrains.exposed.sql.transactions.transaction
 import java.time.Instant
-import java.time.LocalDateTime
-import java.time.ZoneId
-import java.time.ZoneOffset
 
 class UserRepository(private val database: Database) : IUserRepository {
     init {
@@ -21,12 +19,13 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
+    @Deprecated("", ReplaceWith("toUser()"))
     private fun ResultRow.toUserEntity(): User = toUser()
 
     suspend fun <T> query(block: suspend () -> T): T =
         newSuspendedTransaction(Dispatchers.IO) { block() }
 
-    override suspend fun create(user: User): User {
+    override suspend fun save(user: User): User {
         return query {
             Users.insert {
                 it[id] = user.id
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index 08235238..0d217de1 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -10,7 +10,6 @@ import java.security.*
 import java.security.interfaces.RSAPrivateKey
 import java.security.interfaces.RSAPublicKey
 import java.time.Instant
-import java.time.LocalDateTime
 import java.util.*
 
 class UserAuthService(
@@ -43,7 +42,7 @@ class UserAuthService(
             publicKey = "",
             createdAt = Instant.now(),
         )
-        val createdUser = userRepository.create(registerUser)
+        val createdUser = userRepository.save(registerUser)
 
         val keyPair = generateKeyPair()
         val privateKey = keyPair.private as RSAPrivateKey
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index fcbc60cb..09af8fc4 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -42,7 +42,7 @@ class UserService(private val userRepository: IUserRepository) {
     }
 
     suspend fun create(user: User): User {
-        return userRepository.create(user)
+        return userRepository.save(user)
     }
 
     suspend fun findFollowersById(id: Long): List<User> {
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
index 87d91ca0..df9265f0 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
@@ -18,7 +18,7 @@ class ActivityPubKtTest {
     fun HttpSignTest(): Unit = runBlocking {
 
         val ktorKeyMap = KtorKeyMap(object : IUserRepository {
-            override suspend fun create(user: User): User {
+            override suspend fun save(user: User): User {
                 TODO("Not yet implemented")
             }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index 204f6c8c..fd3ee6dd 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -13,7 +13,7 @@ class KtorKeyMapTest {
     @Test
     fun getPrivateKey() {
         val ktorKeyMap = KtorKeyMap(object : IUserRepository {
-            override suspend fun create(user: User): User {
+            override suspend fun save(user: User): User {
                 TODO("Not yet implemented")
             }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
index 12f9162e..4ddc8e9c 100644
--- a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
@@ -16,7 +16,6 @@ import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import java.time.Clock
 import java.time.Instant
-import java.time.LocalDateTime
 import java.time.ZoneId
 
 
@@ -45,7 +44,7 @@ class UserRepositoryTest {
     @Test
     fun `findFollowersById フォロワー一覧を取得`() = runTest {
         val userRepository = UserRepository(db)
-        val user = userRepository.create(
+        val user = userRepository.save(
             User(
                 id = 0L,
                 name = "test",
@@ -60,7 +59,7 @@ class UserRepositoryTest {
                 createdAt = Instant.now(Clock.tickMillis(ZoneId.systemDefault()))
             )
         )
-        val follower = userRepository.create(
+        val follower = userRepository.save(
             User(
                 id = 1L,
                 name = "follower",
@@ -75,7 +74,7 @@ class UserRepositoryTest {
                 createdAt = Instant.now(Clock.tickMillis(ZoneId.systemDefault()))
             )
         )
-        val follower2 = userRepository.create(
+        val follower2 = userRepository.save(
             User(
                 id = 3L,
                 name = "follower2",
@@ -101,7 +100,7 @@ class UserRepositoryTest {
     @Test
     fun `createFollower フォロワー追加`() = runTest {
         val userRepository = UserRepository(db)
-        val user = userRepository.create(
+        val user = userRepository.save(
             User(0L,
                 "test",
                 "example.com",
@@ -115,7 +114,7 @@ class UserRepositoryTest {
                 createdAt = Instant.now()
             )
         )
-        val follower = userRepository.create(
+        val follower = userRepository.save(
             User(1L,
                 "follower",
                 "follower.example.com",

From 7bba9efddc4313b33442cca2990d3fc54e3c95d0 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 11:08:18 +0900
Subject: [PATCH 08/45] =?UTF-8?q?feat:=20save=E3=82=92insert=E3=81=8B?=
 =?UTF-8?q?=E3=82=89upsert=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../hideout/repository/UserRepository.kt      | 75 ++++++++++---------
 1 file changed, 38 insertions(+), 37 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index a416ff5d..f77c17ef 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -19,27 +19,41 @@ class UserRepository(private val database: Database) : IUserRepository {
         }
     }
 
-    @Deprecated("", ReplaceWith("toUser()"))
-    private fun ResultRow.toUserEntity(): User = toUser()
-
     suspend fun <T> query(block: suspend () -> T): T =
         newSuspendedTransaction(Dispatchers.IO) { block() }
 
     override suspend fun save(user: User): User {
         return query {
-            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
+            val singleOrNull = Users.select { Users.id eq user.id }.singleOrNull()
+            if (singleOrNull == null) {
+                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
+                }
+            } 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
+                }
             }
             return@query user
         }
@@ -57,7 +71,7 @@ class UserRepository(private val database: Database) : IUserRepository {
     override suspend fun findById(id: Long): User? {
         return query {
             Users.select { Users.id eq id }.map {
-                it.toUserEntity()
+                it.toUser()
             }.singleOrNull()
         }
     }
@@ -65,7 +79,7 @@ class UserRepository(private val database: Database) : IUserRepository {
     override suspend fun findByIds(ids: List<Long>): List<User> {
         return query {
             Users.select { Users.id inList ids }.map {
-                it.toUserEntity()
+                it.toUser()
             }
         }
     }
@@ -73,7 +87,7 @@ class UserRepository(private val database: Database) : IUserRepository {
     override suspend fun findByName(name: String): User? {
         return query {
             Users.select { Users.name eq name }.map {
-                it.toUserEntity()
+                it.toUser()
             }.singleOrNull()
         }
     }
@@ -84,19 +98,19 @@ class UserRepository(private val database: Database) : IUserRepository {
             names.forEach { (name, domain) ->
                 selectAll.orWhere { Users.name eq name and (Users.domain eq domain) }
             }
-            selectAll.map { it.toUserEntity() }
+            selectAll.map { it.toUser() }
         }
     }
 
     override suspend fun findByUrl(url: String): User? {
         return query {
-            Users.select { Users.url eq url }.singleOrNull()?.toUserEntity()
+            Users.select { Users.url eq url }.singleOrNull()?.toUser()
         }
     }
 
     override suspend fun findByUrls(urls: List<String>): List<User> {
         return query {
-            Users.select { Users.url inList urls }.map { it.toUserEntity() }
+            Users.select { Users.url inList urls }.map { it.toUser() }
         }
     }
 
@@ -148,20 +162,6 @@ class UserRepository(private val database: Database) : IUserRepository {
     }
 
 
-    override suspend fun update(userEntity: User) {
-        return query {
-            Users.update({ Users.id eq userEntity.id }) {
-                it[name] = userEntity.name
-                it[domain] = userEntity.domain
-                it[screenName] = userEntity.screenName
-                it[description] = userEntity.description
-                it[inbox] = userEntity.inbox
-                it[outbox] = userEntity.outbox
-                it[url] = userEntity.url
-            }
-        }
-    }
-
     override suspend fun delete(id: Long) {
         query {
             Users.deleteWhere { Users.id.eq(id) }
@@ -182,7 +182,7 @@ class UserRepository(private val database: Database) : IUserRepository {
 
     override suspend fun findAllByLimitAndByOffset(limit: Int, offset: Long): List<User> {
         return query {
-            Users.selectAll().limit(limit, offset).map { it.toUserEntity() }
+            Users.selectAll().limit(limit, offset).map { it.toUser() }
         }
     }
 }
@@ -202,6 +202,7 @@ object Users : Table("users") {
     val createdAt = long("created_at")
 
     override val primaryKey: PrimaryKey = PrimaryKey(id)
+
     init {
         uniqueIndex(name, domain)
     }

From ccfd3a62f613cf188ddc6eca43f85e38ee2a24ed Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 11:46:27 +0900
Subject: [PATCH 09/45] =?UTF-8?q?test:=20=E3=83=86=E3=82=B9=E3=83=88?=
 =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt   | 4 ----
 src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt | 4 ----
 2 files changed, 8 deletions(-)

diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
index df9265f0..f110cf35 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
@@ -62,10 +62,6 @@ class ActivityPubKtTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun update(userEntity: User) {
-                TODO("Not yet implemented")
-            }
-
             override suspend fun delete(id: Long) {
                 TODO("Not yet implemented")
             }
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index fd3ee6dd..419a0ae4 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -57,10 +57,6 @@ class KtorKeyMapTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun update(userEntity: User) {
-                TODO("Not yet implemented")
-            }
-
             override suspend fun delete(id: Long) {
                 TODO("Not yet implemented")
             }

From 7100c4e531c5c6287dbb67bec8fd7194407f95c5 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 11:57:18 +0900
Subject: [PATCH 10/45] =?UTF-8?q?feat:=20Repository=E3=81=ABID=E7=99=BA?=
 =?UTF-8?q?=E8=A1=8C=E3=82=92=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/Application.kt  |  6 ++++--
 .../usbharu/hideout/repository/IUserRepository.kt   |  2 ++
 .../usbharu/hideout/repository/UserRepository.kt    |  7 ++++++-
 .../dev/usbharu/hideout/plugins/KtorKeyMapTest.kt   |  4 ++++
 .../hideout/repository/UserRepositoryTest.kt        | 13 +++++++++++--
 5 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt
index 149a839e..d5ecffdc 100644
--- a/src/main/kotlin/dev/usbharu/hideout/Application.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt
@@ -12,6 +12,7 @@ import dev.usbharu.hideout.repository.*
 import dev.usbharu.hideout.routing.register
 import dev.usbharu.hideout.service.IPostService
 import dev.usbharu.hideout.service.IUserAuthService
+import dev.usbharu.hideout.service.IdGenerateService
 import dev.usbharu.hideout.service.TwitterSnowflakeIdGenerateService
 import dev.usbharu.hideout.service.activitypub.*
 import dev.usbharu.hideout.service.impl.PostService
@@ -57,7 +58,7 @@ fun Application.parent() {
             )
         }
 
-        single<IUserRepository> { UserRepository(get()) }
+        single<IUserRepository> { UserRepository(get(),get()) }
         single<IUserAuthService> { UserAuthService(get()) }
         single<HttpSignatureVerifyService> { HttpSignatureVerifyServiceImpl(get()) }
         single<JobQueueParentService> {
@@ -82,7 +83,8 @@ fun Application.parent() {
         single<ActivityPubUserService> { ActivityPubUserServiceImpl(get(), get(), get()) }
         single<ActivityPubNoteService> { ActivityPubNoteServiceImpl(get(), get(), get()) }
         single<IPostService> { PostService(get(), get()) }
-        single<IPostRepository> { PostRepositoryImpl(get(), TwitterSnowflakeIdGenerateService) }
+        single<IPostRepository> { PostRepositoryImpl(get(), get()) }
+        single<IdGenerateService> {TwitterSnowflakeIdGenerateService}
     }
 
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
index c8a0b1a3..58d56ba9 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
@@ -29,4 +29,6 @@ interface IUserRepository {
     suspend fun createFollower(id: Long, follower: Long)
     suspend fun deleteFollower(id: Long, follower: Long)
     suspend fun findFollowersById(id: Long): List<User>
+
+    suspend fun nextId():Long
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index f77c17ef..ceb6db1b 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -2,6 +2,7 @@ package dev.usbharu.hideout.repository
 
 import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.UsersFollowers
+import dev.usbharu.hideout.service.IdGenerateService
 import kotlinx.coroutines.Dispatchers
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
@@ -9,7 +10,7 @@ import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransacti
 import org.jetbrains.exposed.sql.transactions.transaction
 import java.time.Instant
 
-class UserRepository(private val database: Database) : IUserRepository {
+class UserRepository(private val database: Database,private val idGenerateService: IdGenerateService) : IUserRepository {
     init {
         transaction(database) {
             SchemaUtils.create(Users)
@@ -185,6 +186,10 @@ class UserRepository(private val database: Database) : IUserRepository {
             Users.selectAll().limit(limit, offset).map { it.toUser() }
         }
     }
+
+    override suspend fun nextId(): Long {
+        return idGenerateService.generateId()
+    }
 }
 
 object Users : Table("users") {
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index 419a0ae4..08a1bdac 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -81,6 +81,10 @@ class KtorKeyMapTest {
                 TODO("Not yet implemented")
             }
 
+            override suspend fun nextId(): Long {
+                TODO("Not yet implemented")
+            }
+
         })
 
         ktorKeyMap.getPrivateKey("test")
diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
index 4ddc8e9c..43dc236e 100644
--- a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
@@ -4,6 +4,7 @@ package dev.usbharu.hideout.repository
 
 import dev.usbharu.hideout.domain.model.User
 import dev.usbharu.hideout.domain.model.UsersFollowers
+import dev.usbharu.hideout.service.IdGenerateService
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
 import org.jetbrains.exposed.sql.Database
@@ -43,7 +44,11 @@ class UserRepositoryTest {
 
     @Test
     fun `findFollowersById フォロワー一覧を取得`() = runTest {
-        val userRepository = UserRepository(db)
+        val userRepository = UserRepository(db, object : IdGenerateService {
+            override suspend fun generateId(): Long {
+                TODO("Not yet implemented")
+            }
+        })
         val user = userRepository.save(
             User(
                 id = 0L,
@@ -99,7 +104,11 @@ class UserRepositoryTest {
 
     @Test
     fun `createFollower フォロワー追加`() = runTest {
-        val userRepository = UserRepository(db)
+        val userRepository = UserRepository(db, object : IdGenerateService {
+            override suspend fun generateId(): Long {
+                TODO("Not yet implemented")
+            }
+        })
         val user = userRepository.save(
             User(0L,
                 "test",

From f7beff3295ebb44a74036f640956b082eb7bfeb1 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 13:49:57 +0900
Subject: [PATCH 11/45] =?UTF-8?q?refactor:=20UsersFollowers=E3=82=92?=
 =?UTF-8?q?=E7=A7=BB=E5=8B=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../usbharu/hideout/domain/model/UsersFollowers.kt  | 13 -------------
 .../usbharu/hideout/repository/UserRepository.kt    | 12 +++++++++++-
 .../hideout/repository/UserRepositoryTest.kt        |  1 -
 3 files changed, 11 insertions(+), 15 deletions(-)
 delete mode 100644 src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
deleted file mode 100644
index ede23ade..00000000
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UsersFollowers.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package dev.usbharu.hideout.domain.model
-
-import dev.usbharu.hideout.repository.Users
-import org.jetbrains.exposed.dao.id.LongIdTable
-
-object UsersFollowers : LongIdTable("users_followers") {
-    val userId = long("user_id").references(Users.id).index()
-    val followerId = long("follower_id").references(Users.id)
-
-    init {
-        uniqueIndex(userId, followerId)
-    }
-}
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index ceb6db1b..a1ff7791 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -1,9 +1,10 @@
 package dev.usbharu.hideout.repository
 
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UsersFollowers
+import dev.usbharu.hideout.repository.UsersFollowers
 import dev.usbharu.hideout.service.IdGenerateService
 import kotlinx.coroutines.Dispatchers
+import org.jetbrains.exposed.dao.id.LongIdTable
 import org.jetbrains.exposed.sql.*
 import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
 import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
@@ -229,3 +230,12 @@ fun ResultRow.toUser(): User {
         Instant.ofEpochMilli((this[Users.createdAt]))
     )
 }
+
+object UsersFollowers : LongIdTable("users_followers") {
+    val userId = long("user_id").references(Users.id).index()
+    val followerId = long("follower_id").references(Users.id)
+
+    init {
+        uniqueIndex(userId, followerId)
+    }
+}
diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
index 43dc236e..a1c3bfeb 100644
--- a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
@@ -3,7 +3,6 @@
 package dev.usbharu.hideout.repository
 
 import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.domain.model.UsersFollowers
 import dev.usbharu.hideout.service.IdGenerateService
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest

From e040f6c8118646e25225db35cb5a55803ca84766 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 13:51:48 +0900
Subject: [PATCH 12/45] =?UTF-8?q?refactor:=20UserAuthentication=E3=82=92?=
 =?UTF-8?q?=E5=89=8A=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../domain/model/UserAuthentication.kt        | 21 -------------------
 1 file changed, 21 deletions(-)
 delete mode 100644 src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
deleted file mode 100644
index 9dbd767f..00000000
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/UserAuthentication.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package dev.usbharu.hideout.domain.model
-
-import dev.usbharu.hideout.repository.Users
-import org.jetbrains.exposed.dao.id.LongIdTable
-import org.jetbrains.exposed.sql.ReferenceOption
-
-@Deprecated("")
-data class UserAuthentication(
-    val userId: Long,
-    val hash: String?,
-    val publicKey: String,
-    val privateKey: String?
-)
-
-@Deprecated("")
-object UsersAuthentication : LongIdTable("users_auth") {
-    val userId = long("user_id").references(Users.id, onUpdate = ReferenceOption.CASCADE)
-    val hash = varchar("hash", length = 64).nullable()
-    val publicKey = varchar("public_key", length = 1000_000)
-    val privateKey = varchar("private_key", length = 1000_000).nullable()
-}

From 79205fc253f1d7e05dd2bcc1a81507bfe9ed601a Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 13:56:20 +0900
Subject: [PATCH 13/45] =?UTF-8?q?feat:=20UserCreateDto=E3=82=92=E4=BD=9C?=
 =?UTF-8?q?=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../hideout/domain/model/hideout/dto/UserCreateDto.kt    | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt
new file mode 100644
index 00000000..ddab1b2f
--- /dev/null
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt
@@ -0,0 +1,9 @@
+package dev.usbharu.hideout.domain.model.hideout.dto
+
+data class UserCreateDto(
+    val name:String,
+    val domain:String,
+    val screenName:String,
+    val description:String,
+    val password:String
+)

From f77d1512341b9feee9ead7d619b9d126df9ff2ae Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 13:56:46 +0900
Subject: [PATCH 14/45] =?UTF-8?q?refactor:=20User=E3=82=92=E7=A7=BB?=
 =?UTF-8?q?=E5=8B=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../usbharu/hideout/domain/model/{ => hideout/entity}/User.kt  | 2 +-
 .../kotlin/dev/usbharu/hideout/repository/IUserRepository.kt   | 2 +-
 .../kotlin/dev/usbharu/hideout/repository/UserRepository.kt    | 3 +--
 .../hideout/service/activitypub/ActivityPubUserServiceImpl.kt  | 3 +--
 .../kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt | 2 +-
 .../kotlin/dev/usbharu/hideout/service/impl/UserService.kt     | 2 +-
 .../kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt    | 3 +--
 src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt  | 3 +--
 .../dev/usbharu/hideout/repository/UserRepositoryTest.kt       | 2 +-
 .../service/activitypub/ActivityPubFollowServiceImplTest.kt    | 3 +--
 .../service/activitypub/ActivityPubNoteServiceImplTest.kt      | 2 +-
 11 files changed, 11 insertions(+), 16 deletions(-)
 rename src/main/kotlin/dev/usbharu/hideout/domain/model/{ => hideout/entity}/User.kt (86%)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/User.kt
similarity index 86%
rename from src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
rename to src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/User.kt
index 3f54f7bb..319d1f8c 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/User.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/entity/User.kt
@@ -1,4 +1,4 @@
-package dev.usbharu.hideout.domain.model
+package dev.usbharu.hideout.domain.model.hideout.entity
 
 import java.time.Instant
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
index 58d56ba9..1f198526 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
@@ -1,6 +1,6 @@
 package dev.usbharu.hideout.repository
 
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 
 interface IUserRepository {
     suspend fun save(user: User): User
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index a1ff7791..8ab5cce7 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -1,7 +1,6 @@
 package dev.usbharu.hideout.repository
 
-import dev.usbharu.hideout.domain.model.User
-import dev.usbharu.hideout.repository.UsersFollowers
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.service.IdGenerateService
 import kotlinx.coroutines.Dispatchers
 import org.jetbrains.exposed.dao.id.LongIdTable
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 11e855c0..71e10238 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -2,7 +2,7 @@ package dev.usbharu.hideout.service.activitypub
 
 import com.fasterxml.jackson.module.kotlin.readValue
 import dev.usbharu.hideout.config.Config
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.ap.Image
 import dev.usbharu.hideout.domain.model.ap.Key
 import dev.usbharu.hideout.domain.model.ap.Person
@@ -17,7 +17,6 @@ import io.ktor.client.statement.*
 import io.ktor.http.*
 import org.slf4j.LoggerFactory
 import java.time.Instant
-import java.time.LocalDateTime
 
 class ActivityPubUserServiceImpl(
     private val userService: UserService,
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index 0d217de1..cd2d6ccb 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -1,7 +1,7 @@
 package dev.usbharu.hideout.service.impl
 
 import dev.usbharu.hideout.config.Config
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.IUserAuthService
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index 09af8fc4..7c426341 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -1,6 +1,6 @@
 package dev.usbharu.hideout.service.impl
 
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.repository.IUserRepository
 import java.lang.Integer.min
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
index f110cf35..de740d9a 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
@@ -1,6 +1,6 @@
 package dev.usbharu.hideout.plugins
 
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.ap.JsonLd
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.impl.toPem
@@ -11,7 +11,6 @@ import kotlinx.coroutines.runBlocking
 import org.junit.jupiter.api.Test
 import java.security.KeyPairGenerator
 import java.time.Instant
-import java.time.LocalDateTime
 
 class ActivityPubKtTest {
     @Test
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index 08a1bdac..331e7b5e 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -1,12 +1,11 @@
 package dev.usbharu.hideout.plugins
 
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.impl.toPem
 import org.junit.jupiter.api.Test
 import java.security.KeyPairGenerator
 import java.time.Instant
-import java.time.LocalDateTime
 
 class KtorKeyMapTest {
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
index a1c3bfeb..36bbcf4d 100644
--- a/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/repository/UserRepositoryTest.kt
@@ -2,7 +2,7 @@
 
 package dev.usbharu.hideout.repository
 
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.service.IdGenerateService
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
index cb012e10..c50749f1 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
@@ -6,7 +6,7 @@ package dev.usbharu.hideout.service.activitypub
 import com.fasterxml.jackson.module.kotlin.readValue
 import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.config.ConfigData
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.ap.*
 import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
 import dev.usbharu.hideout.service.impl.UserService
@@ -24,7 +24,6 @@ import org.mockito.ArgumentMatchers.anyString
 import org.mockito.kotlin.*
 import utils.JsonObjectMapper
 import java.time.Instant
-import java.time.LocalDateTime
 
 class ActivityPubFollowServiceImplTest {
     @Test
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
index ec1fa5ee..a0a85f3c 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
@@ -6,7 +6,7 @@ package dev.usbharu.hideout.service.activitypub
 import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.config.ConfigData
 import dev.usbharu.hideout.domain.model.PostEntity
-import dev.usbharu.hideout.domain.model.User
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.job.DeliverPostJob
 import dev.usbharu.hideout.service.impl.UserService
 import dev.usbharu.hideout.service.job.JobQueueParentService

From 48411751dec61457a8fd857973bb11de526bf44f Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 15:04:59 +0900
Subject: [PATCH 15/45] =?UTF-8?q?refactor:=20=E4=B8=80=E9=83=A8=E3=81=AE?=
 =?UTF-8?q?=E5=91=BD=E5=90=8D=E3=82=92=E5=A4=89=E6=9B=B4=E3=80=82=E3=83=A6?=
 =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E3=82=92=E4=BD=9C=E6=88=90=E3=81=A7?=
 =?UTF-8?q?=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/Application.kt |  4 +-
 .../domain/model/hideout/dto/UserCreateDto.kt |  1 -
 .../usbharu/hideout/plugins/ActivityPub.kt    |  8 ++--
 .../hideout/repository/IUserRepository.kt     |  6 ++-
 .../hideout/repository/UserRepository.kt      | 21 ++++++++--
 .../hideout/routing/RegisterRouting.kt        | 14 +++----
 .../routing/activitypub/UserRouting.kt        |  3 +-
 .../routing/wellknown/WebfingerRouting.kt     |  2 +-
 .../hideout/service/IUserAuthService.kt       |  5 ++-
 .../activitypub/ActivityPubUserServiceImpl.kt |  2 +-
 .../hideout/service/impl/UserAuthService.kt   | 32 +--------------
 .../hideout/service/impl/UserService.kt       | 41 +++++++++++++++++--
 12 files changed, 82 insertions(+), 57 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt
index d5ecffdc..487dcb65 100644
--- a/src/main/kotlin/dev/usbharu/hideout/Application.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt
@@ -79,7 +79,7 @@ fun Application.parent() {
         }
         single<ActivityPubFollowService> { ActivityPubFollowServiceImpl(get(), get(), get(), get()) }
         single<ActivityPubService> { ActivityPubServiceImpl(get(), get()) }
-        single<UserService> { UserService(get()) }
+        single<UserService> { UserService(get(),get()) }
         single<ActivityPubUserService> { ActivityPubUserServiceImpl(get(), get(), get()) }
         single<ActivityPubNoteService> { ActivityPubNoteServiceImpl(get(), get(), get()) }
         single<IPostService> { PostService(get(), get()) }
@@ -93,7 +93,7 @@ fun Application.parent() {
     configureStaticRouting()
     configureMonitoring()
     configureSerialization()
-    register(inject<IUserAuthService>().value)
+    register(inject<UserService>().value)
     configureRouting(
         inject<HttpSignatureVerifyService>().value,
         inject<ActivityPubService>().value,
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt
index ddab1b2f..e8a59f26 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/UserCreateDto.kt
@@ -2,7 +2,6 @@ package dev.usbharu.hideout.domain.model.hideout.dto
 
 data class UserCreateDto(
     val name:String,
-    val domain:String,
     val screenName:String,
     val description:String,
     val password:String
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 50313a58..cbb6cab4 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -149,8 +149,8 @@ class KtorKeyMap(private val userAuthRepository: IUserRepository) : KeyMap {
         val username = (keyId ?: throw IllegalArgumentException("keyId is null")).substringBeforeLast("#pubkey")
             .substringAfterLast("/")
         val publicBytes = Base64.getDecoder().decode(
-            userAuthRepository.findByName(
-                username
+            userAuthRepository.findByNameAndDomain(
+                username,Config.configData.domain
             )?.publicKey?.replace("-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----")?.replace("", "")
                 ?.replace("\n", "")
         )
@@ -162,8 +162,8 @@ class KtorKeyMap(private val userAuthRepository: IUserRepository) : KeyMap {
         val username = (keyId ?: throw IllegalArgumentException("keyId is null")).substringBeforeLast("#pubkey")
             .substringAfterLast("/")
         val publicBytes = Base64.getDecoder().decode(
-            userAuthRepository.findByName(
-                username
+            userAuthRepository.findByNameAndDomain(
+                username,Config.configData.domain
             )?.privateKey?.replace("-----BEGIN PRIVATE KEY-----", "")?.replace("-----END PRIVATE KEY-----", "")
                 ?.replace("\n", "")
         )
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
index 1f198526..0d19094f 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/IUserRepository.kt
@@ -9,7 +9,11 @@ interface IUserRepository {
 
     suspend fun findByIds(ids: List<Long>): List<User>
 
-    suspend fun findByName(name: String): User?
+    suspend fun findByName(name: String): List<User>
+
+    suspend fun findByNameAndDomain(name: String, domain: String): User?
+
+    suspend fun findByDomain(domain:String): List<User>
 
     suspend fun findByNameAndDomains(names: List<Pair<String,String>>): List<User>
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
index 8ab5cce7..9a577a83 100644
--- a/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/repository/UserRepository.kt
@@ -10,7 +10,8 @@ import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransacti
 import org.jetbrains.exposed.sql.transactions.transaction
 import java.time.Instant
 
-class UserRepository(private val database: Database,private val idGenerateService: IdGenerateService) : IUserRepository {
+class UserRepository(private val database: Database, private val idGenerateService: IdGenerateService) :
+    IUserRepository {
     init {
         transaction(database) {
             SchemaUtils.create(Users)
@@ -85,11 +86,25 @@ class UserRepository(private val database: Database,private val idGenerateServic
         }
     }
 
-    override suspend fun findByName(name: String): User? {
+    override suspend fun findByName(name: String): List<User> {
         return query {
             Users.select { Users.name eq name }.map {
                 it.toUser()
-            }.singleOrNull()
+            }
+        }
+    }
+
+    override suspend fun findByNameAndDomain(name: String, domain: String): User? {
+        return query {
+            Users.select { Users.name eq name and (Users.domain eq domain) }.singleOrNull()?.toUser()
+        }
+    }
+
+    override suspend fun findByDomain(domain: String): List<User> {
+        return query {
+            Users.select { Users.domain eq domain }.map {
+                it.toUser()
+            }
         }
     }
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt
index a6ba6d4c..b0e2f47e 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt
@@ -1,16 +1,15 @@
 package dev.usbharu.hideout.routing
 
-import dev.usbharu.hideout.plugins.UserSession
-import dev.usbharu.hideout.service.IUserAuthService
+import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
+import dev.usbharu.hideout.service.impl.UserService
 import io.ktor.http.*
 import io.ktor.server.application.*
 import io.ktor.server.auth.*
 import io.ktor.server.request.*
 import io.ktor.server.response.*
 import io.ktor.server.routing.*
-import io.ktor.server.sessions.*
 
-fun Application.register(userAuthService: IUserAuthService) {
+fun Application.register(userService: UserService) {
 
     routing {
         get("/register") {
@@ -39,13 +38,10 @@ fun Application.register(userAuthService: IUserAuthService) {
             val parameters = call.receiveParameters()
             val password = parameters["password"] ?: return@post call.respondRedirect("/register")
             val username = parameters["username"] ?: return@post call.respondRedirect("/register")
-            if (userAuthService.usernameAlreadyUse(username)) {
+            if (userService.usernameAlreadyUse(username)) {
                 return@post call.respondRedirect("/register")
             }
-
-            val hash = userAuthService.hash(password)
-            userAuthService.registerAccount(username,hash)
-//            call.respondRedirect("/login")
+            userService.createLocalUser(UserCreateDto(username, username, "", password))
             call.respondRedirect("/users/$username")
         }
     }
diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index 66fc511c..d25fca2a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -1,5 +1,6 @@
 package dev.usbharu.hideout.routing.activitypub
 
+import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.exception.ParameterNotExistException
 import dev.usbharu.hideout.plugins.respondAp
 import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
@@ -24,7 +25,7 @@ fun Routing.usersAP(activityPubUserService: ActivityPubUserService, userService:
             )
         }
         get {
-            val userEntity = userService.findByName(call.parameters["name"]!!)
+            val userEntity = userService.findByNameLocalUser(call.parameters["name"]!!)
             call.respondText(userEntity.toString() + "\n" + userService.findFollowersById(userEntity.id))
         }
     }
diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt
index f862f745..36948523 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt
@@ -25,7 +25,7 @@ fun Routing.webfinger(userService:UserService){
                 .substringAfter("acct:")
                 .trimStart('@')
 
-            val userEntity = userService.findByName(accountName)
+            val userEntity = userService.findByNameLocalUser(accountName)
 
             val webFinger = WebFinger(
                 subject = acct,
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt
index 1702c41b..5c792ec8 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/IUserAuthService.kt
@@ -1,10 +1,13 @@
 package dev.usbharu.hideout.service
 
+import java.security.KeyPair
+
 interface IUserAuthService {
     fun hash(password: String): String
 
     suspend fun usernameAlreadyUse(username: String): Boolean
-    suspend fun registerAccount(username: String, hash: String)
+
+    suspend fun generateKeyPair():KeyPair
 
     suspend fun verifyAccount(username: String, password: String): Boolean
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 71e10238..57d73d39 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -28,7 +28,7 @@ class ActivityPubUserServiceImpl(
         private val logger = LoggerFactory.getLogger(this::class.java)
     override suspend fun getPersonByName(name: String): Person {
         // TODO: JOINで書き直し
-        val userEntity = userService.findByName(name)
+        val userEntity = userService.findByNameLocalUser(name)
         val userUrl = "${Config.configData.url}/users/$name"
         return Person(
             type = emptyList(),
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index cd2d6ccb..41a38a41 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -1,15 +1,11 @@
 package dev.usbharu.hideout.service.impl
 
 import dev.usbharu.hideout.config.Config
-import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.IUserAuthService
 import io.ktor.util.*
 import java.security.*
-import java.security.interfaces.RSAPrivateKey
-import java.security.interfaces.RSAPublicKey
-import java.time.Instant
 import java.util.*
 
 class UserAuthService(
@@ -27,37 +23,13 @@ class UserAuthService(
         return true
     }
 
-    @Deprecated("")
-    override suspend fun registerAccount(username: String, hash: String) {
-        val url = "${Config.configData.url}/users/$username"
-        val registerUser = User(
-            id = 0L,
-            name = username,
-            domain = Config.configData.domain,
-            screenName = username,
-            description = "",
-            inbox = "$url/inbox",
-            outbox = "$url/outbox",
-            url = url,
-            publicKey = "",
-            createdAt = Instant.now(),
-        )
-        val createdUser = userRepository.save(registerUser)
-
-        val keyPair = generateKeyPair()
-        val privateKey = keyPair.private as RSAPrivateKey
-        val publicKey = keyPair.public as RSAPublicKey
-
-        TODO()
-    }
-
     override suspend fun verifyAccount(username: String, password: String): Boolean {
-        val userEntity = userRepository.findByName(username)
+        val userEntity = userRepository.findByNameAndDomain(username, Config.configData.domain)
             ?: throw UserNotFoundException("$username was not found")
         return userEntity.password == hash(password)
     }
 
-    private fun generateKeyPair(): KeyPair {
+    override suspend fun generateKeyPair(): KeyPair {
         val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
         keyPairGenerator.initialize(1024)
         return keyPairGenerator.generateKeyPair()
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index 7c426341..c67d8ecf 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -1,11 +1,15 @@
 package dev.usbharu.hideout.service.impl
 
+import dev.usbharu.hideout.config.Config
+import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
 import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.repository.IUserRepository
+import dev.usbharu.hideout.service.IUserAuthService
 import java.lang.Integer.min
+import java.time.Instant
 
-class UserService(private val userRepository: IUserRepository) {
+class UserService(private val userRepository: IUserRepository, private val userAuthService: IUserAuthService) {
 
     private val maxLimit = 100
     suspend fun findAll(limit: Int? = maxLimit, offset: Long? = 0): List<User> {
@@ -24,12 +28,16 @@ class UserService(private val userRepository: IUserRepository) {
         return userRepository.findByIds(ids)
     }
 
-    suspend fun findByName(name: String): User {
+    suspend fun findByName(name: String): List<User> {
         return userRepository.findByName(name)
+    }
+
+    suspend fun findByNameLocalUser(name: String): User {
+        return userRepository.findByNameAndDomain(name, Config.configData.domain)
             ?: throw UserNotFoundException("$name was not found.")
     }
 
-    suspend fun findByNameAndDomains(names: List<Pair<String,String>>): List<User> {
+    suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
         return userRepository.findByNameAndDomains(names)
     }
 
@@ -41,10 +49,37 @@ class UserService(private val userRepository: IUserRepository) {
         return userRepository.findByUrls(urls)
     }
 
+    suspend fun usernameAlreadyUse(username: String): Boolean {
+        val findByNameAndDomain = userRepository.findByNameAndDomain(username, Config.configData.domain)
+        return findByNameAndDomain != null
+    }
+
+    @Deprecated("")
     suspend fun create(user: User): User {
         return userRepository.save(user)
     }
 
+    suspend fun createLocalUser(user: UserCreateDto): User {
+        val nextId = userRepository.nextId()
+        val HashedPassword = userAuthService.hash(user.password)
+        val keyPair = userAuthService.generateKeyPair()
+        val userEntity = User(
+            id = nextId,
+            name = user.name,
+            domain = Config.configData.domain,
+            screenName = user.screenName,
+            description = user.description,
+            password = HashedPassword,
+            inbox = "${Config.configData.url}/users/$nextId/inbox",
+            outbox = "${Config.configData.url}/users/$nextId/outbox",
+            url = "${Config.configData.url}/users/$nextId",
+            publicKey = keyPair.public.toPem(),
+            privateKey = keyPair.private.toString(),
+            Instant.now()
+        )
+        return userRepository.save(userEntity)
+    }
+
     suspend fun findFollowersById(id: Long): List<User> {
         return userRepository.findFollowersById(id)
     }

From 6d2999452a8723b96301d872764eaa4321692492 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 15:28:30 +0900
Subject: [PATCH 16/45] =?UTF-8?q?refactor:=20=E4=B8=8D=E8=A6=81=E3=81=AA?=
 =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=BC=E3=83=AB=E3=83=89=E3=82=92=E5=89=8A?=
 =?UTF-8?q?=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/Application.kt              | 2 +-
 .../hideout/service/activitypub/ActivityPubUserServiceImpl.kt   | 2 --
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt
index 487dcb65..baeec6e5 100644
--- a/src/main/kotlin/dev/usbharu/hideout/Application.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt
@@ -80,7 +80,7 @@ fun Application.parent() {
         single<ActivityPubFollowService> { ActivityPubFollowServiceImpl(get(), get(), get(), get()) }
         single<ActivityPubService> { ActivityPubServiceImpl(get(), get()) }
         single<UserService> { UserService(get(),get()) }
-        single<ActivityPubUserService> { ActivityPubUserServiceImpl(get(), get(), get()) }
+        single<ActivityPubUserService> { ActivityPubUserServiceImpl(get(), get()) }
         single<ActivityPubNoteService> { ActivityPubNoteServiceImpl(get(), get(), get()) }
         single<IPostService> { PostService(get(), get()) }
         single<IPostRepository> { PostRepositoryImpl(get(), get()) }
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 57d73d39..014f3ffa 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -8,7 +8,6 @@ import dev.usbharu.hideout.domain.model.ap.Key
 import dev.usbharu.hideout.domain.model.ap.Person
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
-import dev.usbharu.hideout.service.IUserAuthService
 import dev.usbharu.hideout.service.impl.UserService
 import dev.usbharu.hideout.util.HttpUtil.Activity
 import io.ktor.client.*
@@ -20,7 +19,6 @@ import java.time.Instant
 
 class ActivityPubUserServiceImpl(
     private val userService: UserService,
-    private val userAuthService: IUserAuthService,
     private val httpClient: HttpClient
 ) :
     ActivityPubUserService {

From 943b09a3a59cdbae361d2ab14ce3782161e21f6f Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 15:41:31 +0900
Subject: [PATCH 17/45] =?UTF-8?q?feat:=20=E3=83=AA=E3=83=A2=E3=83=BC?=
 =?UTF-8?q?=E3=83=88=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC=E3=81=AE=E4=BD=9C?=
 =?UTF-8?q?=E6=88=90=E3=82=92=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../model/hideout/dto/RemoteUserCreateDto.kt  | 12 ++++++++++
 .../activitypub/ActivityPubUserServiceImpl.kt | 10 ++++----
 .../hideout/service/impl/UserService.kt       | 23 +++++++++++++++----
 3 files changed, 34 insertions(+), 11 deletions(-)
 create mode 100644 src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/RemoteUserCreateDto.kt

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/RemoteUserCreateDto.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/RemoteUserCreateDto.kt
new file mode 100644
index 00000000..35081932
--- /dev/null
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/hideout/dto/RemoteUserCreateDto.kt
@@ -0,0 +1,12 @@
+package dev.usbharu.hideout.domain.model.hideout.dto
+
+data class RemoteUserCreateDto(
+    val name:String,
+    val domain:String,
+    val screenName:String,
+    val description:String,
+    val inbox:String,
+    val outbox:String,
+    val url:String,
+    val publicKey:String,
+)
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 014f3ffa..318cff08 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -2,10 +2,10 @@ package dev.usbharu.hideout.service.activitypub
 
 import com.fasterxml.jackson.module.kotlin.readValue
 import dev.usbharu.hideout.config.Config
-import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.ap.Image
 import dev.usbharu.hideout.domain.model.ap.Key
 import dev.usbharu.hideout.domain.model.ap.Person
+import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
 import dev.usbharu.hideout.service.impl.UserService
@@ -15,7 +15,6 @@ import io.ktor.client.request.*
 import io.ktor.client.statement.*
 import io.ktor.http.*
 import org.slf4j.LoggerFactory
-import java.time.Instant
 
 class ActivityPubUserServiceImpl(
     private val userService: UserService,
@@ -85,9 +84,9 @@ class ActivityPubUserServiceImpl(
                 accept(ContentType.Application.Activity)
             }
             val person = Config.configData.objectMapper.readValue<Person>(httpResponse.bodyAsText())
-            userService.create(
-                User(
-                    id = 0L,
+
+            userService.createRemoteUser(
+                RemoteUserCreateDto(
                     name = person.preferredUsername
                         ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
                     domain = url.substringAfter(":").substringBeforeLast("/"),
@@ -97,7 +96,6 @@ class ActivityPubUserServiceImpl(
                     outbox = person.outbox ?: throw IllegalActivityPubObjectException("outbox is null"),
                     url = url,
                     publicKey = person.publicKey?.publicKeyPem ?: throw IllegalActivityPubObjectException("publicKey is null"),
-                    createdAt = Instant.now()
                 )
             )
             person
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index c67d8ecf..8e0f0f06 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -1,6 +1,7 @@
 package dev.usbharu.hideout.service.impl
 
 import dev.usbharu.hideout.config.Config
+import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
 import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
 import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.exception.UserNotFoundException
@@ -54,11 +55,6 @@ class UserService(private val userRepository: IUserRepository, private val userA
         return findByNameAndDomain != null
     }
 
-    @Deprecated("")
-    suspend fun create(user: User): User {
-        return userRepository.save(user)
-    }
-
     suspend fun createLocalUser(user: UserCreateDto): User {
         val nextId = userRepository.nextId()
         val HashedPassword = userAuthService.hash(user.password)
@@ -80,6 +76,23 @@ class UserService(private val userRepository: IUserRepository, private val userA
         return userRepository.save(userEntity)
     }
 
+    suspend fun createRemoteUser(user: RemoteUserCreateDto): User {
+        val nextId = userRepository.nextId()
+        val userEntity = User(
+            id = nextId,
+            name = user.name,
+            domain = user.domain,
+            screenName = user.screenName,
+            description = user.description,
+            inbox = user.inbox,
+            outbox = user.outbox,
+            url = user.url,
+            publicKey = user.publicKey,
+            createdAt = Instant.now()
+        )
+        return userRepository.save(userEntity)
+    }
+
     suspend fun findFollowersById(id: Long): List<User> {
         return userRepository.findFollowersById(id)
     }

From b21e658cd00c5c76fb61ad9f014980003ee47e79 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 16:00:01 +0900
Subject: [PATCH 18/45] =?UTF-8?q?refactor:=20UserService=E3=82=92=E3=82=A4?=
 =?UTF-8?q?=E3=83=B3=E3=82=BF=E3=83=BC=E3=83=95=E3=82=A7=E3=83=BC=E3=82=B9?=
 =?UTF-8?q?=E3=81=AB=E6=8A=BD=E5=87=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/Application.kt | 12 ++++---
 .../dev/usbharu/hideout/plugins/Routing.kt    |  4 +--
 .../hideout/routing/RegisterRouting.kt        |  4 +--
 .../routing/activitypub/UserRouting.kt        |  5 ++-
 .../routing/wellknown/WebfingerRouting.kt     |  4 +--
 .../ActivityPubFollowServiceImpl.kt           |  8 ++---
 .../activitypub/ActivityPubNoteServiceImpl.kt |  4 +--
 .../activitypub/ActivityPubUserServiceImpl.kt |  4 +--
 .../hideout/service/impl/IUserService.kt      | 33 +++++++++++++++++++
 .../hideout/service/impl/UserService.kt       | 29 ++++++++--------
 .../hideout/plugins/ActivityPubKtTest.kt      | 16 +++++++--
 .../usbharu/hideout/plugins/KtorKeyMapTest.kt | 11 ++++++-
 .../routing/activitypub/InboxRoutingKtTest.kt |  5 +--
 .../routing/activitypub/UsersAPTest.kt        |  3 +-
 .../ActivityPubFollowServiceImplTest.kt       |  6 ++--
 .../ActivityPubNoteServiceImplTest.kt         |  4 +--
 16 files changed, 106 insertions(+), 46 deletions(-)
 create mode 100644 src/main/kotlin/dev/usbharu/hideout/service/impl/IUserService.kt

diff --git a/src/main/kotlin/dev/usbharu/hideout/Application.kt b/src/main/kotlin/dev/usbharu/hideout/Application.kt
index baeec6e5..3fe5d5a1 100644
--- a/src/main/kotlin/dev/usbharu/hideout/Application.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/Application.kt
@@ -8,13 +8,17 @@ import dev.usbharu.hideout.config.ConfigData
 import dev.usbharu.hideout.domain.model.job.DeliverPostJob
 import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
 import dev.usbharu.hideout.plugins.*
-import dev.usbharu.hideout.repository.*
+import dev.usbharu.hideout.repository.IPostRepository
+import dev.usbharu.hideout.repository.IUserRepository
+import dev.usbharu.hideout.repository.PostRepositoryImpl
+import dev.usbharu.hideout.repository.UserRepository
 import dev.usbharu.hideout.routing.register
 import dev.usbharu.hideout.service.IPostService
 import dev.usbharu.hideout.service.IUserAuthService
 import dev.usbharu.hideout.service.IdGenerateService
 import dev.usbharu.hideout.service.TwitterSnowflakeIdGenerateService
 import dev.usbharu.hideout.service.activitypub.*
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.impl.PostService
 import dev.usbharu.hideout.service.impl.UserAuthService
 import dev.usbharu.hideout.service.impl.UserService
@@ -79,7 +83,7 @@ fun Application.parent() {
         }
         single<ActivityPubFollowService> { ActivityPubFollowServiceImpl(get(), get(), get(), get()) }
         single<ActivityPubService> { ActivityPubServiceImpl(get(), get()) }
-        single<UserService> { UserService(get(),get()) }
+        single<IUserService> { UserService(get(),get()) }
         single<ActivityPubUserService> { ActivityPubUserServiceImpl(get(), get()) }
         single<ActivityPubNoteService> { ActivityPubNoteServiceImpl(get(), get(), get()) }
         single<IPostService> { PostService(get(), get()) }
@@ -93,11 +97,11 @@ fun Application.parent() {
     configureStaticRouting()
     configureMonitoring()
     configureSerialization()
-    register(inject<UserService>().value)
+    register(inject<IUserService>().value)
     configureRouting(
         inject<HttpSignatureVerifyService>().value,
         inject<ActivityPubService>().value,
-        inject<UserService>().value,
+        inject<IUserService>().value,
         inject<ActivityPubUserService>().value,
         inject<IPostService>().value
     )
diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
index 8ae17d25..f6bebf53 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/Routing.kt
@@ -8,7 +8,7 @@ import dev.usbharu.hideout.routing.wellknown.webfinger
 import dev.usbharu.hideout.service.IPostService
 import dev.usbharu.hideout.service.activitypub.ActivityPubService
 import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.signature.HttpSignatureVerifyService
 import io.ktor.server.application.*
 import io.ktor.server.plugins.autohead.*
@@ -17,7 +17,7 @@ import io.ktor.server.routing.*
 fun Application.configureRouting(
     httpSignatureVerifyService: HttpSignatureVerifyService,
     activityPubService: ActivityPubService,
-    userService: UserService,
+    userService: IUserService,
     activityPubUserService: ActivityPubUserService,
     postService: IPostService
 ) {
diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt
index b0e2f47e..c20221cc 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/RegisterRouting.kt
@@ -1,7 +1,7 @@
 package dev.usbharu.hideout.routing
 
 import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import io.ktor.http.*
 import io.ktor.server.application.*
 import io.ktor.server.auth.*
@@ -9,7 +9,7 @@ import io.ktor.server.request.*
 import io.ktor.server.response.*
 import io.ktor.server.routing.*
 
-fun Application.register(userService: UserService) {
+fun Application.register(userService: IUserService) {
 
     routing {
         get("/register") {
diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index d25fca2a..95b22635 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -1,10 +1,9 @@
 package dev.usbharu.hideout.routing.activitypub
 
-import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.exception.ParameterNotExistException
 import dev.usbharu.hideout.plugins.respondAp
 import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.util.HttpUtil.Activity
 import dev.usbharu.hideout.util.HttpUtil.JsonLd
 import io.ktor.http.*
@@ -13,7 +12,7 @@ import io.ktor.server.request.*
 import io.ktor.server.response.*
 import io.ktor.server.routing.*
 
-fun Routing.usersAP(activityPubUserService: ActivityPubUserService, userService: UserService) {
+fun Routing.usersAP(activityPubUserService: ActivityPubUserService, userService: IUserService) {
     route("/users/{name}") {
         createChild(ContentTypeRouteSelector(ContentType.Application.Activity, ContentType.Application.JsonLd)).handle {
             val name =
diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt
index 36948523..411e3095 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/wellknown/WebfingerRouting.kt
@@ -4,14 +4,14 @@ import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.domain.model.wellknown.WebFinger
 import dev.usbharu.hideout.exception.IllegalParameterException
 import dev.usbharu.hideout.exception.ParameterNotExistException
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.util.HttpUtil.Activity
 import io.ktor.http.*
 import io.ktor.server.application.*
 import io.ktor.server.response.*
 import io.ktor.server.routing.*
 
-fun Routing.webfinger(userService:UserService){
+fun Routing.webfinger(userService: IUserService){
     route("/.well-known/webfinger"){
         get {
             val acct = call.request.queryParameters["resource"]?.decodeURLPart()
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt
index b734aba1..fcd94662 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt
@@ -1,14 +1,14 @@
 package dev.usbharu.hideout.service.activitypub
 
 import com.fasterxml.jackson.module.kotlin.readValue
-import dev.usbharu.hideout.domain.model.ap.Accept
-import dev.usbharu.hideout.domain.model.ap.Follow
 import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.domain.model.ActivityPubResponse
 import dev.usbharu.hideout.domain.model.ActivityPubStringResponse
+import dev.usbharu.hideout.domain.model.ap.Accept
+import dev.usbharu.hideout.domain.model.ap.Follow
 import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
 import dev.usbharu.hideout.plugins.postAp
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.job.JobQueueParentService
 import io.ktor.client.*
 import io.ktor.http.*
@@ -17,7 +17,7 @@ import kjob.core.job.JobProps
 class ActivityPubFollowServiceImpl(
     private val jobQueueParentService: JobQueueParentService,
     private val activityPubUserService: ActivityPubUserService,
-    private val userService: UserService,
+    private val userService: IUserService,
     private val httpClient: HttpClient
 ) : ActivityPubFollowService {
     override suspend fun receiveFollow(follow: Follow): ActivityPubResponse {
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
index 445e5a48..f9b4702c 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
@@ -7,7 +7,7 @@ import dev.usbharu.hideout.domain.model.ap.Create
 import dev.usbharu.hideout.domain.model.ap.Note
 import dev.usbharu.hideout.domain.model.job.DeliverPostJob
 import dev.usbharu.hideout.plugins.postAp
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.job.JobQueueParentService
 import io.ktor.client.*
 import kjob.core.job.JobProps
@@ -17,7 +17,7 @@ import java.time.Instant
 class ActivityPubNoteServiceImpl(
     private val httpClient: HttpClient,
     private val jobQueueParentService: JobQueueParentService,
-    private val userService: UserService
+    private val userService: IUserService
 ) : ActivityPubNoteService {
 
     private val logger = LoggerFactory.getLogger(this::class.java)
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 318cff08..4aca8b88 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -8,7 +8,7 @@ import dev.usbharu.hideout.domain.model.ap.Person
 import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.util.HttpUtil.Activity
 import io.ktor.client.*
 import io.ktor.client.request.*
@@ -17,7 +17,7 @@ import io.ktor.http.*
 import org.slf4j.LoggerFactory
 
 class ActivityPubUserServiceImpl(
-    private val userService: UserService,
+    private val userService: IUserService,
     private val httpClient: HttpClient
 ) :
     ActivityPubUserService {
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/IUserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/IUserService.kt
new file mode 100644
index 00000000..b41f31fd
--- /dev/null
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/IUserService.kt
@@ -0,0 +1,33 @@
+package dev.usbharu.hideout.service.impl
+
+import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
+import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
+import dev.usbharu.hideout.domain.model.hideout.entity.User
+
+interface IUserService {
+    suspend fun findAll(limit: Int? = 100, offset: Long? = 0): List<User>
+
+    suspend fun findById(id: Long): User
+
+    suspend fun findByIds(ids: List<Long>): List<User>
+
+    suspend fun findByName(name: String): List<User>
+
+    suspend fun findByNameLocalUser(name: String): User
+
+    suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User>
+
+    suspend fun findByUrl(url: String): User
+
+    suspend fun findByUrls(urls: List<String>): List<User>
+
+    suspend fun usernameAlreadyUse(username: String): Boolean
+
+    suspend fun createLocalUser(user: UserCreateDto): User
+
+    suspend fun createRemoteUser(user: RemoteUserCreateDto): User
+
+    suspend fun findFollowersById(id: Long): List<User>
+
+    suspend fun addFollowers(id: Long, follower: Long)
+}
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index 8e0f0f06..560eaebf 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -10,10 +10,11 @@ import dev.usbharu.hideout.service.IUserAuthService
 import java.lang.Integer.min
 import java.time.Instant
 
-class UserService(private val userRepository: IUserRepository, private val userAuthService: IUserAuthService) {
+class UserService(private val userRepository: IUserRepository, private val userAuthService: IUserAuthService) :
+    IUserService {
 
     private val maxLimit = 100
-    suspend fun findAll(limit: Int? = maxLimit, offset: Long? = 0): List<User> {
+    override suspend fun findAll(limit: Int?, offset: Long?): List<User> {
 
         return userRepository.findAllByLimitAndByOffset(
             min(limit ?: maxLimit, maxLimit),
@@ -21,41 +22,41 @@ class UserService(private val userRepository: IUserRepository, private val userA
         )
     }
 
-    suspend fun findById(id: Long): User {
+    override suspend fun findById(id: Long): User {
         return userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
     }
 
-    suspend fun findByIds(ids: List<Long>): List<User> {
+    override suspend fun findByIds(ids: List<Long>): List<User> {
         return userRepository.findByIds(ids)
     }
 
-    suspend fun findByName(name: String): List<User> {
+    override suspend fun findByName(name: String): List<User> {
         return userRepository.findByName(name)
     }
 
-    suspend fun findByNameLocalUser(name: String): User {
+    override suspend fun findByNameLocalUser(name: String): User {
         return userRepository.findByNameAndDomain(name, Config.configData.domain)
             ?: throw UserNotFoundException("$name was not found.")
     }
 
-    suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
+    override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
         return userRepository.findByNameAndDomains(names)
     }
 
-    suspend fun findByUrl(url: String): User {
+    override suspend fun findByUrl(url: String): User {
         return userRepository.findByUrl(url) ?: throw UserNotFoundException("$url was not found.")
     }
 
-    suspend fun findByUrls(urls: List<String>): List<User> {
+    override suspend fun findByUrls(urls: List<String>): List<User> {
         return userRepository.findByUrls(urls)
     }
 
-    suspend fun usernameAlreadyUse(username: String): Boolean {
+    override suspend fun usernameAlreadyUse(username: String): Boolean {
         val findByNameAndDomain = userRepository.findByNameAndDomain(username, Config.configData.domain)
         return findByNameAndDomain != null
     }
 
-    suspend fun createLocalUser(user: UserCreateDto): User {
+    override suspend fun createLocalUser(user: UserCreateDto): User {
         val nextId = userRepository.nextId()
         val HashedPassword = userAuthService.hash(user.password)
         val keyPair = userAuthService.generateKeyPair()
@@ -76,7 +77,7 @@ class UserService(private val userRepository: IUserRepository, private val userA
         return userRepository.save(userEntity)
     }
 
-    suspend fun createRemoteUser(user: RemoteUserCreateDto): User {
+    override suspend fun createRemoteUser(user: RemoteUserCreateDto): User {
         val nextId = userRepository.nextId()
         val userEntity = User(
             id = nextId,
@@ -93,11 +94,11 @@ class UserService(private val userRepository: IUserRepository, private val userA
         return userRepository.save(userEntity)
     }
 
-    suspend fun findFollowersById(id: Long): List<User> {
+    override suspend fun findFollowersById(id: Long): List<User> {
         return userRepository.findFollowersById(id)
     }
 
-    suspend fun addFollowers(id: Long, follower: Long) {
+    override suspend fun addFollowers(id: Long, follower: Long) {
         return userRepository.createFollower(id, follower)
     }
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
index de740d9a..63ff36cf 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/ActivityPubKtTest.kt
@@ -1,7 +1,7 @@
 package dev.usbharu.hideout.plugins
 
-import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.ap.JsonLd
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.repository.IUserRepository
 import dev.usbharu.hideout.service.impl.toPem
 import io.ktor.client.*
@@ -29,7 +29,11 @@ class ActivityPubKtTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByName(name: String): User {
+            override suspend fun findByName(name: String): List<User> {
+                TODO()
+            }
+
+            override suspend fun findByNameAndDomain(name: String, domain: String): User? {
                 val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
                 keyPairGenerator.initialize(1024)
                 val generateKeyPair = keyPairGenerator.generateKeyPair()
@@ -49,6 +53,10 @@ class ActivityPubKtTest {
                 )
             }
 
+            override suspend fun findByDomain(domain: String): List<User> {
+                TODO("Not yet implemented")
+            }
+
             override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
                 TODO("Not yet implemented")
             }
@@ -85,6 +93,10 @@ class ActivityPubKtTest {
                 TODO("Not yet implemented")
             }
 
+            override suspend fun nextId(): Long {
+                TODO("Not yet implemented")
+            }
+
         })
 
         val httpClient = HttpClient(MockEngine { httpRequestData ->
diff --git a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
index 331e7b5e..ad462b04 100644
--- a/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/plugins/KtorKeyMapTest.kt
@@ -24,7 +24,11 @@ class KtorKeyMapTest {
                 TODO("Not yet implemented")
             }
 
-            override suspend fun findByName(name: String): User {
+            override suspend fun findByName(name: String): List<User> {
+                TODO()
+            }
+
+            override suspend fun findByNameAndDomain(name: String, domain: String): User? {
                 val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
                 keyPairGenerator.initialize(1024)
                 val generateKeyPair = keyPairGenerator.generateKeyPair()
@@ -42,6 +46,11 @@ class KtorKeyMapTest {
                     generateKeyPair.private.toPem(),
                     createdAt = Instant.now()
                 )
+
+            }
+
+            override suspend fun findByDomain(domain: String): List<User> {
+                TODO("Not yet implemented")
             }
 
             override suspend fun findByNameAndDomains(names: List<Pair<String, String>>): List<User> {
diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt
index 5fa97051..94ee5880 100644
--- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/InboxRoutingKtTest.kt
@@ -6,6 +6,7 @@ import dev.usbharu.hideout.plugins.configureSerialization
 import dev.usbharu.hideout.plugins.configureStatusPages
 import dev.usbharu.hideout.service.activitypub.ActivityPubService
 import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.impl.UserService
 import dev.usbharu.hideout.service.signature.HttpSignatureVerifyService
 import io.ktor.client.request.*
@@ -45,7 +46,7 @@ class InboxRoutingKtTest {
         val activityPubService = mock<ActivityPubService>{
             on { parseActivity(any()) } doThrow JsonParseException()
         }
-        val userService = mock<UserService>()
+        val userService = mock<IUserService>()
         val activityPubUserService = mock<ActivityPubUserService>()
         application {
             configureStatusPages()
@@ -82,7 +83,7 @@ class InboxRoutingKtTest {
         val activityPubService = mock<ActivityPubService>{
             on { parseActivity(any()) } doThrow JsonParseException()
         }
-        val userService = mock<UserService>()
+        val userService = mock<IUserService>()
         val activityPubUserService = mock<ActivityPubUserService>()
         application {
             configureStatusPages()
diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
index fd537617..d4db2cff 100644
--- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
@@ -13,6 +13,7 @@ import dev.usbharu.hideout.plugins.configureRouting
 import dev.usbharu.hideout.plugins.configureSerialization
 import dev.usbharu.hideout.service.activitypub.ActivityPubService
 import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.impl.UserService
 import dev.usbharu.hideout.service.signature.HttpSignatureVerifyService
 import dev.usbharu.hideout.util.HttpUtil.Activity
@@ -62,7 +63,7 @@ class UsersAPTest {
 
         val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {}
         val activityPubService = mock<ActivityPubService> {}
-        val userService = mock<UserService> {}
+        val userService = mock<IUserService> {}
 
         val activityPubUserService = mock<ActivityPubUserService> {
             onBlocking { getPersonByName(anyString()) } doReturn person
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
index c50749f1..e37652dd 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
@@ -6,10 +6,10 @@ package dev.usbharu.hideout.service.activitypub
 import com.fasterxml.jackson.module.kotlin.readValue
 import dev.usbharu.hideout.config.Config
 import dev.usbharu.hideout.config.ConfigData
-import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.ap.*
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.job.JobQueueParentService
 import io.ktor.client.*
 import io.ktor.client.engine.mock.*
@@ -87,7 +87,7 @@ class ActivityPubFollowServiceImplTest {
         val activityPubUserService = mock<ActivityPubUserService> {
             onBlocking { fetchPerson(anyString()) } doReturn person
         }
-        val userService = mock<UserService> {
+        val userService = mock<IUserService> {
             onBlocking { findByUrls(any()) } doReturn listOf(
                 User(
                     id = 1L,
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
index a0a85f3c..bb15ffde 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImplTest.kt
@@ -8,7 +8,7 @@ import dev.usbharu.hideout.config.ConfigData
 import dev.usbharu.hideout.domain.model.PostEntity
 import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.domain.model.job.DeliverPostJob
-import dev.usbharu.hideout.service.impl.UserService
+import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.service.job.JobQueueParentService
 import io.ktor.client.*
 import io.ktor.client.engine.mock.*
@@ -54,7 +54,7 @@ class ActivityPubNoteServiceImplTest {
                 createdAt = Instant.now()
             )
         )
-        val userService = mock<UserService> {
+        val userService = mock<IUserService> {
             onBlocking { findById(eq(1L)) } doReturn User(
                 1L,
                 "test",

From d2183c4b477eea1852610da8c8d20fa1e14dc74d Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 17:54:42 +0900
Subject: [PATCH 19/45] =?UTF-8?q?fix:=20PrivateKey=E3=82=92=E6=96=87?=
 =?UTF-8?q?=E5=AD=97=E5=88=97=E3=81=AB=E3=81=99=E3=82=8B=E5=87=A6=E7=90=86?=
 =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index 560eaebf..5e0018ab 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -71,7 +71,7 @@ class UserService(private val userRepository: IUserRepository, private val userA
             outbox = "${Config.configData.url}/users/$nextId/outbox",
             url = "${Config.configData.url}/users/$nextId",
             publicKey = keyPair.public.toPem(),
-            privateKey = keyPair.private.toString(),
+            privateKey = keyPair.private.toPem(),
             Instant.now()
         )
         return userRepository.save(userEntity)

From 84e84694ea7c673a9292fbebafbc680254a6f976 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 17:54:59 +0900
Subject: [PATCH 20/45] =?UTF-8?q?test:=20UserService=E3=81=AE=E3=83=86?=
 =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../hideout/service/impl/UserServiceTest.kt   | 88 +++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt

diff --git a/src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt
new file mode 100644
index 00000000..45965180
--- /dev/null
+++ b/src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt
@@ -0,0 +1,88 @@
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package dev.usbharu.hideout.service.impl
+
+import dev.usbharu.hideout.config.Config
+import dev.usbharu.hideout.config.ConfigData
+import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
+import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
+import dev.usbharu.hideout.repository.IUserRepository
+import dev.usbharu.hideout.service.IUserAuthService
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.jupiter.api.Test
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.kotlin.*
+import java.security.KeyPairGenerator
+import kotlin.test.assertEquals
+import kotlin.test.assertNull
+
+class UserServiceTest{
+    @Test
+    fun `createLocalUser ローカルユーザーを作成できる`() = runTest {
+        Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
+        val userRepository = mock<IUserRepository> {
+            onBlocking { nextId() } doReturn 110001L
+        }
+        val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair()
+        val userAuthService = mock<IUserAuthService> {
+            onBlocking { hash(anyString()) } doReturn "hashedPassword"
+            onBlocking { generateKeyPair() } doReturn generateKeyPair
+        }
+        val userService = UserService(userRepository, userAuthService)
+        userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test"))
+        verify(userRepository, times(1)).save(any())
+        argumentCaptor<dev.usbharu.hideout.domain.model.hideout.entity.User> {
+            verify(userRepository, 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/110001", firstValue.url)
+            assertEquals("example.com", firstValue.domain)
+            assertEquals("https://example.com/users/110001/inbox", firstValue.inbox)
+            assertEquals("https://example.com/users/110001/outbox", firstValue.outbox)
+            assertEquals(generateKeyPair.public.toPem(),firstValue.publicKey)
+            assertEquals(generateKeyPair.private.toPem(),firstValue.privateKey)
+        }
+    }
+
+    @Test
+    fun `createRemoteUser リモートユーザーを作成できる`() = runTest {
+
+        Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
+
+
+        val userRepository = mock<IUserRepository>{
+            onBlocking { nextId() } doReturn 113345L
+        }
+        val userService = UserService(userRepository,mock())
+        val user = RemoteUserCreateDto(
+            "test",
+            "example.com",
+            "testUser",
+            "test user",
+            "https://example.com/inbox",
+            "https://example.com/outbox",
+            "https://example.com",
+            "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----"
+        )
+        userService.createRemoteUser(user)
+        verify(userRepository, times(1)).save(any())
+        argumentCaptor<dev.usbharu.hideout.domain.model.hideout.entity.User> {
+            verify(userRepository, 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://example.com", firstValue.url)
+            assertEquals("example.com", firstValue.domain)
+            assertEquals("https://example.com/inbox", firstValue.inbox)
+            assertEquals("https://example.com/outbox", firstValue.outbox)
+            assertEquals("-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",firstValue.publicKey)
+            assertNull(firstValue.privateKey)
+        }
+    }
+}

From 5be32970dafbd3586074aba453ae6f7980cffdcf Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 23:06:07 +0900
Subject: [PATCH 21/45] =?UTF-8?q?fix:=20User=E3=81=AEinbox/outbox/url?=
 =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/service/impl/UserService.kt  | 6 +++---
 .../dev/usbharu/hideout/service/impl/UserServiceTest.kt     | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
index 5e0018ab..fcf30dcb 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserService.kt
@@ -67,9 +67,9 @@ class UserService(private val userRepository: IUserRepository, private val userA
             screenName = user.screenName,
             description = user.description,
             password = HashedPassword,
-            inbox = "${Config.configData.url}/users/$nextId/inbox",
-            outbox = "${Config.configData.url}/users/$nextId/outbox",
-            url = "${Config.configData.url}/users/$nextId",
+            inbox = "${Config.configData.url}/users/${user.name}/inbox",
+            outbox = "${Config.configData.url}/users/${user.name}/outbox",
+            url = "${Config.configData.url}/users/${user.name}",
             publicKey = keyPair.public.toPem(),
             privateKey = keyPair.private.toPem(),
             Instant.now()
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt
index 45965180..31967bbe 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/impl/UserServiceTest.kt
@@ -39,10 +39,10 @@ class UserServiceTest{
             assertEquals("XXXXXXXXXXXXX", firstValue.description)
             assertEquals("hashedPassword", firstValue.password)
             assertEquals(110001L, firstValue.id)
-            assertEquals("https://example.com/users/110001", firstValue.url)
+            assertEquals("https://example.com/users/test", firstValue.url)
             assertEquals("example.com", firstValue.domain)
-            assertEquals("https://example.com/users/110001/inbox", firstValue.inbox)
-            assertEquals("https://example.com/users/110001/outbox", firstValue.outbox)
+            assertEquals("https://example.com/users/test/inbox", firstValue.inbox)
+            assertEquals("https://example.com/users/test/outbox", firstValue.outbox)
             assertEquals(generateKeyPair.public.toPem(),firstValue.publicKey)
             assertEquals(generateKeyPair.private.toPem(),firstValue.privateKey)
         }

From e4046b5c778774c1b57347869873c2658db6822f Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Fri, 28 Apr 2023 23:36:27 +0900
Subject: [PATCH 22/45] =?UTF-8?q?fix:=20=E3=83=89=E3=83=A1=E3=82=A4?=
 =?UTF-8?q?=E3=83=B3=E3=81=AE=E6=8A=BD=E5=87=BA=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/domain/model/ap/JsonLd.kt      | 10 +++++++++-
 .../service/activitypub/ActivityPubUserServiceImpl.kt  |  2 +-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt
index 9700c9d0..f6c4c73a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/JsonLd.kt
@@ -2,6 +2,7 @@ package dev.usbharu.hideout.domain.model.ap
 
 import com.fasterxml.jackson.annotation.JsonAutoDetect
 import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonInclude
 import com.fasterxml.jackson.annotation.JsonProperty
 import com.fasterxml.jackson.core.JsonGenerator
 import com.fasterxml.jackson.databind.JsonDeserializer
@@ -15,7 +16,8 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize
 open class JsonLd {
     @JsonProperty("@context")
     @JsonDeserialize(contentUsing = ContextDeserializer::class)
-    @JsonSerialize(using = ContextSerializer::class)
+    @JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY, using = ContextSerializer::class)
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
     var context: List<String> = emptyList()
 
     @JsonCreator
@@ -57,6 +59,12 @@ class ContextDeserializer : JsonDeserializer<String>() {
 }
 
 class ContextSerializer : JsonSerializer<List<String>>() {
+
+
+    override fun isEmpty(value: List<String>?): Boolean {
+        return value.isNullOrEmpty()
+    }
+
     override fun serialize(value: List<String>?, gen: JsonGenerator?, serializers: SerializerProvider?) {
         if (value.isNullOrEmpty()) {
             gen?.writeNull()
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index 4aca8b88..d63c048f 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -89,7 +89,7 @@ class ActivityPubUserServiceImpl(
                 RemoteUserCreateDto(
                     name = person.preferredUsername
                         ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
-                    domain = url.substringAfter(":").substringBeforeLast("/"),
+                    domain = url.substringAfter("://").substringBefore("/"),
                     screenName = (person.name ?: person.preferredUsername) ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
                     description = person.summary ?: "",
                     inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"),

From 4ac23c225a492dd078455fceed6faf948099153b Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 13:02:38 +0900
Subject: [PATCH 23/45] =?UTF-8?q?fix:=20=E8=BB=BD=E5=BE=AE=E3=81=AA?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E3=80=81=E3=83=AD=E3=82=AC=E3=83=BC=E3=82=92?=
 =?UTF-8?q?=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/routing/activitypub/UserRouting.kt     | 3 ++-
 .../hideout/service/activitypub/ActivityPubNoteServiceImpl.kt  | 2 +-
 .../hideout/service/activitypub/ActivityPubUserServiceImpl.kt  | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index 95b22635..6f5e8f2b 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -31,10 +31,11 @@ fun Routing.usersAP(activityPubUserService: ActivityPubUserService, userService:
 }
 
 class ContentTypeRouteSelector(private vararg val contentType: ContentType) : RouteSelector() {
-    override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {
+        override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {
 
         val requestContentType =
             ContentType.parse(context.call.request.accept() ?: return RouteSelectorEvaluation.FailedParameter)
+        context.call.application.log.debug("Content-Type: {}", contentType)
         return if (contentType.any { contentType -> contentType.match(requestContentType) }) {
             RouteSelectorEvaluation.Constant
         } else {
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
index f9b4702c..bca90430 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
@@ -45,7 +45,7 @@ class ActivityPubNoteServiceImpl(
             attributedTo = actor,
             content = postEntity.text,
             published = Instant.ofEpochMilli(postEntity.createdAt).toString(),
-            to = listOf("https://www.w3.org/ns/activitystreams#Public", actor + "/followers")
+            to = listOf("https://www.w3.org/ns/activitystreams#Public", actor + "/follower")
         )
         val inbox = props[DeliverPostJob.inbox]
         logger.debug("createNoteJob: actor={}, note={}, inbox={}", actor, postEntity, inbox)
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index d63c048f..e8444ba0 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -89,7 +89,7 @@ class ActivityPubUserServiceImpl(
                 RemoteUserCreateDto(
                     name = person.preferredUsername
                         ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
-                    domain = url.substringAfter("://").substringBefore("/"),
+                    domain = url.substringAfter("://").substringBeforeLast("/"),
                     screenName = (person.name ?: person.preferredUsername) ?: throw IllegalActivityPubObjectException("preferredUsername is null"),
                     description = person.summary ?: "",
                     inbox = person.inbox ?: throw IllegalActivityPubObjectException("inbox is null"),

From fc3ab2854b2f44614d97b1db9189381a4a8196b1 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 13:25:12 +0900
Subject: [PATCH 24/45] =?UTF-8?q?feat:=20Accept=E3=83=98=E3=83=83=E3=83=80?=
 =?UTF-8?q?=E3=83=BC=E3=81=AE=E3=83=AD=E3=82=B0=E3=82=92=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../routing/activitypub/UserRouting.kt        |  7 +-
 .../routing/activitypub/UsersAPTest.kt        | 87 ++++++++++++++++++-
 2 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index 6f5e8f2b..70201496 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -35,8 +35,11 @@ class ContentTypeRouteSelector(private vararg val contentType: ContentType) : Ro
 
         val requestContentType =
             ContentType.parse(context.call.request.accept() ?: return RouteSelectorEvaluation.FailedParameter)
-        context.call.application.log.debug("Content-Type: {}", contentType)
-        return if (contentType.any { contentType -> contentType.match(requestContentType) }) {
+        context.call.application.log.debug("Content-Type: {}", requestContentType)
+        return if (contentType.any { contentType ->
+            context.call.application.log.debug(contentType.toString())
+                contentType.match(requestContentType)
+            }) {
             RouteSelectorEvaluation.Constant
         } else {
             RouteSelectorEvaluation.FailedParameter
diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
index d4db2cff..30a3e0bd 100644
--- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
@@ -14,19 +14,21 @@ import dev.usbharu.hideout.plugins.configureSerialization
 import dev.usbharu.hideout.service.activitypub.ActivityPubService
 import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
 import dev.usbharu.hideout.service.impl.IUserService
-import dev.usbharu.hideout.service.impl.UserService
 import dev.usbharu.hideout.service.signature.HttpSignatureVerifyService
 import dev.usbharu.hideout.util.HttpUtil.Activity
+import dev.usbharu.hideout.util.HttpUtil.JsonLd
 import io.ktor.client.request.*
 import io.ktor.client.statement.*
 import io.ktor.http.*
 import io.ktor.server.config.*
 import io.ktor.server.testing.*
+import org.junit.jupiter.api.Disabled
 import org.junit.jupiter.api.Test
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.mock
 import kotlin.test.assertEquals
+import kotlin.test.assertTrue
 
 
 class UsersAPTest {
@@ -71,7 +73,13 @@ class UsersAPTest {
 
         application {
             configureSerialization()
-            configureRouting(httpSignatureVerifyService, activityPubService, userService, activityPubUserService,mock())
+            configureRouting(
+                httpSignatureVerifyService,
+                activityPubService,
+                userService,
+                activityPubUserService,
+                mock()
+            )
         }
         client.get("/users/test") {
             accept(ContentType.Application.Activity)
@@ -89,4 +97,79 @@ class UsersAPTest {
             assertEquals(person, readValue)
         }
     }
+
+    @Test()
+    @Disabled
+    fun `ユーザのURLにAcceptヘッダーをActivityとJson-LDにしてアクセスしたときPersonが返ってくる`() = testApplication {
+        environment {
+            config = ApplicationConfig("empty.conf")
+        }
+        val person = Person(
+            type = emptyList(),
+            name = "test",
+            id = "http://example.com/users/test",
+            preferredUsername = "test",
+            summary = "test user",
+            inbox = "http://example.com/users/test/inbox",
+            outbox = "http://example.com/users/test/outbox",
+            url = "http://example.com/users/test",
+            icon = Image(
+                type = emptyList(),
+                name = "http://example.com/users/test/icon.png",
+                mediaType = "image/png",
+                url = "http://example.com/users/test/icon.png"
+            ),
+            publicKey = Key(
+                type = emptyList(),
+                name = "Public Key",
+                id = "http://example.com/users/test#pubkey",
+                owner = "https://example.com/users/test",
+                publicKeyPem = "-----BEGIN PUBLIC KEY-----\n\n-----END PUBLIC KEY-----"
+            )
+        )
+        person.context = listOf("https://www.w3.org/ns/activitystreams")
+
+        val httpSignatureVerifyService = mock<HttpSignatureVerifyService> {}
+        val activityPubService = mock<ActivityPubService> {}
+        val userService = mock<IUserService> {}
+
+        val activityPubUserService = mock<ActivityPubUserService> {
+            onBlocking { getPersonByName(anyString()) } doReturn person
+        }
+
+        application {
+            configureSerialization()
+            configureRouting(
+                httpSignatureVerifyService,
+                activityPubService,
+                userService,
+                activityPubUserService,
+                mock()
+            )
+        }
+        client.get("/users/test") {
+            accept(ContentType.Application.JsonLd)
+            accept(ContentType.Application.Activity)
+        }.let {
+            val objectMapper = jacksonObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
+                .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
+                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+            objectMapper.configOverride(List::class.java).setSetterInfo(
+                JsonSetter.Value.forValueNulls(
+                    Nulls.AS_EMPTY
+                )
+            )
+            val actual = it.bodyAsText()
+            val readValue = objectMapper.readValue<Person>(actual)
+            assertEquals(person, readValue)
+        }
+    }
+
+    @Test
+    @Disabled
+    fun contentType_Test() {
+        val listOf = listOf(ContentType.Application.JsonLd, ContentType.Application.Activity)
+        assertTrue(listOf.any { contentType -> contentType.match("application/ld+json; profile=\"\\\"https://www.w3.org/ns/activitystreams\\\",application/activity+json\"") })
+        assertTrue(ContentType.Application.JsonLd.match("application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""))
+    }
 }

From 68d438bdb465c30d83f38723decb0aa464b019d7 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 13:36:41 +0900
Subject: [PATCH 25/45] =?UTF-8?q?fix:=20Accept=E3=83=98=E3=83=83=E3=83=80?=
 =?UTF-8?q?=E3=83=BC=E3=81=AE=E5=88=A4=E5=AE=9A=E6=96=B9=E6=B3=95=E3=82=92?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../hideout/routing/activitypub/UserRouting.kt        | 11 +++++------
 .../hideout/routing/activitypub/UsersAPTest.kt        |  7 +++----
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index 70201496..2864ba23 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -31,15 +31,14 @@ fun Routing.usersAP(activityPubUserService: ActivityPubUserService, userService:
 }
 
 class ContentTypeRouteSelector(private vararg val contentType: ContentType) : RouteSelector() {
-        override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {
+    override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {
 
+        context.call.application.log.debug("Accept: ${context.call.request.accept()}")
         val requestContentType =
             ContentType.parse(context.call.request.accept() ?: return RouteSelectorEvaluation.FailedParameter)
-        context.call.application.log.debug("Content-Type: {}", requestContentType)
-        return if (contentType.any { contentType ->
-            context.call.application.log.debug(contentType.toString())
-                contentType.match(requestContentType)
-            }) {
+
+        return if (contentType.find { contentType: ContentType -> contentType.match(requestContentType) }
+                .let { true }) {
             RouteSelectorEvaluation.Constant
         } else {
             RouteSelectorEvaluation.FailedParameter
diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
index 30a3e0bd..e5ec1457 100644
--- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
@@ -22,7 +22,6 @@ import io.ktor.client.statement.*
 import io.ktor.http.*
 import io.ktor.server.config.*
 import io.ktor.server.testing.*
-import org.junit.jupiter.api.Disabled
 import org.junit.jupiter.api.Test
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.kotlin.doReturn
@@ -99,7 +98,7 @@ class UsersAPTest {
     }
 
     @Test()
-    @Disabled
+//    @Disabled
     fun `ユーザのURLにAcceptヘッダーをActivityとJson-LDにしてアクセスしたときPersonが返ってくる`() = testApplication {
         environment {
             config = ApplicationConfig("empty.conf")
@@ -166,10 +165,10 @@ class UsersAPTest {
     }
 
     @Test
-    @Disabled
+//    @Disabled
     fun contentType_Test() {
         val listOf = listOf(ContentType.Application.JsonLd, ContentType.Application.Activity)
-        assertTrue(listOf.any { contentType -> contentType.match("application/ld+json; profile=\"\\\"https://www.w3.org/ns/activitystreams\\\",application/activity+json\"") })
+        assertTrue(listOf.find { contentType -> contentType.match("application/ld+json; profile=\"\\\"https://www.w3.org/ns/activitystreams\\\",application/activity+json\"") }.let { true })
         assertTrue(ContentType.Application.JsonLd.match("application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""))
     }
 }

From 54145dbde10ef8a4ff96da20ac37c1057700eca1 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 14:16:48 +0900
Subject: [PATCH 26/45] =?UTF-8?q?feat:=20Get=E3=83=AA=E3=82=AF=E3=82=A8?=
 =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=82=E7=BD=B2=E5=90=8D=E3=81=A7=E3=81=8D?=
 =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt |  7 +++++++
 .../activitypub/ActivityPubFollowServiceImpl.kt       |  4 ++--
 .../service/activitypub/ActivityPubUserService.kt     |  2 +-
 .../service/activitypub/ActivityPubUserServiceImpl.kt | 11 ++++++++---
 .../activitypub/ActivityPubFollowServiceImplTest.kt   |  2 +-
 5 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index cbb6cab4..87397704 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -44,6 +44,13 @@ suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonL
     }
 }
 
+suspend fun HttpClient.getAp(urlString: String,username: String):HttpResponse {
+    return this.get(urlString){
+        header("Accept",ContentType.Application.Activity)
+        header("Signature","keyId=\"$username\",algorithm=\"#rsa-sha\",headers=\"(request-target) digest date\"")
+    }
+}
+
 class HttpSignaturePluginConfig {
     lateinit var keyMap: KeyMap
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt
index fcd94662..988cb81e 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImpl.kt
@@ -32,9 +32,9 @@ class ActivityPubFollowServiceImpl(
 
     override suspend fun receiveFollowJob(props: JobProps<ReceiveFollowJob>) {
         val actor = props[ReceiveFollowJob.actor]
-        val person = activityPubUserService.fetchPerson(actor)
-        val follow = Config.configData.objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow])
         val targetActor = props[ReceiveFollowJob.targetActor]
+        val person = activityPubUserService.fetchPerson(actor,targetActor)
+        val follow = Config.configData.objectMapper.readValue<Follow>(props[ReceiveFollowJob.follow])
         httpClient.postAp(
             urlString = person.inbox ?: throw IllegalArgumentException("inbox is not found"),
             username = "$targetActor#pubkey",
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserService.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserService.kt
index a698670b..3446da24 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserService.kt
@@ -5,5 +5,5 @@ import dev.usbharu.hideout.domain.model.ap.Person
 interface ActivityPubUserService {
     suspend fun getPersonByName(name:String): Person
 
-    suspend fun fetchPerson(url:String): Person
+    suspend fun fetchPerson(url: String, targetActor: String? = null): Person
 }
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
index e8444ba0..94c8557a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubUserServiceImpl.kt
@@ -8,6 +8,7 @@ import dev.usbharu.hideout.domain.model.ap.Person
 import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
 import dev.usbharu.hideout.exception.UserNotFoundException
 import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
+import dev.usbharu.hideout.plugins.getAp
 import dev.usbharu.hideout.service.impl.IUserService
 import dev.usbharu.hideout.util.HttpUtil.Activity
 import io.ktor.client.*
@@ -52,7 +53,7 @@ class ActivityPubUserServiceImpl(
         )
     }
 
-    override suspend fun fetchPerson(url: String): Person {
+    override suspend fun fetchPerson(url: String, targetActor: String?): Person {
         return try {
             val userEntity = userService.findByUrl(url)
             return Person(
@@ -80,8 +81,12 @@ class ActivityPubUserServiceImpl(
             )
 
         } catch (e: UserNotFoundException) {
-            val httpResponse = httpClient.get(url) {
-                accept(ContentType.Application.Activity)
+            val httpResponse = if (targetActor != null) {
+                httpClient.getAp(url,"$targetActor#pubkey")
+            }else {
+                httpClient.get(url) {
+                    accept(ContentType.Application.Activity)
+                }
             }
             val person = Config.configData.objectMapper.readValue<Person>(httpResponse.bodyAsText())
 
diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
index e37652dd..6a668e34 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
@@ -85,7 +85,7 @@ class ActivityPubFollowServiceImplTest {
 
         )
         val activityPubUserService = mock<ActivityPubUserService> {
-            onBlocking { fetchPerson(anyString()) } doReturn person
+            onBlocking { fetchPerson(anyString(), any()) } doReturn person
         }
         val userService = mock<IUserService> {
             onBlocking { findByUrls(any()) } doReturn listOf(

From 97c18b07547967cbe90f372997d65827620c7b19 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 14:25:12 +0900
Subject: [PATCH 27/45] =?UTF-8?q?fix:=20Signature=E3=83=98=E3=83=83?=
 =?UTF-8?q?=E3=83=80=E3=83=BC=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 87397704..6013cea5 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -47,7 +47,7 @@ suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonL
 suspend fun HttpClient.getAp(urlString: String,username: String):HttpResponse {
     return this.get(urlString){
         header("Accept",ContentType.Application.Activity)
-        header("Signature","keyId=\"$username\",algorithm=\"#rsa-sha\",headers=\"(request-target) digest date\"")
+        header("Signature","keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) digest date\"")
     }
 }
 

From bd927677a0a629a7ca95037e8f8f0977b26e0ad2 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 14:44:43 +0900
Subject: [PATCH 28/45] =?UTF-8?q?fix:=20=E3=81=AA=E3=81=9C=E3=81=8B?=
 =?UTF-8?q?=E5=BF=85=E3=81=9AJson=E3=82=92=E8=BF=94=E3=81=99=E3=82=88?=
 =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=AA=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F?=
 =?UTF-8?q?=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../routing/activitypub/UserRouting.kt        |  3 +-
 .../routing/activitypub/UsersAPTest.kt        | 45 ++++++++++++++++++-
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index 2864ba23..559ca0a0 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -37,8 +37,7 @@ class ContentTypeRouteSelector(private vararg val contentType: ContentType) : Ro
         val requestContentType =
             ContentType.parse(context.call.request.accept() ?: return RouteSelectorEvaluation.FailedParameter)
 
-        return if (contentType.find { contentType: ContentType -> contentType.match(requestContentType) }
-                .let { true }) {
+        return if (contentType.find { contentType: ContentType -> contentType.match(requestContentType) } != null) {
             RouteSelectorEvaluation.Constant
         } else {
             RouteSelectorEvaluation.FailedParameter
diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
index e5ec1457..9f713056 100644
--- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
@@ -9,6 +9,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
 import dev.usbharu.hideout.domain.model.ap.Image
 import dev.usbharu.hideout.domain.model.ap.Key
 import dev.usbharu.hideout.domain.model.ap.Person
+import dev.usbharu.hideout.domain.model.hideout.entity.User
 import dev.usbharu.hideout.plugins.configureRouting
 import dev.usbharu.hideout.plugins.configureSerialization
 import dev.usbharu.hideout.service.activitypub.ActivityPubService
@@ -25,7 +26,9 @@ import io.ktor.server.testing.*
 import org.junit.jupiter.api.Test
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
+import java.time.Instant
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
 
@@ -168,7 +171,47 @@ class UsersAPTest {
 //    @Disabled
     fun contentType_Test() {
         val listOf = listOf(ContentType.Application.JsonLd, ContentType.Application.Activity)
-        assertTrue(listOf.find { contentType -> contentType.match("application/ld+json; profile=\"\\\"https://www.w3.org/ns/activitystreams\\\",application/activity+json\"") }.let { true })
+        assertTrue(listOf.find { contentType ->
+            contentType.match("application/ld+json; profile=\"\\\"https://www.w3.org/ns/activitystreams\\\",application/activity+json\"")
+        }.let { it != null })
         assertTrue(ContentType.Application.JsonLd.match("application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""))
     }
+
+    @Test
+    fun ユーザーのURLにAcceptヘッダーをhtmlにしてアクセスしたときはただの文字を返す() = testApplication {
+        environment {
+            config = ApplicationConfig("empty.conf")
+        }
+        val userService = mock<IUserService> {
+            onBlocking { findByNameLocalUser(eq("test")) } doReturn User(
+                1L,
+                "test",
+                "example.com",
+                "test",
+                "",
+                "hashedPassword",
+                "https://example.com/inbox",
+                "https://example.com/outbox",
+                "https://example.com",
+                "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",
+                "-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----",
+                Instant.now()
+            )
+        }
+        application {
+            configureRouting(
+                mock(),
+                mock(),
+                userService,
+                mock(),
+                mock()
+            )
+        }
+        client.get("/users/test") {
+            accept(ContentType.Text.Html)
+        }.let {
+            assertEquals(HttpStatusCode.OK, it.status)
+            assertTrue(it.contentType()?.match(ContentType.Text.Plain) == true)
+        }
+    }
 }

From 2e5dab4378f6b8720aeae95d93d639faa0eed18e Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 14:46:22 +0900
Subject: [PATCH 29/45] =?UTF-8?q?fix:=20get=E3=83=AA=E3=82=AF=E3=82=A8?=
 =?UTF-8?q?=E3=82=B9=E3=83=88=E3=81=8B=E3=82=89digest=E3=82=92=E5=89=8A?=
 =?UTF-8?q?=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 6013cea5..74fcfff7 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -47,7 +47,7 @@ suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonL
 suspend fun HttpClient.getAp(urlString: String,username: String):HttpResponse {
     return this.get(urlString){
         header("Accept",ContentType.Application.Activity)
-        header("Signature","keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) digest date\"")
+        header("Signature","keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) date\"")
     }
 }
 

From 26b98ab9c5462eda1e420bf9c5064746a7665a79 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 15:11:24 +0900
Subject: [PATCH 30/45] =?UTF-8?q?fix:=20ContentType=E3=81=AE=E5=88=A4?=
 =?UTF-8?q?=E5=AE=9A=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../usbharu/hideout/routing/activitypub/UserRouting.kt    | 8 ++++----
 .../usbharu/hideout/routing/activitypub/UsersAPTest.kt    | 4 +++-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index 559ca0a0..6212297a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -34,10 +34,10 @@ class ContentTypeRouteSelector(private vararg val contentType: ContentType) : Ro
     override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {
 
         context.call.application.log.debug("Accept: ${context.call.request.accept()}")
-        val requestContentType =
-            ContentType.parse(context.call.request.accept() ?: return RouteSelectorEvaluation.FailedParameter)
-
-        return if (contentType.find { contentType: ContentType -> contentType.match(requestContentType) } != null) {
+        val requestContentType = context.call.request.accept() ?: return RouteSelectorEvaluation.FailedParameter
+        return if (requestContentType.split(",")
+                .find { contentType.find { contentType -> contentType.match(it) } != null } != null
+        ) {
             RouteSelectorEvaluation.Constant
         } else {
             RouteSelectorEvaluation.FailedParameter
diff --git a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
index 9f713056..0e997f43 100644
--- a/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/routing/activitypub/UsersAPTest.kt
@@ -170,9 +170,11 @@ class UsersAPTest {
     @Test
 //    @Disabled
     fun contentType_Test() {
+
+        assertTrue(ContentType.Application.Activity.match("application/activity+json"))
         val listOf = listOf(ContentType.Application.JsonLd, ContentType.Application.Activity)
         assertTrue(listOf.find { contentType ->
-            contentType.match("application/ld+json; profile=\"\\\"https://www.w3.org/ns/activitystreams\\\",application/activity+json\"")
+            contentType.match("application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"")
         }.let { it != null })
         assertTrue(ContentType.Application.JsonLd.match("application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""))
     }

From bb7123564cee90d7fa198bf0ea1e21d65f5aa61d Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 15:24:28 +0900
Subject: [PATCH 31/45] =?UTF-8?q?feat:=20Get=E3=83=AA=E3=82=AF=E3=82=A8?=
 =?UTF-8?q?=E3=82=B9=E3=83=88=E3=81=AE=E3=83=AD=E3=82=B0=E3=82=92=E8=BF=BD?=
 =?UTF-8?q?=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/routing/activitypub/UserRouting.kt      | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
index 6212297a..10401627 100644
--- a/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/routing/activitypub/UserRouting.kt
@@ -15,6 +15,8 @@ import io.ktor.server.routing.*
 fun Routing.usersAP(activityPubUserService: ActivityPubUserService, userService: IUserService) {
     route("/users/{name}") {
         createChild(ContentTypeRouteSelector(ContentType.Application.Activity, ContentType.Application.JsonLd)).handle {
+            call.application.log.debug("Signature: ${call.request.header("Signature")}")
+            call.application.log.debug("Authorization: ${call.request.header("Authorization")}")
             val name =
                 call.parameters["name"] ?: throw ParameterNotExistException("Parameter(name='name') does not exist.")
             val person = activityPubUserService.getPersonByName(name)

From 50a5eef279e262f027274838baafa8d031c319a5 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 15:44:48 +0900
Subject: [PATCH 32/45] =?UTF-8?q?feat:=20Host=E3=81=AE=E7=BD=B2=E5=90=8D?=
 =?UTF-8?q?=E3=81=AB=E5=AF=BE=E5=BF=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 74fcfff7..6ed1783d 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -47,7 +47,7 @@ suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonL
 suspend fun HttpClient.getAp(urlString: String,username: String):HttpResponse {
     return this.get(urlString){
         header("Accept",ContentType.Application.Activity)
-        header("Signature","keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) date\"")
+        header("Signature","keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
     }
 }
 
@@ -63,6 +63,7 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
 
 
         request.header("Date", format.format(Date()))
+        request.header("Host",request.url.host+request.url.port.toString())
         println(request.bodyType)
         println(request.bodyType?.type)
         if (request.bodyType?.type == String::class) {
@@ -110,7 +111,9 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
                     "date" -> {
                         "Date"
                     }
-
+                    "host" -> {
+                        "Host"
+                    }
                     else -> {
                         it
                     }

From b72e36ba8c7558e4ad57029c7efcdab7cd639079 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 15:52:59 +0900
Subject: [PATCH 33/45] =?UTF-8?q?fix:=20=E3=83=9B=E3=82=B9=E3=83=88?=
 =?UTF-8?q?=E3=81=AE=E3=83=9D=E3=83=BC=E3=83=88=E7=95=AA=E5=8F=B7=E3=81=8C?=
 =?UTF-8?q?=E3=81=8A=E3=81=8B=E3=81=97=E3=81=8F=E3=81=AA=E3=82=8B=E3=81=AE?=
 =?UTF-8?q?=E3=81=A7=E3=81=A8=E3=82=8A=E3=81=82=E3=81=88=E3=81=9A=E5=89=8A?=
 =?UTF-8?q?=E9=99=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 6ed1783d..c76d52e0 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -63,7 +63,7 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
 
 
         request.header("Date", format.format(Date()))
-        request.header("Host",request.url.host+request.url.port.toString())
+        request.header("Host", "${request.url.host}")
         println(request.bodyType)
         println(request.bodyType?.type)
         if (request.bodyType?.type == String::class) {

From 7915189163b31949a53c765fb41e4fba7df12c14 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 16:04:17 +0900
Subject: [PATCH 34/45] =?UTF-8?q?fix:=20Signature=E3=83=98=E3=83=83?=
 =?UTF-8?q?=E3=83=80=E3=83=BC=E3=82=92=E5=B0=91=E3=81=97=E6=96=B0=E3=81=97?=
 =?UTF-8?q?=E3=81=84=E4=BB=95=E6=A7=98=E3=81=AB=E6=BA=96=E6=8B=A0=E3=81=99?=
 =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index c76d52e0..ffdaaf21 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -149,6 +149,11 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
 
 
             })
+
+            val signatureHeader = request.headers.get("Signature")
+            val replace = signatureHeader?.replace("; ", ",")?.replace(";",",")
+            request.headers.remove("Signature")
+            request.header("Signature", replace)
         }
 
     }

From 2fde447e5aa1e2d9c6cd620d65b5664f4b5c492d Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 16:19:07 +0900
Subject: [PATCH 35/45] =?UTF-8?q?fix:=20Signature=E3=83=98=E3=83=83?=
 =?UTF-8?q?=E3=83=80=E3=83=BC=E3=81=AE=E5=A4=89=E6=9B=B4=E3=82=92=E3=81=99?=
 =?UTF-8?q?=E3=81=B9=E3=81=A6=E3=81=AE=E3=83=98=E3=83=83=E3=83=80=E3=83=BC?=
 =?UTF-8?q?=E3=81=AB=E9=81=A9=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index ffdaaf21..46140f4f 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -150,10 +150,9 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
 
             })
 
-            val signatureHeader = request.headers.get("Signature")
-            val replace = signatureHeader?.replace("; ", ",")?.replace(";",",")
+            val signatureHeader = request.headers.getAll("Signature").orEmpty()
             request.headers.remove("Signature")
-            request.header("Signature", replace)
+            signatureHeader.map { it.replace("; ",",").replace(";",",") }.forEach { request.header("Signature", it) }
         }
 
     }

From 93a554e988542daacb0e116fc321c89faed45a0b Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 16:27:42 +0900
Subject: [PATCH 36/45] =?UTF-8?q?fix:=20PEM=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/service/impl/UserAuthService.kt     | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index 41a38a41..74355630 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -44,11 +44,11 @@ class UserAuthService(
 fun PublicKey.toPem(): String {
     return "-----BEGIN PUBLIC KEY-----\n" +
             Base64.getEncoder().encodeToString(encoded).chunked(64).joinToString("\n") +
-            "\n-----END PUBLIC KEY-----\n"
+            "\n-----END PUBLIC KEY-----"
 }
 
 fun PrivateKey.toPem(): String {
-    return "-----BEGIN PRIVATE KEY-----" +
+    return "-----BEGIN PRIVATE KEY-----\n" +
             Base64.getEncoder().encodeToString(encoded).chunked(64).joinToString("\n") +
-            "\n-----END PRIVATE KEY-----\n"
+            "\n-----END PRIVATE KEY-----"
 }

From 887db080d03671c339ab729ba4276ba21278b317 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 16:47:58 +0900
Subject: [PATCH 37/45] =?UTF-8?q?fix:=20=E9=8D=B5=E3=82=92=E5=BC=B7?=
 =?UTF-8?q?=E5=9B=BA=E3=81=AB=E3=80=81PEM=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/service/impl/UserAuthService.kt     | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
index 74355630..60aa97a4 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/impl/UserAuthService.kt
@@ -31,7 +31,7 @@ class UserAuthService(
 
     override suspend fun generateKeyPair(): KeyPair {
         val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
-        keyPairGenerator.initialize(1024)
+        keyPairGenerator.initialize(2048)
         return keyPairGenerator.generateKeyPair()
     }
 
@@ -44,11 +44,11 @@ class UserAuthService(
 fun PublicKey.toPem(): String {
     return "-----BEGIN PUBLIC KEY-----\n" +
             Base64.getEncoder().encodeToString(encoded).chunked(64).joinToString("\n") +
-            "\n-----END PUBLIC KEY-----"
+            "\n-----END PUBLIC KEY-----\n"
 }
 
 fun PrivateKey.toPem(): String {
     return "-----BEGIN PRIVATE KEY-----\n" +
             Base64.getEncoder().encodeToString(encoded).chunked(64).joinToString("\n") +
-            "\n-----END PRIVATE KEY-----"
+            "\n-----END PRIVATE KEY-----\n"
 }

From b5b8a6a73fb17d34271c384077988556a651588c Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 17:01:02 +0900
Subject: [PATCH 38/45] =?UTF-8?q?fix:=20Signature=E3=83=98=E3=83=83?=
 =?UTF-8?q?=E3=83=80=E3=83=BC=E3=81=AE=E5=BD=A2=E5=BC=8F=E3=82=92=E5=A4=89?=
 =?UTF-8?q?=E6=9B=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 46140f4f..312c38e0 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -152,7 +152,7 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
 
             val signatureHeader = request.headers.getAll("Signature").orEmpty()
             request.headers.remove("Signature")
-            signatureHeader.map { it.replace("; ",",").replace(";",",") }.forEach { request.header("Signature", it) }
+            signatureHeader.map { it.replace("; ",",").replace(";",",") }.joinToString().let { request.header("Signature", it)}
         }
 
     }

From 01bb4fc56b9ff74bfeea39586d4f08b898e0c590 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 17:10:58 +0900
Subject: [PATCH 39/45] =?UTF-8?q?fix:=20Signature=E3=83=98=E3=83=83?=
 =?UTF-8?q?=E3=83=80=E3=83=BC=E3=81=AE=E5=BD=A2=E5=BC=8F=E3=82=92=E5=A4=89?=
 =?UTF-8?q?=E6=9B=B42?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/plugins/ActivityPub.kt  | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
index 312c38e0..af7c4b86 100644
--- a/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/plugins/ActivityPub.kt
@@ -44,10 +44,10 @@ suspend fun HttpClient.postAp(urlString: String, username: String, jsonLd: JsonL
     }
 }
 
-suspend fun HttpClient.getAp(urlString: String,username: String):HttpResponse {
-    return this.get(urlString){
-        header("Accept",ContentType.Application.Activity)
-        header("Signature","keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
+suspend fun HttpClient.getAp(urlString: String, username: String): HttpResponse {
+    return this.get(urlString) {
+        header("Accept", ContentType.Application.Activity)
+        header("Signature", "keyId=\"$username\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date\"")
     }
 }
 
@@ -111,9 +111,11 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
                     "date" -> {
                         "Date"
                     }
+
                     "host" -> {
                         "Host"
                     }
+
                     else -> {
                         it
                     }
@@ -152,7 +154,8 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
 
             val signatureHeader = request.headers.getAll("Signature").orEmpty()
             request.headers.remove("Signature")
-            signatureHeader.map { it.replace("; ",",").replace(";",",") }.joinToString().let { request.header("Signature", it)}
+            signatureHeader.map { it.replace("; ", ",").replace(";", ",") }.joinToString(",")
+                .let { request.header("Signature", it) }
         }
 
     }
@@ -164,7 +167,7 @@ class KtorKeyMap(private val userAuthRepository: IUserRepository) : KeyMap {
             .substringAfterLast("/")
         val publicBytes = Base64.getDecoder().decode(
             userAuthRepository.findByNameAndDomain(
-                username,Config.configData.domain
+                username, Config.configData.domain
             )?.publicKey?.replace("-----BEGIN PUBLIC KEY-----", "-----END PUBLIC KEY-----")?.replace("", "")
                 ?.replace("\n", "")
         )
@@ -177,7 +180,7 @@ class KtorKeyMap(private val userAuthRepository: IUserRepository) : KeyMap {
             .substringAfterLast("/")
         val publicBytes = Base64.getDecoder().decode(
             userAuthRepository.findByNameAndDomain(
-                username,Config.configData.domain
+                username, Config.configData.domain
             )?.privateKey?.replace("-----BEGIN PRIVATE KEY-----", "")?.replace("-----END PRIVATE KEY-----", "")
                 ?.replace("\n", "")
         )

From b5f6c60e056970747a412ad8af71e2c4d1b4b008 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 17:49:29 +0900
Subject: [PATCH 40/45] =?UTF-8?q?feat:=20Create=E3=82=A2=E3=82=AF=E3=83=86?=
 =?UTF-8?q?=E3=82=A3=E3=83=93=E3=83=86=E3=82=A3=E3=81=ABactor=E3=82=92?=
 =?UTF-8?q?=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../dev/usbharu/hideout/domain/model/ap/Create.kt | 11 ++++++++++-
 .../dev/usbharu/hideout/domain/model/ap/Object.kt | 15 +++++++++++----
 .../activitypub/ActivityPubNoteServiceImpl.kt     |  3 ++-
 3 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
index 46f89ec4..4739176a 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
@@ -4,7 +4,16 @@ open class Create : Object {
     var `object`: Object? = null
 
     protected constructor() : super()
-    constructor(type: List<String> = emptyList(), name: String, `object`: Object?) : super(add(type, "Create"), name) {
+    constructor(
+        type: List<String> = emptyList(),
+        name: String? = null,
+        `object`: Object?,
+        actor: String? = null
+    ) : super(
+        add(type, "Create"),
+        name,
+        actor
+    ) {
         this.`object` = `object`
     }
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
index e13d3eb5..efcaedf3 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
@@ -9,9 +9,10 @@ open class Object : JsonLd {
     @JsonSerialize(using = TypeSerializer::class)
     private var type: List<String> = emptyList()
     var name: String? = null
+    var actor: String? = null
 
     protected constructor()
-    constructor(type: List<String>, name: String) : super() {
+    constructor(type: List<String>, name: String? = null,actor:String? = null) : super() {
         this.type = type
         this.name = name
     }
@@ -25,22 +26,28 @@ open class Object : JsonLd {
         }
     }
 
+
+
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is Object) return false
+        if (!super.equals(other)) return false
 
         if (type != other.type) return false
-        return name == other.name
+        if (name != other.name) return false
+        return actor == other.actor
     }
 
     override fun hashCode(): Int {
-        var result = type.hashCode()
+        var result = super.hashCode()
+        result = 31 * result + type.hashCode()
         result = 31 * result + (name?.hashCode() ?: 0)
+        result = 31 * result + (actor?.hashCode() ?: 0)
         return result
     }
 
     override fun toString(): String {
-        return "Object(type=$type, name=$name) ${super.toString()}"
+        return "Object(type=$type, name=$name, actor=$actor) ${super.toString()}"
     }
 
 
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
index bca90430..80f0666b 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
@@ -54,7 +54,8 @@ class ActivityPubNoteServiceImpl(
             username = "$actor#pubkey",
             jsonLd = Create(
                 name = "Create Note",
-                `object` = note
+                `object` = note,
+                actor = note.attributedTo
             )
         )
     }

From f31f89a5403bb48d2db52e31e684d9df42d9f2e2 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 17:54:36 +0900
Subject: [PATCH 41/45] =?UTF-8?q?feat:=20Create=E3=82=A2=E3=82=AF=E3=83=86?=
 =?UTF-8?q?=E3=82=A3=E3=83=93=E3=83=86=E3=82=A3=E3=81=ABactor=E3=82=92?=
 =?UTF-8?q?=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt | 4 +---
 src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt | 4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt
index 7b6d397a..b2274eb6 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Accept.kt
@@ -2,7 +2,6 @@ package dev.usbharu.hideout.domain.model.ap
 
 open class Accept : Object {
     var `object`: Object? = null
-    var actor: String? = null
 
     protected constructor() : super()
     constructor(
@@ -10,9 +9,8 @@ open class Accept : Object {
         name: String,
         `object`: Object?,
         actor: String?
-    ) : super(add(type, "Accept"), name) {
+    ) : super(add(type, "Accept"), name,actor) {
         this.`object` = `object`
-        this.actor = actor
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt
index 9ed6e67a..cf6d1303 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Follow.kt
@@ -2,7 +2,6 @@ package dev.usbharu.hideout.domain.model.ap
 
 open class Follow : Object {
     var `object`: String? = null
-    var actor: String? = null
 
     protected constructor() : super()
     constructor(
@@ -10,9 +9,8 @@ open class Follow : Object {
         name: String,
         `object`: String?,
         actor: String?
-    ) : super(add(type, "Follow"), name) {
+    ) : super(add(type, "Follow"), name,actor) {
         this.`object` = `object`
-        this.actor = actor
     }
 
 

From 814fe4857913470389fa50540805639eab903684 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 17:59:57 +0900
Subject: [PATCH 42/45] =?UTF-8?q?fix:=20actor=E3=81=8C=E5=88=9D=E6=9C=9F?=
 =?UTF-8?q?=E5=8C=96=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA=E3=81=8B?=
 =?UTF-8?q?=E3=81=A3=E3=81=9F=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
index efcaedf3..080f21ef 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
@@ -15,6 +15,7 @@ open class Object : JsonLd {
     constructor(type: List<String>, name: String? = null,actor:String? = null) : super() {
         this.type = type
         this.name = name
+        this.actor = actor
     }
 
     companion object {

From ef713e6d364553449407905e801e3c92c5617729 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 18:27:15 +0900
Subject: [PATCH 43/45] =?UTF-8?q?feat:=20Create=E3=81=ABid=E3=82=92?=
 =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt  | 6 ++++--
 .../kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt     | 4 +---
 .../kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt    | 8 +++++---
 .../kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt  | 4 +++-
 .../kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt  | 4 +---
 .../service/activitypub/ActivityPubNoteServiceImpl.kt     | 3 ++-
 6 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
index 4739176a..540e57aa 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Create.kt
@@ -8,11 +8,13 @@ open class Create : Object {
         type: List<String> = emptyList(),
         name: String? = null,
         `object`: Object?,
-        actor: String? = null
+        actor: String? = null,
+        id: String? = null
     ) : super(
         add(type, "Create"),
         name,
-        actor
+        actor,
+        id
     ) {
         this.`object` = `object`
     }
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt
index 3b1f168a..935a531b 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Key.kt
@@ -1,7 +1,6 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Key : Object {
-    var id: String? = null
     var owner: String? = null
     var publicKeyPem: String? = null
 
@@ -12,8 +11,7 @@ open class Key : Object {
         id: String?,
         owner: String?,
         publicKeyPem: String?
-    ) : super(add(type, "Key"), name) {
-        this.id = id
+    ) : super(add(type, "Key"), name,id) {
         this.owner = owner
         this.publicKeyPem = publicKeyPem
     }
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt
index 0250301c..e62fccc2 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Note.kt
@@ -1,7 +1,6 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Note : Object {
-    var id: String? = null
     var attributedTo: String? = null
     var content: String? = null
     var published: String? = null
@@ -16,8 +15,11 @@ open class Note : Object {
         content: String?,
         published: String?,
         to: List<String> = emptyList()
-    ) : super(add(type, "Note"), name) {
-        this.id = id
+    ) : super(
+        type = add(type, "Note"),
+        name = name,
+        id = id
+    ) {
         this.attributedTo = attributedTo
         this.content = content
         this.published = published
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
index 080f21ef..c66e7224 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Object.kt
@@ -10,12 +10,14 @@ open class Object : JsonLd {
     private var type: List<String> = emptyList()
     var name: String? = null
     var actor: String? = null
+    var id:String? = null
 
     protected constructor()
-    constructor(type: List<String>, name: String? = null,actor:String? = null) : super() {
+    constructor(type: List<String>, name: String? = null,actor:String? = null,id:String? = null) : super() {
         this.type = type
         this.name = name
         this.actor = actor
+        this.id = id
     }
 
     companion object {
diff --git a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt
index 6fecebc6..8a4e5711 100644
--- a/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/domain/model/ap/Person.kt
@@ -1,7 +1,6 @@
 package dev.usbharu.hideout.domain.model.ap
 
 open class Person : Object {
-    private var id: String? = null
     var preferredUsername: String? = null
     var summary: String? = null
     var inbox: String? = null
@@ -22,8 +21,7 @@ open class Person : Object {
         url: String?,
         icon: Image?,
         publicKey: Key?
-    ) : super(add(type, "Person"), name) {
-        this.id = id
+    ) : super(add(type, "Person"), name,id = id) {
         this.preferredUsername = preferredUsername
         this.summary = summary
         this.inbox = inbox
diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
index 80f0666b..d111f5d9 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
@@ -55,7 +55,8 @@ class ActivityPubNoteServiceImpl(
             jsonLd = Create(
                 name = "Create Note",
                 `object` = note,
-                actor = note.attributedTo
+                actor = note.attributedTo,
+                id = "${Config.configData.url}/create/${postEntity.id}"
             )
         )
     }

From 58bf367d60588f72af86cb4887b7a5164026496d Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 18:52:37 +0900
Subject: [PATCH 44/45] =?UTF-8?q?feat:=20Create=E3=81=AEID=E3=82=92?=
 =?UTF-8?q?=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../hideout/service/activitypub/ActivityPubNoteServiceImpl.kt   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
index d111f5d9..72eb6acf 100644
--- a/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
+++ b/src/main/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubNoteServiceImpl.kt
@@ -56,7 +56,7 @@ class ActivityPubNoteServiceImpl(
                 name = "Create Note",
                 `object` = note,
                 actor = note.attributedTo,
-                id = "${Config.configData.url}/create/${postEntity.id}"
+                id = "${Config.configData.url}/create/note/${postEntity.id}"
             )
         )
     }

From f2766ea65eb88b662f80c6902c10ec76096e75e1 Mon Sep 17 00:00:00 2001
From: usbharu <64310155+usbharu@users.noreply.github.com>
Date: Sat, 29 Apr 2023 21:50:01 +0900
Subject: [PATCH 45/45] =?UTF-8?q?test:=20Json=E3=81=AE=E3=82=B7=E3=83=AA?=
 =?UTF-8?q?=E3=82=A2=E3=83=A9=E3=82=A4=E3=82=BA=E3=81=8C=E5=B0=91=E3=81=97?=
 =?UTF-8?q?=E5=A4=89=E3=82=8F=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE?=
 =?UTF-8?q?=E3=81=A7=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../service/activitypub/ActivityPubFollowServiceImplTest.kt    | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
index 6a668e34..a8eae660 100644
--- a/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
+++ b/src/test/kotlin/dev/usbharu/hideout/service/activitypub/ActivityPubFollowServiceImplTest.kt
@@ -50,8 +50,9 @@ class ActivityPubFollowServiceImplTest {
             val follow = scheduleContext.props.props[ReceiveFollowJob.follow.name]
             assertEquals("https://follower.example.com", actor)
             assertEquals("https://example.com", targetActor)
+            //language=JSON
             assertEquals(
-                """{"type":"Follow","name":"Follow","object":"https://example.com","actor":"https://follower.example.com","@context":null}""",
+                """{"type":"Follow","name":"Follow","actor":"https://follower.example.com","object":"https://example.com","@context":null}""",
                 follow
             )
         }