diff --git a/src/main/java/org/sopt/seonyakServer/domain/member/controller/MemberController.java b/src/main/java/org/sopt/seonyakServer/domain/member/controller/MemberController.java index 3439abd..9d43b17 100644 --- a/src/main/java/org/sopt/seonyakServer/domain/member/controller/MemberController.java +++ b/src/main/java/org/sopt/seonyakServer/domain/member/controller/MemberController.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.sopt.seonyakServer.domain.member.dto.LoginSuccessResponse; +import org.sopt.seonyakServer.domain.member.dto.NicknameRequest; import org.sopt.seonyakServer.domain.member.service.MemberService; import org.sopt.seonyakServer.global.common.external.client.dto.MemberLoginRequest; import org.springframework.http.ResponseEntity; @@ -14,16 +15,25 @@ @RestController @RequiredArgsConstructor -@RequestMapping("/api/v1/auth") +@RequestMapping("/api/v1") public class MemberController { private final MemberService memberService; - @PostMapping("/login") + @PostMapping("/auth/login") public ResponseEntity login( @RequestParam final String authorizationCode, @RequestBody @Valid final MemberLoginRequest loginRequest ) { return ResponseEntity.ok(memberService.create(authorizationCode, loginRequest)); } + + @PostMapping("/nickname") + public ResponseEntity validNickname( + @RequestBody final NicknameRequest nicknameRequest + ) { + memberService.validNickname(nicknameRequest); + + return ResponseEntity.ok().build(); + } } diff --git a/src/main/java/org/sopt/seonyakServer/domain/member/dto/NicknameRequest.java b/src/main/java/org/sopt/seonyakServer/domain/member/dto/NicknameRequest.java new file mode 100644 index 0000000..5766b87 --- /dev/null +++ b/src/main/java/org/sopt/seonyakServer/domain/member/dto/NicknameRequest.java @@ -0,0 +1,9 @@ +package org.sopt.seonyakServer.domain.member.dto; + +public record NicknameRequest( + String nickname +) { + public static NicknameRequest of(final String nickname) { + return new NicknameRequest(nickname); + } +} diff --git a/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java b/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java index a5b91d8..48c4850 100644 --- a/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java +++ b/src/main/java/org/sopt/seonyakServer/domain/member/repository/MemberRepository.java @@ -7,4 +7,6 @@ public interface MemberRepository extends JpaRepository { Optional findBySocialTypeAndSocialId(SocialType socialType, String socialId); + + boolean existsByNickname(String nickname); } diff --git a/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java b/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java index fdcf52c..97f954d 100644 --- a/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java +++ b/src/main/java/org/sopt/seonyakServer/domain/member/service/MemberService.java @@ -2,6 +2,7 @@ import lombok.RequiredArgsConstructor; import org.sopt.seonyakServer.domain.member.dto.LoginSuccessResponse; +import org.sopt.seonyakServer.domain.member.dto.NicknameRequest; import org.sopt.seonyakServer.domain.member.model.Member; import org.sopt.seonyakServer.domain.member.model.SocialType; import org.sopt.seonyakServer.domain.member.repository.MemberRepository; @@ -24,6 +25,8 @@ public class MemberService { private final GoogleSocialService googleSocialService; private final MemberManagementService memberManagementService; + public static final String NICKNAME_PATTERN = "^[a-zA-Z0-9가-힣]{2,8}$"; + // JWT Access Token 생성 public LoginSuccessResponse create( final String authorizationCode, @@ -87,4 +90,15 @@ public LoginSuccessResponse getTokenByMemberId(final Long id) { return LoginSuccessResponse.of(jwtTokenProvider.issueAccessToken(memberAuthentication)); } + + // 닉네임 유효성 검증 + public void validNickname(final NicknameRequest nicknameRequest) { + if (!nicknameRequest.nickname().matches(NICKNAME_PATTERN)) { // 형식 체크 + throw new CustomException(ErrorType.INVALID_NICKNAME_ERROR); + } + + if (memberRepository.existsByNickname(nicknameRequest.nickname())) { // 중복 체크 + throw new CustomException(ErrorType.NICKNAME_DUP_ERROR); + } + } } diff --git a/src/main/java/org/sopt/seonyakServer/global/exception/enums/ErrorType.java b/src/main/java/org/sopt/seonyakServer/global/exception/enums/ErrorType.java index e328d60..d6e9ab2 100644 --- a/src/main/java/org/sopt/seonyakServer/global/exception/enums/ErrorType.java +++ b/src/main/java/org/sopt/seonyakServer/global/exception/enums/ErrorType.java @@ -22,6 +22,7 @@ public enum ErrorType { INVALID_CODE_HEADER_ERROR(HttpStatus.BAD_REQUEST, "40007", "code 헤더값의 형식이 잘못되었습니다."), INVALID_SOCIAL_TYPE_ERROR(HttpStatus.BAD_REQUEST, "40008", "유효하지 않은 Social Type입니다."), BEARER_LOST_ERROR(HttpStatus.BAD_REQUEST, "40009", "요청한 토큰이 Bearer 토큰이 아닙니다."), + INVALID_NICKNAME_ERROR(HttpStatus.BAD_REQUEST, "40010", "닉네임이 조건을 만족하지 않습니다."), MAP_TO_JSON_ERROR(HttpStatus.BAD_REQUEST, "40016", "Map을 JSON 문자열로 변환하는 중 오류가 발생했습니다."), JSON_TO_MAP_ERROR(HttpStatus.BAD_REQUEST, "40017", "JSON 문자열을 Map으로 변환하는 중 오류가 발생했습니다."),