-
Notifications
You must be signed in to change notification settings - Fork 3
feat : 닉네임 한글로 랜덤 생성 #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package org.ezcode.codetest.domain.user.model.enums; | ||
|
|
||
| public enum Adjective { | ||
| 멋있는, 용감한, 지혜로운, 화려한, 귀여운, 빠른, 우아한, 차분한, 활발한, 낙천적인, | ||
| 신중한, 다정한, 수줍은, 배려심깊은, 온화한, 고요한, 명랑한, 정직한, 활기찬, 친절한, | ||
| 대담한, 유쾌한, 상냥한, 유능한, 청명한, 명석한, 순수한, 부지런한, 용의주도한, 근면한, | ||
| 사려깊은, 명민한, 단호한, 냉철한, 호기심많은, 생기있는, 열정적인, 자유로운, 모험적인, 헌신적인, | ||
| 깔끔한, 독창적인, 진중한, 똑똑한, 실용적인, 신비한, 젠틀한, 유연한, 다재다능한, 배짱있는, | ||
| 순발력있는, 선량한, 인내심강한, 집중력있는, 민첩한, 풍부한, 과감한, 창의적인, 합리적인, 끈질긴, | ||
| 호감가는, 매력적인, 성실한, 강직한, 강한, 따뜻한, 겸손한, 깨끗한, 솔직한, 여유로운, | ||
| 정중한, 낭만적인, 조용한, 담백한, 균형잡힌, 용맹한, 재치있는, 평화로운, 반듯한, 침착한, | ||
| 성격좋은, 책임감있는, 다감한, 푸근한, 온순한, 시원한, 명쾌한, 적응력강한, 근엄한, 정돈된, | ||
| 유쾌발랄한, 기운찬, 생동감있는, 적극적인, 야무진, 통찰력있는, 포용력있는, 추진력있는, 자제력있는, 열의있는 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package org.ezcode.codetest.domain.user.model.enums; | ||
|
|
||
| public enum Noun { | ||
| 다람쥐, 여우, 사자, 독수리, 고양이, 토끼, 늑대, 부엉이, 코끼리, 호랑이, | ||
| 펭귄, 고래, 하마, 치타, 스컹크, 개미, 판다, 미어캣, 침팬지, 바다표범, | ||
| 거북이, 흑표범, 제비, 두루미, 수달, 기린, 삵, 두더지, 캥거루, 백조, | ||
| 청설모, 돌고래, 까마귀, 다람이, 삽살개, 들소, 갈매기, 두꺼비, 족제비, 코뿔소, | ||
| 산양, 올빼미, 알파카, 스라소니, 수리부엉이, 원숭이, 문어, 뱀장어, 메추라기, 기러기, | ||
| 앵무새, 너구리, 청둥오리, 고슴도치, 사슴, 아르마딜로, 말, 버팔로, 쥐, 뱀, | ||
| 까치, 도마뱀, 너털곰, 스컹크곰, 오소리, 타조, 얼룩말, 해달, 족제비쥐, 앵무, | ||
| 붉은여우, 산호, 코끼리개미, 사마귀, 박쥐, 해파리, 해마, 노루, 담비, 고라니, | ||
| 공작, 새우, 매, 독수리부엉이, 개, 고양이상어, 악어, 큰눈도롱뇽, 망토원숭이, 비버, | ||
| 코알라, 바다사자, 기린사슴, 비둘기, 토끼상어, 족제비상어, 검독수리, 황조롱이, 흰수염고래, 퓨마 | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |||||||||||||||||||||||||||||||||||
| public class CustomOAuth2UserService extends DefaultOAuth2UserService { | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| private final UserRepository userRepository; | ||||||||||||||||||||||||||||||||||||
| private final UserDomainService userDomainService; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||
| @Transactional | ||||||||||||||||||||||||||||||||||||
|
|
@@ -51,7 +52,8 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic | |||||||||||||||||||||||||||||||||||
| User findUser = userRepository.getUserByEmail(oAuth2Response.getEmail()); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (findUser == null) { | ||||||||||||||||||||||||||||||||||||
| User newUser = User.googleUser(oAuth2Response.getEmail(), username); | ||||||||||||||||||||||||||||||||||||
| String nickname = userDomainService.generateUniqueNickname(); | ||||||||||||||||||||||||||||||||||||
| User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname); | ||||||||||||||||||||||||||||||||||||
| log.info("newUser: {} 새로운 유저", newUser); | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+55
to
57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain닉네임 생성 실패 시 예외 유형 매핑 필요
try {
+ String nickname = userDomainService.generateUniqueNickname();
+ User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
+ userRepository.createUser(newUser);
- String nickname = userDomainService.generateUniqueNickname();
- User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
- userRepository.createUser(newUser);
} catch (IllegalStateException e) {
log.error("중복 닉네임 생성 실패 : {}", e.getMessage());
throw new OAuth2AuthenticationException("닉네임 생성 실패입니다");
} catch (Exception e) {
...
}generateUniqueNickname 메서드 정의와 CustomOAuth2UserService 내 호출 부분을 확인하기 위해 아래 스크립트를 실행하겠습니다. 🏁 Script executed: #!/bin/bash
set -e
echo "=== generateUniqueNickname 정의 위치 및 예외 선언 확인 ==="
rg -n "generateUniqueNickname" -C3 src
echo ""
echo "=== CustomOAuth2UserService 내 호출 위치 및 예외 처리 현황 ==="
rg -n "generateUniqueNickname" -C10 src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.javaLength of output: 2724 generateUniqueNickname 메서드의 구현 전체와 🏁 Script executed: #!/bin/bash
set -e
echo "=== generateUniqueNickname 전체 구현 확인 ==="
rg -n "public String generateUniqueNickname" -C20 src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.java
echo ""
echo "=== IllegalStateException throw 여부 확인 ==="
rg -n "throw new IllegalStateException" -C2 src/main/java/org/ezcode/codetest/domain/user/service/UserDomainService.javaLength of output: 1814 닉네임 생성 실패 예외 매핑 추가 필요
@@ if (findUser == null) {
- String nickname = userDomainService.generateUniqueNickname();
- User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
- log.info("newUser: {} 새로운 유저", newUser);
- try {
- userRepository.createUser(newUser);
- } catch (Exception e) {
- log.error("OAuth 사용자 생성 실패 : {}", e.getMessage());
- throw new OAuth2AuthenticationException("사용자 생성 실패입니다");
- }
+ try {
+ String nickname = userDomainService.generateUniqueNickname();
+ User newUser = User.googleUser(oAuth2Response.getEmail(), username, nickname);
+ log.info("newUser: {} 새로운 유저", newUser);
+ userRepository.createUser(newUser);
+ } catch (IllegalStateException e) {
+ log.error("중복 닉네임 생성 실패 : {}", e.getMessage());
+ throw new OAuth2AuthenticationException("닉네임 생성 실패입니다");
+ } catch (Exception e) {
+ log.error("OAuth 사용자 생성 실패 : {}", e.getMessage());
+ throw new OAuth2AuthenticationException("사용자 생성 실패입니다");
+ }위 변경을 통해 닉네임 생성 실패 시에도 OAuth2 필터 단계에서 일관된 예외 처리 흐름이 보장됩니다. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 합당한데? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @pokerbearkr 말씀해주신 대로 예외 매핑을 적용하도록 하겠습니다. 아래 계획대로 • CustomOAuth2UserService 의 </plan_code_changes> ⏳ Preparing changes... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A summary of the edits CodeRabbit can apply:
A plan of each step that CodeRabbit will take in order to execute the edits for each file (with inline rough draft snippets): ✏️ src/main/java/org/ezcode/codetest/domain/user/service/CustomOAuth2UserService.javaDelete the current block spanning lines 55-63 (the standalone nickname generation, new User creation, and single Exception catch). Insert the following replacement starting at line 55:\n No additional imports are necessary because IllegalStateException is part of java.lang; ensure existing imports remain untouched. Re-compile and run the OAuth flow (or unit tests that simulate nickname collision) to verify IllegalStateException is now translated into OAuth2AuthenticationException and handled uniformly by the filter layer.
|
||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||
| userRepository.createUser(newUser); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,70 +1,90 @@ | ||
| package org.ezcode.codetest.domain.user.service; | ||
| package org.ezcode.codetest.domain.user.service; | ||
|
|
||
| import org.ezcode.codetest.domain.user.exception.AuthException; | ||
| import org.ezcode.codetest.domain.user.exception.AuthExceptionCode; | ||
| import org.ezcode.codetest.domain.user.model.entity.User; | ||
| import org.ezcode.codetest.domain.user.repository.UserRepository; | ||
| import org.ezcode.codetest.infrastructure.security.jwt.PasswordEncoder; | ||
| import org.springframework.stereotype.Service; | ||
| import org.ezcode.codetest.domain.user.exception.AuthException; | ||
| import org.ezcode.codetest.domain.user.exception.AuthExceptionCode; | ||
| import org.ezcode.codetest.domain.user.model.entity.User; | ||
| import org.ezcode.codetest.domain.user.model.enums.Adjective; | ||
| import org.ezcode.codetest.domain.user.model.enums.Noun; | ||
| import org.ezcode.codetest.domain.user.repository.UserRepository; | ||
| import org.ezcode.codetest.infrastructure.security.jwt.PasswordEncoder; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| import org.springframework.transaction.annotation.Transactional; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| @Slf4j | ||
| @Service | ||
| @RequiredArgsConstructor | ||
| @Transactional | ||
| public class UserDomainService { | ||
| private final UserRepository userRepository; | ||
| private final PasswordEncoder passwordEncoder; | ||
| @Slf4j | ||
| @Service | ||
| @RequiredArgsConstructor | ||
| @Transactional | ||
| public class UserDomainService { | ||
| private final UserRepository userRepository; | ||
| private final PasswordEncoder passwordEncoder; | ||
| private static final java.util.Random RANDOM = new java.util.Random(); | ||
|
|
||
| public void checkEmailUnique(String email) { | ||
| if (userRepository.findByEmail(email).isPresent()) { | ||
| throw new AuthException(AuthExceptionCode.ALREADY_EXIST_USER); | ||
| public void checkEmailUnique(String email) { | ||
| if (userRepository.findByEmail(email).isPresent()) { | ||
| throw new AuthException(AuthExceptionCode.ALREADY_EXIST_USER); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public void createUser(User user) { | ||
| userRepository.createUser(user); | ||
| } | ||
| public void createUser(User user) { | ||
| userRepository.createUser(user); | ||
| } | ||
|
|
||
| public User getUser(String email) { | ||
| return userRepository.findByEmail(email) | ||
| .orElseThrow(() -> new AuthException(AuthExceptionCode.USER_NOT_FOUND)); | ||
| } | ||
| public User getUser(String email) { | ||
| return userRepository.findByEmail(email) | ||
| .orElseThrow(() -> new AuthException(AuthExceptionCode.USER_NOT_FOUND)); | ||
| } | ||
|
|
||
| public User getUserById(Long id) { | ||
| return userRepository.findUserById(id) | ||
| .orElseThrow(()->new AuthException(AuthExceptionCode.USER_NOT_FOUND)); | ||
| } | ||
| public User getUserById(Long id) { | ||
| return userRepository.findUserById(id) | ||
| .orElseThrow(()->new AuthException(AuthExceptionCode.USER_NOT_FOUND)); | ||
| } | ||
|
|
||
| public void userPasswordCheck(String email, String password) { | ||
| User user = userRepository.findByEmail(email) | ||
| .orElseThrow(() -> new AuthException(AuthExceptionCode.USER_NOT_FOUND));; | ||
| public void userPasswordCheck(String email, String password) { | ||
| User user = userRepository.findByEmail(email) | ||
| .orElseThrow(() -> new AuthException(AuthExceptionCode.USER_NOT_FOUND));; | ||
|
|
||
| if (!passwordEncoder.matches(password, user.getPassword())) { | ||
| throw new AuthException(AuthExceptionCode.PASSWORD_NOT_MATCH); | ||
| if (!passwordEncoder.matches(password, user.getPassword())) { | ||
| throw new AuthException(AuthExceptionCode.PASSWORD_NOT_MATCH); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public String encodePassword(String password) { | ||
| return passwordEncoder.encode(password); | ||
| } | ||
| public String encodePassword(String password) { | ||
| return passwordEncoder.encode(password); | ||
| } | ||
|
|
||
| public User getOAuthUser(String email, String provider) { | ||
| return userRepository.findByEmailAndProvider(email, provider); | ||
| } | ||
| public User getOAuthUser(String email, String provider) { | ||
| return userRepository.findByEmailAndProvider(email, provider); | ||
| } | ||
|
|
||
| public void passwordComparison(String newPassword, String oldPassword) { | ||
| if (passwordEncoder.matches(newPassword, oldPassword)) { | ||
| throw new AuthException(AuthExceptionCode.PASSWORD_IS_SAME); | ||
| public void passwordComparison(String newPassword, String oldPassword) { | ||
| if (passwordEncoder.matches(newPassword, oldPassword)) { | ||
| throw new AuthException(AuthExceptionCode.PASSWORD_IS_SAME); | ||
| } | ||
| } | ||
|
|
||
| public void isDeletedUser(User user) { | ||
| if (user.isDeleted()) { | ||
| throw new AuthException(AuthExceptionCode.ALREADY_WITHDRAW_USER); | ||
| } | ||
| } | ||
|
|
||
| public String generateUniqueNickname() { | ||
| for (int i = 0; i < 10000000; i++) { | ||
| String nickname = generateRandomNickname(); | ||
| if(!userRepository.existsByNickname(nickname)) { | ||
| return nickname; | ||
| } | ||
| } | ||
| throw new IllegalStateException("중복된 닉네임 생성 불가"); | ||
| } | ||
| } | ||
|
|
||
| public void isDeletedUser(User user) { | ||
| if (user.isDeleted()) { | ||
| throw new AuthException(AuthExceptionCode.ALREADY_WITHDRAW_USER); | ||
| private static String generateRandomNickname() { | ||
| Adjective adjective = Adjective.values()[RANDOM.nextInt(Adjective.values().length)]; | ||
| Noun noun = Noun.values()[RANDOM.nextInt(Noun.values().length)]; | ||
| int number = RANDOM.nextInt(1000); | ||
| return adjective.name() + noun.name() + number; | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
랜덤 비밀번호 평문 저장은 보안 위험
OAuth 가입 시
password(UUID.randomUUID().toString())로 무작위 문자열을 그대로 저장하고 있습니다.비밀번호를 사용하지 않는 계정이라면 NULL 처리하거나, 최소한
PasswordEncoder로 해싱한 값을 저장하여 평문 노출을 방지해주세요.또는,
Also applies to: 107-118
🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
알아서할게 토끼야
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kimminu7 알겠습니다! 필요하시면 언제든지 말씀해 주세요.