[#44] 매장 기능 도입 #45

Merged
pricelees merged 116 commits from feat/#44 into main 2025-09-20 03:15:06 +00:00
Showing only changes of commit 9b13448abd - Show all commits

View File

@ -10,18 +10,20 @@ import io.restassured.response.ValidatableResponse
import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.equalTo
import org.springframework.http.HttpStatus import org.springframework.http.HttpStatus
import roomescape.admin.exception.AdminErrorCode import roomescape.admin.exception.AdminErrorCode
import roomescape.auth.business.CLAIM_ADMIN_TYPE_KEY
import roomescape.auth.business.CLAIM_PERMISSION_KEY import roomescape.auth.business.CLAIM_PERMISSION_KEY
import roomescape.auth.business.CLAIM_STORE_ID_KEY
import roomescape.auth.exception.AuthErrorCode import roomescape.auth.exception.AuthErrorCode
import roomescape.auth.infrastructure.jwt.JwtUtils import roomescape.auth.infrastructure.jwt.JwtUtils
import roomescape.auth.infrastructure.persistence.LoginHistoryRepository import roomescape.auth.infrastructure.persistence.LoginHistoryRepository
import roomescape.auth.web.LoginRequest import roomescape.auth.web.LoginRequest
import roomescape.common.dto.PrincipalType import roomescape.common.dto.PrincipalType
import roomescape.user.exception.UserErrorCode
import roomescape.user.infrastructure.persistence.UserEntity
import roomescape.supports.AdminFixture import roomescape.supports.AdminFixture
import roomescape.supports.FunSpecSpringbootTest import roomescape.supports.FunSpecSpringbootTest
import roomescape.supports.UserFixture import roomescape.supports.UserFixture
import roomescape.supports.runTest import roomescape.supports.runTest
import roomescape.user.exception.UserErrorCode
import roomescape.user.infrastructure.persistence.UserEntity
class AuthApiTest( class AuthApiTest(
@SpykBean private val jwtUtils: JwtUtils, @SpykBean private val jwtUtils: JwtUtils,
@ -31,17 +33,25 @@ class AuthApiTest(
init { init {
context("로그인을 시도한다.") { context("로그인을 시도한다.") {
context("성공 응답") { context("성공 응답") {
test("관리자") { listOf(
val admin = authUtil.createAdmin(AdminFixture.default) AdminFixture.storeDefault,
runLoginSuccessTest( AdminFixture.hqDefault
id = admin.id, ).forEach {
account = admin.account, test("${it.type} 타입 관리자") {
password = admin.password, val admin = authUtil.createAdmin(it)
type = PrincipalType.ADMIN,
) { runLoginSuccessTest(
val token: String = it.extract().path("data.accessToken") id = admin.id,
jwtUtils.extractSubject(token) shouldBe admin.id.toString() account = admin.account,
jwtUtils.extractClaim(token, CLAIM_PERMISSION_KEY) shouldBe admin.permissionLevel.name password = admin.password,
type = PrincipalType.ADMIN,
) {
val token: String = it.extract().path("data.accessToken")
jwtUtils.extractSubject(token) shouldBe admin.id.toString()
jwtUtils.extractClaim(token, CLAIM_STORE_ID_KEY) shouldBe admin.storeId?.toString()
jwtUtils.extractClaim(token, CLAIM_ADMIN_TYPE_KEY) shouldBe admin.type.name
jwtUtils.extractClaim(token, CLAIM_PERMISSION_KEY) shouldBe admin.permissionLevel.name
}
} }
} }
@ -61,52 +71,54 @@ class AuthApiTest(
} }
context("실패 응답") { context("실패 응답") {
test("비밀번호가 틀린 경우") { context("계정이 맞으면 로그인 실패 이력을 남긴다.") {
val admin = authUtil.createAdmin(AdminFixture.default) test("비밀번호가 틀린 경우") {
val request = LoginRequest(admin.account, "wrong_password", PrincipalType.ADMIN) val admin = authUtil.createAdmin(AdminFixture.default)
val request = LoginRequest(admin.account, "wrong_password", PrincipalType.ADMIN)
runTest( runTest(
using = { using = {
body(request) body(request)
}, },
on = { on = {
post("/auth/login") post("/auth/login")
}, },
expect = { expect = {
statusCode(HttpStatus.UNAUTHORIZED.value()) statusCode(HttpStatus.UNAUTHORIZED.value())
body("code", equalTo(AuthErrorCode.LOGIN_FAILED.errorCode)) body("code", equalTo(AuthErrorCode.LOGIN_FAILED.errorCode))
} }
).also { ).also {
assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) { assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) {
it.success shouldBe false it.success shouldBe false
it.principalType shouldBe PrincipalType.ADMIN it.principalType shouldBe PrincipalType.ADMIN
}
} }
} }
}
test("토큰 생성 과정에서 오류가 발생하는 경우") { test("토큰 생성 과정에서 오류가 발생하는 경우") {
val admin = authUtil.createAdmin(AdminFixture.default) val admin = authUtil.createAdmin(AdminFixture.default)
val request = LoginRequest(admin.account, admin.password, PrincipalType.ADMIN) val request = LoginRequest(admin.account, admin.password, PrincipalType.ADMIN)
every { every {
jwtUtils.createToken(any(), any()) jwtUtils.createToken(any(), any())
} throws RuntimeException("토큰 생성 실패") } throws RuntimeException("토큰 생성 실패")
runTest( runTest(
using = { using = {
body(request) body(request)
}, },
on = { on = {
post("/auth/login") post("/auth/login")
}, },
expect = { expect = {
statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()) statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value())
body("code", equalTo(AuthErrorCode.TEMPORARY_AUTH_ERROR.errorCode)) body("code", equalTo(AuthErrorCode.TEMPORARY_AUTH_ERROR.errorCode))
} }
).also { ).also {
assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) { assertSoftly(loginHistoryRepository.findByPrincipalId(admin.id)[0]) {
it.success shouldBe false it.success shouldBe false
it.principalType shouldBe PrincipalType.ADMIN it.principalType shouldBe PrincipalType.ADMIN
}
} }
} }
} }
@ -162,39 +174,6 @@ class AuthApiTest(
} }
} }
} }
context("로그인 상태를 확인한다.") {
test("성공 응답") {
val token = authUtil.defaultUserLogin()
runTest(
token = token,
on = {
get("/auth/login/check")
},
expect = {
statusCode(HttpStatus.OK.value())
}
).also {
val name: String = it.extract().path("data.name")
val type: String = it.extract().path("data.type")
name.isBlank() shouldBe false
type shouldBe PrincipalType.USER.name
}
}
test("로그인 상태가 아니면 실패한다.") {
runTest(
on = {
get("/auth/login/check")
},
expect = {
statusCode(HttpStatus.UNAUTHORIZED.value())
}
)
}
}
} }
private fun runLoginSuccessTest( private fun runLoginSuccessTest(