Conversation
|
Warning Rate limit exceeded@ohyuchan123 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 40 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (4)
워크스루이 풀 리퀘스트는 사용자 프로필 및 비밀번호 업데이트 기능을 추가하는 변경 사항을 포함합니다. 보안 구성에서 변경 사항
시퀀스 다이어그램sequenceDiagram
participant Client
participant ProfileController
participant MemberService
participant MemberRepository
participant Member
Client->>ProfileController: 프로필 업데이트 요청
ProfileController->>MemberService: updateProfile(email, nickname, intro)
MemberService->>MemberRepository: findByEmail(email)
MemberRepository-->>MemberService: Member 객체
MemberService->>Member: updateProfile(nickname, intro)
Member-->>MemberService: 업데이트된 Member
MemberService-->>ProfileController: 업데이트된 Member
ProfileController-->>Client: 프로필 응답
관련 가능성 있는 PR
토끼의 시
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (1)
src/main/java/com/mycom/socket/go_socket/entity/Member.java (1)
59-61: 비밀번호 업데이트 시 유효성 검증 추가비밀번호 업데이트 시 인코딩된 비밀번호가 null이 아닌지 검증이 필요합니다.
public void updatePassword(String encodedPassword) { + if (encodedPassword == null || encodedPassword.isBlank()) { + throw new IllegalArgumentException("비밀번호는 null이거나 빈 값일 수 없습니다."); + } this.password = encodedPassword; }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/main/java/com/mycom/socket/auth/config/SecurityConfig.java(1 hunks)src/main/java/com/mycom/socket/go_socket/controller/ProfileController.java(1 hunks)src/main/java/com/mycom/socket/go_socket/dto/request/PasswordUpdateRequest.java(1 hunks)src/main/java/com/mycom/socket/go_socket/dto/request/ProfileUpdateRequest.java(1 hunks)src/main/java/com/mycom/socket/go_socket/entity/Member.java(1 hunks)src/main/java/com/mycom/socket/go_socket/service/MemberService.java(2 hunks)
| public record ProfileUpdateRequest( | ||
| String nickname, | ||
| String intro | ||
| ) {} No newline at end of file |
There was a problem hiding this comment.
🛠️ Refactor suggestion
필드 유효성 검증 추가 필요
프로필 업데이트 요청 DTO에 다음과 같은 유효성 검증 어노테이션을 추가하는 것이 좋습니다:
public record ProfileUpdateRequest(
+ @NotBlank(message = "닉네임은 필수입니다")
+ @Size(min = 2, max = 20, message = "닉네임은 2자 이상 20자 이하여야 합니다")
String nickname,
+ @Size(max = 100, message = "자기소개는 100자를 초과할 수 없습니다")
String intro
) {}Committable suggestion skipped: line range outside the PR's diff.
| public record PasswordUpdateRequest( | ||
| String currentPassword, | ||
| String newPassword | ||
| ) {} |
There was a problem hiding this comment.
🛠️ Refactor suggestion
비밀번호 유효성 검증 및 보안 규칙 추가 필요
비밀번호 업데이트 요청 DTO에 다음과 같은 보안 검증을 추가해야 합니다:
public record PasswordUpdateRequest(
+ @NotBlank(message = "현재 비밀번호는 필수입니다")
String currentPassword,
+ @NotBlank(message = "새 비밀번호는 필수입니다")
+ @Pattern(
+ regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$",
+ message = "비밀번호는 8자 이상이며, 영문자, 숫자, 특수문자를 포함해야 합니다"
+ )
String newPassword
) {}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public record PasswordUpdateRequest( | |
| String currentPassword, | |
| String newPassword | |
| ) {} | |
| public record PasswordUpdateRequest( | |
| @NotBlank(message = "현재 비밀번호는 필수입니다") | |
| String currentPassword, | |
| @NotBlank(message = "새 비밀번호는 필수입니다") | |
| @Pattern( | |
| regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$", | |
| message = "비밀번호는 8자 이상이며, 영문자, 숫자, 특수문자를 포함해야 합니다" | |
| ) | |
| String newPassword | |
| ) {} |
| if (!passwordEncoder.matches(currentPassword, member.getPassword())) { | ||
| throw new NotFoundException("사용자를 찾을 수 없습니다."); | ||
| } |
There was a problem hiding this comment.
보안 개선: 비밀번호 오류와 사용자 없음에 대한 예외 구분 필요
현재 구현은 사용자를 찾을 수 없는 경우와 비밀번호가 일치하지 않는 경우에 동일한 예외를 발생시킵니다. 이는 보안상 좋지 않은 방식입니다.
- if (!passwordEncoder.matches(currentPassword, member.getPassword())) {
- throw new NotFoundException("사용자를 찾을 수 없습니다.");
- }
+ if (!passwordEncoder.matches(currentPassword, member.getPassword())) {
+ throw new InvalidPasswordException("현재 비밀번호가 일치하지 않습니다.");
+ }Committable suggestion skipped: line range outside the PR's diff.
| @Transactional | ||
| public void updatePassword(String email, String currentPassword, String newPassword) { | ||
| Member member = memberRepository.findByEmail(email) | ||
| .orElseThrow(() -> new NotFoundException("사용자를 찾을 수 없습니다.")); | ||
|
|
||
| if (!passwordEncoder.matches(currentPassword, member.getPassword())) { | ||
| throw new NotFoundException("사용자를 찾을 수 없습니다."); | ||
| } | ||
|
|
||
| member.updatePassword(passwordEncoder.encode(newPassword)); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
신규 비밀번호 검증 로직 추가 필요
현재 비밀번호와 동일한 새 비밀번호를 허용하는 문제가 있습니다. 또한 이전 비밀번호 재사용에 대한 검증이 없습니다.
@Transactional
public void updatePassword(String email, String currentPassword, String newPassword) {
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new NotFoundException("사용자를 찾을 수 없습니다."));
if (!passwordEncoder.matches(currentPassword, member.getPassword())) {
- throw new NotFoundException("사용자를 찾을 수 없습니다.");
+ throw new InvalidPasswordException("현재 비밀번호가 일치하지 않습니다.");
}
+ if (passwordEncoder.matches(newPassword, member.getPassword())) {
+ throw new InvalidPasswordException("새 비밀번호는 현재 비밀번호와 달라야 합니다.");
+ }
+
member.updatePassword(passwordEncoder.encode(newPassword));
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Transactional | |
| public void updatePassword(String email, String currentPassword, String newPassword) { | |
| Member member = memberRepository.findByEmail(email) | |
| .orElseThrow(() -> new NotFoundException("사용자를 찾을 수 없습니다.")); | |
| if (!passwordEncoder.matches(currentPassword, member.getPassword())) { | |
| throw new NotFoundException("사용자를 찾을 수 없습니다."); | |
| } | |
| member.updatePassword(passwordEncoder.encode(newPassword)); | |
| } | |
| @Transactional | |
| public void updatePassword(String email, String currentPassword, String newPassword) { | |
| Member member = memberRepository.findByEmail(email) | |
| .orElseThrow(() -> new NotFoundException("사용자를 찾을 수 없습니다.")); | |
| if (!passwordEncoder.matches(currentPassword, member.getPassword())) { | |
| throw new InvalidPasswordException("현재 비밀번호가 일치하지 않습니다."); | |
| } | |
| if (passwordEncoder.matches(newPassword, member.getPassword())) { | |
| throw new InvalidPasswordException("새 비밀번호는 현재 비밀번호와 달라야 합니다."); | |
| } | |
| member.updatePassword(passwordEncoder.encode(newPassword)); | |
| } |
| public void updateProfile(String nickname, String intro) { | ||
| this.nickname = nickname; | ||
| this.intro = intro; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
프로필 이미지 URL 업데이트 메소드 누락
프로필 이미지 URL 필드가 존재하지만 업데이트 메소드가 누락되었습니다.
public void updateProfile(String nickname, String intro) {
this.nickname = nickname;
this.intro = intro;
}
+
+ public void updateProfileImage(String profileImgUrl) {
+ this.profileImgUrl = profileImgUrl;
+ }Committable suggestion skipped: line range outside the PR's diff.
| @PutMapping | ||
| public ProfileResponse updateProfile( | ||
| @AuthenticationPrincipal MemberDetails memberDetails, | ||
| @RequestBody ProfileUpdateRequest request | ||
| ) { | ||
| Member updatedMember = memberService.updateProfile( | ||
| memberDetails.getMember().getEmail(), | ||
| request.nickname(), | ||
| request.intro() | ||
| ); | ||
| return ProfileResponse.of(updatedMember); | ||
| } |
There was a problem hiding this comment.
프로필 업데이트 엔드포인트의 유효성 검증 추가 필요
프로필 업데이트 메서드에 입력값 유효성 검증이 누락되어 있습니다. 닉네임의 길이 제한이나 특수문자 제한 등의 검증이 필요합니다.
다음과 같이 수정하는 것을 제안합니다:
@PutMapping
public ProfileResponse updateProfile(
@AuthenticationPrincipal MemberDetails memberDetails,
- @RequestBody ProfileUpdateRequest request
+ @RequestBody @Valid ProfileUpdateRequest request
) {ProfileUpdateRequest에 다음과 같은 제약조건을 추가하세요:
public record ProfileUpdateRequest(
@NotBlank(message = "닉네임은 필수입니다")
@Size(min = 2, max = 20, message = "닉네임은 2-20자 사이여야 합니다")
@Pattern(regexp = "^[a-zA-Z0-9가-힣]*$", message = "닉네임은 한글, 영문, 숫자만 가능합니다")
String nickname,
@Size(max = 200, message = "자기소개는 200자를 초과할 수 없습니다")
String intro
) {}| @PutMapping("/password") | ||
| public void updatePassword( | ||
| @AuthenticationPrincipal MemberDetails memberDetails, | ||
| @RequestBody PasswordUpdateRequest request | ||
| ) { | ||
| memberService.updatePassword( | ||
| memberDetails.getMember().getEmail(), | ||
| request.currentPassword(), | ||
| request.newPassword() | ||
| ); | ||
| } |
There was a problem hiding this comment.
비밀번호 변경 엔드포인트의 보안 강화 필요
비밀번호 변경 로직에 다음과 같은 보안 개선이 필요합니다:
- 비밀번호 복잡도 검증
- 이전 비밀번호와 동일한지 확인
- 응답 상태 코드 명시
다음과 같이 수정을 제안합니다:
@PutMapping("/password")
+ @ResponseStatus(HttpStatus.NO_CONTENT)
public void updatePassword(
@AuthenticationPrincipal MemberDetails memberDetails,
- @RequestBody PasswordUpdateRequest request
+ @RequestBody @Valid PasswordUpdateRequest request
) {PasswordUpdateRequest에 다음과 같은 제약조건을 추가하세요:
public record PasswordUpdateRequest(
@NotBlank(message = "현재 비밀번호는 필수입니다")
String currentPassword,
@NotBlank(message = "새 비밀번호는 필수입니다")
@Pattern(
regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,}$",
message = "비밀번호는 8자 이상이며, 영문자, 숫자, 특수문자를 포함해야 합니다"
)
String newPassword
) {}| .authorizeHttpRequests(auth -> auth | ||
| .requestMatchers( | ||
| "/","/api/auth/**", "/swagger-ui/**", "/v3/api-docs/**" | ||
| "/","/api/auth/**", "/api/profile/**", "/swagger-ui/**", "/v3/api-docs/**" |
There was a problem hiding this comment.
보안 설정 변경 필요: 프로필 엔드포인트 인증 필수
프로필 관련 엔드포인트(/api/profile/**)를 인증 없이 접근 가능하도록 설정한 것은 보안상 위험합니다. 프로필 수정은 인증된 사용자만 가능해야 합니다.
다음과 같이 수정을 제안합니다:
.requestMatchers(
- "/","/api/auth/**", "/api/profile/**", "/swagger-ui/**", "/v3/api-docs/**"
+ "/","/api/auth/**", "/swagger-ui/**", "/v3/api-docs/**"
).permitAll()추가로 특정 프로필 엔드포인트에 대한 세분화된 권한 설정이 필요합니다:
.requestMatchers(HttpMethod.GET, "/api/profile/**").authenticated()
.requestMatchers(HttpMethod.PUT, "/api/profile/**").authenticated()
📌 관련 이슈
#32 사용자 프로필 수정
✨ 과제 내용
사요자는 자신의 프로필을 수정할 수 있습니다.
추가적으로 구현해야 되는 부분
📸 스크린샷(선택)
📚 레퍼런스 (또는 새로 알게 된 내용) 혹은 궁금한 사항들
Summary by CodeRabbit
새로운 기능
보안 개선
/api/profile/**경로에 대한 접근 권한 설정 업데이트기타 변경사항