refactor: 不要なコードを削除

This commit is contained in:
usbharu 2023-08-11 11:25:26 +09:00
parent 8654c627d1
commit de79c91710
8 changed files with 129 additions and 131 deletions

View File

@ -0,0 +1,13 @@
package dev.usbharu.hideout.query
import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
interface JwtRefreshTokenQueryService {
suspend fun findById(id: Long): JwtRefreshToken
suspend fun findByToken(token: String): JwtRefreshToken
suspend fun findByUserId(userId: Long): JwtRefreshToken
suspend fun deleteById(id: Long)
suspend fun deleteByToken(token: String)
suspend fun deleteByUserId(userId: Long)
suspend fun deleteAll()
}

View File

@ -0,0 +1,38 @@
package dev.usbharu.hideout.query
import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
import dev.usbharu.hideout.repository.JwtRefreshTokens
import dev.usbharu.hideout.repository.toJwtRefreshToken
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.deleteAll
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.select
import org.koin.core.annotation.Single
@Single
class JwtRefreshTokenQueryServiceImpl : JwtRefreshTokenQueryService {
override suspend fun findById(id: Long): JwtRefreshToken =
JwtRefreshTokens.select { JwtRefreshTokens.id.eq(id) }.single().toJwtRefreshToken()
override suspend fun findByToken(token: String): JwtRefreshToken =
JwtRefreshTokens.select { JwtRefreshTokens.refreshToken.eq(token) }.single().toJwtRefreshToken()
override suspend fun findByUserId(userId: Long): JwtRefreshToken =
JwtRefreshTokens.select { JwtRefreshTokens.userId.eq(userId) }.single().toJwtRefreshToken()
override suspend fun deleteById(id: Long) {
JwtRefreshTokens.deleteWhere { JwtRefreshTokens.id eq id }
}
override suspend fun deleteByToken(token: String) {
JwtRefreshTokens.deleteWhere { refreshToken eq token }
}
override suspend fun deleteByUserId(userId: Long) {
JwtRefreshTokens.deleteWhere { JwtRefreshTokens.userId eq userId }
}
override suspend fun deleteAll() {
JwtRefreshTokens.deleteAll()
}
}

View File

@ -8,13 +8,6 @@ interface IJwtRefreshTokenRepository {
suspend fun save(token: JwtRefreshToken) suspend fun save(token: JwtRefreshToken)
suspend fun findById(id: Long): JwtRefreshToken? suspend fun findById(id: Long): JwtRefreshToken?
suspend fun findByToken(token: String): JwtRefreshToken?
suspend fun findByUserId(userId: Long): JwtRefreshToken?
suspend fun delete(token: JwtRefreshToken) suspend fun delete(token: JwtRefreshToken)
suspend fun deleteById(id: Long)
suspend fun deleteByToken(token: String)
suspend fun deleteByUserId(userId: Long)
suspend fun deleteAll()
} }

View File

