Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
33b16b8
[Refactor] #158 관리자용 리프레시토큰 발급 메서드 생성
JJUYAAA Jan 4, 2026
879fe81
[Feat] #158 관리자용 로그인 응답 DTO 생성
JJUYAAA Jan 4, 2026
91c6b73
[Feat] #158 관리자용 토큰 발급 서비스 코드 생성
JJUYAAA Jan 4, 2026
d6ca881
[Refactor] #158 관리자용 토큰 발급 관련 환경변수 추가
JJUYAAA Jan 4, 2026
b719b48
[Refactor] #158 관리자용 토큰 발급 서비스 - AuthServiceFacade에 추가
JJUYAAA Jan 4, 2026
6415657
[Refactor] #158 Redis에 관리자용 토큰 저장하는 로직 추가
JJUYAAA Jan 4, 2026
848cc4c
[Refactor] #158 관리자용 토큰 발급 API - Controller에 추가
JJUYAAA Jan 4, 2026
243f444
[Test] #158 application-test.yml에 관리자용 토큰 발급 관련 환경변수 추가
JJUYAAA Jan 4, 2026
cb8d305
[Test] #158 TestInitializer에 특정한 ID의 유저 생성하는 메서드 추가
JJUYAAA Jan 4, 2026
dca8923
[Test] #158 관리자용 토큰 발급 서비스 테스트코드 작성
JJUYAAA Jan 4, 2026
ca4909e
[Test] #158 AuthControllerTest에 관리자용 토큰 발급 API 테스트 추가
JJUYAAA Jan 4, 2026
ecf97e3
[Test] #158 AuthControllerTest 보강 - 401 반환 테스트
JJUYAAA Jan 4, 2026
274e51a
[Refactor] #158 Role-ADMIN 추가
JJUYAAA Jan 10, 2026
284159f
[Refactor] #158 관리자용 refreshToken 생성 메서드 삭제, 관리자용 accessToken 생성 메서드 추가
JJUYAAA Jan 10, 2026
51f4224
[Refactor] #158 관리자용 로그인 ResponseDTO 수정
JJUYAAA Jan 10, 2026
53d27a8
[Refactor] #158 관리자용 로그인 서비스 코드 수정 - refreshToken 제거
JJUYAAA Jan 10, 2026
7f4d66a
[Refactor] #158 RedisRefreshTokenRepository 수정 - refreshToken 제거
JJUYAAA Jan 10, 2026
a8f2b1c
[Refactor] #158 AdminAllowlistFilter 추가
JJUYAAA Jan 10, 2026
40de914
[Test] #158 AdminLoginServiceImplTest 수정
JJUYAAA Jan 10, 2026
3b12825
[Test] #158 AuthControllerTest 수정
JJUYAAA Jan 10, 2026
64b4e4b
[Refactor] #158 Image 업로드 API - PreAuthorize 수정
JJUYAAA Jan 10, 2026
c25b0f4
[Refactor] #158 ExceptionTranslationFilter 뒤에 AdminAllowListFilter를 추가
JJUYAAA Jan 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
import com.kuit.findyou.domain.auth.dto.ReissueTokenRequest;
import com.kuit.findyou.domain.auth.dto.ReissueTokenResponse;
import com.kuit.findyou.domain.auth.dto.request.GuestLoginRequest;
import com.kuit.findyou.domain.auth.dto.response.AdminLoginResponse;
import com.kuit.findyou.domain.auth.dto.response.GuestLoginResponse;
import com.kuit.findyou.domain.auth.dto.request.KakaoLoginRequest;
import com.kuit.findyou.domain.auth.dto.response.KakaoLoginResponse;
import com.kuit.findyou.domain.auth.service.AuthServiceFacade;
import com.kuit.findyou.global.common.annotation.CustomExceptionDescription;
import com.kuit.findyou.global.common.exception.CustomException;
import com.kuit.findyou.global.common.response.BaseResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.UNAUTHORIZED;
import static com.kuit.findyou.global.common.swagger.SwaggerResponseDescription.*;

