Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.be.sportizebe.domain.user.controller;

import com.be.sportizebe.domain.user.dto.request.ChangePasswordRequest;
import com.be.sportizebe.domain.user.dto.request.SignUpRequest;
import com.be.sportizebe.domain.user.dto.request.UpdateProfileRequest;
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
Expand Down Expand Up @@ -64,4 +65,14 @@ public ResponseEntity<BaseResponse<UserInfoResponse>> getMyInfo(
UserInfoResponse response = userService.getUserInfo(userAuthInfo.getId());
return ResponseEntity.ok(BaseResponse.success("사용자 정보 조회 성공", response));
}

@PutMapping("/password")
@Operation(summary = "비밀번호 변경", description = "현재 비밀번호를 확인 후 새 비밀번호로 변경합니다.")
public ResponseEntity<BaseResponse<Void>> changePassword(
@AuthenticationPrincipal UserAuthInfo userAuthInfo,
@RequestBody @Valid ChangePasswordRequest request
) {
userService.changePassword(userAuthInfo.getId(), request);
return ResponseEntity.ok(BaseResponse.success("비밀번호 변경 성공", null));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.be.sportizebe.domain.user.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

@Schema(description = "비밀번호 변경 요청")
public record ChangePasswordRequest(
@Schema(description = "현재 비밀번호")
@NotBlank(message = "현재 비밀번호는 필수입니다.")
String currentPassword,

@Schema(description = "새 비밀번호")
@NotBlank(message = "새 비밀번호는 필수입니다.")
@Size(min = 8, max = 20, message = "비밀번호는 8자 이상 20자 이하로 입력해주세요.")
String newPassword
) {
}
4 changes: 4 additions & 0 deletions src/main/java/com/be/sportizebe/domain/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,8 @@ public void updateProfile(String nickname, String introduce) {
this.nickname = nickname;
this.introduce = introduce;
}

public void updatePassword(String encodedPassword) {
this.password = encodedPassword;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ public enum UserErrorCode implements BaseErrorCode {
USER_NOT_FOUND("USER_0005", "회원을 찾을 수 없습니다.", HttpStatus.NOT_FOUND),

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

private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.be.sportizebe.domain.user.service;

import com.be.sportizebe.domain.user.dto.request.ChangePasswordRequest;
import com.be.sportizebe.domain.user.dto.request.SignUpRequest;
import com.be.sportizebe.domain.user.dto.request.UpdateProfileRequest;
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
Expand All @@ -21,4 +22,7 @@ public interface UserService {

// 사용자 정보 조회
UserInfoResponse getUserInfo(Long userId);

// 비밀번호 변경
void changePassword(Long userId, ChangePasswordRequest request);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.be.sportizebe.domain.user.service;

import com.be.sportizebe.domain.user.dto.request.ChangePasswordRequest;
import com.be.sportizebe.domain.user.dto.request.SignUpRequest;
import com.be.sportizebe.domain.user.dto.request.UpdateProfileRequest;
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
Expand Down Expand Up @@ -27,7 +28,7 @@
public class UserServiceImpl implements UserService {

private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final PasswordEncoder passwordEncoder; // 비밀번호 인코딩 목적
private final UserCacheService userCacheService;
private final S3Service s3Service;

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

return UserInfoResponse.from(userAuthInfo);
}

@Override
@Transactional
public void changePassword(Long userId, ChangePasswordRequest request) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new CustomException(UserErrorCode.USER_NOT_FOUND));

// 현재 비밀번호 확인
if (!passwordEncoder.matches(request.currentPassword(), user.getPassword())) {
throw new CustomException(UserErrorCode.CURRENT_PASSWORD_MISMATCH);
}

// 새 비밀번호가 현재 비밀번호와 동일한지 확인
if (passwordEncoder.matches(request.newPassword(), user.getPassword())) {
throw new CustomException(UserErrorCode.SAME_PASSWORD);
}

// 비밀번호 변경
String encodedNewPassword = passwordEncoder.encode(request.newPassword());
user.updatePassword(encodedNewPassword);

log.info("사용자 비밀번호 변경 완료: userId={}", userId);
}
}