feat: 起動からユーザー作成、ログインまでのトランザクションを修正

This commit is contained in:
usbharu 2023-08-11 12:22:56 +09:00
parent de79c91710
commit 3f96397768
18 changed files with 179 additions and 94 deletions

View File

@ -14,14 +14,13 @@ import dev.usbharu.hideout.domain.model.job.ReceiveFollowJob
import dev.usbharu.hideout.plugins.* import dev.usbharu.hideout.plugins.*
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.repository.IUserRepository
import dev.usbharu.hideout.routing.register import dev.usbharu.hideout.routing.register
import dev.usbharu.hideout.service.activitypub.ActivityPubService import dev.usbharu.hideout.service.activitypub.ActivityPubService
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.IPostApiService
import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.IUserApiService
import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import dev.usbharu.hideout.service.auth.IJwtService
import dev.usbharu.hideout.service.core.IMetaService import dev.usbharu.hideout.service.core.IMetaService
import dev.usbharu.hideout.service.core.IServerInitialiseService import dev.usbharu.hideout.service.core.IServerInitialiseService
import dev.usbharu.hideout.service.core.IdGenerateService import dev.usbharu.hideout.service.core.IdGenerateService
@ -29,7 +28,6 @@ import dev.usbharu.hideout.service.core.TwitterSnowflakeIdGenerateService
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.reaction.IReactionService import dev.usbharu.hideout.service.reaction.IReactionService
import dev.usbharu.hideout.service.user.IUserAuthService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.IUserService
import dev.usbharu.kjob.exposed.ExposedKJob import dev.usbharu.kjob.exposed.ExposedKJob
import io.ktor.client.* import io.ktor.client.*
@ -97,6 +95,7 @@ fun Application.parent() {
} }
} }
configureKoin(module, HideoutModule().module) configureKoin(module, HideoutModule().module)
configureStatusPages()
runBlocking { runBlocking {
inject<IServerInitialiseService>().value.init() inject<IServerInitialiseService>().value.init()
} }
@ -105,7 +104,7 @@ fun Application.parent() {
configureStaticRouting() configureStaticRouting()
configureMonitoring() configureMonitoring()
configureSerialization() configureSerialization()
register(inject<IUserService>().value) register(inject<IUserApiService>().value)
configureSecurity( configureSecurity(
inject<JwkProvider>().value, inject<JwkProvider>().value,
@ -119,11 +118,9 @@ fun Application.parent() {
postService = inject<IPostApiService>().value, postService = inject<IPostApiService>().value,
userApiService = inject<IUserApiService>().value, userApiService = inject<IUserApiService>().value,
reactionService = inject<IReactionService>().value, reactionService = inject<IReactionService>().value,
userAuthService = inject<IUserAuthService>().value,
userRepository = inject<IUserRepository>().value,
jwtService = inject<IJwtService>().value,
userQueryService = inject<UserQueryService>().value, userQueryService = inject<UserQueryService>().value,
followerQueryService = inject<FollowerQueryService>().value followerQueryService = inject<FollowerQueryService>().value,
userAuthApiService = inject<UserAuthApiService>().value
) )
} }

View File

@ -0,0 +1,14 @@
package dev.usbharu.hideout.exception
class InvalidUsernameOrPasswordException : Exception {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(
message,
cause,
enableSuppression,
writableStackTrace
)
}

View File

@ -0,0 +1,14 @@
package dev.usbharu.hideout.exception
class UsernameAlreadyExistException : Exception {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(
message,
cause,
enableSuppression,
writableStackTrace
)
}

View File

