Skip to content

Commit e4a1912

Browse files
authored
✨ [feat] 사용자 회원탈퇴, 닉네임 수정 (#40)
* ✨ feat: 회원 탈퇴 기능 구현 * ✨ feat: 닉네임 수정 기능 구현 * chore: Java 스타일 수정 * 🐛 fix: @controller -> @RestController 수정 --------- Co-authored-by: github-actions <>
1 parent 0ba0181 commit e4a1912

File tree

5 files changed

+88
-2
lines changed

5 files changed

+88
-2
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
}

backend/src/main/java/io/f1/backend/global/util/SecurityUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import io.f1.backend.domain.user.dto.UserPrincipal;
44
import io.f1.backend.domain.user.entity.User;
55

6+
import jakarta.servlet.http.HttpSession;
7+
68
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
79
import org.springframework.security.core.Authentication;
810
import org.springframework.security.core.context.SecurityContextHolder;
@@ -37,4 +39,15 @@ public static Long getCurrentUserId() {
3739
public static String getCurrentUserNickname() {
3840
return getCurrentUserPrincipal().getUserNickname();
3941
}
42+
43+
public static void logout(HttpSession session) {
44+
if (session != null) {
45+
session.invalidate();
46+
}
47+
clearAuthentication();
48+
}
49+
50+
private static void clearAuthentication() {
51+
SecurityContextHolder.clearContext();
52+
}
4053
}

0 commit comments

Comments
 (0)