Skip to content

Commit 0f6c5a8

Browse files
authored
관리자 로그인 관련 더미 API 추가 (#245)
* feat: 관리자 로그인 관련 더미 API 추가 * refactor: 랜덤 코드 생성 유틸 공통화 * refactor: CodeGeneratorUtil.java private 생성자 추가 * refactor: request Email 유효성 검사 추가
1 parent 052560a commit 0f6c5a8

10 files changed

Lines changed: 177 additions & 11 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.ject.support.common.util;
2+
3+
import java.security.SecureRandom;
4+
import java.util.stream.Collectors;
5+
6+
public class CodeGeneratorUtil {
7+
8+
private CodeGeneratorUtil() {
9+
throw new UnsupportedOperationException("인스턴스화 방지");
10+
}
11+
12+
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
13+
private static final int DIGIT_BOUND = 10;
14+
15+
public static String generateAuthCode(int length) {
16+
return SECURE_RANDOM.ints(length, 0, DIGIT_BOUND)
17+
.mapToObj(String::valueOf)
18+
.collect(Collectors.joining());
19+
}
20+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.ject.support.domain.admin.controller;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.tags.Tag;
5+
import jakarta.validation.Valid;
6+
import org.ject.support.domain.admin.dto.AdminVerifyEmailRequest;
7+
import org.ject.support.domain.admin.dto.AdminAuthSendEmailRequest;
8+
import org.ject.support.domain.admin.dto.AdminAuthSendEmailResponse;
9+
import org.ject.support.domain.admin.dto.AdminVerifyEmailResponse;
10+
import org.ject.support.domain.admin.dto.AdminVerifySlackRequest;
11+
import org.springframework.web.bind.annotation.RequestBody;
12+
13+
@Tag(name = "Admin", description = "관리자 API")
14+
public interface AdminAuthApiSpec {
15+
16+
@Operation(
17+
summary = "관리자 인증 이메일 코드 전송",
18+
description = "관리자 인증 코드를 이메일로 전송합니다."
19+
)
20+
AdminAuthSendEmailResponse sendAdminAuthEmailCode(@RequestBody @Valid AdminAuthSendEmailRequest request);
21+
22+
@Operation(
23+
summary = "관리자 인증 이메일 코드 검증",
24+
description = "관리자 인증 이메일 코드를 검증합니다."
25+
)
26+
AdminVerifyEmailResponse verifyAdminAuthEmailCode(@RequestBody @Valid AdminVerifyEmailRequest request);
27+
28+
@Operation(
29+
summary = "관리자 인증 Slack 코드 검증",
30+
description = "관리자 인증 Slack 코드를 검증합니다."
31+
)
32+
boolean verifyAdminAuthSlackCode(@RequestBody @Valid AdminVerifySlackRequest request);
33+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.ject.support.domain.admin.controller;
2+
3+
import jakarta.validation.Valid;
4+
import lombok.RequiredArgsConstructor;
5+
import org.ject.support.domain.admin.dto.AdminVerifyEmailRequest;
6+
import org.ject.support.domain.admin.dto.AdminAuthSendEmailRequest;
7+
import org.ject.support.domain.admin.dto.AdminAuthSendEmailResponse;
8+
import org.ject.support.domain.admin.dto.AdminVerifyEmailResponse;
9+
import org.ject.support.domain.admin.dto.AdminVerifySlackRequest;
10+
import org.springframework.web.bind.annotation.PostMapping;
11+
import org.springframework.web.bind.annotation.RequestBody;
12+
import org.springframework.web.bind.annotation.RequestMapping;
13+
import org.springframework.web.bind.annotation.RestController;
14+
15+
@RestController
16+
@RequiredArgsConstructor
17+
@RequestMapping("/admin")
18+
public class AdminAuthController implements AdminAuthApiSpec {
19+
20+
@PostMapping("/auth/email-codes")
21+
public AdminAuthSendEmailResponse sendAdminAuthEmailCode(@RequestBody @Valid AdminAuthSendEmailRequest request) {
22+
// TODO : 관리자 인증 코드 전송 로직 구현
23+
return AdminAuthSendEmailResponse.builder()
24+
.email("test@tset.com")
25+
.build();
26+
}
27+
28+
@PostMapping("/auth/email-codes/verify")
29+
public AdminVerifyEmailResponse verifyAdminAuthEmailCode(@RequestBody @Valid AdminVerifyEmailRequest request) {
30+
// TODO : 관리자 인증 이메일 코드 검증 로직 구현, Slack 인증 코드 전송
31+
return AdminVerifyEmailResponse.builder()
32+
.email("test@tset.com")
33+
.build();
34+
}
35+
36+
@PostMapping("/auth/slack-codes/verify")
37+
public boolean verifyAdminAuthSlackCode(@RequestBody @Valid AdminVerifySlackRequest request) {
38+
// TODO : 관리자 인증 Slack 코드 검증 로직 구현, accessToken 발급
39+
return false;
40+
}
41+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.ject.support.domain.admin.dto;
2+
3+
import jakarta.validation.constraints.Email;
4+
import jakarta.validation.constraints.NotBlank;
5+
6+
public record AdminAuthSendEmailRequest(
7+
@NotBlank(message = "Email은 필수 입력 값입니다.")
8+
@Email(message = "유효하지 않은 이메일 형식입니다.")
9+
String email
10+
) {
11+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.ject.support.domain.admin.dto;
2+
3+
import lombok.Builder;
4+
5+
@Builder
6+
public record AdminAuthSendEmailResponse(String email) {
7+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.ject.support.domain.admin.dto;
2+
3+
import jakarta.validation.constraints.Email;
4+
import jakarta.validation.constraints.NotBlank;
5+
import jakarta.validation.constraints.Size;
6+
7+
public record AdminVerifyEmailRequest(
8+
@NotBlank(message = "Email은 필수 입력 값입니다.")
9+
@Email(message = "유효하지 않은 이메일 형식입니다.")
10+
String email,
11+
12+
@NotBlank(message = "Code는 필수 입력 값입니다.")
13+
@Size(min = 6, max = 6, message = "Code는 6자리여야 합니다.")
14+
String code
15+
) {
16+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.ject.support.domain.admin.dto;
2+
3+
import lombok.Builder;
4+
5+
@Builder
6+
public record AdminVerifyEmailResponse(String email) {
7+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.ject.support.domain.admin.dto;
2+
3+
import jakarta.validation.constraints.Email;
4+
import jakarta.validation.constraints.NotBlank;
5+
import jakarta.validation.constraints.Size;
6+
7+
public record AdminVerifySlackRequest(
8+
@NotBlank(message = "Email은 필수 입력 값입니다.")
9+
@Email(message = "유효하지 않은 이메일 형식입니다.")
10+
String email,
11+
12+
@NotBlank(message = "Code는 필수 입력 값입니다.")
13+
@Size(min = 6, max = 6, message = "Code는 4자리여야 합니다.")
14+
String code
15+
) {
16+
}

src/main/java/org/ject/support/external/email/service/EmailAuthService.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import lombok.RequiredArgsConstructor;
44
import lombok.extern.slf4j.Slf4j;
5+
import org.ject.support.common.util.CodeGeneratorUtil;
56
import org.springframework.data.redis.core.RedisTemplate;
67
import org.springframework.stereotype.Service;
78

8-
import java.security.SecureRandom;
99
import java.time.Duration;
1010
import java.util.Map;
1111

@@ -21,20 +21,11 @@ public class EmailAuthService {
2121
private final RedisTemplate<String, String> redisTemplate;
2222

2323
public void sendAuthCode(String sendGroupCode, String toAddress) {
24-
String authCode = generateAuthCode();
24+
String authCode = CodeGeneratorUtil.generateAuthCode(AUTH_CODE_LENGTH);
2525
sendAuthCodeEmail(sendGroupCode, toAddress, authCode);
2626
storeAuthCode(toAddress, authCode);
2727
}
2828

29-
private String generateAuthCode() {
30-
SecureRandom random = new SecureRandom();
31-
StringBuilder builder = new StringBuilder();
32-
for (int i = 0; i < AUTH_CODE_LENGTH; i++) {
33-
builder.append(random.nextInt(10));
34-
}
35-
return builder.toString();
36-
}
37-
3829
private void sendAuthCodeEmail(String sendGroupCode, String toAddress, String authCode) {
3930
emailSendService.sendTemplatedEmail(sendGroupCode, toAddress, Map.of("auth-code", authCode));
4031
log.info("인증 번호 전송 - email: {}, code: {}", toAddress, authCode);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.ject.support.common.util;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
import static org.junit.jupiter.api.Assertions.assertNotNull;
8+
9+
class CodeGeneratorUtilTest {
10+
11+
@Test
12+
@DisplayName("랜덤 인증 코드 생성 테스트")
13+
void generateAuthCode_length_check() {
14+
// given
15+
int length = 6;
16+
17+
// when
18+
String code = CodeGeneratorUtil.generateAuthCode(length);
19+
20+
// then
21+
assertNotNull(code);
22+
assertEquals(length, code.length());
23+
}
24+
}

0 commit comments

Comments
 (0)