-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUserController.java
More file actions
150 lines (133 loc) · 6.15 KB
/
UserController.java
File metadata and controls
150 lines (133 loc) · 6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.rentify.rentify_api.user.controller;
import com.rentify.rentify_api.common.response.ApiResponse;
import com.rentify.rentify_api.post.dto.PostDetailResponse;
import com.rentify.rentify_api.rental.dto.RentalResponse;
import com.rentify.rentify_api.user.dto.CreateUserRequest;
import com.rentify.rentify_api.user.dto.LoginRequest;
import com.rentify.rentify_api.user.dto.PasswordUpdateRequest;
import com.rentify.rentify_api.user.dto.UserResponse;
import com.rentify.rentify_api.user.entity.LoginResponse;
import com.rentify.rentify_api.user.service.UserService;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import java.net.URI;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController implements UserApiDocs {
private final UserService userService;
@Override
@PostMapping
public ResponseEntity<ApiResponse<Void>> createUser(
@RequestHeader(value = "Idempotency-Key") UUID idempotencyKey,
@Valid @RequestBody CreateUserRequest request
) {
Long userId = userService.signup(idempotencyKey, request);
URI location = URI.create("/api/users/" + userId);
return ResponseEntity.created(location)
.body(ApiResponse.success(HttpStatus.CREATED, "회원가입 성공"));
}
@Hidden
@GetMapping("/{id}")
public ResponseEntity<ApiResponse<UserResponse>> getUserById(@PathVariable Long id) {
UserResponse response = userService.getUserInfo(id);
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, response));
}
@PostMapping("/login")
@Override
public ResponseEntity<ApiResponse<Void>> login(
@RequestBody LoginRequest request,
HttpServletResponse httpResponse
) {
LoginResponse response = userService.login(request);
// AccessToken 쿠키 설정
Cookie accessTokenCookie = new Cookie("accessToken", response.getAccessToken());
accessTokenCookie.setHttpOnly(true); // XSS 공격 방지
//accessTokenCookie.setSecure(true); // HTTPS에서만 전송
accessTokenCookie.setPath("/");
accessTokenCookie.setMaxAge(30 * 60); // 30분
httpResponse.addCookie(accessTokenCookie);
// RefreshToken 쿠키 설정
Cookie refreshTokenCookie = new Cookie("refreshToken", response.getRefreshToken());
refreshTokenCookie.setHttpOnly(true);
//refreshTokenCookie.setSecure(true);
refreshTokenCookie.setPath("/");
refreshTokenCookie.setMaxAge(14 * 24 * 60 * 60); // 14일
httpResponse.addCookie(refreshTokenCookie);
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, "로그인 성공"));
}
@PostMapping("/logout")
@Override
public ResponseEntity<ApiResponse<Void>> logout(
@AuthenticationPrincipal Long userId,
HttpServletResponse response
) {
// RefreshToken DB에서 삭제
userService.logout(userId);
// AccessToken 쿠키 삭제
Cookie accessTokenCookie = new Cookie("accessToken", null);
accessTokenCookie.setHttpOnly(true);
accessTokenCookie.setPath("/");
accessTokenCookie.setMaxAge(0); // 즉시 만료
response.addCookie(accessTokenCookie);
// RefreshToken 쿠키 삭제
Cookie refreshTokenCookie = new Cookie("refreshToken", null);
refreshTokenCookie.setHttpOnly(true);
refreshTokenCookie.setPath("/");
refreshTokenCookie.setMaxAge(0); // 즉시 만료
response.addCookie(refreshTokenCookie);
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, "로그아웃 성공"));
}
@Override
@GetMapping("/me/posts")
public ResponseEntity<ApiResponse<Page<PostDetailResponse>>> getMyPosts(
@AuthenticationPrincipal Long userId,
@RequestParam(defaultValue = "false") boolean includeHidden,
@ParameterObject @PageableDefault(sort = "createAt", direction = Sort.Direction.DESC) Pageable pageable
) {
Page<PostDetailResponse> posts = userService.getMyPosts(userId, includeHidden, pageable);
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, posts));
}
@Override
@GetMapping("/me/rentals")
public ResponseEntity<ApiResponse<Page<RentalResponse>>> getMyRentals(
@AuthenticationPrincipal Long userId,
@RequestParam(required = false) String role,
@ParameterObject @PageableDefault(sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable
) {
Page<RentalResponse> rentals = userService.getMyRentals(userId, role, pageable);
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, rentals));
}
@Override
@PatchMapping("/me/password")
public ResponseEntity<ApiResponse<Void>> changePassword(
@AuthenticationPrincipal Long userId,
@Valid @RequestBody PasswordUpdateRequest request
) {
userService.changePassword(userId, request);
return ResponseEntity.ok(ApiResponse.success(HttpStatus.OK, "패스워드 변경 성공"));
}
}