Skip to content

Commit

Permalink
Merge pull request #94 from Central-MakeUs/dev
Browse files Browse the repository at this point in the history
[CI/CD] dev 브랜치 최신화 반영하여 배포
  • Loading branch information
dainnida authored Feb 11, 2025
2 parents 33bdbce + 3df866a commit 919ff5a
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.cmc.mercury.domain.user.controller;

import com.cmc.mercury.domain.user.entity.User;
import com.cmc.mercury.domain.user.service.SignOffService;
import com.cmc.mercury.global.oauth.annotation.AuthUser;
import com.cmc.mercury.global.response.SuccessResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/signoff")
@RequiredArgsConstructor
@Tag(name = "SignOffController", description = "로그아웃 & 탈퇴 API")
public class SignOffController {

private final SignOffService signOffService;

@PostMapping("/logout")
@Operation(summary = "로그아웃",
description = "로그인한 사용자의 refresh token을 무효화시킵니다.(호출 후 프론트측의 access token을 무력화시켜주세요!)")
public SuccessResponse<User> logout(@AuthUser User user, HttpServletRequest request, HttpServletResponse response) {

User logoutUser = signOffService.logout(user);
clearAuthContext(request, response);

return SuccessResponse.ok(logoutUser);
}

@PostMapping("/withdraw")
@Operation(summary = "회원탈퇴(soft delete)",
description = "로그인한 사용자의 refresh token을 무효화시키며 상태를 INAVTIVE로 바꿉니다.(호출 후 프론트측의 access token을 무력화시켜주세요!)")
public SuccessResponse<User> withdraw(@AuthUser User user, HttpServletRequest request, HttpServletResponse response) {

User deletedUser = signOffService.withdraw(user);
clearAuthContext(request, response);

return SuccessResponse.ok(deletedUser);
}

private void clearAuthContext(HttpServletRequest request, HttpServletResponse response) {

// HttpSession & SecurityContext 초기화
request.getSession().invalidate(); // 세션 초기화
SecurityContextHolder.clearContext(); // Spring Security 인증 정보 제거

// HttpOnly 쿠키 제거
Cookie cookie = new Cookie("refreshToken", null);
cookie.setHttpOnly(true);
// cookie.setSecure(true);
cookie.setPath("/");
cookie.setMaxAge(0); // 쿠키 즉시 삭제
response.addCookie(cookie);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
@Tag(name = "UserController", description = "유저 관련 API")
@Tag(name = "UserController", description = "개발 환경에서의 유저 관련 API")
public class UserController {

private final UserService userService;
Expand All @@ -39,10 +39,12 @@ public SuccessResponse<?> deleteTestUser(@RequestParam String email) {
@PostMapping("/refresh/accessToken")
@Operation(summary = "테스트 계정 토큰 재발급", description = "개발 환경에서 사용할 테스트 계정의 새로운 access 토큰을 발급합니다.")
public SuccessResponse<User> refreshTestToken(@RequestBody UserTestRequest request) {

return SuccessResponse.ok(userService.refreshTestToken(request));
}

@GetMapping()
@GetMapping
@Operation(summary = "사용자 리스트 조회", description = "모든 사용자의 정보를 조회합니다.")
public SuccessResponse<List<User>> getAllUsers() {

return SuccessResponse.ok(userService.getListUsers());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.cmc.mercury.domain.user.service;

import com.cmc.mercury.domain.user.entity.User;
import com.cmc.mercury.domain.user.entity.UserStatus;
import com.cmc.mercury.global.exception.CustomException;
import com.cmc.mercury.global.exception.ErrorCode;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
@Slf4j
public class SignOffService {

@Transactional
public User logout(User user) {

// DB에서 refresh token 제거
user.updateRefreshToken(null);

return user;
}

@Transactional
public User withdraw(User user) {

if (user.getUserStatus() == UserStatus.INACTIVE) {
throw new CustomException(ErrorCode.ALREADY_WITHDRAWN);
}

user.deleteUser();
user.updateRefreshToken(null); // Refresh Token 삭제

return user;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ private void setTestUserTokens(User user, boolean isShortLivedAccessToken) {
response.addCookie(refreshTokenCookie);
}

public List<User> getListUsers() {
public List<User> getListUsers() {

return userRepository.findAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public enum ErrorCode {
// User
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "User404", "사용자를 찾을 수 없습니다."),
DUPLICATE_USER(HttpStatus.CONFLICT, "User409", "이미 존재하는 사용자입니다."),
ALREADY_WITHDRAWN(HttpStatus.CONFLICT, "User409", "이미 탈퇴한 사용자입니다."),

// Book
BOOK_NOT_FOUND(HttpStatus.NOT_FOUND, "Book404", "도서를 찾을 수 없습니다."),
Expand Down

0 comments on commit 919ff5a

Please sign in to comment.