Skip to content

Commit 0f52704

Browse files
committed
Merge remote-tracking branch 'origin/dev' into feat/20
2 parents 9157f7c + 509026e commit 0f52704

File tree

15 files changed

+317
-4
lines changed

15 files changed

+317
-4
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.f1.backend.domain.user.api;
2+
3+
import static io.f1.backend.global.util.SecurityUtils.logout;
4+
5+
import io.f1.backend.domain.user.app.UserService;
6+
import io.f1.backend.domain.user.dto.SignupRequestDto;
7+
import io.f1.backend.domain.user.dto.UserPrincipal;
8+
9+
import jakarta.servlet.http.HttpSession;
10+
11+
import lombok.RequiredArgsConstructor;
12+
13+
import org.springframework.http.ResponseEntity;
14+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
15+
import org.springframework.web.bind.annotation.DeleteMapping;
16+
import org.springframework.web.bind.annotation.PutMapping;
17+
import org.springframework.web.bind.annotation.RequestBody;
18+
import org.springframework.web.bind.annotation.RequestMapping;
19+
import org.springframework.web.bind.annotation.RestController;
20+
21+
@RestController
22+
@RequiredArgsConstructor
23+
@RequestMapping("/user/me")
24+
public class UserController {
25+
26+
private final UserService userService;
27+
28+
@DeleteMapping
29+
public ResponseEntity<Void> deleteCurrentUser(
30+
@AuthenticationPrincipal UserPrincipal userPrincipal, HttpSession httpSession) {
31+
userService.deleteUser(userPrincipal.getUserId());
32+
logout(httpSession);
33+
return ResponseEntity.noContent().build();
34+
}
35+
36+
@PutMapping
37+
public ResponseEntity<Void> updateNickname(
38+
@AuthenticationPrincipal UserPrincipal userPrincipal,
39+
@RequestBody SignupRequestDto signupRequest,
40+
HttpSession httpSession) {
41+
userService.updateNickname(
42+
userPrincipal.getUserId(), signupRequest.nickname(), httpSession);
43+
return ResponseEntity.noContent().build();
44+
}
45+
}

backend/src/main/java/io/f1/backend/domain/user/app/UserService.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public SignupResponseDto signup(HttpSession session, SignupRequestDto signupRequ
3232
validateNicknameFormat(nickname);
3333
validateNicknameDuplicate(nickname);
3434

35-
User user = updateUserNickname(authenticationUser.userId(), nickname);
35+
User user = initNickname(authenticationUser.userId(), nickname);
3636
updateSessionAfterSignup(session, user);
3737
SecurityUtils.setAuthentication(user);
3838

@@ -68,7 +68,7 @@ public void validateNicknameDuplicate(String nickname) {
6868
}
6969

7070
@Transactional
71-
public User updateUserNickname(Long userId, String nickname) {
71+
public User initNickname(Long userId, String nickname) {
7272
User user =
7373
userRepository
7474
.findById(userId)
@@ -82,4 +82,23 @@ private void updateSessionAfterSignup(HttpSession session, User user) {
8282
session.removeAttribute(OAUTH_USER);
8383
session.setAttribute(USER, AuthenticationUser.from(user));
8484
}
85+
86+
@Transactional
87+
public void deleteUser(Long userId) {
88+
User user =
89+
userRepository
90+
.findById(userId)
91+
.orElseThrow(() -> new RuntimeException("E404001: 존재하지 않는 회원입니다."));
92+
userRepository.delete(user);
93+
}
94+
95+
@Transactional
96+
public void updateNickname(Long userId, String newNickname, HttpSession session) {
97+
validateNicknameFormat(newNickname);
98+
validateNicknameDuplicate(newNickname);
99+
100+
User user = initNickname(userId, newNickname);
101+
session.setAttribute(USER, AuthenticationUser.from(user));
102+
SecurityUtils.setAuthentication(user);
103+
}
85104
}

backend/src/main/java/io/f1/backend/global/config/SecurityConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public SecurityFilterChain userFilterChain(HttpSecurity http) throws Exception {
4242
.permitAll()
4343
.requestMatchers("/ws/**")
4444
.authenticated()
45+
.requestMatchers("/user/me")
46+
.hasRole("USER")
4547
.anyRequest()
4648
.authenticated())
4749
.formLogin(AbstractHttpConfigurer::disable)

backend/src/main/java/io/f1/backend/global/config/WebConfig.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.f1.backend.global.config;
22

3+
import org.springframework.context.annotation.Bean;
34
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.web.filter.HiddenHttpMethodFilter;
46
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
57
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
68

@@ -14,4 +16,9 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
1416
registry.addResourceHandler("/images/thumbnail/**")
1517
.addResourceLocations("file:images/thumbnail/");
1618
}
19+
20+
@Bean
21+
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
22+
return new HiddenHttpMethodFilter();
23+
}
1724
}
Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
package io.f1.backend.global.exception;
22

