Skip to content

Commit adefb7d

Browse files
committed
✨Feat: 비밀번호 변경 구현
1 parent df938f0 commit adefb7d

File tree

6 files changed

+65
-2
lines changed

6 files changed

+65
-2
lines changed

src/main/java/com/be/sportizebe/domain/user/controller/UserController.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.be.sportizebe.domain.user.controller;
22

3+
import com.be.sportizebe.domain.user.dto.request.ChangePasswordRequest;
34
import com.be.sportizebe.domain.user.dto.request.SignUpRequest;
45
import com.be.sportizebe.domain.user.dto.request.UpdateProfileRequest;
56
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
@@ -64,4 +65,14 @@ public ResponseEntity<BaseResponse<UserInfoResponse>> getMyInfo(
6465
UserInfoResponse response = userService.getUserInfo(userAuthInfo.getId());
6566
return ResponseEntity.ok(BaseResponse.success("사용자 정보 조회 성공", response));
6667
}
68+
69+
@PutMapping("/password")
70+
@Operation(summary = "비밀번호 변경", description = "현재 비밀번호를 확인 후 새 비밀번호로 변경합니다.")
71+
public ResponseEntity<BaseResponse<Void>> changePassword(
72+
@AuthenticationPrincipal UserAuthInfo userAuthInfo,
73+
@RequestBody @Valid ChangePasswordRequest request
74+
) {
75+
userService.changePassword(userAuthInfo.getId(), request);
76+
return ResponseEntity.ok(BaseResponse.success("비밀번호 변경 성공", null));
77+
}
6778
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.be.sportizebe.domain.user.dto.request;
2+
3+
import io.swagger.v3.oas.annotations.media.Schema;
4+
import jakarta.validation.constraints.NotBlank;
5+
import jakarta.validation.constraints.Size;
6+
7+
@Schema(description = "비밀번호 변경 요청")
8+
public record ChangePasswordRequest(
9+
@Schema(description = "현재 비밀번호")
10+
@NotBlank(message = "현재 비밀번호는 필수입니다.")
11+
String currentPassword,
12+
13+
@Schema(description = "새 비밀번호")
14+
@NotBlank(message = "새 비밀번호는 필수입니다.")
15+
@Size(min = 8, max = 20, message = "비밀번호는 8자 이상 20자 이하로 입력해주세요.")
16+
String newPassword
17+
) {
18+
}

src/main/java/com/be/sportizebe/domain/user/entity/User.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,8 @@ public void updateProfile(String nickname, String introduce) {
8080
this.nickname = nickname;
8181
this.introduce = introduce;
8282
}
83+
84+
public void updatePassword(String encodedPassword) {
85+
this.password = encodedPassword;
86+
}
8387
}

src/main/java/com/be/sportizebe/domain/user/exception/UserErrorCode.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public enum UserErrorCode implements BaseErrorCode {
1818
USER_NOT_FOUND("USER_0005", "회원을 찾을 수 없습니다.", HttpStatus.NOT_FOUND),
1919

2020
USER_DELETE_FAILED("USER_0006", "사용자 삭제에 실패했습니다.", HttpStatus.INTERNAL_SERVER_ERROR),
21-
S3_DELETE_FAILED("USER_0007", "S3 이미지 삭제에 실패했습니다.", HttpStatus.INTERNAL_SERVER_ERROR);
21+
S3_DELETE_FAILED("USER_0007", "S3 이미지 삭제에 실패했습니다.", HttpStatus.INTERNAL_SERVER_ERROR),
22+
CURRENT_PASSWORD_MISMATCH("USER_0009", "현재 비밀번호가 일치하지 않습니다.", HttpStatus.BAD_REQUEST),
23+
SAME_PASSWORD("USER_0010", "새 비밀번호는 현재 비밀번호와 달라야 합니다.", HttpStatus.BAD_REQUEST);
2224

2325
private final String code;
2426
private final String message;

src/main/java/com/be/sportizebe/domain/user/service/UserService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.be.sportizebe.domain.user.service;
22

3+
import com.be.sportizebe.domain.user.dto.request.ChangePasswordRequest;
34
import com.be.sportizebe.domain.user.dto.request.SignUpRequest;
45
import com.be.sportizebe.domain.user.dto.request.UpdateProfileRequest;
56
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
@@ -21,4 +22,7 @@ public interface UserService {
2122

2223
// 사용자 정보 조회
2324
UserInfoResponse getUserInfo(Long userId);
25+
26+
// 비밀번호 변경
27+
void changePassword(Long userId, ChangePasswordRequest request);
2428
}

src/main/java/com/be/sportizebe/domain/user/service/UserServiceImpl.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.be.sportizebe.domain.user.service;
22

3+
import com.be.sportizebe.domain.user.dto.request.ChangePasswordRequest;
34
import com.be.sportizebe.domain.user.dto.request.SignUpRequest;
45
import com.be.sportizebe.domain.user.dto.request.UpdateProfileRequest;
56
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
@@ -27,7 +28,7 @@
2728
public class UserServiceImpl implements UserService {
2829

2930
private final UserRepository userRepository;
30-
private final PasswordEncoder passwordEncoder;
31+
private final PasswordEncoder passwordEncoder; // 비밀번호 인코딩 목적
3132
private final UserCacheService userCacheService;
3233
private final S3Service s3Service;
3334

@@ -119,4 +120,27 @@ public UserInfoResponse getUserInfo(Long userId) {
119120

120121
return UserInfoResponse.from(userAuthInfo);
121122
}
123+
124+
@Override
125+
@Transactional
126+
public void changePassword(Long userId, ChangePasswordRequest request) {
127+
User user = userRepository.findById(userId)
128+
.orElseThrow(() -> new CustomException(UserErrorCode.USER_NOT_FOUND));
129+
130+
// 현재 비밀번호 확인
131+
if (!passwordEncoder.matches(request.currentPassword(), user.getPassword())) {
132+
throw new CustomException(UserErrorCode.CURRENT_PASSWORD_MISMATCH);
133+
}
134+
135+
// 새 비밀번호가 현재 비밀번호와 동일한지 확인
136+
if (passwordEncoder.matches(request.newPassword(), user.getPassword())) {
137+
throw new CustomException(UserErrorCode.SAME_PASSWORD);
138+
}
139+
140+
// 비밀번호 변경
141+
String encodedNewPassword = passwordEncoder.encode(request.newPassword());
142+
user.updatePassword(encodedNewPassword);
143+
144+
log.info("사용자 비밀번호 변경 완료: userId={}", userId);
145+
}
122146
}

0 commit comments

Comments
 (0)