From 8cdcc81aafcdcafe2a24f725427a384c37766bbb Mon Sep 17 00:00:00 2001 From: sdw086 Date: Fri, 15 May 2026 17:37:35 +0900 Subject: [PATCH] =?UTF-8?q?[api]=20=ED=9A=8C=EC=9B=90=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=ED=99=95=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/modules/user/UserController.java | 50 +++++++++++++++++-- .../user/dto/UserPasswordChangeDto.java | 12 +++++ .../user/dto/UserPasswordCheckDto.java | 11 ++++ .../user/form/UserPasswordChangeForm.java | 22 ++++++++ .../user/form/UserPasswordCheckForm.java | 19 +++++++ .../api/modules/user/mapper/UserMapper.java | 3 ++ .../api/modules/user/service/UserService.java | 38 ++++++++++++++ .../modules/user/vo/UserPasswordCheckVo.java | 14 ++++++ src/main/resources/mapper/User/UserMapper.xml | 10 ++++ 9 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/alist/api/modules/user/dto/UserPasswordChangeDto.java create mode 100644 src/main/java/com/alist/api/modules/user/dto/UserPasswordCheckDto.java create mode 100644 src/main/java/com/alist/api/modules/user/form/UserPasswordChangeForm.java create mode 100644 src/main/java/com/alist/api/modules/user/form/UserPasswordCheckForm.java create mode 100644 src/main/java/com/alist/api/modules/user/vo/UserPasswordCheckVo.java diff --git a/src/main/java/com/alist/api/modules/user/UserController.java b/src/main/java/com/alist/api/modules/user/UserController.java index d20a676..cde3643 100644 --- a/src/main/java/com/alist/api/modules/user/UserController.java +++ b/src/main/java/com/alist/api/modules/user/UserController.java @@ -3,19 +3,20 @@ package com.alist.api.modules.user; import com.alist.api.common.response.ApiResponse; import com.alist.api.common.response.ApiResponseCode; import com.alist.api.modules.user.form.MigrationUserForm; +import com.alist.api.modules.user.form.UserPasswordChangeForm; +import com.alist.api.modules.user.form.UserPasswordCheckForm; import com.alist.api.modules.user.form.UserSignupForm; +import com.alist.api.modules.user.mapper.UserMapper; import com.alist.api.modules.user.service.UserService; import com.alist.api.modules.user.vo.MigrationUserVo; +import com.alist.api.modules.user.vo.UserPasswordCheckVo; import com.alist.api.modules.user.vo.UserVo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Tag(name = "05. 사용자 관리", description = "사용자 회원가입 및 관리 API") @Slf4j @@ -63,4 +64,45 @@ public class UserController { return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "이전 회원"); } + @Operation( + summary = "사용자 비밀번호 확인", + description = "로그인한 사용자의 현재 비밀번호가 일치하는지 확인합니다." + ) + @PostMapping("/password/check") + public ResponseEntity> passwordCheck( + @Valid @RequestBody UserPasswordCheckForm userPasswordCheckForm + ) { + UserPasswordCheckVo result = userService.selectPasswordCheck(userPasswordCheckForm.toUserPasswordCheckDto()); + + if (!result.isPasswordMatched()) { + if (result.getResultCode() == 4003) { + return ApiResponse.entity(result, ApiResponseCode.CODE_4001); + } else if (result.getResultCode() == 2003) { + return ApiResponse.entity(result, ApiResponseCode.CODE_2003); + } + } + + return ApiResponse.entity(result, ApiResponseCode.CODE_200); + } + + @Operation( + summary = "사용자 비밀번호 수정", + description = "로그인한 사용자의 현재 비밀번호를 확인한 뒤 새 비밀번호로 변경합니다." + ) + @PatchMapping("/password") + public ResponseEntity> updatePassword( + @Valid @RequestBody UserPasswordChangeForm userPasswordChangeForm + ) { + UserPasswordChangeVo result = userService.updatePassword(userPasswordChangeForm.toUserPasswordChangeDto()); + + if (!result.isPasswordChanged()) { + if (result.getResultCode() == 4003 || result.getResultCode() == 4001) { + return ApiResponse.entity(result, ApiResponseCode.CODE_4001); + } + + return ApiResponse.entity(result, ApiResponseCode.CODE_2003); + } + + return ApiResponse.entity(result, ApiResponseCode.CODE_2005, "비밀번호 변경"); + } } \ No newline at end of file diff --git a/src/main/java/com/alist/api/modules/user/dto/UserPasswordChangeDto.java b/src/main/java/com/alist/api/modules/user/dto/UserPasswordChangeDto.java new file mode 100644 index 0000000..24c11a8 --- /dev/null +++ b/src/main/java/com/alist/api/modules/user/dto/UserPasswordChangeDto.java @@ -0,0 +1,12 @@ +package com.alist.api.modules.user.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserPasswordChangeDto { + private Integer userTokenIdx; + private String currentPassword; + private String newPassword; +} diff --git a/src/main/java/com/alist/api/modules/user/dto/UserPasswordCheckDto.java b/src/main/java/com/alist/api/modules/user/dto/UserPasswordCheckDto.java new file mode 100644 index 0000000..4ef3a49 --- /dev/null +++ b/src/main/java/com/alist/api/modules/user/dto/UserPasswordCheckDto.java @@ -0,0 +1,11 @@ +package com.alist.api.modules.user.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserPasswordCheckDto { + private Integer userTokenIdx; + private String password; +} diff --git a/src/main/java/com/alist/api/modules/user/form/UserPasswordChangeForm.java b/src/main/java/com/alist/api/modules/user/form/UserPasswordChangeForm.java new file mode 100644 index 0000000..373cb48 --- /dev/null +++ b/src/main/java/com/alist/api/modules/user/form/UserPasswordChangeForm.java @@ -0,0 +1,22 @@ +package com.alist.api.modules.user.form; + +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserPasswordChangeForm { + @NotBlank(message = "현재 비밀번호는 필수입니다.") + private String currentPassword; + + @NotBlank(message = "새 비밀번호는 필수입니다.") + private String newPassword; + + public UserPasswordChangeDto toUserPasswordChangeDto() { + UserPasswordChangeDto dto = new UserPasswordChangeDto(); + dto.setCurrentPassword(currentPassword); + dto.setNewPassword(newPassword); + return dto; + } +} diff --git a/src/main/java/com/alist/api/modules/user/form/UserPasswordCheckForm.java b/src/main/java/com/alist/api/modules/user/form/UserPasswordCheckForm.java new file mode 100644 index 0000000..724019d --- /dev/null +++ b/src/main/java/com/alist/api/modules/user/form/UserPasswordCheckForm.java @@ -0,0 +1,19 @@ +package com.alist.api.modules.user.form; + +import com.alist.api.modules.user.dto.UserPasswordCheckDto; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserPasswordCheckForm { + @NotBlank(message = "비밀번호는 필수입니다.") + private String password; + + public UserPasswordCheckDto toUserPasswordCheckDto() { + UserPasswordCheckDto userPasswordCheckDto = new UserPasswordCheckDto(); + userPasswordCheckDto.setPassword(password); + return userPasswordCheckDto; + } +} diff --git a/src/main/java/com/alist/api/modules/user/mapper/UserMapper.java b/src/main/java/com/alist/api/modules/user/mapper/UserMapper.java index 61d7c1f..b1258a4 100644 --- a/src/main/java/com/alist/api/modules/user/mapper/UserMapper.java +++ b/src/main/java/com/alist/api/modules/user/mapper/UserMapper.java @@ -2,6 +2,7 @@ package com.alist.api.modules.user.mapper; import com.alist.api.modules.user.dto.UserDto; import com.alist.api.modules.user.dto.UserTokenDto; +import com.alist.api.modules.user.vo.UserVo; import org.apache.ibatis.annotations.Mapper; @Mapper @@ -11,4 +12,6 @@ public interface UserMapper { int insertUserSignup(UserDto userDto); int insertUserTokenSignup(UserTokenDto userTokenDto); + + UserVo selectUserByUserIdx(Integer userIdx); } diff --git a/src/main/java/com/alist/api/modules/user/service/UserService.java b/src/main/java/com/alist/api/modules/user/service/UserService.java index aa068a6..21bf4b5 100644 --- a/src/main/java/com/alist/api/modules/user/service/UserService.java +++ b/src/main/java/com/alist/api/modules/user/service/UserService.java @@ -1,6 +1,7 @@ package com.alist.api.modules.user.service; import com.alist.api.common.utils.ApiKeyGenerator; +import com.alist.api.common.utils.SecurityUtil; import com.alist.api.modules.migration.alist.user.dto.AlistUserDto; import com.alist.api.modules.migration.alist.user.service.AlistUserService; import com.alist.api.modules.migration.alist.user.vo.AlistUserVo; @@ -8,9 +9,11 @@ import com.alist.api.modules.migration.eltown.user.dto.EltownUserDto; import com.alist.api.modules.migration.eltown.user.service.EltownUserService; import com.alist.api.modules.migration.eltown.user.vo.EltownUserVo; import com.alist.api.modules.user.dto.UserDto; +import com.alist.api.modules.user.dto.UserPasswordCheckDto; import com.alist.api.modules.user.dto.UserTokenDto; import com.alist.api.modules.user.mapper.UserMapper; import com.alist.api.modules.user.vo.MigrationUserVo; +import com.alist.api.modules.user.vo.UserPasswordCheckVo; import com.alist.api.modules.user.vo.UserVo; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DuplicateKeyException; @@ -107,4 +110,39 @@ public class UserService { return result; } + + @Transactional(readOnly = true) + public UserPasswordCheckVo selectPasswordCheck(UserPasswordCheckDto userPasswordCheckDto) { + UserPasswordCheckVo result = new UserPasswordCheckVo(); + + Integer userTokenIdx = SecurityUtil.getLoginUserTokenIdx(); + userPasswordCheckDto.setUserTokenIdx(userTokenIdx); + + if (userTokenIdx == null || userPasswordCheckDto.getPassword() == null) { + result.setPasswordMatched(false); + result.setResultCode(4003); + return result; + } + + UserVo userVo = userMapper.selectUserByUserIdx(userPasswordCheckDto.getUserTokenIdx()); + + if (userVo == null || userVo.getPassword() == null) { + result.setPasswordMatched(false); + result.setResultCode(2003); + return result; + } + + boolean matched = passwordEncoder.matches(userPasswordCheckDto.getPassword(), userVo.getPassword()); + + if (!matched) { + result.setPasswordMatched(false); + result.setResultCode(2003); + return result; + } + + result.setPasswordMatched(true); + result.setResultCode(200); + + return result; + } } diff --git a/src/main/java/com/alist/api/modules/user/vo/UserPasswordCheckVo.java b/src/main/java/com/alist/api/modules/user/vo/UserPasswordCheckVo.java new file mode 100644 index 0000000..bb5d85b --- /dev/null +++ b/src/main/java/com/alist/api/modules/user/vo/UserPasswordCheckVo.java @@ -0,0 +1,14 @@ +package com.alist.api.modules.user.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UserPasswordCheckVo { + private boolean passwordMatched; + + @JsonIgnore + private Integer resultCode; +} diff --git a/src/main/resources/mapper/User/UserMapper.xml b/src/main/resources/mapper/User/UserMapper.xml index 296f1fd..d273b46 100644 --- a/src/main/resources/mapper/User/UserMapper.xml +++ b/src/main/resources/mapper/User/UserMapper.xml @@ -20,4 +20,14 @@ where id = #{id} + +