diff --git a/src/main/java/com/codeit/todo/common/exception/user/UpdatePasswordException.java b/src/main/java/com/codeit/todo/common/exception/user/UpdatePasswordException.java new file mode 100644 index 0000000..d4b52b3 --- /dev/null +++ b/src/main/java/com/codeit/todo/common/exception/user/UpdatePasswordException.java @@ -0,0 +1,13 @@ +package com.codeit.todo.common.exception.user; + +import com.codeit.todo.common.exception.ApplicationException; +import com.codeit.todo.common.exception.payload.ErrorStatus; + +public class UpdatePasswordException extends ApplicationException { + /** + * @param errorStatus 상태 코드, 메세지, 발생시간을 저장한 객체 + */ + public UpdatePasswordException(ErrorStatus errorStatus) { + super(errorStatus); + } +} diff --git a/src/main/java/com/codeit/todo/domain/User.java b/src/main/java/com/codeit/todo/domain/User.java index 1cf1965..c87138a 100644 --- a/src/main/java/com/codeit/todo/domain/User.java +++ b/src/main/java/com/codeit/todo/domain/User.java @@ -51,4 +51,8 @@ public User(int userId, String name, String email, String password, String profi public void updateProfilePic(String completePicUrl){ this.profilePic = completePicUrl; } + + public void updatePassword(String password){ + this.password = password; + } } diff --git a/src/main/java/com/codeit/todo/service/user/UserService.java b/src/main/java/com/codeit/todo/service/user/UserService.java index 5fcc420..3be3aac 100644 --- a/src/main/java/com/codeit/todo/service/user/UserService.java +++ b/src/main/java/com/codeit/todo/service/user/UserService.java @@ -2,9 +2,11 @@ import com.codeit.todo.web.dto.request.auth.LoginRequest; import com.codeit.todo.web.dto.request.auth.SignUpRequest; +import com.codeit.todo.web.dto.request.auth.UpdatePasswordRequest; import com.codeit.todo.web.dto.request.auth.UpdatePictureRequest; import com.codeit.todo.web.dto.response.auth.ReadUserResponse; import com.codeit.todo.web.dto.response.auth.SignUpResponse; +import com.codeit.todo.web.dto.response.auth.UpdatePasswordResponse; import com.codeit.todo.web.dto.response.auth.UpdatePictureResponse; public interface UserService { @@ -16,4 +18,6 @@ public interface UserService { ReadUserResponse findUserInfo(int userId); UpdatePictureResponse updateProfilePicture(int userId, UpdatePictureRequest pictureRequest); + + UpdatePasswordResponse updatePassword(int userId, UpdatePasswordRequest passwordRequest); } diff --git a/src/main/java/com/codeit/todo/service/user/impl/UserServiceImpl.java b/src/main/java/com/codeit/todo/service/user/impl/UserServiceImpl.java index 6520502..277cc40 100644 --- a/src/main/java/com/codeit/todo/service/user/impl/UserServiceImpl.java +++ b/src/main/java/com/codeit/todo/service/user/impl/UserServiceImpl.java @@ -4,6 +4,7 @@ import com.codeit.todo.common.exception.ApplicationException; import com.codeit.todo.common.exception.payload.ErrorStatus; import com.codeit.todo.common.exception.user.SignUpException; +import com.codeit.todo.common.exception.user.UpdatePasswordException; import com.codeit.todo.common.exception.user.UserNotFoundException; import com.codeit.todo.domain.User; import com.codeit.todo.repository.UserRepository; @@ -11,9 +12,11 @@ import com.codeit.todo.service.user.UserService; import com.codeit.todo.web.dto.request.auth.LoginRequest; import com.codeit.todo.web.dto.request.auth.SignUpRequest; +import com.codeit.todo.web.dto.request.auth.UpdatePasswordRequest; import com.codeit.todo.web.dto.request.auth.UpdatePictureRequest; import com.codeit.todo.web.dto.response.auth.ReadUserResponse; import com.codeit.todo.web.dto.response.auth.SignUpResponse; +import com.codeit.todo.web.dto.response.auth.UpdatePasswordResponse; import com.codeit.todo.web.dto.response.auth.UpdatePictureResponse; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.AuthenticationManager; @@ -40,6 +43,8 @@ public class UserServiceImpl implements UserService { private static final int CONFLICT = 409; private static final int BAD_REQUEST = 400; + private static final int UNAUTHORIZED = 401; + @Transactional @Override @@ -49,12 +54,10 @@ public SignUpResponse signUpUser(SignUpRequest request) { if(userRepository.findByEmail(email).isPresent()) throw new SignUpException(ErrorStatus.toErrorStatus("이미 존재하는 이메일입니다", CONFLICT)); //비밀번호, 비밀번호 확인이 일치하는지 확인 - String password = request.password(); - String passwordCheck = request.passwordCheck(); - if(!password.equals(passwordCheck)) throw new SignUpException(ErrorStatus.toErrorStatus("비밀번호가 일치하지 않습니다", BAD_REQUEST)); + passwordMatchValidation(request.password(), request.passwordCheck()); //비밀번호 암호화 - String encodedPassword = passwordEncoder.encode(password); + String encodedPassword = passwordEncoder.encode(request.password()); //회원가입 시 기본 프로필 이미지 등록 String profilePic = "https://slid-todo.s3.ap-northeast-2.amazonaws.com/auth/default_profilepic_mouse.png"; @@ -113,11 +116,35 @@ public UpdatePictureResponse updateProfilePicture(int userId, UpdatePictureReque return new UpdatePictureResponse(userId); } + @Transactional + @Override + public UpdatePasswordResponse updatePassword(int userId, UpdatePasswordRequest passwordRequest) { + User user = getUser(userId); + + //현재 비밀번호 확인 + String dbPassword = user.getPassword(); + String currentPassword = passwordRequest.currentPassword(); + if(!passwordEncoder.matches(currentPassword, dbPassword)) throw new UpdatePasswordException(ErrorStatus.toErrorStatus("현재 비밀번호가 일치하지 않습니다", UNAUTHORIZED)); + + passwordMatchValidation(passwordRequest.newPassword(), passwordRequest.newPasswordCheck()); + + //비밀번호 암호화 + String encodedPassword = passwordEncoder.encode(passwordRequest.newPassword()); + user.updatePassword(encodedPassword); + + return new UpdatePasswordResponse(userId); + } + private User getUser(int userId){ User user = userRepository.findById(userId) .orElseThrow(()-> new UserNotFoundException(String.valueOf(userId), "User")); return user; } + //비밀번호, 비밀번호 확인이 일치하는지 확인 + private void passwordMatchValidation(String password, String passwordCheck){ + if(!password.equals(passwordCheck)) throw new UpdatePasswordException(ErrorStatus.toErrorStatus("비밀번호가 일치하지 않습니다", BAD_REQUEST)); + } + } diff --git a/src/main/java/com/codeit/todo/web/controller/AuthController.java b/src/main/java/com/codeit/todo/web/controller/AuthController.java index bf6440e..e0367ba 100644 --- a/src/main/java/com/codeit/todo/web/controller/AuthController.java +++ b/src/main/java/com/codeit/todo/web/controller/AuthController.java @@ -5,8 +5,10 @@ import com.codeit.todo.service.user.UserService; import com.codeit.todo.web.dto.request.auth.LoginRequest; import com.codeit.todo.web.dto.request.auth.SignUpRequest; +import com.codeit.todo.web.dto.request.auth.UpdatePasswordRequest; import com.codeit.todo.web.dto.request.auth.UpdatePictureRequest; import com.codeit.todo.web.dto.response.Response; +import com.codeit.todo.web.dto.response.auth.UpdatePasswordResponse; import com.codeit.todo.web.dto.response.auth.UpdatePictureResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -23,9 +25,6 @@ public class AuthController { private final UserService userService; - private final JwtTokenProvider jwtTokenProvider; - - @Operation(summary = "회원가입", description = "이름, 이메일, 비밀번호로 회원가입") @ApiResponses(value = { @@ -75,4 +74,20 @@ public Response updateUserProfilePicture( int userId = userDetails.getUserId(); return Response.ok(userService.updateProfilePicture(userId, pictureRequest)); } + + @Operation( + summary = "비밀번호 변정", + description = "기존 비밀번호를 확인하고, 새로운 비밀번호로 변경" + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "변경 성공") + }) + @PutMapping("/password") + public Response updateUserPassword( + @AuthenticationPrincipal CustomUserDetails userDetails, + @RequestBody UpdatePasswordRequest passwordRequest + ) { + int userId = userDetails.getUserId(); + return Response.ok(userService.updatePassword(userId, passwordRequest)); + } } diff --git a/src/main/java/com/codeit/todo/web/dto/request/auth/UpdatePasswordRequest.java b/src/main/java/com/codeit/todo/web/dto/request/auth/UpdatePasswordRequest.java new file mode 100644 index 0000000..182d26f --- /dev/null +++ b/src/main/java/com/codeit/todo/web/dto/request/auth/UpdatePasswordRequest.java @@ -0,0 +1,13 @@ +package com.codeit.todo.web.dto.request.auth; + +import jakarta.validation.constraints.NotNull; + +public record UpdatePasswordRequest( + @NotNull + String currentPassword, + @NotNull + String newPassword, + @NotNull + String newPasswordCheck +){ +} diff --git a/src/main/java/com/codeit/todo/web/dto/response/auth/UpdatePasswordResponse.java b/src/main/java/com/codeit/todo/web/dto/response/auth/UpdatePasswordResponse.java new file mode 100644 index 0000000..b90a52d --- /dev/null +++ b/src/main/java/com/codeit/todo/web/dto/response/auth/UpdatePasswordResponse.java @@ -0,0 +1,6 @@ +package com.codeit.todo.web.dto.response.auth; + +public record UpdatePasswordResponse( + int userId +){ +}