@ -2,7 +2,6 @@ package dev.usbharu.hideout.plugins
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.repository.IUserRepository
import dev.usbharu.hideout.routing.activitypub.inbox import dev.usbharu.hideout.routing.activitypub.inbox
import dev.usbharu.hideout.routing.activitypub.outbox import dev.usbharu.hideout.routing.activitypub.outbox
import dev.usbharu.hideout.routing.activitypub.usersAP import dev.usbharu.hideout.routing.activitypub.usersAP
@ -14,10 +13,9 @@ import dev.usbharu.hideout.service.activitypub.ActivityPubService
import dev.usbharu.hideout.service.activitypub.ActivityPubUserService import dev.usbharu.hideout.service.activitypub.ActivityPubUserService
import dev.usbharu.hideout.service.api.IPostApiService import dev.usbharu.hideout.service.api.IPostApiService
import dev.usbharu.hideout.service.api.IUserApiService import dev.usbharu.hideout.service.api.IUserApiService
import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService import dev.usbharu.hideout.service.auth.HttpSignatureVerifyService
import dev.usbharu.hideout.service.auth.IJwtService
import dev.usbharu.hideout.service.reaction.IReactionService import dev.usbharu.hideout.service.reaction.IReactionService
import dev.usbharu.hideout.service.user.IUserAuthService
import dev.usbharu.hideout.service.user.IUserService import dev.usbharu.hideout.service.user.IUserService
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.plugins.autohead.* import io.ktor.server.plugins.autohead.*
@ -32,11 +30,9 @@ fun Application.configureRouting(
postService: IPostApiService, postService: IPostApiService,
userApiService: IUserApiService, userApiService: IUserApiService,
reactionService: IReactionService, reactionService: IReactionService,
userAuthService: IUserAuthService,
userRepository: IUserRepository,
jwtService: IJwtService,
userQueryService: UserQueryService, userQueryService: UserQueryService,
followerQueryService: FollowerQueryService followerQueryService: FollowerQueryService,
userAuthApiService: UserAuthApiService
) { ) {
install(AutoHeadResponse) install(AutoHeadResponse)
routing { routing {
@ -47,7 +43,7 @@ fun Application.configureRouting(
route("/api/internal/v1") { route("/api/internal/v1") {
posts(postService, reactionService) posts(postService, reactionService)
users(userService, userApiService) users(userService, userApiService)
auth(userAuthService, jwtService, userQueryService) auth(userAuthApiService)
} }
} }
} }

View File

@ -1,5 +1,6 @@
package dev.usbharu.hideout.plugins package dev.usbharu.hideout.plugins
import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.plugins.statuspages.* import io.ktor.server.plugins.statuspages.*
@ -10,8 +11,12 @@ fun Application.configureStatusPages() {
exception<IllegalArgumentException> { call, cause -> exception<IllegalArgumentException> { call, cause ->
call.respondText(text = "400: $cause", status = HttpStatusCode.BadRequest) call.respondText(text = "400: $cause", status = HttpStatusCode.BadRequest)
} }
exception<InvalidUsernameOrPasswordException> { call, _ ->
call.respond(401)
}
exception<Throwable> { call, cause -> exception<Throwable> { call, cause ->
call.respondText(text = "500: $cause", status = HttpStatusCode.InternalServerError) call.respondText(text = "500: ${cause.stackTraceToString()}", status = HttpStatusCode.InternalServerError)
cause.printStackTrace()
} }
} }
} }

View File

@ -9,4 +9,5 @@ interface UserQueryService {
suspend fun findByNameAndDomain(name: String, domain: String): User suspend fun findByNameAndDomain(name: String, domain: String): User
suspend fun findByUrl(url: String): User suspend fun findByUrl(url: String): User
suspend fun findByIds(ids: List<Long>): List<User> suspend fun findByIds(ids: List<Long>): List<User>
suspend fun existByNameAndDomain(name: String, domain: String): Boolean
} }

View File

@ -24,4 +24,8 @@ class UserQueryServiceImpl : UserQueryService {
override suspend fun findByIds(ids: List<Long>): List<User> = override suspend fun findByIds(ids: List<Long>): List<User> =
Users.select { Users.id inList ids }.map { it.toUser() } Users.select { Users.id inList ids }.map { it.toUser() }
override suspend fun existByNameAndDomain(name: String, domain: String): Boolean {
return Users.select { Users.name eq name and (Users.domain eq domain) }.empty().not()
}
} }

View File