3+
import io.f1.backend.global.exception.errorcode.ErrorCode;
4+
35
public class CustomException extends RuntimeException {
46

5-
public CustomException(String message) {
6-
super(message);
7+
private final ErrorCode errorCode;
8+
9+
public CustomException(ErrorCode errorCode) {
10+
super(errorCode.getMessage());
11+
this.errorCode = errorCode;
12+
}
13+
14+
public ErrorCode getErrorCode() {
15+
return errorCode;
716
}
817
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.f1.backend.global.exception.errorcode;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
import org.springframework.http.HttpStatus;
7+
8+
@Getter
9+
@RequiredArgsConstructor
10+
public enum AuthErrorCode implements ErrorCode {
11+
UNAUTHORIZED("E401001", HttpStatus.UNAUTHORIZED, "로그인이 필요합니다."),
12+
AUTH_SESSION_NOT_FOUND("E401002", HttpStatus.UNAUTHORIZED, "세션이 존재하지 않습니다. 로그인 후 이용해주세요."),
13+
AUTH_SESSION_EXPIRED("E401003", HttpStatus.UNAUTHORIZED, "세션이 만료되었습니다. 다시 로그인해주세요."),
14+
AUTH_SESSION_LOST("E401004", HttpStatus.UNAUTHORIZED, "세션 정보가 유실되었습니다. 다시 로그인해주세요."),
15+
FORBIDDEN("E403001", HttpStatus.FORBIDDEN, "권한이 없습니다."),
16+
17+
LOGIN_FAILED("E401005", HttpStatus.UNAUTHORIZED, "아이디 또는 비밀번호가 일치하지 않습니다.");
18+
19+
private final String code;
20+
21+
private final HttpStatus httpStatus;
22+
23+
private final String message;
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.f1.backend.global.exception.errorcode;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
import org.springframework.http.HttpStatus;
7+
8+
@Getter
9+
@RequiredArgsConstructor
10+
public enum CommonErrorCode implements ErrorCode {
11+
BAD_REQUEST_DATA("E400001", HttpStatus.BAD_REQUEST, "잘못된 요청 데이터입니다."),
12+
INVALID_PAGINATION("E400006", HttpStatus.BAD_REQUEST, "page와 size는 1 이상의 정수여야 합니다."),
13+
INTERNAL_SERVER_ERROR(
14+
"E500001", HttpStatus.INTERNAL_SERVER_ERROR, "서버에러가 발생했습니다. 관리자에게 문의해주세요."),
15+
INVALID_JSON_FORMAT("E400008", HttpStatus.BAD_REQUEST, "요청 형식이 올바르지 않습니다. JSON 문법을 확인해주세요.");
16+
17+
private final String code;
18+
19+
private final HttpStatus httpStatus;
20+
21+
private final String message;
22+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.f1.backend.global.exception.errorcode;
2+
3+
import org.springframework.http.HttpStatus;
4+
5+
public interface ErrorCode {
6+
7+
String getCode();
8+
9+
HttpStatus getHttpStatus();
10+
11+
String getMessage();
12+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.f1.backend.global.exception.errorcode;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
import org.springframework.http.HttpStatus;
7+
8+
@Getter
9+
@RequiredArgsConstructor
10+
public enum QuestionErrorCode implements ErrorCode {
11+
QUESTION_NOT_FOUND("E404003", HttpStatus.NOT_FOUND, "존재하지 않는 문제입니다.");
12+
13+
private final String code;
14+
15+
private final HttpStatus httpStatus;
16+
17+
private final String message;
18+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.f1.backend.global.exception.errorcode;
2+
3+
import lombok.Getter;
4+
import lombok.RequiredArgsConstructor;
5+
6+
import org.springframework.http.HttpStatus;
7+
8+
@Getter
9+
@RequiredArgsConstructor
10+
public enum QuizErrorCode implements ErrorCode {
11+
FILE_SIZE_TOO_LARGE("E400005", HttpStatus.BAD_REQUEST, "파일 크기가 너무 큽니다."),
12+
UNSUPPORTED_MEDIA_TYPE("E415001", HttpStatus.UNSUPPORTED_MEDIA_TYPE, "지원하지 않는 파일 형식입니다."),
13+
INVALID_FILTER("E400007", HttpStatus.BAD_REQUEST, "title 또는 creator 중 하나만 입력 가능합니다."),
14+
QUIZ_NOT_FOUND("E404002", HttpStatus.NOT_FOUND, "존재하지 않는 퀴즈입니다.");
15+
16+
private final String code;
17+
18+
private final HttpStatus httpStatus;
19+
20+
private final String message;
21+
}

0 commit comments

Comments
 (0)