Skip to content

Commit 7bd443e

Browse files
authored
feat(user): 사용자 이름, 비밀번호 수정 기능 추가 / fix(user/security): 보안 설정 수정
feat(user): 사용자 이름, 비밀번호 수정 기능 추가 / fix(user/security): 보안 설정 수정
2 parents 6086c44 + f1b6653 commit 7bd443e

File tree

6 files changed

+136
-3
lines changed

6 files changed

+136
-3
lines changed

backend/src/main/java/com/backend/domain/user/controller/UserController.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
import com.backend.domain.user.dto.UserDto;
44
import com.backend.domain.user.entity.User;
5+
import com.backend.domain.user.service.JwtService;
56
import com.backend.domain.user.service.UserService;
7+
import com.backend.domain.user.util.JwtUtil;
68
import com.backend.global.response.ApiResponse;
79
import jakarta.mail.MessagingException;
10+
import jakarta.servlet.http.HttpServletRequest;
811
import jakarta.validation.Valid;
912
import jakarta.validation.constraints.Email;
1013
import jakarta.validation.constraints.NotBlank;
@@ -17,6 +20,8 @@
1720
@RequiredArgsConstructor
1821
public class UserController {
1922
private final UserService userService;
23+
private final JwtService jwtService;
24+
private final JwtUtil jwtUtil;
2025

2126
/**
2227
* id를 입력받아 회원이 존재하면 해당 회원을 반환하는 api입니다.
@@ -63,6 +68,7 @@ record GetUsersResponse(
6368

6469
@GetMapping("/api/users")
6570
public ApiResponse<GetUsersResponse> getUsers(){
71+
System.out.println("다건 조회");
6672
List<User> users = userService.findByAll();
6773

6874
List<UserDto> userDtoList = users.stream()
@@ -135,6 +141,61 @@ public ApiResponse<DeleteResponse> softDelete(
135141
return ApiResponse.success(new DeleteResponse(new UserDto(softDeleteUser)));
136142
}
137143

144+
145+
/**
146+
* 이름 변경
147+
*/
148+
record ModifyNameRequest (
149+
@NotBlank(message = "이름은 필수 입력값 입니다.")
150+
String name
151+
){
152+
153+
}
154+
record ModifyNameResponse (
155+
UserDto userDto
156+
){
157+
158+
}
159+
@PostMapping("/api/user/name")
160+
public ApiResponse<ModifyNameResponse> modifyName(
161+
HttpServletRequest request,
162+
@Valid @RequestBody ModifyNameRequest modifyNameRequest
163+
){
164+
String email = jwtUtil.getEmail(request);
165+
System.out.println("email: " + email);
166+
System.out.println("변경전 name :" + modifyNameRequest.name);
167+
User user = userService.modifyName(email, modifyNameRequest.name);
168+
169+
System.out.println("변경후 name :" + user.getName());
170+
return ApiResponse.success(new ModifyNameResponse(new UserDto(user)));
171+
}
172+
173+
/**
174+
* 비밀번호 변경
175+
*/
176+
record ModifyPasswordRequest (
177+
@NotBlank(message = "비밀번호는 필수 입력값 입니다.")
178+
String password,
179+
String passwordCheck
180+
){
181+
182+
}
183+
record ModifyPasswordResponse (
184+
UserDto userDto
185+
){
186+
187+
}
188+
@PostMapping("/api/user/password")
189+
public ApiResponse<ModifyPasswordResponse> modifyPassword(
190+
HttpServletRequest request,
191+
@Valid @RequestBody ModifyPasswordRequest modifyPasswordRequest
192+
){
193+
String email = jwtUtil.getEmail(request);
194+
User user = userService.modifyPassword(email, modifyPasswordRequest.password, modifyPasswordRequest.passwordCheck);
195+
return ApiResponse.success(new ModifyPasswordResponse(new UserDto(user)));
196+
}
197+
198+
138199
/**
139200
* 삭제된 유저 복구
140201
*/

backend/src/main/java/com/backend/domain/user/entity/User.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.backend.domain.user.entity;
22

3+
import com.backend.global.exception.BusinessException;
4+
import com.backend.global.exception.ErrorCode;
35
import jakarta.persistence.*;
46
import lombok.Getter;
57
import lombok.NoArgsConstructor;
@@ -58,4 +60,17 @@ public User(String email, String password, String name) {
5860
this.name = name;
5961
}
6062

63+
public void changeName(String name){
64+
if(this.name==null || name.trim().isEmpty()){
65+
throw new BusinessException(ErrorCode.NAME_NOT_FOUND);
66+
}
67+
this.name = name;
68+
}
69+
70+
public void changePassword(String password){
71+
if(this.password==null || password.trim().isEmpty()){
72+
throw new BusinessException(ErrorCode.NAME_NOT_FOUND);
73+
}
74+
this.password = password;
75+
}
6176
}