@ -2,10 +2,8 @@ package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
import dev.usbharu.hideout.service.core.IdGenerateService import dev.usbharu.hideout.service.core.IdGenerateService
import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import java.time.Instant import java.time.Instant
@ -24,14 +22,9 @@ class JwtRefreshTokenRepositoryImpl(
} }
} }
@Suppress("InjectDispatcher")
suspend fun <T> query(block: suspend () -> T): T =
newSuspendedTransaction(Dispatchers.IO) { block() }
override suspend fun generateId(): Long = idGenerateService.generateId() override suspend fun generateId(): Long = idGenerateService.generateId()
override suspend fun save(token: JwtRefreshToken) { override suspend fun save(token: JwtRefreshToken) {
query {
if (JwtRefreshTokens.select { JwtRefreshTokens.id.eq(token.id) }.empty()) { if (JwtRefreshTokens.select { JwtRefreshTokens.id.eq(token.id) }.empty()) {
JwtRefreshTokens.insert { JwtRefreshTokens.insert {
it[id] = token.id it[id] = token.id
@ -49,57 +42,15 @@ class JwtRefreshTokenRepositoryImpl(
} }
} }
} }
}
override suspend fun findById(id: Long): JwtRefreshToken? { override suspend fun findById(id: Long): JwtRefreshToken? =
return query {
JwtRefreshTokens.select { JwtRefreshTokens.id.eq(id) }.singleOrNull()?.toJwtRefreshToken() JwtRefreshTokens.select { JwtRefreshTokens.id.eq(id) }.singleOrNull()?.toJwtRefreshToken()
}
}
override suspend fun findByToken(token: String): JwtRefreshToken? {
return query {
JwtRefreshTokens.select { JwtRefreshTokens.refreshToken.eq(token) }.singleOrNull()?.toJwtRefreshToken()
}
}
override suspend fun findByUserId(userId: Long): JwtRefreshToken? {
return query {
JwtRefreshTokens.select { JwtRefreshTokens.userId.eq(userId) }.singleOrNull()?.toJwtRefreshToken()
}
}
override suspend fun delete(token: JwtRefreshToken) { override suspend fun delete(token: JwtRefreshToken) {
return query {
JwtRefreshTokens.deleteWhere { id eq token.id } JwtRefreshTokens.deleteWhere { id eq token.id }
} }
} }
override suspend fun deleteById(id: Long) {
return query {
JwtRefreshTokens.deleteWhere { JwtRefreshTokens.id eq id }
}
}
override suspend fun deleteByToken(token: String) {
return query {
JwtRefreshTokens.deleteWhere { refreshToken eq token }
}
}
override suspend fun deleteByUserId(userId: Long) {
return query {
JwtRefreshTokens.deleteWhere { JwtRefreshTokens.userId eq userId }
}
}
override suspend fun deleteAll() {
return query {
JwtRefreshTokens.deleteAll()
}
}
}
fun ResultRow.toJwtRefreshToken(): JwtRefreshToken { fun ResultRow.toJwtRefreshToken(): JwtRefreshToken {
return JwtRefreshToken( return JwtRefreshToken(
this[JwtRefreshTokens.id], this[JwtRefreshTokens.id],

View File

@ -1,9 +1,7 @@
package dev.usbharu.hideout.repository package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.Jwt import dev.usbharu.hideout.domain.model.hideout.entity.Jwt
import kotlinx.coroutines.Dispatchers
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.koin.core.annotation.Single import org.koin.core.annotation.Single
import java.util.* import java.util.*
@ -18,12 +16,7 @@ class MetaRepositoryImpl(private val database: Database) : IMetaRepository {
} }
} }
@Suppress("InjectDispatcher")
suspend fun <T> query(block: suspend () -> T): T =
newSuspendedTransaction(Dispatchers.IO) { block() }
override suspend fun save(meta: dev.usbharu.hideout.domain.model.hideout.entity.Meta) { override suspend fun save(meta: dev.usbharu.hideout.domain.model.hideout.entity.Meta) {
return query {
if (Meta.select { Meta.id eq 1 }.empty()) { if (Meta.select { Meta.id eq 1 }.empty()) {
Meta.insert { Meta.insert {
it[id] = 1 it[id] = 1
@ -41,11 +34,9 @@ class MetaRepositoryImpl(private val database: Database) : IMetaRepository {
} }
} }
} }
}
override suspend fun get(): dev.usbharu.hideout.domain.model.hideout.entity.Meta? { override suspend fun get(): dev.usbharu.hideout.domain.model.hideout.entity.Meta? {
return query { return Meta.select { Meta.id eq 1 }.singleOrNull()?.let {
Meta.select { Meta.id eq 1 }.singleOrNull()?.let {
dev.usbharu.hideout.domain.model.hideout.entity.Meta( dev.usbharu.hideout.domain.model.hideout.entity.Meta(
it[Meta.version], it[Meta.version],
Jwt(UUID.fromString(it[Meta.kid]), it[Meta.jwtPrivateKey], it[Meta.jwtPublicKey]) Jwt(UUID.fromString(it[Meta.kid]), it[Meta.jwtPrivateKey], it[Meta.jwtPublicKey])
@ -53,7 +44,6 @@ class MetaRepositoryImpl(private val database: Database) : IMetaRepository {
} }
} }
} }
}
object Meta : Table("meta_info") { object Meta : Table("meta_info") {
val id = long("id") val id = long("id")

View File

@ -8,6 +8,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken 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.UserQueryService 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
@ -25,7 +26,8 @@ import java.util.*
class JwtServiceImpl( class JwtServiceImpl(
private val metaService: IMetaService, private val metaService: IMetaService,
private val refreshTokenRepository: IJwtRefreshTokenRepository, private val refreshTokenRepository: IJwtRefreshTokenRepository,
private val userQueryService: UserQueryService private val userQueryService: UserQueryService,
private val refreshTokenQueryService: JwtRefreshTokenQueryService
) : IJwtService { ) : IJwtService {
private val privateKey by lazy { private val privateKey by lazy {
@ -69,8 +71,11 @@ class JwtServiceImpl(
} }
override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken { override suspend fun refreshToken(refreshToken: RefreshToken): JwtToken {
val token = refreshTokenRepository.findByToken(refreshToken.refreshToken) val token = try {
?: throw InvalidRefreshTokenException("Invalid Refresh Token") refreshTokenQueryService.findByToken(refreshToken.refreshToken)
} catch (_: NoSuchElementException) {
throw InvalidRefreshTokenException("Invalid Refresh Token")
}
val user = userQueryService.findById(token.userId) val user = userQueryService.findById(token.userId)
@ -87,14 +92,14 @@ class JwtServiceImpl(
} }
override suspend fun revokeToken(refreshToken: RefreshToken) { override suspend fun revokeToken(refreshToken: RefreshToken) {
refreshTokenRepository.deleteByToken(refreshToken.refreshToken) refreshTokenQueryService.deleteByToken(refreshToken.refreshToken)
} }
override suspend fun revokeToken(user: User) { override suspend fun revokeToken(user: User) {
refreshTokenRepository.deleteByUserId(user.id) refreshTokenQueryService.deleteByUserId(user.id)
} }
override suspend fun revokeAll() { override suspend fun revokeAll() {
refreshTokenRepository.deleteAll() refreshTokenQueryService.deleteAll()
} }
} }

View File

@ -10,6 +10,7 @@ import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.insert import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
@ -53,10 +54,12 @@ class JwtRefreshTokenRepositoryImplTest {
val expiresAt = now.plus(10, ChronoUnit.MINUTES) val expiresAt = now.plus(10, ChronoUnit.MINUTES)
val expect = JwtRefreshToken(1L, 2L, "refreshToken", now, expiresAt) val expect = JwtRefreshToken(1L, 2L, "refreshToken", now, expiresAt)
newSuspendedTransaction {
repository.save(expect) repository.save(expect)
val actual = repository.findById(1L) val actual = repository.findById(1L)
assertEquals(expect, actual) assertEquals(expect, actual)
} }
}
@Test @Test
fun `save 存在する場合はupdateする`() = runTest { fun `save 存在する場合はupdateする`() = runTest {
@ -68,7 +71,7 @@ class JwtRefreshTokenRepositoryImplTest {
} }
} }
) )
transaction { newSuspendedTransaction {
JwtRefreshTokens.insert { JwtRefreshTokens.insert {
it[id] = 1L it[id] = 1L
it[userId] = 2L it[userId] = 2L
@ -76,8 +79,6 @@ class JwtRefreshTokenRepositoryImplTest {
it[createdAt] = Instant.now().toEpochMilli() it[createdAt] = Instant.now().toEpochMilli()
it[expiresAt] = Instant.now().plus(10, ChronoUnit.MINUTES).toEpochMilli() it[expiresAt] = Instant.now().plus(10, ChronoUnit.MINUTES).toEpochMilli()
} }
}
repository.save( repository.save(
JwtRefreshToken( JwtRefreshToken(
id = 1L, id = 1L,
@ -87,6 +88,8 @@ class JwtRefreshTokenRepositoryImplTest {
expiresAt = Instant.now().plus(10, ChronoUnit.MINUTES) expiresAt = Instant.now().plus(10, ChronoUnit.MINUTES)
) )
) )
}
transaction { transaction {
val toJwtRefreshToken = JwtRefreshTokens.select { JwtRefreshTokens.id.eq(1L) }.single().toJwtRefreshToken() val toJwtRefreshToken = JwtRefreshTokens.select { JwtRefreshTokens.id.eq(1L) }.single().toJwtRefreshToken()
assertEquals("refreshToken2", toJwtRefreshToken.refreshToken) assertEquals("refreshToken2", toJwtRefreshToken.refreshToken)

View File

@ -12,6 +12,7 @@ import dev.usbharu.hideout.domain.model.hideout.entity.JwtRefreshToken
import dev.usbharu.hideout.domain.model.hideout.entity.User import dev.usbharu.hideout.domain.model.hideout.entity.User
import dev.usbharu.hideout.domain.model.hideout.form.RefreshToken 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.UserQueryService 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
@ -21,6 +22,7 @@ import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import org.mockito.kotlin.doReturn import org.mockito.kotlin.doReturn
import org.mockito.kotlin.doThrow
import org.mockito.kotlin.mock import org.mockito.kotlin.mock
import java.security.KeyPairGenerator import java.security.KeyPairGenerator
import java.security.interfaces.RSAPrivateKey import java.security.interfaces.RSAPrivateKey
@ -50,7 +52,7 @@ class JwtServiceImplTest {
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { val refreshTokenRepository = mock<IJwtRefreshTokenRepository> {
onBlocking { generateId() } doReturn 1L onBlocking { generateId() } doReturn 1L
} }
val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, mock()) val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, mock(), mock())
val token = jwtService.createToken( val token = jwtService.createToken(
User( User(
id = 1L, id = 1L,
@ -93,6 +95,10 @@ class JwtServiceImplTest {
val generateKeyPair = keyPairGenerator.generateKeyPair() val generateKeyPair = keyPairGenerator.generateKeyPair()
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { val refreshTokenRepository = mock<IJwtRefreshTokenRepository> {
onBlocking { generateId() } doReturn 2L
}
val jwtRefreshTokenQueryService = mock<JwtRefreshTokenQueryService> {
onBlocking { findByToken("refreshToken") } doReturn JwtRefreshToken( onBlocking { findByToken("refreshToken") } doReturn JwtRefreshToken(
id = 1L, id = 1L,
userId = 1L, userId = 1L,
@ -100,7 +106,6 @@ class JwtServiceImplTest {
createdAt = Instant.now().minus(60, ChronoUnit.MINUTES), createdAt = Instant.now().minus(60, ChronoUnit.MINUTES),
expiresAt = Instant.now().plus(14, ChronoUnit.DAYS).minus(60, ChronoUnit.MINUTES) expiresAt = Instant.now().plus(14, ChronoUnit.DAYS).minus(60, ChronoUnit.MINUTES)
) )
onBlocking { generateId() } doReturn 2L
} }
val userService = mock<UserQueryService> { val userService = mock<UserQueryService> {
onBlocking { findById(1L) } doReturn User( onBlocking { findById(1L) } doReturn User(
@ -125,7 +130,7 @@ class JwtServiceImplTest {
Base64Util.encode(generateKeyPair.public.encoded) Base64Util.encode(generateKeyPair.public.encoded)
) )
} }
val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, userService) val jwtService = JwtServiceImpl(metaService, refreshTokenRepository, userService, jwtRefreshTokenQueryService)
val refreshToken = jwtService.refreshToken(RefreshToken("refreshToken")) val refreshToken = jwtService.refreshToken(RefreshToken("refreshToken"))
assertNotEquals("", refreshToken.token) assertNotEquals("", refreshToken.token)
assertNotEquals("", refreshToken.refreshToken) assertNotEquals("", refreshToken.refreshToken)
@ -147,16 +152,16 @@ class JwtServiceImplTest {
@Test @Test
fun `refreshToken 無効なリフレッシュトークンは失敗する`() = runTest { fun `refreshToken 無効なリフレッシュトークンは失敗する`() = runTest {
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { val refreshTokenRepository = mock<JwtRefreshTokenQueryService> {
onBlocking { findByToken("InvalidRefreshToken") } doReturn null onBlocking { findByToken("InvalidRefreshToken") } doThrow NoSuchElementException()
} }
val jwtService = JwtServiceImpl(mock(), refreshTokenRepository, mock()) val jwtService = JwtServiceImpl(mock(), mock(), mock(), refreshTokenRepository)
assertThrows<InvalidRefreshTokenException> { jwtService.refreshToken(RefreshToken("InvalidRefreshToken")) } assertThrows<InvalidRefreshTokenException> { jwtService.refreshToken(RefreshToken("InvalidRefreshToken")) }
} }
@Test @Test
fun `refreshToken 未来に作成されたリフレッシュトークンは失敗する`() = runTest { fun `refreshToken 未来に作成されたリフレッシュトークンは失敗する`() = runTest {
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { val refreshTokenRepository = mock<JwtRefreshTokenQueryService> {
onBlocking { findByToken("refreshToken") } doReturn JwtRefreshToken( onBlocking { findByToken("refreshToken") } doReturn JwtRefreshToken(
id = 1L, id = 1L,
userId = 1L, userId = 1L,
@ -165,13 +170,13 @@ class JwtServiceImplTest {
expiresAt = Instant.now().plus(10, ChronoUnit.MINUTES).plus(14, ChronoUnit.DAYS) expiresAt = Instant.now().plus(10, ChronoUnit.MINUTES).plus(14, ChronoUnit.DAYS)
) )
} }
val jwtService = JwtServiceImpl(mock(), refreshTokenRepository, mock()) val jwtService = JwtServiceImpl(mock(), mock(), mock(), refreshTokenRepository)
assertThrows<InvalidRefreshTokenException> { jwtService.refreshToken(RefreshToken("refreshToken")) } assertThrows<InvalidRefreshTokenException> { jwtService.refreshToken(RefreshToken("refreshToken")) }
} }
@Test @Test
fun `refreshToken 期限切れのリフレッシュトークンでは失敗する`() = runTest { fun `refreshToken 期限切れのリフレッシュトークンでは失敗する`() = runTest {
val refreshTokenRepository = mock<IJwtRefreshTokenRepository> { val refreshTokenRepository = mock<JwtRefreshTokenQueryService> {
onBlocking { findByToken("refreshToken") } doReturn JwtRefreshToken( onBlocking { findByToken("refreshToken") } doReturn JwtRefreshToken(
id = 1L, id = 1L,
userId = 1L, userId = 1L,
@ -180,7 +185,7 @@ class JwtServiceImplTest {
expiresAt = Instant.now().minus(16, ChronoUnit.DAYS) expiresAt = Instant.now().minus(16, ChronoUnit.DAYS)
) )
} }
val jwtService = JwtServiceImpl(mock(), refreshTokenRepository, mock()) val jwtService = JwtServiceImpl(mock(), mock(), mock(), refreshTokenRepository)
assertThrows<InvalidRefreshTokenException> { jwtService.refreshToken(RefreshToken("refreshToken")) } assertThrows<InvalidRefreshTokenException> { jwtService.refreshToken(RefreshToken("refreshToken")) }
} }
} }