refactor: 命名規則を統一

This commit is contained in:
usbharu 2023-08-11 16:44:23 +09:00
parent 60f0e1a4bf
commit e4ff750f25
50 changed files with 484 additions and 484 deletions

View File

@ -17,15 +17,15 @@ import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.routing.register import dev.usbharu.hideout.routing.register
import dev.usbharu.hideout.service.ap.APService import dev.usbharu.hideout.service.ap.APService
import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.ap.APUserService
import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.PostApiService
import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.UserApiService
import dev.usbharu.hideout.service.api.UserAuthApiService import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.api.WebFingerApiService import dev.usbharu.hideout.service.api.WebFingerApiService
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import dev.usbharu.hideout.service.core.* import dev.usbharu.hideout.service.core.*
import dev.usbharu.hideout.service.job.JobQueueParentService import dev.usbharu.hideout.service.job.JobQueueParentService
import dev.usbharu.hideout.service.job.KJobJobQueueParentService import dev.usbharu.hideout.service.job.KJobJobQueueParentService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import dev.usbharu.kjob.exposed.ExposedKJob import dev.usbharu.kjob.exposed.ExposedKJob
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.engine.cio.* import io.ktor.client.engine.cio.*
@ -94,26 +94,26 @@ fun Application.parent() {
configureKoin(module, HideoutModule().module) configureKoin(module, HideoutModule().module)
configureStatusPages() configureStatusPages()
runBlocking { runBlocking {
inject<IServerInitialiseService>().value.init() inject<ServerInitialiseService>().value.init()
} }
configureCompression() configureCompression()
configureHTTP() configureHTTP()
configureStaticRouting() configureStaticRouting()
configureMonitoring() configureMonitoring()
configureSerialization() configureSerialization()
register(inject<IUserApiService>().value) register(inject<UserApiService>().value)
configureSecurity( configureSecurity(
inject<JwkProvider>().value, inject<JwkProvider>().value,
inject<IMetaService>().value inject<MetaService>().value
) )
configureRouting( configureRouting(
httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value, httpSignatureVerifyService = inject<HttpSignatureVerifyService>().value,
apService = inject<APService>().value, apService = inject<APService>().value,
userService = inject<IUserService>().value, userService = inject<UserService>().value,
apUserService = inject<APUserService>().value, apUserService = inject<APUserService>().value,
postService = inject<IPostApiService>().value, postService = inject<PostApiService>().value,
userApiService = inject<IUserApiService>().value, userApiService = inject<UserApiService>().value,
userQueryService = inject<UserQueryService>().value, userQueryService = inject<UserQueryService>().value,
followerQueryService = inject<FollowerQueryService>().value, followerQueryService = inject<FollowerQueryService>().value,
userAuthApiService = inject<UserAuthApiService>().value, userAuthApiService = inject<UserAuthApiService>().value,

View File

@ -4,7 +4,7 @@ import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.ap.JsonLd import dev.usbharu.hideout.domain.model.ap.JsonLd
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.user.UserAuthService import dev.usbharu.hideout.service.user.UserAuthServiceImpl
import dev.usbharu.hideout.util.HttpUtil.Activity import dev.usbharu.hideout.util.HttpUtil.Activity
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.plugins.api.* import io.ktor.client.plugins.api.*
@ -73,7 +73,7 @@ val httpSignaturePlugin = createClientPlugin("HttpSign", ::HttpSignaturePluginCo
println("Digest !!") println("Digest !!")
// UserAuthService.sha256.reset() // UserAuthService.sha256.reset()
val digest = val digest =
Base64.getEncoder().encodeToString(UserAuthService.sha256.digest(body.toByteArray(Charsets.UTF_8))) Base64.getEncoder().encodeToString(UserAuthServiceImpl.sha256.digest(body.toByteArray(Charsets.UTF_8)))
request.headers.append("Digest", "sha-256=$digest") request.headers.append("Digest", "sha-256=$digest")
} }

View File

@ -11,13 +11,13 @@ import dev.usbharu.hideout.routing.api.internal.v1.users
import dev.usbharu.hideout.routing.wellknown.webfinger import dev.usbharu.hideout.routing.wellknown.webfinger
import dev.usbharu.hideout.service.ap.APService import dev.usbharu.hideout.service.ap.APService
import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.ap.APUserService
import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.PostApiService
import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.UserApiService
import dev.usbharu.hideout.service.api.UserAuthApiService import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.api.WebFingerApiService import dev.usbharu.hideout.service.api.WebFingerApiService
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.plugins.autohead.* import io.ktor.server.plugins.autohead.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
@ -26,10 +26,10 @@ import io.ktor.server.routing.*
fun Application.configureRouting( fun Application.configureRouting(
httpSignatureVerifyService: HttpSignatureVerifyService, httpSignatureVerifyService: HttpSignatureVerifyService,
apService: APService, apService: APService,
userService: IUserService, userService: UserService,
apUserService: APUserService, apUserService: APUserService,
postService: IPostApiService, postService: PostApiService,
userApiService: IUserApiService, userApiService: UserApiService,
userQueryService: UserQueryService, userQueryService: UserQueryService,
followerQueryService: FollowerQueryService, followerQueryService: FollowerQueryService,
userAuthApiService: UserAuthApiService, userAuthApiService: UserAuthApiService,

View File

@ -2,7 +2,7 @@ package dev.usbharu.hideout.plugins
import com.auth0.jwk.JwkProvider import com.auth0.jwk.JwkProvider
import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.service.core.IMetaService import dev.usbharu.hideout.service.core.MetaService
import dev.usbharu.hideout.util.JsonWebKeyUtil import dev.usbharu.hideout.util.JsonWebKeyUtil
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
@ -16,7 +16,7 @@ const val TOKEN_AUTH = "jwt-auth"
@Suppress("MagicNumber") @Suppress("MagicNumber")
fun Application.configureSecurity( fun Application.configureSecurity(
jwkProvider: JwkProvider, jwkProvider: JwkProvider,
metaService: IMetaService metaService: MetaService
) { ) {
val issuer = Config.configData.url val issuer = Config.configData.url
install(Authentication) { install(Authentication) {

View File

@ -1,18 +0,0 @@
package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.User
@Suppress("TooManyFunctions")
interface IUserRepository {
suspend fun save(user: User): User
suspend fun findById(id: Long): User?
suspend fun delete(id: Long)
suspend fun deleteFollowRequest(id: Long, follower: Long)
suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean
suspend fun nextId(): Long
}

View File

@ -2,7 +2,7 @@ package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
interface IJwtRefreshTokenRepository { interface JwtRefreshTokenRepository {
suspend fun generateId(): Long suspend fun generateId(): Long
suspend fun save(token: JwtRefreshToken) suspend fun save(token: JwtRefreshToken)

View File

@ -13,7 +13,7 @@ class JwtRefreshTokenRepositoryImpl(
private val database: Database, private val database: Database,
private val idGenerateService: IdGenerateService private val idGenerateService: IdGenerateService
) : ) :
IJwtRefreshTokenRepository { JwtRefreshTokenRepository {
init { init {
transaction(database) { transaction(database) {

View File

@ -2,7 +2,7 @@ package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.domain.model.hideout.entity.Meta
interface IMetaRepository { interface MetaRepository {
suspend fun save(meta: Meta) suspend fun save(meta: Meta)

View File

@ -7,7 +7,7 @@ import org.koin.core.annotation.Single
import java.util.* import java.util.*
@Single @Single
class MetaRepositoryImpl(private val database: Database) : IMetaRepository { class MetaRepositoryImpl(private val database: Database) : MetaRepository {
init { init {
transaction(database) { transaction(database) {

View File

@ -3,7 +3,7 @@ package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.Post import dev.usbharu.hideout.domain.model.hideout.entity.Post
@Suppress("LongParameterList") @Suppress("LongParameterList")
interface IPostRepository { interface PostRepository {
suspend fun generateId(): Long suspend fun generateId(): Long
suspend fun save(post: Post): Post suspend fun save(post: Post): Post
suspend fun delete(id: Long) suspend fun delete(id: Long)

View File

@ -9,7 +9,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@Single @Single
class PostRepositoryImpl(database: Database, private val idGenerateService: IdGenerateService) : IPostRepository { class PostRepositoryImpl(database: Database, private val idGenerateService: IdGenerateService) : PostRepository {
init { init {
transaction(database) { transaction(database) {

View File

@ -1,137 +1,18 @@
package dev.usbharu.hideout.repository package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.service.core.IdGenerateService
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.transaction
import org.koin.core.annotation.Single
import java.time.Instant
@Single @Suppress("TooManyFunctions")
class UserRepository(private val database: Database, private val idGenerateService: IdGenerateService) : interface UserRepository {
IUserRepository { suspend fun save(user: User): User
init {
transaction(database) {
SchemaUtils.create(Users)
SchemaUtils.create(UsersFollowers)
SchemaUtils.createMissingTablesAndColumns(Users)
SchemaUtils.createMissingTablesAndColumns(UsersFollowers)
SchemaUtils.create(FollowRequests)
SchemaUtils.createMissingTablesAndColumns(FollowRequests)
}
}
override suspend fun save(user: User): User { suspend fun findById(id: Long): User?
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 user
}
override suspend fun findById(id: Long): User? { suspend fun delete(id: Long)
return Users.select { Users.id eq id }.map {
it.toUser()
}.singleOrNull()
}
override suspend fun deleteFollowRequest(id: Long, follower: Long) { suspend fun deleteFollowRequest(id: Long, follower: Long)
FollowRequests.deleteWhere { userId.eq(id) and followerId.eq(follower) }
}
override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean { suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean
return FollowRequests.select { (FollowRequests.userId eq id) and (FollowRequests.followerId eq follower) }
.singleOrNull() != null
}
override suspend fun delete(id: Long) { suspend fun nextId(): Long
Users.deleteWhere { Users.id.eq(id) }
}
override suspend fun nextId(): Long = idGenerateService.generateId()
}
object Users : Table("users") {
val id = long("id")
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).nullable()
val createdAt = long("created_at")
override val primaryKey: PrimaryKey = PrimaryKey(id)
init {
uniqueIndex(name, domain)
}
}
fun ResultRow.toUser(): User {
return User(
id = this[Users.id],
name = this[Users.name],
domain = this[Users.domain],
screenName = this[Users.screenName],
description = this[Users.description],
password = this[Users.password],
inbox = this[Users.inbox],
outbox = this[Users.outbox],
url = this[Users.url],
publicKey = this[Users.publicKey],
privateKey = this[Users.privateKey],
createdAt = 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)
}
}
object FollowRequests : LongIdTable("follow_requests") {
val userId = long("user_id").references(Users.id)
val followerId = long("follower_id").references(Users.id)
init {
uniqueIndex(userId, followerId)
}
} }

View File

@ -0,0 +1,137 @@
package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.service.core.IdGenerateService
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.transaction
import org.koin.core.annotation.Single
import java.time.Instant
@Single
class UserRepositoryImpl(private val database: Database, private val idGenerateService: IdGenerateService) :
UserRepository {
init {
transaction(database) {
SchemaUtils.create(Users)
SchemaUtils.create(UsersFollowers)
SchemaUtils.createMissingTablesAndColumns(Users)
SchemaUtils.createMissingTablesAndColumns(UsersFollowers)
SchemaUtils.create(FollowRequests)
SchemaUtils.createMissingTablesAndColumns(FollowRequests)
}
}
override suspend fun save(user: User): User {
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 user
}
override suspend fun findById(id: Long): User? {
return Users.select { Users.id eq id }.map {
it.toUser()
}.singleOrNull()
}
override suspend fun deleteFollowRequest(id: Long, follower: Long) {
FollowRequests.deleteWhere { userId.eq(id) and followerId.eq(follower) }
}
override suspend fun findFollowRequestsById(id: Long, follower: Long): Boolean {
return FollowRequests.select { (FollowRequests.userId eq id) and (FollowRequests.followerId eq follower) }
.singleOrNull() != null
}
override suspend fun delete(id: Long) {
Users.deleteWhere { Users.id.eq(id) }
}
override suspend fun nextId(): Long = idGenerateService.generateId()
}
object Users : Table("users") {
val id = long("id")
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).nullable()
val createdAt = long("created_at")
override val primaryKey: PrimaryKey = PrimaryKey(id)
init {
uniqueIndex(name, domain)
}
}
fun ResultRow.toUser(): User {
return User(
id = this[Users.id],
name = this[Users.name],
domain = this[Users.domain],
screenName = this[Users.screenName],
description = this[Users.description],
password = this[Users.password],
inbox = this[Users.inbox],
outbox = this[Users.outbox],
url = this[Users.url],
publicKey = this[Users.publicKey],
privateKey = this[Users.privateKey],
createdAt = 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)
}
}
object FollowRequests : LongIdTable("follow_requests") {
val userId = long("user_id").references(Users.id)
val followerId = long("follower_id").references(Users.id)
init {
uniqueIndex(userId, followerId)
}
}

View File

@ -1,6 +1,6 @@
package dev.usbharu.hideout.routing package dev.usbharu.hideout.routing
import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.UserApiService
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.auth.* import io.ktor.server.auth.*
@ -8,7 +8,7 @@ import io.ktor.server.request.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
fun Application.register(userApiService: IUserApiService) { fun Application.register(userApiService: UserApiService) {
routing { routing {
get("/register") { get("/register") {
val principal = call.principal<UserIdPrincipal>() val principal = call.principal<UserIdPrincipal>()

View File

@ -4,7 +4,7 @@ import dev.usbharu.hideout.domain.model.hideout.form.Post
import dev.usbharu.hideout.domain.model.hideout.form.Reaction import dev.usbharu.hideout.domain.model.hideout.form.Reaction
import dev.usbharu.hideout.exception.ParameterNotExistException import dev.usbharu.hideout.exception.ParameterNotExistException
import dev.usbharu.hideout.plugins.TOKEN_AUTH import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.PostApiService
import dev.usbharu.hideout.util.InstantParseUtil import dev.usbharu.hideout.util.InstantParseUtil
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
@ -15,7 +15,7 @@ import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
@Suppress("LongMethod") @Suppress("LongMethod")
fun Route.posts(postApiService: IPostApiService) { fun Route.posts(postApiService: PostApiService) {
route("/posts") { route("/posts") {
authenticate(TOKEN_AUTH) { authenticate(TOKEN_AUTH) {
post { post {

View File

@ -5,8 +5,8 @@ import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
import dev.usbharu.hideout.domain.model.hideout.form.UserCreate import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
import dev.usbharu.hideout.exception.ParameterNotExistException import dev.usbharu.hideout.exception.ParameterNotExistException
import dev.usbharu.hideout.plugins.TOKEN_AUTH import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.UserApiService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import dev.usbharu.hideout.util.AcctUtil import dev.usbharu.hideout.util.AcctUtil
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
@ -17,7 +17,7 @@ import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
@Suppress("LongMethod", "CognitiveComplexMethod") @Suppress("LongMethod", "CognitiveComplexMethod")
fun Route.users(userService: IUserService, userApiService: IUserApiService) { fun Route.users(userService: UserService, userApiService: UserApiService) {
route("/users") { route("/users") {
get { get {
call.respond(userApiService.findAll()) call.respond(userApiService.findAll())

View File

@ -6,7 +6,7 @@ import dev.usbharu.hideout.domain.model.ap.Accept
import dev.usbharu.hideout.domain.model.ap.Follow import dev.usbharu.hideout.domain.model.ap.Follow
import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import io.ktor.http.* import io.ktor.http.*
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@ -16,7 +16,7 @@ interface APAcceptService {
@Single @Single
class APAcceptServiceImpl( class APAcceptServiceImpl(
private val userService: IUserService, private val userService: UserService,
private val userQueryService: UserQueryService private val userQueryService: UserQueryService
) : APAcceptService { ) : APAcceptService {
override suspend fun receiveAccept(accept: Accept): ActivityPubResponse { override suspend fun receiveAccept(accept: Accept): ActivityPubResponse {

View File

@ -7,7 +7,7 @@ import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
import dev.usbharu.hideout.query.PostQueryService import dev.usbharu.hideout.query.PostQueryService
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.reaction.IReactionService import dev.usbharu.hideout.service.reaction.ReactionService
import io.ktor.http.* import io.ktor.http.*
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@ -17,7 +17,7 @@ interface APLikeService {
@Single @Single
class APLikeServiceImpl( class APLikeServiceImpl(
private val reactionService: IReactionService, private val reactionService: ReactionService,
private val apUserService: APUserService, private val apUserService: APUserService,
private val apNoteService: APNoteService, private val apNoteService: APNoteService,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,

View File

@ -13,7 +13,7 @@ import dev.usbharu.hideout.plugins.postAp
import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.PostQueryService import dev.usbharu.hideout.query.PostQueryService
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.repository.IPostRepository import dev.usbharu.hideout.repository.PostRepository
import dev.usbharu.hideout.service.job.JobQueueParentService import dev.usbharu.hideout.service.job.JobQueueParentService
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.statement.* import io.ktor.client.statement.*
@ -35,7 +35,7 @@ interface APNoteService {
class APNoteServiceImpl( class APNoteServiceImpl(
private val httpClient: HttpClient, private val httpClient: HttpClient,
private val jobQueueParentService: JobQueueParentService, private val jobQueueParentService: JobQueueParentService,
private val postRepository: IPostRepository, private val postRepository: PostRepository,
private val apUserService: APUserService, private val apUserService: APUserService,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService, private val followerQueryService: FollowerQueryService,

View File

@ -11,7 +11,7 @@ import dev.usbharu.hideout.plugins.postAp
import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.PostQueryService import dev.usbharu.hideout.query.PostQueryService
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.repository.IPostRepository import dev.usbharu.hideout.repository.PostRepository
import dev.usbharu.hideout.service.job.JobQueueParentService import dev.usbharu.hideout.service.job.JobQueueParentService
import io.ktor.client.* import io.ktor.client.*
import kjob.core.job.JobProps import kjob.core.job.JobProps
@ -28,7 +28,7 @@ interface APReactionService {
@Single @Single
class APReactionServiceImpl( class APReactionServiceImpl(
private val jobQueueParentService: JobQueueParentService, private val jobQueueParentService: JobQueueParentService,
private val iPostRepository: IPostRepository, private val postRepository: PostRepository,
private val httpClient: HttpClient, private val httpClient: HttpClient,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService, private val followerQueryService: FollowerQueryService,

View File

@ -11,7 +11,7 @@ import dev.usbharu.hideout.plugins.postAp
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.job.JobQueueParentService import dev.usbharu.hideout.service.job.JobQueueParentService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import io.ktor.client.* import io.ktor.client.*
import io.ktor.http.* import io.ktor.http.*
import kjob.core.job.JobProps import kjob.core.job.JobProps
@ -26,7 +26,7 @@ interface APReceiveFollowService {
class APReceiveFollowServiceImpl( class APReceiveFollowServiceImpl(
private val jobQueueParentService: JobQueueParentService, private val jobQueueParentService: JobQueueParentService,
private val apUserService: APUserService, private val apUserService: APUserService,
private val userService: IUserService, private val userService: UserService,
private val httpClient: HttpClient, private val httpClient: HttpClient,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val transaction: Transaction private val transaction: Transaction

View File

@ -6,7 +6,7 @@ import dev.usbharu.hideout.domain.model.ap.Follow
import dev.usbharu.hideout.domain.model.ap.Undo import dev.usbharu.hideout.domain.model.ap.Undo
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import io.ktor.http.* import io.ktor.http.*
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@ -17,7 +17,7 @@ interface APUndoService {
@Single @Single
@Suppress("UnsafeCallOnNullableType") @Suppress("UnsafeCallOnNullableType")
class APUndoServiceImpl( class APUndoServiceImpl(
private val userService: IUserService, private val userService: UserService,
private val apUserService: APUserService, private val apUserService: APUserService,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val transaction: Transaction private val transaction: Transaction

View File

@ -10,7 +10,7 @@ import dev.usbharu.hideout.exception.ap.IllegalActivityPubObjectException
import dev.usbharu.hideout.plugins.getAp import dev.usbharu.hideout.plugins.getAp
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import dev.usbharu.hideout.util.HttpUtil.Activity import dev.usbharu.hideout.util.HttpUtil.Activity
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.request.* import io.ktor.client.request.*
@ -33,7 +33,7 @@ interface APUserService {
@Single @Single
class APUserServiceImpl( class APUserServiceImpl(
private val userService: IUserService, private val userService: UserService,
private val httpClient: HttpClient, private val httpClient: HttpClient,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val transaction: Transaction private val transaction: Transaction

View File

@ -7,16 +7,16 @@ import dev.usbharu.hideout.domain.model.hideout.dto.ReactionResponse
import dev.usbharu.hideout.domain.model.hideout.form.Post import dev.usbharu.hideout.domain.model.hideout.form.Post
import dev.usbharu.hideout.query.PostResponseQueryService import dev.usbharu.hideout.query.PostResponseQueryService
import dev.usbharu.hideout.query.ReactionQueryService import dev.usbharu.hideout.query.ReactionQueryService
import dev.usbharu.hideout.repository.IUserRepository import dev.usbharu.hideout.repository.UserRepository
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.post.IPostService import dev.usbharu.hideout.service.post.PostService
import dev.usbharu.hideout.service.reaction.IReactionService import dev.usbharu.hideout.service.reaction.ReactionService
import dev.usbharu.hideout.util.AcctUtil import dev.usbharu.hideout.util.AcctUtil
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import java.time.Instant import java.time.Instant
@Suppress("LongParameterList") @Suppress("LongParameterList")
interface IPostApiService { interface PostApiService {
suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): PostResponse suspend fun createPost(postForm: dev.usbharu.hideout.domain.model.hideout.form.Post, userId: Long): PostResponse
suspend fun getById(id: Long, userId: Long?): PostResponse suspend fun getById(id: Long, userId: Long?): PostResponse
suspend fun getAll( suspend fun getAll(
@ -45,13 +45,13 @@ interface IPostApiService {
@Single @Single
class PostApiServiceImpl( class PostApiServiceImpl(
private val postService: IPostService, private val postService: PostService,
private val userRepository: IUserRepository, private val userRepository: UserRepository,
private val postResponseQueryService: PostResponseQueryService, private val postResponseQueryService: PostResponseQueryService,
private val reactionQueryService: ReactionQueryService, private val reactionQueryService: ReactionQueryService,
private val reactionService: IReactionService, private val reactionService: ReactionService,
private val transaction: Transaction private val transaction: Transaction
) : IPostApiService { ) : PostApiService {
override suspend fun createPost(postForm: Post, userId: Long): PostResponse { override suspend fun createPost(postForm: Post, userId: Long): PostResponse {
return transaction.transaction { return transaction.transaction {
val createdPost = postService.createLocal( val createdPost = postService.createLocal(

View File

@ -8,11 +8,11 @@ import dev.usbharu.hideout.exception.UsernameAlreadyExistException
import dev.usbharu.hideout.query.FollowerQueryService import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import kotlin.math.min import kotlin.math.min
interface IUserApiService { interface UserApiService {
suspend fun findAll(limit: Int? = 100, offset: Long = 0): List<UserResponse> suspend fun findAll(limit: Int? = 100, offset: Long = 0): List<UserResponse>
suspend fun findById(id: Long): UserResponse suspend fun findById(id: Long): UserResponse
@ -36,9 +36,9 @@ interface IUserApiService {
class UserApiServiceImpl( class UserApiServiceImpl(
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService, private val followerQueryService: FollowerQueryService,
private val userService: IUserService, private val userService: UserService,
private val transaction: Transaction private val transaction: Transaction
) : IUserApiService { ) : UserApiService {
override suspend fun findAll(limit: Int?, offset: Long): List<UserResponse> = override suspend fun findAll(limit: Int?, offset: Long): List<UserResponse> =
userQueryService.findAll(min(limit ?: 100, 100), offset).map { UserResponse.from(it) } userQueryService.findAll(min(limit ?: 100, 100), offset).map { UserResponse.from(it) }

View File

@ -5,9 +5,9 @@ import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.auth.IJwtService import dev.usbharu.hideout.service.auth.JwtService
import dev.usbharu.hideout.service.core.Transaction import dev.usbharu.hideout.service.core.Transaction
import dev.usbharu.hideout.service.user.UserAuthService import dev.usbharu.hideout.service.user.UserAuthServiceImpl
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
interface UserAuthApiService { interface UserAuthApiService {
@ -17,9 +17,9 @@ interface UserAuthApiService {
@Single @Single
class UserAuthApiServiceImpl( class UserAuthApiServiceImpl(
private val userAuthService: UserAuthService, private val userAuthService: UserAuthServiceImpl,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val jwtService: IJwtService, private val jwtService: JwtService,
private val transaction: Transaction private val transaction: Transaction
) : UserAuthApiService { ) : UserAuthApiService {
override suspend fun login(username: String, password: String): JwtToken { override suspend fun login(username: String, password: String): JwtToken {

View File

@ -10,8 +10,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
import dev.usbharu.hideout.exception.InvalidRefreshTokenException import dev.usbharu.hideout.exception.InvalidRefreshTokenException
import dev.usbharu.hideout.query.JwtRefreshTokenQueryService import dev.usbharu.hideout.query.JwtRefreshTokenQueryService
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository import dev.usbharu.hideout.repository.JwtRefreshTokenRepository
import dev.usbharu.hideout.service.core.IMetaService import dev.usbharu.hideout.service.core.MetaService
import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.hideout.util.RsaUtil
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@ -19,7 +19,7 @@ import java.time.Instant
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
import java.util.* import java.util.*
interface IJwtService { interface JwtService {
suspend fun createToken(user: User): JwtToken suspend fun createToken(user: User): JwtToken
suspend fun refreshToken(refreshToken: RefreshToken): JwtToken suspend fun refreshToken(refreshToken: RefreshToken): JwtToken
@ -31,11 +31,11 @@ interface IJwtService {
@Suppress("InjectDispatcher") @Suppress("InjectDispatcher")
@Single @Single
class JwtServiceImpl( class JwtServiceImpl(
private val metaService: IMetaService, private val metaService: MetaService,
private val refreshTokenRepository: IJwtRefreshTokenRepository, private val refreshTokenRepository: JwtRefreshTokenRepository,
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val refreshTokenQueryService: JwtRefreshTokenQueryService private val refreshTokenQueryService: JwtRefreshTokenQueryService
) : IJwtService { ) : JwtService {
private val privateKey = runBlocking { private val privateKey = runBlocking {
RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey) RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey)

View File

@ -3,7 +3,7 @@ package dev.usbharu.hideout.service.core
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.domain.model.hideout.entity.Meta
interface IMetaService { interface MetaService {
suspend fun getMeta(): Meta suspend fun getMeta(): Meta
suspend fun updateMeta(meta: Meta) suspend fun updateMeta(meta: Meta)
suspend fun getJwtMeta(): Jwt suspend fun getJwtMeta(): Jwt

View File

@ -3,12 +3,12 @@ package dev.usbharu.hideout.service.core
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.domain.model.hideout.entity.Meta
import dev.usbharu.hideout.exception.NotInitException import dev.usbharu.hideout.exception.NotInitException
import dev.usbharu.hideout.repository.IMetaRepository import dev.usbharu.hideout.repository.MetaRepository
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@Single @Single
class MetaServiceImpl(private val metaRepository: IMetaRepository, private val transaction: Transaction) : class MetaServiceImpl(private val metaRepository: MetaRepository, private val transaction: Transaction) :
IMetaService { MetaService {
override suspend fun getMeta(): Meta = override suspend fun getMeta(): Meta =
transaction.transaction { metaRepository.get() ?: throw NotInitException("Meta is null") } transaction.transaction { metaRepository.get() ?: throw NotInitException("Meta is null") }

View File

@ -1,5 +1,5 @@
package dev.usbharu.hideout.service.core package dev.usbharu.hideout.service.core
interface IServerInitialiseService { interface ServerInitialiseService {
suspend fun init() suspend fun init()
} }

View File

@ -2,7 +2,7 @@ package dev.usbharu.hideout.service.core
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.domain.model.hideout.entity.Meta
import dev.usbharu.hideout.repository.IMetaRepository import dev.usbharu.hideout.repository.MetaRepository
import dev.usbharu.hideout.util.ServerUtil import dev.usbharu.hideout.util.ServerUtil
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import org.slf4j.Logger import org.slf4j.Logger
@ -12,10 +12,10 @@ import java.util.*
@Single @Single
class ServerInitialiseServiceImpl( class ServerInitialiseServiceImpl(
private val metaRepository: IMetaRepository, private val metaRepository: MetaRepository,
private val transaction: Transaction private val transaction: Transaction
) : ) :
IServerInitialiseService { ServerInitialiseService {
val logger: Logger = LoggerFactory.getLogger(ServerInitialiseServiceImpl::class.java) val logger: Logger = LoggerFactory.getLogger(ServerInitialiseServiceImpl::class.java)

View File

@ -3,6 +3,6 @@ package dev.usbharu.hideout.service.post
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
import dev.usbharu.hideout.domain.model.hideout.entity.Post import dev.usbharu.hideout.domain.model.hideout.entity.Post
interface IPostService { interface PostService {
suspend fun createLocal(post: PostCreateDto): Post suspend fun createLocal(post: PostCreateDto): Post
} }

View File

@ -3,18 +3,18 @@ package dev.usbharu.hideout.service.post
import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto import dev.usbharu.hideout.domain.model.hideout.dto.PostCreateDto
import dev.usbharu.hideout.domain.model.hideout.entity.Post import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.exception.UserNotFoundException import dev.usbharu.hideout.exception.UserNotFoundException
import dev.usbharu.hideout.repository.IPostRepository import dev.usbharu.hideout.repository.PostRepository
import dev.usbharu.hideout.repository.IUserRepository import dev.usbharu.hideout.repository.UserRepository
import dev.usbharu.hideout.service.ap.APNoteService import dev.usbharu.hideout.service.ap.APNoteService
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import java.time.Instant import java.time.Instant
@Single @Single
class PostServiceImpl( class PostServiceImpl(
private val postRepository: IPostRepository, private val postRepository: PostRepository,
private val userRepository: IUserRepository, private val userRepository: UserRepository,
private val apNoteService: APNoteService private val apNoteService: APNoteService
) : IPostService { ) : PostService {
override suspend fun createLocal(post: PostCreateDto): Post { override suspend fun createLocal(post: PostCreateDto): Post {
val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found") val user = userRepository.findById(post.userId) ?: throw UserNotFoundException("${post.userId} was not found")
val id = postRepository.generateId() val id = postRepository.generateId()

View File

@ -1,6 +1,6 @@
package dev.usbharu.hideout.service.reaction package dev.usbharu.hideout.service.reaction
interface IReactionService { interface ReactionService {
suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long)
suspend fun sendReaction(name: String, userId: Long, postId: Long) suspend fun sendReaction(name: String, userId: Long, postId: Long)
suspend fun removeReaction(userId: Long, postId: Long) suspend fun removeReaction(userId: Long, postId: Long)

View File

@ -11,7 +11,7 @@ class ReactionServiceImpl(
private val reactionRepository: ReactionRepository, private val reactionRepository: ReactionRepository,
private val apReactionService: APReactionService, private val apReactionService: APReactionService,
private val reactionQueryService: ReactionQueryService private val reactionQueryService: ReactionQueryService
) : IReactionService { ) : ReactionService {
override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) { override suspend fun receiveReaction(name: String, domain: String, userId: Long, postId: Long) {
if (reactionQueryService.reactionAlreadyExist(postId, userId, 0).not()) { if (reactionQueryService.reactionAlreadyExist(postId, userId, 0).not()) {
reactionRepository.save( reactionRepository.save(

View File

@ -1,13 +0,0 @@
package dev.usbharu.hideout.service.user
import java.security.KeyPair
interface IUserAuthService {
fun hash(password: String): String
suspend fun usernameAlreadyUse(username: String): Boolean
suspend fun generateKeyPair(): KeyPair
suspend fun verifyAccount(username: String, password: String): Boolean
}

View File

@ -1,34 +0,0 @@
package dev.usbharu.hideout.service.user
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
@Suppress("TooManyFunctions")
interface IUserService {
suspend fun usernameAlreadyUse(username: String): Boolean
suspend fun createLocalUser(user: UserCreateDto): User
suspend fun createRemoteUser(user: RemoteUserCreateDto): User
/**
* フォローリクエストを送信する
*
* @param id
* @param followerId
* @return リクエストが成功したか
*/
suspend fun followRequest(id: Long, followerId: Long): Boolean
/**
* フォローする
*
* @param id
* @param followerId
*/
suspend fun follow(id: Long, followerId: Long)
suspend fun unfollow(id: Long, followerId: Long): Boolean
}

View File

@ -1,53 +1,13 @@
package dev.usbharu.hideout.service.user package dev.usbharu.hideout.service.user
import dev.usbharu.hideout.config.Config import java.security.KeyPair
import dev.usbharu.hideout.query.UserQueryService
import io.ktor.util.*
import org.koin.core.annotation.Single
import java.security.*
import java.util.*
@Single interface UserAuthService {
class UserAuthService( fun hash(password: String): String
val userQueryService: UserQueryService
) : IUserAuthService {
override fun hash(password: String): String { suspend fun usernameAlreadyUse(username: String): Boolean
val digest = sha256.digest(password.toByteArray(Charsets.UTF_8))
return hex(digest)
}
override suspend fun usernameAlreadyUse(username: String): Boolean { suspend fun generateKeyPair(): KeyPair
userQueryService.findByName(username)
return true
}
override suspend fun verifyAccount(username: String, password: String): Boolean { suspend fun verifyAccount(username: String, password: String): Boolean
val userEntity = userQueryService.findByNameAndDomain(username, Config.configData.domain)
return userEntity.password == hash(password)
}
override suspend fun generateKeyPair(): KeyPair {
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
keyPairGenerator.initialize(keySize)
return keyPairGenerator.generateKeyPair()
}
companion object {
val sha256: MessageDigest = MessageDigest.getInstance("SHA-256")
const val keySize = 2048
const val pemSize = 64
}
}
fun PublicKey.toPem(): String {
return "-----BEGIN PUBLIC KEY-----\n" +
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthService.pemSize).joinToString("\n") +
"\n-----END PUBLIC KEY-----\n"
}
fun PrivateKey.toPem(): String {
return "-----BEGIN PRIVATE KEY-----\n" +
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthService.pemSize).joinToString("\n") +
"\n-----END PRIVATE KEY-----\n"
} }

View File

@ -0,0 +1,53 @@
package dev.usbharu.hideout.service.user
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.query.UserQueryService
import io.ktor.util.*
import org.koin.core.annotation.Single
import java.security.*
import java.util.*
@Single
class UserAuthServiceImpl(
val userQueryService: UserQueryService
) : UserAuthService {
override fun hash(password: String): String {
val digest = sha256.digest(password.toByteArray(Charsets.UTF_8))
return hex(digest)
}
override suspend fun usernameAlreadyUse(username: String): Boolean {
userQueryService.findByName(username)
return true
}
override suspend fun verifyAccount(username: String, password: String): Boolean {
val userEntity = userQueryService.findByNameAndDomain(username, Config.configData.domain)
return userEntity.password == hash(password)
}
override suspend fun generateKeyPair(): KeyPair {
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
keyPairGenerator.initialize(keySize)
return keyPairGenerator.generateKeyPair()
}
companion object {
val sha256: MessageDigest = MessageDigest.getInstance("SHA-256")
const val keySize = 2048
const val pemSize = 64
}
}
fun PublicKey.toPem(): String {
return "-----BEGIN PUBLIC KEY-----\n" +
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthServiceImpl.pemSize).joinToString("\n") +
"\n-----END PUBLIC KEY-----\n"
}
fun PrivateKey.toPem(): String {
return "-----BEGIN PRIVATE KEY-----\n" +
Base64.getEncoder().encodeToString(encoded).chunked(UserAuthServiceImpl.pemSize).joinToString("\n") +
"\n-----END PRIVATE KEY-----\n"
}

View File

@ -1,97 +1,34 @@
package dev.usbharu.hideout.service.user package dev.usbharu.hideout.service.user
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.exception.UserNotFoundException
import dev.usbharu.hideout.query.FollowerQueryService
import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.repository.IUserRepository
import dev.usbharu.hideout.service.ap.APSendFollowService
import org.koin.core.annotation.Single
import java.time.Instant
@Single @Suppress("TooManyFunctions")
class UserService( interface UserService {
private val userRepository: IUserRepository,
private val userAuthService: IUserAuthService,
private val apSendFollowService: APSendFollowService,
private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService
) :
IUserService {
override suspend fun usernameAlreadyUse(username: String): Boolean { suspend fun usernameAlreadyUse(username: String): Boolean
val findByNameAndDomain = userQueryService.findByNameAndDomain(username, Config.configData.domain)
return findByNameAndDomain != null
}
override suspend fun createLocalUser(user: UserCreateDto): 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/${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(),
createdAt = Instant.now()
)
return userRepository.save(userEntity)
}
override suspend fun createRemoteUser(user: RemoteUserCreateDto): User { 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)
}
// TODO APのフォロー処理を作る /**
override suspend fun followRequest(id: Long, followerId: Long): Boolean { * フォローリクエストを送信する
val user = userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.") *
val follower = userRepository.findById(followerId) ?: throw UserNotFoundException("$followerId was not found.") * @param id
return if (user.domain == Config.configData.domain) { * @param followerId
follow(id, followerId) * @return リクエストが成功したか
true */
} else { suspend fun followRequest(id: Long, followerId: Long): Boolean
if (userRepository.findFollowRequestsById(id, followerId)) {
// do-nothing
} else {
apSendFollowService.sendFollow(SendFollowDto(follower, user))
}
false
}
}
override suspend fun follow(id: Long, followerId: Long) { /**
followerQueryService.appendFollower(id, followerId) * フォローする
if (userRepository.findFollowRequestsById(id, followerId)) { *
userRepository.deleteFollowRequest(id, followerId) * @param id
} * @param followerId
} */
suspend fun follow(id: Long, followerId: Long)
override suspend fun unfollow(id: Long, followerId: Long): Boolean { suspend fun unfollow(id: Long, followerId: Long): Boolean
followerQueryService.removeFollower(id, followerId)
return false
}
} }

View File

@ -0,0 +1,97 @@
package dev.usbharu.hideout.service.user
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto
import dev.usbharu.hideout.domain.model.hideout.dto.SendFollowDto
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.query.FollowerQueryService
import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.repository.UserRepository
import dev.usbharu.hideout.service.ap.APSendFollowService
import org.koin.core.annotation.Single
import java.time.Instant
@Single
class UserServiceImpl(
private val userRepository: UserRepository,
private val userAuthService: UserAuthService,
private val apSendFollowService: APSendFollowService,
private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService
) :
UserService {
override suspend fun usernameAlreadyUse(username: String): Boolean {
val findByNameAndDomain = userQueryService.findByNameAndDomain(username, Config.configData.domain)
return findByNameAndDomain != null
}
override 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/${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(),
createdAt = Instant.now()
)
return userRepository.save(userEntity)
}
override 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)
}
// TODO APのフォロー処理を作る
override suspend fun followRequest(id: Long, followerId: Long): Boolean {
val user = userRepository.findById(id) ?: throw UserNotFoundException("$id was not found.")
val follower = userRepository.findById(followerId) ?: throw UserNotFoundException("$followerId was not found.")
return if (user.domain == Config.configData.domain) {
follow(id, followerId)
true
} else {
if (userRepository.findFollowRequestsById(id, followerId)) {
// do-nothing
} else {
apSendFollowService.sendFollow(SendFollowDto(follower, user))
}
false
}
}
override suspend fun follow(id: Long, followerId: Long) {
followerQueryService.appendFollower(id, followerId)
if (userRepository.findFollowRequestsById(id, followerId)) {
userRepository.deleteFollowRequest(id, followerId)
}
}
override suspend fun unfollow(id: Long, followerId: Long): Boolean {
followerQueryService.removeFollower(id, followerId)
return false
}
}

View File

@ -18,9 +18,9 @@ import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.routing.api.internal.v1.auth import dev.usbharu.hideout.routing.api.internal.v1.auth
import dev.usbharu.hideout.service.api.UserAuthApiService import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.auth.IJwtService import dev.usbharu.hideout.service.auth.JwtService
import dev.usbharu.hideout.service.core.IMetaService import dev.usbharu.hideout.service.core.MetaService
import dev.usbharu.hideout.service.user.IUserAuthService import dev.usbharu.hideout.service.user.UserAuthService
import dev.usbharu.hideout.util.Base64Util import dev.usbharu.hideout.util.Base64Util
import dev.usbharu.hideout.util.JsonWebKeyUtil import dev.usbharu.hideout.util.JsonWebKeyUtil
import io.ktor.client.request.* import io.ktor.client.request.*
@ -51,7 +51,7 @@ class SecurityKtTest {
val userAuthService = mock<UserAuthApiService> { val userAuthService = mock<UserAuthApiService> {
onBlocking { login(eq("testUser"), eq("password")) } doReturn jwtToken onBlocking { login(eq("testUser"), eq("password")) } doReturn jwtToken
} }
val metaService = mock<IMetaService>() val metaService = mock<MetaService>()
val userQueryService = mock<UserQueryService> { val userQueryService = mock<UserQueryService> {
onBlocking { findByNameAndDomain(eq("testUser"), eq("example.com")) } doReturn User( onBlocking { findByNameAndDomain(eq("testUser"), eq("example.com")) } doReturn User(
id = 1L, id = 1L,
@ -93,12 +93,12 @@ class SecurityKtTest {
config = ApplicationConfig("empty.conf") config = ApplicationConfig("empty.conf")
} }
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper()) Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
mock<IUserAuthService> { mock<UserAuthService> {
onBlocking { verifyAccount(anyString(), anyString()) }.doReturn(false) onBlocking { verifyAccount(anyString(), anyString()) }.doReturn(false)
} }
val metaService = mock<IMetaService>() val metaService = mock<MetaService>()
mock<UserQueryService>() mock<UserQueryService>()
mock<IJwtService>() mock<JwtService>()
val jwkProvider = mock<JwkProvider>() val jwkProvider = mock<JwkProvider>()
val userAuthApiService = mock<UserAuthApiService> { val userAuthApiService = mock<UserAuthApiService> {
onBlocking { login(anyString(), anyString()) } doThrow InvalidUsernameOrPasswordException() onBlocking { login(anyString(), anyString()) } doThrow InvalidUsernameOrPasswordException()
@ -126,7 +126,7 @@ class SecurityKtTest {
config = ApplicationConfig("empty.conf") config = ApplicationConfig("empty.conf")
} }
Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper()) Config.configData = ConfigData(url = "http://example.com", objectMapper = jacksonObjectMapper())
val metaService = mock<IMetaService>() val metaService = mock<MetaService>()
val jwkProvider = mock<JwkProvider>() val jwkProvider = mock<JwkProvider>()
val userAuthApiService = mock<UserAuthApiService> { val userAuthApiService = mock<UserAuthApiService> {
onBlocking { login(anyString(), eq("InvalidPassword")) } doThrow InvalidUsernameOrPasswordException() onBlocking { login(anyString(), eq("InvalidPassword")) } doThrow InvalidUsernameOrPasswordException()
@ -247,7 +247,7 @@ class SecurityKtTest {
.withClaim("uid", 123456L) .withClaim("uid", 123456L)
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() }.doReturn( onBlocking { getJwtMeta() }.doReturn(
Jwt( Jwt(
kid, kid,
@ -308,7 +308,7 @@ class SecurityKtTest {
.withClaim("uid", 123345L) .withClaim("uid", 123345L)
.withExpiresAt(now.minus(30, ChronoUnit.MINUTES)) .withExpiresAt(now.minus(30, ChronoUnit.MINUTES))
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() }.doReturn( onBlocking { getJwtMeta() }.doReturn(
Jwt( Jwt(
kid, kid,
@ -367,7 +367,7 @@ class SecurityKtTest {
.withClaim("uid", 12345L) .withClaim("uid", 12345L)
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() }.doReturn( onBlocking { getJwtMeta() }.doReturn(
Jwt( Jwt(
kid, kid,
@ -426,7 +426,7 @@ class SecurityKtTest {
.withClaim("uid", null as Long?) .withClaim("uid", null as Long?)
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() }.doReturn( onBlocking { getJwtMeta() }.doReturn(
Jwt( Jwt(
kid, kid,
@ -484,7 +484,7 @@ class SecurityKtTest {
.withKeyId(kid.toString()) .withKeyId(kid.toString())
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
.sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey)) .sign(Algorithm.RSA256(rsaPublicKey, keyPair.private as RSAPrivateKey))
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() }.doReturn( onBlocking { getJwtMeta() }.doReturn(
Jwt( Jwt(
kid, kid,

View File

@ -6,7 +6,7 @@ import dev.usbharu.hideout.plugins.configureStatusPages
import dev.usbharu.hideout.service.ap.APService import dev.usbharu.hideout.service.ap.APService
import dev.usbharu.hideout.service.ap.APUserService import dev.usbharu.hideout.service.ap.APUserService
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.config.* import io.ktor.server.config.*
@ -47,7 +47,7 @@ class InboxRoutingKtTest {
val apService = mock<APService> { val apService = mock<APService> {
on { parseActivity(any()) } doThrow JsonParseException() on { parseActivity(any()) } doThrow JsonParseException()
} }
mock<IUserService>() mock<UserService>()
mock<APUserService>() mock<APUserService>()
application { application {
configureStatusPages() configureStatusPages()
@ -88,7 +88,7 @@ class InboxRoutingKtTest {
val apService = mock<APService> { val apService = mock<APService> {
on { parseActivity(any()) } doThrow JsonParseException() on { parseActivity(any()) } doThrow JsonParseException()
} }
mock<IUserService>() mock<UserService>()
mock<APUserService>() mock<APUserService>()
application { application {
configureStatusPages() configureStatusPages()

View File

@ -10,7 +10,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
import dev.usbharu.hideout.plugins.TOKEN_AUTH import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.plugins.configureSecurity import dev.usbharu.hideout.plugins.configureSecurity
import dev.usbharu.hideout.plugins.configureSerialization import dev.usbharu.hideout.plugins.configureSerialization
import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.PostApiService
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.statement.* import io.ktor.client.statement.*
import io.ktor.http.* import io.ktor.http.*
@ -60,7 +60,7 @@ class PostsTest {
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { onBlocking {
getAll( getAll(
since = anyOrNull(), since = anyOrNull(),
@ -135,7 +135,7 @@ class PostsTest {
) )
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { onBlocking {
getAll( getAll(
since = anyOrNull(), since = anyOrNull(),
@ -191,7 +191,7 @@ class PostsTest {
createdAt = Instant.now().toEpochMilli(), createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1" url = "https://example.com/posts/1"
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { getById(any(), anyOrNull()) } doReturn post onBlocking { getById(any(), anyOrNull()) } doReturn post
} }
application { application {
@ -230,7 +230,7 @@ class PostsTest {
createdAt = Instant.now().toEpochMilli(), createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/1" url = "https://example.com/posts/1"
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { getById(any(), isNotNull()) } doReturn post onBlocking { getById(any(), isNotNull()) } doReturn post
} }
val claim = mock<Claim> { val claim = mock<Claim> {
@ -273,7 +273,7 @@ class PostsTest {
val payload = mock<Payload> { val payload = mock<Payload> {
on { getClaim(eq("uid")) } doReturn claim on { getClaim(eq("uid")) } doReturn claim
} }
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { createPost(any(), any()) } doAnswer { onBlocking { createPost(any(), any()) } doAnswer {
val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0) val argument = it.getArgument<dev.usbharu.hideout.domain.model.hideout.form.Post>(0)
val userId = it.getArgument<Long>(1) val userId = it.getArgument<Long>(1)
@ -360,7 +360,7 @@ class PostsTest {
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { onBlocking {
getByUser( getByUser(
nameOrId = any(), nameOrId = any(),
@ -421,7 +421,7 @@ class PostsTest {
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { onBlocking {
getByUser( getByUser(
nameOrId = eq("test1"), nameOrId = eq("test1"),
@ -482,7 +482,7 @@ class PostsTest {
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { onBlocking {
getByUser( getByUser(
nameOrId = eq("test1@example.com"), nameOrId = eq("test1@example.com"),
@ -543,7 +543,7 @@ class PostsTest {
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { onBlocking {
getByUser( getByUser(
nameOrId = eq("@test1@example.com"), nameOrId = eq("@test1@example.com"),
@ -593,7 +593,7 @@ class PostsTest {
createdAt = Instant.now().toEpochMilli(), createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
} }
application { application {
@ -633,7 +633,7 @@ class PostsTest {
createdAt = Instant.now().toEpochMilli(), createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
} }
application { application {
@ -673,7 +673,7 @@ class PostsTest {
createdAt = Instant.now().toEpochMilli(), createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
} }
application { application {
@ -713,7 +713,7 @@ class PostsTest {
createdAt = Instant.now().toEpochMilli(), createdAt = Instant.now().toEpochMilli(),
url = "https://example.com/posts/2" url = "https://example.com/posts/2"
) )
val postService = mock<IPostApiService> { val postService = mock<PostApiService> {
onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post onBlocking { getById(eq(12345L), anyOrNull()) } doReturn post
} }
application { application {

View File

@ -10,8 +10,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.UserCreate
import dev.usbharu.hideout.plugins.TOKEN_AUTH import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.plugins.configureSecurity import dev.usbharu.hideout.plugins.configureSecurity
import dev.usbharu.hideout.plugins.configureSerialization import dev.usbharu.hideout.plugins.configureSerialization
import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.UserApiService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.statement.* import io.ktor.client.statement.*
import io.ktor.http.* import io.ktor.http.*
@ -53,7 +53,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
), ),
) )
val userService = mock<IUserApiService> { val userService = mock<UserApiService> {
onBlocking { findAll(anyOrNull(), anyOrNull()) } doReturn users onBlocking { findAll(anyOrNull(), anyOrNull()) } doReturn users
} }
application { application {
@ -77,7 +77,7 @@ class UsersTest {
config = ApplicationConfig("empty.conf") config = ApplicationConfig("empty.conf")
} }
val userCreateDto = UserCreate("test", "XXXXXXX") val userCreateDto = UserCreate("test", "XXXXXXX")
val userService = mock<IUserService> { val userService = mock<UserService> {
onBlocking { usernameAlreadyUse(any()) } doReturn false onBlocking { usernameAlreadyUse(any()) } doReturn false
onBlocking { createLocalUser(any()) } doReturn User( onBlocking { createLocalUser(any()) } doReturn User(
id = 12345, id = 12345,
@ -122,7 +122,7 @@ class UsersTest {
config = ApplicationConfig("empty.conf") config = ApplicationConfig("empty.conf")
} }
val userCreateDto = UserCreate("test", "XXXXXXX") val userCreateDto = UserCreate("test", "XXXXXXX")
val userService = mock<IUserService> { val userService = mock<UserService> {
onBlocking { usernameAlreadyUse(any()) } doReturn true onBlocking { usernameAlreadyUse(any()) } doReturn true
} }
application { application {
@ -157,7 +157,7 @@ class UsersTest {
"https://example.com/test", "https://example.com/test",
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findByAcct(any()) } doReturn userResponse onBlocking { findByAcct(any()) } doReturn userResponse
} }
application { application {
@ -190,7 +190,7 @@ class UsersTest {
"https://example.com/test", "https://example.com/test",
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findById(any()) } doReturn userResponse onBlocking { findById(any()) } doReturn userResponse
} }
application { application {
@ -223,7 +223,7 @@ class UsersTest {
"https://example.com/test", "https://example.com/test",
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findByAcct(any()) } doReturn userResponse onBlocking { findByAcct(any()) } doReturn userResponse
} }
application { application {
@ -256,7 +256,7 @@ class UsersTest {
"https://example.com/test", "https://example.com/test",
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findByAcct(any()) } doReturn userResponse onBlocking { findByAcct(any()) } doReturn userResponse
} }
application { application {
@ -301,7 +301,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findFollowersByAcct(any()) } doReturn followers onBlocking { findFollowersByAcct(any()) } doReturn followers
} }
application { application {
@ -346,7 +346,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findFollowersByAcct(any()) } doReturn followers onBlocking { findFollowersByAcct(any()) } doReturn followers
} }
application { application {
@ -391,7 +391,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findFollowers(any()) } doReturn followers onBlocking { findFollowers(any()) } doReturn followers
} }
application { application {
@ -423,7 +423,7 @@ class UsersTest {
on { getClaim(eq("uid")) } doReturn claim on { getClaim(eq("uid")) } doReturn claim
} }
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findByAcct(any()) } doReturn UserResponse( onBlocking { findByAcct(any()) } doReturn UserResponse(
"1235", "1235",
"follower1", "follower1",
@ -434,7 +434,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
} }
val userService = mock<IUserService> { val userService = mock<UserService> {
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn true onBlocking { followRequest(eq(1235), eq(1234)) } doReturn true
} }
application { application {
@ -473,7 +473,7 @@ class UsersTest {
on { getClaim(eq("uid")) } doReturn claim on { getClaim(eq("uid")) } doReturn claim
} }
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findByAcct(any()) } doReturn UserResponse( onBlocking { findByAcct(any()) } doReturn UserResponse(
"1235", "1235",
"follower1", "follower1",
@ -484,7 +484,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
} }
val userService = mock<IUserService> { val userService = mock<UserService> {
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false
} }
application { application {
@ -523,7 +523,7 @@ class UsersTest {
on { getClaim(eq("uid")) } doReturn claim on { getClaim(eq("uid")) } doReturn claim
} }
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findById(any()) } doReturn UserResponse( onBlocking { findById(any()) } doReturn UserResponse(
"1235", "1235",
"follower1", "follower1",
@ -534,7 +534,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
} }
val userService = mock<IUserService> { val userService = mock<UserService> {
onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false onBlocking { followRequest(eq(1235), eq(1234)) } doReturn false
} }
application { application {
@ -586,7 +586,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findFollowingsByAcct(any()) } doReturn followers onBlocking { findFollowingsByAcct(any()) } doReturn followers
} }
application { application {
@ -631,7 +631,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findFollowingsByAcct(any()) } doReturn followers onBlocking { findFollowingsByAcct(any()) } doReturn followers
} }
application { application {
@ -676,7 +676,7 @@ class UsersTest {
Instant.now().toEpochMilli() Instant.now().toEpochMilli()
) )
) )
val userApiService = mock<IUserApiService> { val userApiService = mock<UserApiService> {
onBlocking { findFollowings(any()) } doReturn followers onBlocking { findFollowings(any()) } doReturn followers
} }
application { application {

View File

@ -11,7 +11,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.job.JobQueueParentService import dev.usbharu.hideout.service.job.JobQueueParentService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.UserService
import io.ktor.client.* import io.ktor.client.*
import io.ktor.client.engine.mock.* import io.ktor.client.engine.mock.*
import kjob.core.dsl.ScheduleContext import kjob.core.dsl.ScheduleContext
@ -128,7 +128,7 @@ class APReceiveFollowServiceImplTest {
) )
} }
val userService = mock<IUserService> { val userService = mock<UserService> {
onBlocking { followRequest(any(), any()) } doReturn false onBlocking { followRequest(any(), any()) } doReturn false
} }
val activityPubFollowService = val activityPubFollowService =

View File

@ -14,8 +14,8 @@ import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
import dev.usbharu.hideout.exception.InvalidRefreshTokenException import dev.usbharu.hideout.exception.InvalidRefreshTokenException
import dev.usbharu.hideout.query.JwtRefreshTokenQueryService import dev.usbharu.hideout.query.JwtRefreshTokenQueryService
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository import dev.usbharu.hideout.repository.JwtRefreshTokenRepository
import dev.usbharu.hideout.service.core.IMetaService import dev.usbharu.hideout.service.core.MetaService
import dev.usbharu.hideout.util.Base64Util import dev.usbharu.hideout.util.Base64Util
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -42,14 +42,14 @@ class JwtServiceImplTest {
keyPairGenerator.initialize(2048) keyPairGenerator.initialize(2048)
val generateKeyPair = keyPairGenerator.generateKeyPair() val generateKeyPair = keyPairGenerator.generateKeyPair()
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() } doReturn Jwt( onBlocking { getJwtMeta() } doReturn Jwt(
kid, kid,
Base64Util.encode(generateKeyPair.private.encoded), Base64Util.encode(generateKeyPair.private.encoded),
Base64Util.encode(generateKeyPair.public.encoded) Base64Util.encode(generateKeyPair.public.encoded)
) )
} }
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { val refreshTokenRepository = mock<JwtRefreshTokenRepository> {
onBlocking { generateId() } doReturn 1L onBlocking { generateId() } doReturn 1L
} }
val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, mock(), mock()) val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, mock(), mock())
@ -94,7 +94,7 @@ class JwtServiceImplTest {
keyPairGenerator.initialize(2048) keyPairGenerator.initialize(2048)
val generateKeyPair = keyPairGenerator.generateKeyPair() val generateKeyPair = keyPairGenerator.generateKeyPair()
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { val refreshTokenRepository = mock<JwtRefreshTokenRepository> {
onBlocking { generateId() } doReturn 2L onBlocking { generateId() } doReturn 2L
} }
@ -123,7 +123,7 @@ class JwtServiceImplTest {
createdAt = Instant.now() createdAt = Instant.now()
) )
} }
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() } doReturn Jwt( onBlocking { getJwtMeta() } doReturn Jwt(
kid, kid,
Base64Util.encode(generateKeyPair.private.encoded), Base64Util.encode(generateKeyPair.private.encoded),
@ -160,7 +160,7 @@ class JwtServiceImplTest {
keyPairGenerator.initialize(2048) keyPairGenerator.initialize(2048)
val generateKeyPair = keyPairGenerator.generateKeyPair() val generateKeyPair = keyPairGenerator.generateKeyPair()
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() } doReturn Jwt( onBlocking { getJwtMeta() } doReturn Jwt(
kid, kid,
Base64Util.encode(generateKeyPair.private.encoded), Base64Util.encode(generateKeyPair.private.encoded),
@ -187,7 +187,7 @@ class JwtServiceImplTest {
keyPairGenerator.initialize(2048) keyPairGenerator.initialize(2048)
val generateKeyPair = keyPairGenerator.generateKeyPair() val generateKeyPair = keyPairGenerator.generateKeyPair()
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() } doReturn Jwt( onBlocking { getJwtMeta() } doReturn Jwt(
kid, kid,
Base64Util.encode(generateKeyPair.private.encoded), Base64Util.encode(generateKeyPair.private.encoded),
@ -214,7 +214,7 @@ class JwtServiceImplTest {
keyPairGenerator.initialize(2048) keyPairGenerator.initialize(2048)
val generateKeyPair = keyPairGenerator.generateKeyPair() val generateKeyPair = keyPairGenerator.generateKeyPair()
val metaService = mock<IMetaService> { val metaService = mock<MetaService> {
onBlocking { getJwtMeta() } doReturn Jwt( onBlocking { getJwtMeta() } doReturn Jwt(
kid, kid,
Base64Util.encode(generateKeyPair.private.encoded), Base64Util.encode(generateKeyPair.private.encoded),

View File

@ -5,7 +5,7 @@ package dev.usbharu.hideout.service.core
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.domain.model.hideout.entity.Meta
import dev.usbharu.hideout.exception.NotInitException import dev.usbharu.hideout.exception.NotInitException
import dev.usbharu.hideout.repository.IMetaRepository import dev.usbharu.hideout.repository.MetaRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -19,7 +19,7 @@ class MetaServiceImplTest {
@Test @Test
fun `getMeta メタデータを取得できる`() = runTest { fun `getMeta メタデータを取得できる`() = runTest {
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda")) val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { get() } doReturn meta onBlocking { get() } doReturn meta
} }
val metaService = MetaServiceImpl(metaRepository, TestTransaction) val metaService = MetaServiceImpl(metaRepository, TestTransaction)
@ -29,7 +29,7 @@ class MetaServiceImplTest {
@Test @Test
fun `getMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest { fun `getMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest {
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { get() } doReturn null onBlocking { get() } doReturn null
} }
val metaService = MetaServiceImpl(metaRepository, TestTransaction) val metaService = MetaServiceImpl(metaRepository, TestTransaction)
@ -39,7 +39,7 @@ class MetaServiceImplTest {
@Test @Test
fun `updateMeta メタデータを保存できる`() = runTest { fun `updateMeta メタデータを保存できる`() = runTest {
val meta = Meta("1.0.1", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda")) val meta = Meta("1.0.1", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { save(any()) } doReturn Unit onBlocking { save(any()) } doReturn Unit
} }
val metaServiceImpl = MetaServiceImpl(metaRepository, TestTransaction) val metaServiceImpl = MetaServiceImpl(metaRepository, TestTransaction)
@ -53,7 +53,7 @@ class MetaServiceImplTest {
@Test @Test
fun `getJwtMeta Jwtメタデータを取得できる`() = runTest { fun `getJwtMeta Jwtメタデータを取得できる`() = runTest {
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda")) val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "sdfsdjk", "adafda"))
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { get() } doReturn meta onBlocking { get() } doReturn meta
} }
val metaService = MetaServiceImpl(metaRepository, TestTransaction) val metaService = MetaServiceImpl(metaRepository, TestTransaction)
@ -63,7 +63,7 @@ class MetaServiceImplTest {
@Test @Test
fun `getJwtMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest { fun `getJwtMeta メタデータが無いときはNotInitExceptionがthrowされる`() = runTest {
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { get() } doReturn null onBlocking { get() } doReturn null
} }
val metaService = MetaServiceImpl(metaRepository, TestTransaction) val metaService = MetaServiceImpl(metaRepository, TestTransaction)

View File

@ -4,7 +4,7 @@ package dev.usbharu.hideout.service.core
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
import dev.usbharu.hideout.domain.model.hideout.entity.Meta import dev.usbharu.hideout.domain.model.hideout.entity.Meta
import dev.usbharu.hideout.repository.IMetaRepository import dev.usbharu.hideout.repository.MetaRepository
import dev.usbharu.hideout.util.ServerUtil import dev.usbharu.hideout.util.ServerUtil
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -17,7 +17,7 @@ import kotlin.test.assertEquals
class ServerInitialiseServiceImplTest { class ServerInitialiseServiceImplTest {
@Test @Test
fun `init メタデータが無いときに初期化を実行する`() = runTest { fun `init メタデータが無いときに初期化を実行する`() = runTest {
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { get() } doReturn null onBlocking { get() } doReturn null
onBlocking { save(any()) } doReturn Unit onBlocking { save(any()) } doReturn Unit
} }
@ -30,7 +30,7 @@ class ServerInitialiseServiceImplTest {
@Test @Test
fun `init メタデータが存在して同じバージョンのときは何もしない`() = runTest { fun `init メタデータが存在して同じバージョンのときは何もしない`() = runTest {
val meta = Meta(ServerUtil.getImplementationVersion(), Jwt(UUID.randomUUID(), "aaafafd", "afafasdf")) val meta = Meta(ServerUtil.getImplementationVersion(), Jwt(UUID.randomUUID(), "aaafafd", "afafasdf"))
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { get() } doReturn meta onBlocking { get() } doReturn meta
} }
val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository, TestTransaction) val serverInitialiseServiceImpl = ServerInitialiseServiceImpl(metaRepository, TestTransaction)
@ -41,7 +41,7 @@ class ServerInitialiseServiceImplTest {
@Test @Test
fun `init メタデータが存在して違うバージョンのときはバージョンを変更する`() = runTest { fun `init メタデータが存在して違うバージョンのときはバージョンを変更する`() = runTest {
val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "aaafafd", "afafasdf")) val meta = Meta("1.0.0", Jwt(UUID.randomUUID(), "aaafafd", "afafasdf"))
val metaRepository = mock<IMetaRepository> { val metaRepository = mock<MetaRepository> {
onBlocking { get() } doReturn meta onBlocking { get() } doReturn meta
onBlocking { save(any()) } doReturn Unit onBlocking { save(any()) } doReturn Unit
} }

View File

@ -6,7 +6,7 @@ import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.config.ConfigData import dev.usbharu.hideout.config.ConfigData
import dev.usbharu.hideout.domain.model.hideout.dto.RemoteUserCreateDto 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.dto.UserCreateDto
import dev.usbharu.hideout.repository.IUserRepository import dev.usbharu.hideout.repository.UserRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@ -20,15 +20,15 @@ class UserServiceTest {
@Test @Test
fun `createLocalUser ローカルユーザーを作成できる`() = runTest { fun `createLocalUser ローカルユーザーを作成できる`() = runTest {
Config.configData = ConfigData(domain = "example.com", url = "https://example.com") Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
val userRepository = mock<IUserRepository> { val userRepository = mock<UserRepository> {
onBlocking { nextId() } doReturn 110001L onBlocking { nextId() } doReturn 110001L
} }
val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair() val generateKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair()
val userAuthService = mock<IUserAuthService> { val userAuthService = mock<UserAuthService> {
onBlocking { hash(anyString()) } doReturn "hashedPassword" onBlocking { hash(anyString()) } doReturn "hashedPassword"
onBlocking { generateKeyPair() } doReturn generateKeyPair onBlocking { generateKeyPair() } doReturn generateKeyPair
} }
val userService = UserService(userRepository, userAuthService, mock(), mock(), mock()) val userService = UserServiceImpl(userRepository, userAuthService, mock(), mock(), mock())
userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test")) userService.createLocalUser(UserCreateDto("test", "testUser", "XXXXXXXXXXXXX", "test"))
verify(userRepository, times(1)).save(any()) verify(userRepository, times(1)).save(any())
argumentCaptor<dev.usbharu.hideout.domain.model.hideout.entity.User> { argumentCaptor<dev.usbharu.hideout.domain.model.hideout.entity.User> {
@ -51,10 +51,10 @@ class UserServiceTest {
fun `createRemoteUser リモートユーザーを作成できる`() = runTest { fun `createRemoteUser リモートユーザーを作成できる`() = runTest {
Config.configData = ConfigData(domain = "example.com", url = "https://example.com") Config.configData = ConfigData(domain = "example.com", url = "https://example.com")
val userRepository = mock<IUserRepository> { val userRepository = mock<UserRepository> {
onBlocking { nextId() } doReturn 113345L onBlocking { nextId() } doReturn 113345L
} }
val userService = UserService(userRepository, mock(), mock(), mock(), mock()) val userService = UserServiceImpl(userRepository, mock(), mock(), mock(), mock())
val user = RemoteUserCreateDto( val user = RemoteUserCreateDto(
"test", "test",
"example.com", "example.com",