backend/src/main/java/com/backend/domain/user/service/UserService.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,30 @@ public User restore(@NotBlank String email) {
106106
throw new BusinessException(ErrorCode.VALIDATION_FAILED);
107107
}
108108
}
109+
110+
public User modifyName(String email, @NotBlank(message = "이름은 필수 입력값 입니다.") String name) {
111+
User user = userRepository.findByEmail(email).orElseThrow(() -> new BusinessException(ErrorCode.VALIDATION_FAILED));
112+
user.changeName(name);
113+
return user;
114+
115+
}
116+
117+
public User modifyPassword(String email, @NotBlank(message = "비밀번호는 필수 입력값 입니다.") String password) {
118+
User user = userRepository.findByEmail(email).orElseThrow(() -> new BusinessException(ErrorCode.VALIDATION_FAILED));
119+
user.changePassword(password);
120+
return user;
121+
}
122+
123+
public User modifyPassword(String email, @NotBlank(message = "비밀번호는 필수 입력값 입니다.") String password, String passwordCheck) {
124+
User user = userRepository.findByEmail(email).orElseThrow(() -> new BusinessException(ErrorCode.VALIDATION_FAILED));
125+
126+
if(password.equals(passwordCheck)){
127+
user.changePassword(password);
128+
}else{
129+
throw new BusinessException(ErrorCode.PASSWORD_NOT_EQUAL);
130+
}
131+
132+
133+
return user;
134+
}
109135
}

backend/src/main/java/com/backend/domain/user/util/JwtUtil.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ public String createToken(String email, String name) {
4242
claims.put("name", name);
4343

4444
Date now = new Date();
45+
System.out.println("현재 시간 : " + now.toString());
4546
Date expiration = new Date(now.getTime() + tokenValidityMilliSeconds);
47+
System.out.println("만료 시간 : " + expiration.toString());
4648
return Jwts.builder()
4749
.claims(claims)
4850
.issuedAt(now)

backend/src/main/java/com/backend/global/exception/ErrorCode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public enum ErrorCode {
1616
// ========== user 도메인 에러 ==========
1717
Login_Failed("U001", HttpStatus.BAD_REQUEST, "로그인에 실패했습니다."),
1818
Email_verify_Failed("U002", HttpStatus.BAD_REQUEST, "이메일 인증코드가 일치하지 않습니다"),
19+
NAME_NOT_FOUND("U003", HttpStatus.NOT_FOUND, "이름이 입력되지 않았습니다."),
20+
PASSWORD_NOT_FOUND("U004", HttpStatus.NOT_FOUND, "이름이 입력되지 않았습니다."),
21+
PASSWORD_NOT_EQUAL("U005", HttpStatus.BAD_REQUEST, "비밀번호 확인이 일치하지 않습니다."),
1922

2023
// ========== analysis 도메인 에러 ==========
2124
INVALID_GITHUB_URL("A001", HttpStatus.BAD_REQUEST, "올바른 GitHub 저장소 URL이 아닙니다."),

backend/src/main/java/com/backend/global/security/JwtAuthenticationFilter.java

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
1515
import org.springframework.security.core.Authentication;
1616
import org.springframework.security.core.context.SecurityContextHolder;
17+
import org.springframework.util.AntPathMatcher;
1718
import org.springframework.web.filter.OncePerRequestFilter;
1819

1920
import java.io.IOException;
@@ -37,15 +38,40 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
3738

3839
// JWT 검증이 필요 없는 URL (회원가입, 로그인, 이메일 인증코드 발송,이메일 인증코드 검증)
3940
List<ExcludedRequest> excludedRequests = List.of(
41+
// 개발 도구 (모든 메서드 허용)
42+
new ExcludedRequest("/h2-console/**", null),
43+
new ExcludedRequest("/swagger-ui/**", null),
44+
new ExcludedRequest("/v3/api-docs/**", null),
45+
new ExcludedRequest("/swagger-resources/**", null),
46+
new ExcludedRequest("/webjars/**", null),
47+
48+
// 인증 관련 API
4049
new ExcludedRequest("/api/login", "POST"),
4150
new ExcludedRequest("/api/auth", "POST"),
4251
new ExcludedRequest("/api/verify", "POST"),
43-
new ExcludedRequest("/api/user", "POST")
52+
new ExcludedRequest("/api/user", "POST"),
53+
54+
// 커뮤니티 관련 API
55+
new ExcludedRequest("/api/community/**", null),
56+
57+
new ExcludedRequest("/api/analysis/**", null),
58+
new ExcludedRequest("/api/repositories/**", null),
59+
new ExcludedRequest("/api/ai/complete/**", null)
4460
);
4561

46-
// 요청 경로 + 메서드가 일치하는 경우 필터 스킵
62+
AntPathMatcher pathMatcher = new AntPathMatcher();
63+
4764
boolean excluded = excludedRequests.stream()
48-
.anyMatch(ex -> requestURI.startsWith(ex.path()) && ex.method().equalsIgnoreCase(method));
65+
.anyMatch(ex -> {
66+
//요청 url이 List의 url과 일치하는지 확인(/**도 지원)
67+
boolean pathMatches = pathMatcher.match(ex.path(), requestURI);
68+
69+
// 메서드가 null (모든 메서드)이거나, 메서드가 일치하는 경우
70+
boolean methodMatches = ex.method() == null || ex.method().equalsIgnoreCase(method);
71+
72+
//두 조건이 true일때 JWT인증을 스킵
73+
return pathMatches && methodMatches;
74+
});
4975

5076
if (excluded) {
5177
filterChain.doFilter(request, response);

0 commit comments

Comments
 (0)