-
Notifications
You must be signed in to change notification settings - Fork 0
password 변경 및 테스트 코드 작성 #207
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
base: develop
Are you sure you want to change the base?
Changes from all commits
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,20 @@ | ||
| package site.icebang.domain.auth.dto; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.Size; | ||
| import lombok.Getter; | ||
| import lombok.Setter; | ||
|
|
||
| @Getter | ||
| @Setter | ||
| public class ChangePasswordRequestDto { | ||
| @NotBlank(message = "현재 비밀번호는 필수입니다") | ||
| private String currentPassword; | ||
|
|
||
| @NotBlank(message = "새 비밀번호는 필수입니다") | ||
| @Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다") | ||
| private String newPassword; | ||
|
|
||
| @NotBlank(message = "새 비밀번호 확인은 필수입니다") | ||
| private String confirmPassword; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,13 @@ | |
|
|
||
| import site.icebang.common.exception.DuplicateDataException; | ||
| import site.icebang.common.utils.RandomPasswordGenerator; | ||
| import site.icebang.domain.auth.dto.ChangePasswordRequestDto; | ||
| import site.icebang.domain.auth.dto.RegisterDto; | ||
| import site.icebang.domain.auth.mapper.AuthMapper; | ||
| import site.icebang.domain.email.dto.EmailRequest; | ||
| import site.icebang.domain.email.service.EmailService; | ||
| import site.icebang.global.handler.exception.InvalidPasswordException; | ||
| import site.icebang.global.handler.exception.PasswordMismatchException; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
|
|
@@ -51,4 +54,26 @@ public void registerUser(RegisterDto registerDto) { | |
|
|
||
| emailService.send(emailRequest); | ||
| } | ||
|
|
||
| public void changePassword(String email, ChangePasswordRequestDto request) { | ||
| // 1. 새 비밀번호와 확인 비밀번호 일치 검증 | ||
| if (!request.getNewPassword().equals(request.getConfirmPassword())) { | ||
| throw new PasswordMismatchException("새 비밀번호가 일치하지 않습니다"); | ||
| } | ||
|
|
||
|
Comment on lines
+58
to
+63
Collaborator
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. 이 부분은 비즈니스 로직이 아니라 단순한 입력값 검증(validation) 으로 보는 게 맞습니다.
또한 새 비밀번호와 새 비밀번호 확인은 실제 서비스에서도 프론트엔드에서만 체크하고 백엔드에서 별도 검증을 생략하는 경우가 흔합니다.
|
||
| // 2. 사용자 조회 | ||
| String currentHashedPassword = authMapper.findPasswordByEmail(email); | ||
| if (currentHashedPassword == null) { | ||
| throw new IllegalArgumentException("사용자를 찾을 수 없습니다"); // 이건 그대로 | ||
| } | ||
|
|
||
| // 3. 현재 비밀번호 검증 | ||
| if (!passwordEncoder.matches(request.getCurrentPassword(), currentHashedPassword)) { | ||
| throw new InvalidPasswordException("현재 비밀번호가 올바르지 않습니다"); | ||
| } | ||
|
|
||
| // 4. 새 비밀번호 해싱 및 업데이트 | ||
| String hashedNewPassword = passwordEncoder.encode(request.getNewPassword()); | ||
| authMapper.updatePassword(email, hashedNewPassword); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package site.icebang.global.config.Mail; | ||
|
|
||
| import java.util.Properties; | ||
|
|
||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.mail.javamail.JavaMailSender; | ||
| import org.springframework.mail.javamail.JavaMailSenderImpl; | ||
|
|
||
| @Configuration | ||
| public class MailConfig { | ||
|
|
||
| @Bean | ||
| public JavaMailSender javaMailSender() { | ||
| JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); | ||
| mailSender.setHost("smtp.gmail.com"); | ||
| mailSender.setPort(587); | ||
| mailSender.setUsername(""); | ||
| mailSender.setPassword(""); | ||
|
|
||
| Properties props = mailSender.getJavaMailProperties(); | ||
| props.put("mail.transport.protocol", "smtp"); | ||
| props.put("mail.smtp.auth", "true"); | ||
| props.put("mail.smtp.starttls.enable", "true"); | ||
| props.put("mail.debug", "true"); | ||
|
|
||
| return mailSender; | ||
| } | ||
|
Comment on lines
+10
to
+28
Collaborator
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. 저희는 따라서 다음 두 가지 중 하나로 맞춰 주시면 좋겠습니다.
두 방식 중 어떤 것을 선택하든, |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -118,4 +118,10 @@ public ApiResponse<String> handleDuplicateData(DuplicateDataException ex) { | |
| log.warn(ex.getMessage(), ex); | ||
| return ApiResponse.error("Duplicate: " + ex.getMessage(), HttpStatus.CONFLICT); | ||
| } | ||
|
|
||
| @ExceptionHandler({PasswordMismatchException.class, InvalidPasswordException.class}) // 추가 | ||
| @ResponseStatus(HttpStatus.BAD_REQUEST) | ||
| public ApiResponse<String> handlePasswordException(RuntimeException ex) { | ||
| return ApiResponse.error(ex.getMessage(), HttpStatus.BAD_REQUEST); | ||
| } | ||
|
Comment on lines
+121
to
+126
Collaborator
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. 각 도메인에서 400 응답을 내려야 하는 경우마다 |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package site.icebang.global.handler.exception; | ||
|
|
||
| public class InvalidPasswordException extends RuntimeException { | ||
|
|
||
| public InvalidPasswordException(String message) { | ||
| super(message); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package site.icebang.global.handler.exception; | ||
|
|
||
| public class PasswordMismatchException extends RuntimeException { | ||
| public PasswordMismatchException(String message) { | ||
| super(message); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document; | ||
| import static com.epages.restdocs.apispec.ResourceDocumentation.*; | ||
| import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; | ||
| import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch; | ||
| import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; | ||
| import static org.springframework.restdocs.operation.preprocess.Preprocessors.*; | ||
| import static org.springframework.restdocs.payload.PayloadDocumentation.*; | ||
|
|
@@ -611,4 +612,25 @@ void getPermissions_unauthenticated_returns_unauthorized() throws Exception { | |
| .description("HTTP 상태 (UNAUTHORIZED)")) | ||
| .build()))); | ||
| } | ||
|
|
||
| @Test | ||
| @DisplayName("비밀번호 변경 실패 - 미인증 사용자") | ||
| void changePassword_fail_unauthorized() throws Exception { | ||
| // given - 로그인하지 않은 상태 | ||
| Map<String, String> changePasswordRequest = new HashMap<>(); | ||
| changePasswordRequest.put("currentPassword", "qwer1234!A"); | ||
| changePasswordRequest.put("newPassword", "newPassword123!A"); | ||
| changePasswordRequest.put("confirmPassword", "newPassword123!A"); | ||
|
|
||
| // when & then | ||
| mockMvc | ||
| .perform( | ||
| patch(getApiUrlForDocs("/v0/auth/change-password")) | ||
| .contentType(MediaType.APPLICATION_JSON) | ||
| .content(objectMapper.writeValueAsString(changePasswordRequest))) | ||
| .andExpect(status().isUnauthorized()) | ||
| .andExpect(jsonPath("$.success").value(false)) | ||
| .andExpect(jsonPath("$.status").value("UNAUTHORIZED")) | ||
| .andExpect(jsonPath("$.data").doesNotExist()); | ||
| } | ||
|
Comment on lines
+626
to
+635
Collaborator
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. Spring rest api documentation을 위한 처리가 되어있지 않습니다. 확인해주세요 |
||
| } | ||
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.
Pk(BigInteger)로 찾는게 더 빨라 보일 것 같습니다.
Controller에서
이렇게 꺼낼 수 있습니다