@ -1,7 +1,6 @@
package dev.usbharu.hideout.routing package dev.usbharu.hideout.routing
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto import dev.usbharu.hideout.service.api.IUserApiService
import dev.usbharu.hideout.service.user.IUserService
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.*
@ -9,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(userService: IUserService) { fun Application.register(userApiService: IUserApiService) {
routing { routing {
get("/register") { get("/register") {
val principal = call.principal<UserIdPrincipal>() val principal = call.principal<UserIdPrincipal>()
@ -37,10 +36,7 @@ fun Application.register(userService: IUserService) {
val parameters = call.receiveParameters() val parameters = call.receiveParameters()
val password = parameters["password"] ?: return@post call.respondRedirect("/register") val password = parameters["password"] ?: return@post call.respondRedirect("/register")
val username = parameters["username"] ?: return@post call.respondRedirect("/register") val username = parameters["username"] ?: return@post call.respondRedirect("/register")
if (userService.usernameAlreadyUse(username)) { userApiService.createUser(username, password)
return@post call.respondRedirect("/register")
}
userService.createLocalUser(UserCreateDto(username, username, "", password))
call.respondRedirect("/users/$username") call.respondRedirect("/users/$username")
} }
} }

View File

@ -13,6 +13,7 @@ import io.ktor.server.application.*
import io.ktor.server.request.* 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.*
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
fun Routing.usersAP( fun Routing.usersAP(
activityPubUserService: ActivityPubUserService, activityPubUserService: ActivityPubUserService,
@ -32,14 +33,21 @@ fun Routing.usersAP(
) )
} }
get { get {
// TODO: 暫定処置なので治す
newSuspendedTransaction {
val userEntity = userQueryService.findByNameAndDomain( val userEntity = userQueryService.findByNameAndDomain(
call.parameters["name"] ?: throw ParameterNotExistException("Parameter(name='name') does not exist."), call.parameters["name"]
?: throw ParameterNotExistException("Parameter(name='name') does not exist."),
Config.configData.domain Config.configData.domain
) )
call.respondText(userEntity.toString() + "\n" + followerQueryService.findFollowersById(userEntity.id)) call.respondText(userEntity.toString() + "\n" + followerQueryService.findFollowersById(userEntity.id))
} }
} }
} }
}
class ContentTypeRouteSelector(private vararg val contentType: ContentType) : RouteSelector() { class ContentTypeRouteSelector(private vararg val contentType: ContentType) : RouteSelector() {
override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation { override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation {

View File

@ -1,13 +1,9 @@
package dev.usbharu.hideout.routing.api.internal.v1 package dev.usbharu.hideout.routing.api.internal.v1
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
import dev.usbharu.hideout.domain.model.hideout.form.UserLogin import dev.usbharu.hideout.domain.model.hideout.form.UserLogin
import dev.usbharu.hideout.plugins.TOKEN_AUTH import dev.usbharu.hideout.plugins.TOKEN_AUTH
import dev.usbharu.hideout.query.UserQueryService import dev.usbharu.hideout.service.api.UserAuthApiService
import dev.usbharu.hideout.service.auth.IJwtService
import dev.usbharu.hideout.service.user.IUserAuthService
import io.ktor.http.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.auth.* import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.* import io.ktor.server.auth.jwt.*
@ -15,26 +11,15 @@ 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 Route.auth( fun Route.auth(userAuthApiService: UserAuthApiService) {
userAuthService: IUserAuthService,
jwtService: IJwtService,
userQueryService: UserQueryService
) {
post("/login") { post("/login") {
val loginUser = call.receive<UserLogin>() val loginUser = call.receive<UserLogin>()
val check = userAuthService.verifyAccount(loginUser.username, loginUser.password) return@post call.respond(userAuthApiService.login(loginUser.username, loginUser.password))
if (check.not()) {
return@post call.respond(HttpStatusCode.Unauthorized)
}
val user = userQueryService.findByNameAndDomain(loginUser.username, Config.configData.domain)
return@post call.respond(jwtService.createToken(user))
} }
post("/refresh-token") { post("/refresh-token") {
val refreshToken = call.receive<RefreshToken>() val refreshToken = call.receive<RefreshToken>()
return@post call.respond(jwtService.refreshToken(refreshToken)) return@post call.respond(userAuthApiService.refreshToken(refreshToken))
} }
authenticate(TOKEN_AUTH) { authenticate(TOKEN_AUTH) {
get("/auth-check") { get("/auth-check") {

View File

@ -19,4 +19,6 @@ interface IUserApiService {
suspend fun findFollowersByAcct(acct: Acct): List<UserResponse> suspend fun findFollowersByAcct(acct: Acct): List<UserResponse>
suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse> suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse>
suspend fun createUser(username: String, password: String): UserResponse
} }

View File

@ -20,6 +20,7 @@ class PostApiServiceImpl(
private val postResponseQueryService: PostResponseQueryService private val postResponseQueryService: PostResponseQueryService
) : IPostApiService { ) : IPostApiService {
override suspend fun createPost(postForm: FormPost, userId: Long): PostResponse { override suspend fun createPost(postForm: FormPost, userId: Long): PostResponse {
return newSuspendedTransaction {
val createdPost = postService.createLocal( val createdPost = postService.createLocal(
PostCreateDto( PostCreateDto(
text = postForm.text, text = postForm.text,
@ -31,7 +32,8 @@ class PostApiServiceImpl(
) )
) )
val creator = userRepository.findById(userId) val creator = userRepository.findById(userId)
return PostResponse.from(createdPost, creator!!) PostResponse.from(createdPost, creator!!)
}
} }
@Suppress("InjectDispatcher") @Suppress("InjectDispatcher")
@ -47,8 +49,16 @@ class PostApiServiceImpl(
maxId: Long?, maxId: Long?,
limit: Int?, limit: Int?,
userId: Long? userId: Long?
): List<PostResponse> = ): List<PostResponse> = newSuspendedTransaction {
postResponseQueryService.findAll(since?.toEpochMilli(), until?.toEpochMilli(), minId, maxId, limit, userId) postResponseQueryService.findAll(
since?.toEpochMilli(),
until?.toEpochMilli(),
minId,
maxId,
limit,
userId
)
}
override suspend fun getByUser( override suspend fun getByUser(
nameOrId: String, nameOrId: String,

View File

@ -2,16 +2,21 @@ package dev.usbharu.hideout.service.api
import dev.usbharu.hideout.config.Config import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.Acct import dev.usbharu.hideout.domain.model.Acct
import dev.usbharu.hideout.domain.model.hideout.dto.UserCreateDto
import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse import dev.usbharu.hideout.domain.model.hideout.dto.UserResponse
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.user.IUserService
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import kotlin.math.min import kotlin.math.min
@Single @Single
class UserApiServiceImpl( class UserApiServiceImpl(
private val userQueryService: UserQueryService, private val userQueryService: UserQueryService,
private val followerQueryService: FollowerQueryService private val followerQueryService: FollowerQueryService,
private val userService: IUserService
) : IUserApiService { ) : IUserApiService {
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) }
@ -37,4 +42,13 @@ class UserApiServiceImpl(
override suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse> = override suspend fun findFollowingsByAcct(acct: Acct): List<UserResponse> =
followerQueryService.findFollowingByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain) followerQueryService.findFollowingByNameAndDomain(acct.username, acct.domain ?: Config.configData.domain)
.map { UserResponse.from(it) } .map { UserResponse.from(it) }
override suspend fun createUser(username: String, password: String): UserResponse {
return newSuspendedTransaction {
if (userQueryService.existByNameAndDomain(username, Config.configData.domain)) {
throw UsernameAlreadyExistException()
}
UserResponse.from(userService.createLocalUser(UserCreateDto(username, username, "", password)))
}
}
} }

View File

@ -0,0 +1,9 @@
package dev.usbharu.hideout.service.api
import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
interface UserAuthApiService {
suspend fun login(username: String, password: String): JwtToken
suspend fun refreshToken(refreshToken: RefreshToken): JwtToken
}

View File

@ -0,0 +1,34 @@
package dev.usbharu.hideout.service.api
import dev.usbharu.hideout.config.Config
import dev.usbharu.hideout.domain.model.hideout.dto.JwtToken
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken
import dev.usbharu.hideout.exception.InvalidUsernameOrPasswordException
import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.service.auth.IJwtService
import dev.usbharu.hideout.service.user.UserAuthService
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.koin.core.annotation.Single
@Single
class UserAuthApiServiceImpl(
private val userAuthService: UserAuthService,
private val userQueryService: UserQueryService,
private val jwtService: IJwtService
) : UserAuthApiService {
override suspend fun login(username: String, password: String): JwtToken {
return newSuspendedTransaction {
if (userAuthService.verifyAccount(username, password).not()) {
throw InvalidUsernameOrPasswordException()
}
val user = userQueryService.findByNameAndDomain(username, Config.configData.domain)
jwtService.createToken(user)
}
}
override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken {
return newSuspendedTransaction {
jwtService.refreshToken(refreshToken)
}
}
}

View File

@ -13,9 +13,7 @@ import dev.usbharu.hideout.query.UserQueryService
import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository import dev.usbharu.hideout.repository.IJwtRefreshTokenRepository
import dev.usbharu.hideout.service.core.IMetaService import dev.usbharu.hideout.service.core.IMetaService
import dev.usbharu.hideout.util.RsaUtil import dev.usbharu.hideout.util.RsaUtil
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import java.time.Instant import java.time.Instant
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
@ -30,23 +28,16 @@ class JwtServiceImpl(
private val refreshTokenQueryService: JwtRefreshTokenQueryService private val refreshTokenQueryService: JwtRefreshTokenQueryService
) : IJwtService { ) : IJwtService {
private val privateKey by lazy { private val privateKey = runBlocking {
CoroutineScope(Dispatchers.IO).async {
RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey) RsaUtil.decodeRsaPrivateKey(metaService.getJwtMeta().privateKey)
} }
}
private val publicKey by lazy { private val publicKey = runBlocking {
CoroutineScope(Dispatchers.IO).async {
RsaUtil.decodeRsaPublicKey(metaService.getJwtMeta().publicKey) RsaUtil.decodeRsaPublicKey(metaService.getJwtMeta().publicKey)
} }
}
private val keyId by lazy { private val keyId = runBlocking { metaService.getJwtMeta().kid }
CoroutineScope(Dispatchers.IO).async {
metaService.getJwtMeta().kid
}
}
@Suppress("MagicNumber") @Suppress("MagicNumber")
override suspend fun createToken(user: User): JwtToken { override suspend fun createToken(user: User): JwtToken {
@ -54,10 +45,10 @@ class JwtServiceImpl(
val token = JWT.create() val token = JWT.create()
.withAudience("${Config.configData.url}/users/${user.name}") .withAudience("${Config.configData.url}/users/${user.name}")
.withIssuer(Config.configData.url) .withIssuer(Config.configData.url)
.withKeyId(keyId.await().toString()) .withKeyId(keyId.toString())
.withClaim("uid", user.id) .withClaim("uid", user.id)
.withExpiresAt(now.plus(30, ChronoUnit.MINUTES)) .withExpiresAt(now.plus(30, ChronoUnit.MINUTES))
.sign(Algorithm.RSA256(publicKey.await(), privateKey.await())) .sign(Algorithm.RSA256(publicKey, privateKey))
val jwtRefreshToken = JwtRefreshToken( val jwtRefreshToken = JwtRefreshToken(
id = refreshTokenRepository.generateId(), id = refreshTokenRepository.generateId(),

View File

@ -4,13 +4,15 @@ 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.IMetaRepository
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
@Single @Single
class MetaServiceImpl(private val metaRepository: IMetaRepository) : IMetaService { class MetaServiceImpl(private val metaRepository: IMetaRepository) : IMetaService {
override suspend fun getMeta(): Meta = metaRepository.get() ?: throw NotInitException("Meta is null") override suspend fun getMeta(): Meta =
newSuspendedTransaction { metaRepository.get() ?: throw NotInitException("Meta is null") }
override suspend fun updateMeta(meta: Meta) { override suspend fun updateMeta(meta: Meta) = newSuspendedTransaction {
metaRepository.save(meta) metaRepository.save(meta)
} }

View File

@ -4,6 +4,7 @@ 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.IMetaRepository
import dev.usbharu.hideout.util.ServerUtil import dev.usbharu.hideout.util.ServerUtil
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -16,13 +17,14 @@ class ServerInitialiseServiceImpl(private val metaRepository: IMetaRepository) :
val logger: Logger = LoggerFactory.getLogger(ServerInitialiseServiceImpl::class.java) val logger: Logger = LoggerFactory.getLogger(ServerInitialiseServiceImpl::class.java)
override suspend fun init() { override suspend fun init() {
newSuspendedTransaction {
val savedMeta = metaRepository.get() val savedMeta = metaRepository.get()
val implementationVersion = ServerUtil.getImplementationVersion() val implementationVersion = ServerUtil.getImplementationVersion()
if (wasInitialised(savedMeta).not()) { if (wasInitialised(savedMeta).not()) {
logger.info("Start Initialise") logger.info("Start Initialise")
initialise(implementationVersion) initialise(implementationVersion)
logger.info("Finish Initialise") logger.info("Finish Initialise")
return return@newSuspendedTransaction
} }
if (isVersionChanged(requireNotNull(savedMeta))) { if (isVersionChanged(requireNotNull(savedMeta))) {
@ -30,6 +32,7 @@ class ServerInitialiseServiceImpl(private val metaRepository: IMetaRepository) :
updateVersion(savedMeta, implementationVersion) updateVersion(savedMeta, implementationVersion)
} }
} }
}
private fun wasInitialised(meta: Meta?): Boolean { private fun wasInitialised(meta: Meta?): Boolean {
logger.debug("Initialise checking...") logger.debug("Initialise checking...")