@Tag(name = "Login", description = "로그인 관련 API")
Expand All @@ -28,6 +29,9 @@
public class AuthController {
private final AuthServiceFacade authServiceFacade;

@Value("${admin.api.key}")
private String adminApiKey;

@Operation(
summary = "카카오 로그인 API",
description = "카카오 사용자 식별자를 이용해서 유저 정보와 엑세스 토큰을 얻을 수 있습니다. 가입된 회원인지 여부를 반환합니다."
Expand Down Expand Up @@ -58,4 +62,18 @@ public BaseResponse<GuestLoginResponse> guestLogin(@RequestBody GuestLoginReques
public BaseResponse<ReissueTokenResponse> reissueToken(@RequestBody ReissueTokenRequest request){
return BaseResponse.ok(authServiceFacade.reissueToken(request));
}

@Operation(
summary = "서비스 계정 로그인 API (내부 자동화용)",
description = "내부 자동화/관리용 서비스 계정 토큰을 발급합니다. X-ADMIN-KEY 헤더가 필요합니다."
)
@PostMapping("/login/admin")
public BaseResponse<AdminLoginResponse> adminLogin(
@RequestHeader(value = "X-ADMIN-KEY", required = false) String adminKey
Copy link
Collaborator

@JangIkhwan JangIkhwan Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버 간에 인증을 위해서 client credentials라는 방법을 사용하기도 하던데 이렇게 구현하신 이유가 있나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

외부 다수 클라이언트가 붙는 구조가 아니라 내부 자동화 주체 1개만 인증하면 되는 요구사항이라, 인증 인프라를 과도하게 키우기보다는 로그인 단계에서만 API Key를 사용하고, 이후에는 짧은 만료의 access token으로 요청을 처리해 보안 수준은 유지하면서 구현과 운영 복잡도를 낮추는 방식이 적절하다고 생각했습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보안 관점에서는 아쉽지만 그렇게 생각하신다면 알겠습니다

) {
if (adminKey == null || adminKey.isBlank() || !adminApiKey.equals(adminKey)) {
throw new CustomException(UNAUTHORIZED);
}
return BaseResponse.ok(authServiceFacade.adminLogin());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.kuit.findyou.domain.auth.dto.response;

public record AdminLoginResponse(String accessToken, String refreshToken) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ public interface RedisRefreshTokenRepository {
Optional<String> findByUserId(Long userId);

void save(Long id, String refreshToken);
void save(Long id, String refreshToken, long ttlMs);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ public Optional<String> findByUserId(Long userId) {
public void save(Long userId, String refreshToken) {
redisTemplate.opsForValue().set(key(userId), refreshToken, Duration.ofMillis(refreshTokenExpireMs));
}

@Override
public void save(Long userId, String refreshToken, long ttlMs) {
redisTemplate.opsForValue().set(key(userId), refreshToken, Duration.ofMillis(ttlMs));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.kuit.findyou.domain.auth.service;

import com.kuit.findyou.domain.auth.dto.response.AdminLoginResponse;

public interface AdminLoginService {
AdminLoginResponse adminLogin();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.kuit.findyou.domain.auth.service;

import com.kuit.findyou.domain.auth.dto.response.AdminLoginResponse;
import com.kuit.findyou.domain.auth.repository.RedisRefreshTokenRepository;
import com.kuit.findyou.domain.user.model.User;
import com.kuit.findyou.domain.user.repository.UserRepository;
import com.kuit.findyou.global.common.exception.CustomException;
import com.kuit.findyou.global.jwt.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.USER_NOT_FOUND;

@RequiredArgsConstructor
@Service
public class AdminLoginServiceImpl implements AdminLoginService{
private final JwtUtil jwtUtil;
private final UserRepository userRepository;
private final RedisRefreshTokenRepository redisRefreshTokenRepository;

@Value("${admin.admin-user-id}")
private Long adminUserId;

@Value("${admin.refresh-ttl-ms}")
private Long adminRefreshTtlMs;

@Override
public AdminLoginResponse adminLogin() {
User user = userRepository.findById(adminUserId)
.orElseThrow(() -> new CustomException(USER_NOT_FOUND));

String accessToken = jwtUtil.createAccessJwt(user.getId(), user.getRole());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엑세스 토큰은 어떤 권한을 갖고 있나요? 저희 자동화 목적에 맞는 권한만 갖고 있는 게 맞나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 지금은 ROLE을 USER로 갖게끔 되어 있고, 특정한 KEY로 로그인 요청을 보내다보니 상관 없지 않을까 생각했어요.
근데 아예 ROLE에 'ADMIN'이라는 걸 추가하고, 해당 ROLE에게는 특정 API만 호출 가능하도록 수정하는 것이 나을 것 같다는 생각이 듭니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

동의합니다

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이 부분 동의합니다.
현재 구현은 사실상 그냥 kakaoLogin 과 다를 것이 없어보이고, 그냥 DB 에 관리자 유저를 하나 만들어두고 그 유저의 kakaoId 만 알려주면 지금 구현한 adminLogin 기능을 동일하게 대체할 수 있을 것 같아요.

그래서 언급하신 것처럼 ADMIN 이라는 ROLE 을 추가하고, 인스타 포스트 자동화 API 를 ADMIN ROLE 을 가진 유저만 접근할 수 있도록 하는 것이 더 적합한 구현인 것 같슴다

String refreshToken = jwtUtil.createRefreshJwt(user.getId(), adminRefreshTtlMs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리프레시 토큰이 필요한가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Access token을 길게(1년) 주면 만일 한 번 유출되는 경우 1년 동안 뚫린 상태가 되니, Access token은 기존대로 짧게(현재는 1시간), refresh로 자동 갱신을 해서 만일 유출되더라도 바로 끊을 수 있도록 해야한다고 생각했습니다. 또, 운영 자동화 측면에서도 필요하다 생각했습니다.

Copy link
Collaborator

@ksg1227 ksg1227 Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그럼 accessToken 이 만료되면 관리자의 경우에도 refreshToken 을 통해서 reissue 를 해야하는건가요?
제가 알기로는 이 인스타 포스트 자동화 기능을 사용할 때는 일반적인 안드로이드 스튜디오를 활용하는 것이 아니라, 별도의 프로그램을 사용하는 것으로 알아서 PM 님과 이야기 해보아야할 것 같습니다. 아니면 혹시 이 부분까지 이미 토의가 된 것일까여?

추가적으로 만약에 ADMIN ROLE 이 추가된다고 가정한다면, 기존의 reissue API 의 경우 USER ROLE 을 담아 반환하다보니 추가적인 API 를 만들어서 ADMIN ROLE 을 담은 토큰을 재발급해주도록 하거나, 혹은 reissue API 를 수정해서 전달받은 refreshToken 의 ROLE 을 기반으로 분기 처리를 해야되지 않을까 생각됩니다

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상균이형 말대로 토큰 재발급에서 어떤 역할의 토큰을 발급하는지 분기 처리가 필요하겠네요. 리프레시에도 ROLE을 넣도록 JwtUtil을 수정해야할 수 있겠네요.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PM님하고 이야기해봤는데, 결론은 refresh까지 고려하지 않아도 될 것 같습니다.

accessToken만 발급하는걸로 가고, TTL은 일단 임시로 두 달로 설정하기로 했습니다. ADMIN ROLE은 말씀드린대로 추가하는데 따로 reissue 분기는 하지 않을게요!


// 관리자 계정만 TTL 1년으로 저장
redisRefreshTokenRepository.save(user.getId(), refreshToken, adminRefreshTtlMs);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리프레시 토큰 TTL은 어느정도로 생각하시나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재는 PM님이 요청하신대로 1년으로 설정했습니다

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리프레시 토큰이 1년이어야 할 이유를 아직 잘 이해를 못하겠습니다... 리프레시 토큰을 API에서 내보낸다는 건 외부 서버가 리프레시 토큰 로테이션을 할 수 있다는 거 아닌가요? 근데 그러면 리프레시 토큰의 만료 기간이 1년이어야하나요...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음.. 저는 PM님의 요청이었던 'ADMIN'에게 유효기간을 1년 동안 준다' 라는 것에 초점을 맞추고, 1년간 무조건 재로그인 API 호출이 필요 없도록 구현하려고 했습니다.
근데 TTL을 더 짧게 잡고, 그 기간 내에 클라이언트측에서 한 번 이상 access 토큰 만료될 때마다 reissue 호출, 그때마다 refresh를 갱신해 저장하는게 보장돼있다면 더 짧게 해도 괜찮을 것 같아요. 어느 정도의 기간이 적당하다 생각하시나요 ?

Copy link
Collaborator

@JangIkhwan JangIkhwan Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 길어봐야 3달이라고 생각하긴 해요. 근데 홍보용 서버가 어떤 상황인지는 모르겠네요..


return new AdminLoginResponse(accessToken, refreshToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.kuit.findyou.domain.auth.dto.ReissueTokenResponse;
import com.kuit.findyou.domain.auth.dto.request.GuestLoginRequest;
import com.kuit.findyou.domain.auth.dto.request.KakaoLoginRequest;
import com.kuit.findyou.domain.auth.dto.response.AdminLoginResponse;
import com.kuit.findyou.domain.auth.dto.response.GuestLoginResponse;
import com.kuit.findyou.domain.auth.dto.response.KakaoLoginResponse;
import lombok.RequiredArgsConstructor;
Expand All @@ -14,6 +15,7 @@
public class AuthServiceFacade {
private final LoginService loginService;
private final ReissueTokenService reissueTokenService;
private final AdminLoginService adminLoginService;

public KakaoLoginResponse kakaoLogin(KakaoLoginRequest request) {
return loginService.kakaoLogin(request);
Expand All @@ -26,4 +28,8 @@ public GuestLoginResponse guestLogin(GuestLoginRequest request) {
public ReissueTokenResponse reissueToken(ReissueTokenRequest request) {
return reissueTokenService.reissueToken(request);
}

public AdminLoginResponse adminLogin() {
return adminLoginService.adminLogin();
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/kuit/findyou/global/jwt/util/JwtUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ public String createRefreshJwt(Long userId) {
.compact();
}

public String createRefreshJwt(Long userId, long expireMs) {
return Jwts.builder()
.id(UUID.randomUUID().toString())
.claim(JwtClaimKey.USER_ID.getKey(), userId)
.claim(JwtClaimKey.TOKEN_TYPE.getKey(), JwtTokenType.REFRESH_TOKEN)
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + expireMs))
.signWith(secretKey)
.compact();
}

public void validateJwt(String token){
log.info("validateJwt");
try{
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,9 @@ management:
exposure:
include: health, info, prometheus


admin:
admin-user-id: ${ADMIN_USER_ID}
refresh-ttl-ms: ${ADMIN_REFRESH_TTL_MS}
api:
key: ${ADMIN_API_KEY}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import com.kuit.findyou.domain.auth.dto.ReissueTokenRequest;
import com.kuit.findyou.domain.auth.dto.ReissueTokenResponse;
import com.kuit.findyou.domain.auth.dto.request.GuestLoginRequest;
import com.kuit.findyou.domain.auth.dto.response.GuestLoginResponse;
import com.kuit.findyou.domain.auth.dto.request.KakaoLoginRequest;
import com.kuit.findyou.domain.auth.dto.response.AdminLoginResponse;
import com.kuit.findyou.domain.auth.dto.response.GuestLoginResponse;
import com.kuit.findyou.domain.auth.dto.response.KakaoLoginResponse;
import com.kuit.findyou.domain.auth.repository.RedisRefreshTokenRepository;
import com.kuit.findyou.domain.user.model.Role;
Expand All @@ -13,6 +14,7 @@
import com.kuit.findyou.global.common.response.BaseErrorResponse;
import com.kuit.findyou.global.common.response.BaseResponse;
import com.kuit.findyou.global.common.util.DatabaseCleaner;
import com.kuit.findyou.global.common.util.TestInitializer;
import com.kuit.findyou.global.config.RedisTestContainersConfig;
import com.kuit.findyou.global.config.TestDatabaseConfig;
import com.kuit.findyou.global.jwt.util.JwtClaimKey;
Expand All @@ -22,7 +24,10 @@
import io.restassured.RestAssured;
import io.restassured.common.mapper.TypeRef;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
Expand Down Expand Up @@ -60,6 +65,15 @@ class AuthControllerTest {
@Autowired
private DatabaseCleaner databaseCleaner;

@Autowired
TestInitializer testInitializer;

@Value("${admin.api.key}")
String adminApiKey;

@Value("${admin.admin-user-id}")
Long adminUserId;

@Value("${findyou.jwt.secret-key}")
String secret;

Expand Down Expand Up @@ -255,4 +269,139 @@ void reissueToken_shouldReturnNotFound_WhenRefreshTokenIsNotMatched(){
assertThat(response.getCode()).isEqualTo(REFRESH_TOKEN_NOT_FOUND.getCode());
assertThat(response.getMessage()).isEqualTo(REFRESH_TOKEN_NOT_FOUND.getMessage());
}

@DisplayName("관리자 키가 유효하면 관리자 로그인 성공(토큰 반환 + Redis 저장)")
@Test
void adminLogin_shouldReturnTokens_WhenValidAdminKey() {
// given
testInitializer.insertAdminUserWithFixedId(adminUserId, Role.USER);

// when
BaseResponse<AdminLoginResponse> response = given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.header("X-ADMIN-KEY", adminApiKey)
.body("{}")
.when()
.post("/api/v2/auth/login/admin")
.then()
.statusCode(200)
.extract()
.as(new TypeRef<BaseResponse<AdminLoginResponse>>() {});

// then
String access = response.getData().accessToken();
String refresh = response.getData().refreshToken();

assertThat(access).isNotBlank();
assertThat(refresh).isNotBlank();

// access 토큰 검증
assertThat(jwtUtil.getUserId(access)).isEqualTo(adminUserId);
assertThat(jwtUtil.getTokenType(access)).isEqualTo(JwtTokenType.ACCESS_TOKEN);

// refresh 토큰 검증
assertThat(jwtUtil.getUserId(refresh)).isEqualTo(adminUserId);
assertThat(jwtUtil.getTokenType(refresh)).isEqualTo(JwtTokenType.REFRESH_TOKEN);

// Redis에 저장됐는지 확인 (현재 저장값 == 발급 refresh)
String saved = redisRefreshTokenRepository.findByUserId(adminUserId).orElse(null);
assertThat(saved).isEqualTo(refresh);
}

@DisplayName("관리자 키가 틀리면 401을 반환한다")
@Test
void adminLogin_shouldReturnUnauthorized_WhenInvalidAdminKey() {
// given
testInitializer.insertAdminUserWithFixedId(adminUserId, Role.USER);

// when
BaseErrorResponse response = given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.header("X-ADMIN-KEY", "wrong-key")
.body("{}")
.when()
.post("/api/v2/auth/login/admin")
.then()
.extract()
.as(new TypeRef<BaseErrorResponse>() {});

// then
assertThat(response.getCode()).isEqualTo(UNAUTHORIZED.getCode());
assertThat(response.getMessage()).isEqualTo(UNAUTHORIZED.getMessage());
assertThat(response.getSuccess()).isFalse();
}
@DisplayName("관리자 키 헤더가 없으면 401을 반환한다")
@Test
void adminLogin_shouldReturnUnauthorized_WhenAdminKeyMissing() {
// given
testInitializer.insertAdminUserWithFixedId(adminUserId, Role.USER);

// when
BaseErrorResponse response = given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{}")
.when()
.post("/api/v2/auth/login/admin")
.then()
.extract()
.as(new TypeRef<BaseErrorResponse>() {});

// then
assertThat(response.getCode()).isEqualTo(UNAUTHORIZED.getCode());
assertThat(response.getMessage()).isEqualTo(UNAUTHORIZED.getMessage());
assertThat(response.getSuccess()).isFalse();
}

@DisplayName("관리자 키가 빈 문자열이면 401을 반환한다")
@Test
void adminLogin_shouldReturnUnauthorized_WhenAdminKeyIsBlank() {
// given
testInitializer.insertAdminUserWithFixedId(adminUserId, Role.USER);

// when
BaseErrorResponse response = given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.header("X-ADMIN-KEY", "")
.body("{}")
.when()
.post("/api/v2/auth/login/admin")
.then()
.extract()
.as(new TypeRef<BaseErrorResponse>() {});

// then
assertThat(response.getCode()).isEqualTo(UNAUTHORIZED.getCode());
assertThat(response.getMessage()).isEqualTo(UNAUTHORIZED.getMessage());
assertThat(response.getSuccess()).isFalse();
}


@DisplayName("관리자 유저가 존재하지 않으면 404(USER_NOT_FOUND)를 반환한다")
@Test
void adminLogin_shouldReturnNotFound_WhenAdminUserDoesNotExist() {
// given: insertAdminUserWithFixedId 호출 안 함

// when
BaseErrorResponse response = given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.header("X-ADMIN-KEY", adminApiKey)
.body("{}")
.when()
.post("/api/v2/auth/login/admin")
.then()
.extract()
.as(new TypeRef<BaseErrorResponse>() {});

// then
assertThat(response.getCode()).isEqualTo(USER_NOT_FOUND.getCode());
assertThat(response.getMessage()).isEqualTo(USER_NOT_FOUND.getMessage());
assertThat(response.getSuccess()).isFalse();
}


}
Loading