Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ public record UserInfo(
String email
) {
public static UserInfo from(UserModel model) {
if(model == null) {
throw new IllegalArgumentException("UserModel은 null일 수 없습니다.");
}

return new UserInfo(
model.getLoginId(),
model.getName(),
Expand All @@ -20,4 +24,4 @@ public static UserInfo from(UserModel model) {
model.getEmail()
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
package com.loopers.domain.user;

public interface PasswordEncoder {
/**
* 평문 비밀번호를 인코딩한다.
* @param rawPassword 평문 비밀번호 (null 불가)
* @return 인코딩된 비밀번호
* @throws IllegalArgumentException rawPassword가 null인 경우
*/
String encode(String rawPassword);

/**
* 평문 비밀번호와 인코딩된 비밀번호가 일치하는지 검증한다.
* @param rawPassword 평문 비밀번호 (null 불가)
* @param encodedPassword 인코딩된 비밀번호 (null 불가)
* @return 일치 여부
* @throws IllegalArgumentException 파라미터가 null인 경우
*/
boolean matches(String rawPassword, String encodedPassword);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ private void validateEmail(String email) {
if (email == null || email.isBlank()) {
throw new CoreException(ErrorType.BAD_REQUEST, "이메일은 비어있을 수 없습니다.");
}
if (!email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$")) {
if (!email.matches("^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$")) {
throw new CoreException(ErrorType.BAD_REQUEST, "유효하지 않은 이메일 형식입니다.");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ private void validateDifferentFromCurrent(String currentRawPassword, String newR
if (currentRawPassword == null || currentRawPassword.isBlank()) {
throw new CoreException(ErrorType.BAD_REQUEST, "현재 비밀번호는 비어있을 수 없습니다.");
}
if (newRawPassword == null || newRawPassword.isBlank()) {
throw new CoreException(ErrorType.BAD_REQUEST, "새 비밀번호는 비어있을 수 없습니다.");
}
if (currentRawPassword.equals(newRawPassword)) {
throw new CoreException(ErrorType.BAD_REQUEST, "새 비밀번호는 현재 비밀번호와 달라야 합니다.");
}
Expand Down Expand Up @@ -70,4 +67,4 @@ private void validateNotContainsBirthDate(String password, LocalDate birthDate)
throw new CoreException(ErrorType.BAD_REQUEST, "비밀번호에 생년월일을 포함할 수 없습니다.");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

@RequiredArgsConstructor
@RestController
@RequestMapping("/user")
@RequestMapping("/api/v1/users")
public class UserV1Controller implements UserV1ApiSpec {

private final UserFacade userFacade;

@PostMapping("/signup")
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@Override
public ApiResponse<UserV1Dto.SignupResponse> signup(
Expand All @@ -39,7 +39,7 @@ public ApiResponse<UserV1Dto.SignupResponse> signup(
return ApiResponse.success(UserV1Dto.SignupResponse.from(info));
}

@GetMapping
@GetMapping("/me")
@Override
public ApiResponse<UserV1Dto.UserInfoResponse> getMyInfo(
@LoginUser UserModel user
Expand All @@ -48,7 +48,7 @@ public ApiResponse<UserV1Dto.UserInfoResponse> getMyInfo(
return ApiResponse.success(UserV1Dto.UserInfoResponse.from(info));
}

@PatchMapping("/changePassword")
@PatchMapping("/password")
@ResponseStatus(HttpStatus.NO_CONTENT)
@Override
public void changePassword(
Expand All @@ -57,4 +57,4 @@ public void changePassword(
) {
userFacade.changePassword(user, request.currentPassword(), request.newPassword());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public class AuthenticationConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/user")
.addPathPatterns("/user/changePassword");
.addPathPatterns("/api/v1/users/me")
.addPathPatterns("/api/v1/users/password");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,17 @@ void masksLastCharacter_whenNameHasTwoCharacters() {
@DisplayName("비밀번호 변경 시,")
@Nested
class ChangePassword {
@DisplayName("새로운 비밀번호가 비어있으면, BAD_REQUEST 예외가 발생한다.")
@Test
void throwsBadRequest_whenNewPasswordIsBlank() {
// arrange
UserModel userModel = new UserModel(LOGIN_ID, "oldEncoded", NAME, BIRTH_DATE, EMAIL);

// act & assert
assertThatThrownBy(() -> userModel.changePassword(""))
.isInstanceOf(CoreException.class)
.satisfies(e -> assertThat(((CoreException) e).getErrorType()).isEqualTo(ErrorType.BAD_REQUEST));
}

@DisplayName("새로운 암호화된 비밀번호로 변경된다.")
@Test
Expand All @@ -168,4 +179,4 @@ void changesPassword_whenNewEncodedPasswordIsProvided() {
assertThat(userModel.getPassword()).isEqualTo(newEncodedPassword);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,6 @@ void throwsBadRequest_whenPasswordIsTooLong() {
assertThat(exception.getMessage()).contains("8~16자");
}

@DisplayName("비밀번호가 null이면, BAD_REQUEST 예외가 발생한다.")
@Test
void throwsBadRequest_whenPasswordIsNull() {
// act
CoreException exception = assertThrows(CoreException.class, () ->
passwordPolicy.validateForSignup(null, BIRTH_DATE)
);

// assert
assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
assertThat(exception.getMessage()).contains("8~16자");
}

@DisplayName("비밀번호에 생년월일이 포함되면, BAD_REQUEST 예외가 발생한다.")
@Test
void throwsBadRequest_whenPasswordContainsBirthDate() {
Expand Down Expand Up @@ -149,38 +136,6 @@ void throwsBadRequest_whenNewPasswordIsSameAsCurrent() {
assertThat(exception.getMessage()).contains("현재 비밀번호와 달라야");
}

@DisplayName("현재 비밀번호가 null이면, BAD_REQUEST 예외가 발생한다.")
@Test
void throwsBadRequest_whenCurrentPasswordIsNull() {
// arrange
String newPassword = "NewPass456!";

// act
CoreException exception = assertThrows(CoreException.class, () ->
passwordPolicy.validateForChange(null, newPassword, BIRTH_DATE)
);

// assert
assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
assertThat(exception.getMessage()).contains("현재 비밀번호는 비어있을 수 없습니다");
}

@DisplayName("현재 비밀번호가 빈 문자열이면, BAD_REQUEST 예외가 발생한다.")
@Test
void throwsBadRequest_whenCurrentPasswordIsBlank() {
// arrange
String newPassword = "NewPass456!";

// act
CoreException exception = assertThrows(CoreException.class, () ->
passwordPolicy.validateForChange(" ", newPassword, BIRTH_DATE)
);

// assert
assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
assertThat(exception.getMessage()).contains("현재 비밀번호는 비어있을 수 없습니다");
}

@DisplayName("새 비밀번호에 생년월일이 포함되면, BAD_REQUEST 예외가 발생한다.")
@Test
void throwsBadRequest_whenNewPasswordContainsBirthDate() {
Expand Down
Loading