Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.withtime.be.withtimebe.global.error.exception.*;
import org.withtime.be.withtimebe.global.security.constants.AuthenticationConstants;
import org.withtime.be.withtimebe.global.security.domain.CustomUserDetails;
import org.withtime.be.withtimebe.global.security.handler.CustomLogoutHandler;
import org.withtime.be.withtimebe.global.util.CookieUtil;

@Service
Expand All @@ -36,6 +37,7 @@ public class AuthCommandServiceImpl implements AuthCommandService {
private final TokenQueryService tokenQueryService;
private final TokenStorageQueryService tokenStorageQueryService;
private final EmailVerificationCodeStorageQueryService emailVerificationCodeStorageQueryService;
private final CustomLogoutHandler customLogoutHandler;

@Override
public void signUp(AuthRequestDTO.SignUp request) {
Expand Down Expand Up @@ -69,19 +71,7 @@ public void reissueToken(HttpServletRequest request, HttpServletResponse respons

@Override
public void logout(HttpServletRequest request, HttpServletResponse response) {
String accessToken = getAccessToken(request);
String refreshToken = getRefreshToken(request);

tokenStorageCommandService.addBlackList(accessToken);
tokenStorageCommandService.addBlackList(refreshToken);

// μΏ ν‚€μ˜ Refresh Token이 λ‹€λ₯Έ 경우λ₯Ό λŒ€λΉ„ν•΄ Redis Refresh도 Black list 처리
Long userId = getUserId(refreshToken);
tokenStorageCommandService.addBlackList(tokenStorageQueryService.getRefreshToken(userId));
tokenStorageCommandService.deleteRefreshToken(userId);

CookieUtil.deleteCookie(request, response, AuthenticationConstants.ACCESS_TOKEN_NAME);
CookieUtil.deleteCookie(request, response, AuthenticationConstants.REFRESH_TOKEN_NAME);
customLogoutHandler.logout(request, response);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.namul.api.payload.response.DefaultResponse;

Expand Down Expand Up @@ -79,8 +81,8 @@ public DefaultResponse<MemberResponseDTO.ChangeInfo> changeInfo(@AuthenticatedMe
@Operation(summary = "νšŒμ› νƒˆν‡΄ν•˜κΈ° API by μš”μ‹œ", description = "둜그인된 토큰을 μ΄μš©ν•˜μ—¬ νšŒμ› νƒˆν‡΄ν•˜λŠ” API")
@ApiResponse(responseCode = "204", description = "νšŒμ› νƒˆν‡΄ 성곡 (soft delete)")
@DeleteMapping
public DefaultResponse<Void> deleteMember(@AuthenticatedMember Member member) {
memberCommandService.deleteMember(member.getId());
public DefaultResponse<Void> deleteMember(HttpServletRequest request, HttpServletResponse response, @AuthenticatedMember Member member) {
memberCommandService.deleteMember(request, response, member.getId());
return DefaultResponse.noContent();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.withtime.be.withtimebe.domain.member.service.command;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.withtime.be.withtimebe.domain.member.dto.MemberRequestDTO;
import org.withtime.be.withtimebe.domain.member.entity.Member;

Expand All @@ -8,5 +10,5 @@ public interface MemberCommandService {
void changePassword(String email, String password);
Member changeInfo(Long memberId, MemberRequestDTO.ChangeInfo request);
void addPoint(Long memberId, Integer point);
void deleteMember(Long memberId);
void deleteMember(HttpServletRequest request, HttpServletResponse response, Long memberId);
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package org.withtime.be.withtimebe.domain.member.service.command;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.namul.api.payload.error.exception.ServerApplicationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.withtime.be.withtimebe.domain.auth.service.command.AuthCommandService;
import org.withtime.be.withtimebe.domain.member.dto.MemberRequestDTO;
import org.withtime.be.withtimebe.domain.member.entity.Member;
import org.withtime.be.withtimebe.domain.member.repository.MemberRepository;
import org.withtime.be.withtimebe.global.error.code.AuthErrorCode;
import org.withtime.be.withtimebe.global.error.code.MemberErrorCode;
import org.withtime.be.withtimebe.global.error.exception.AuthException;
import org.withtime.be.withtimebe.global.error.exception.MemberException;
import org.withtime.be.withtimebe.global.security.handler.CustomLogoutHandler;

@Service
@RequiredArgsConstructor
Expand All @@ -20,6 +24,7 @@ public class MemberCommandServiceImpl implements MemberCommandService {

private final PasswordEncoder passwordEncoder;
private final MemberRepository memberRepository;
private final CustomLogoutHandler customLogoutHandler;


@Override
Expand Down Expand Up @@ -52,8 +57,10 @@ public void addPoint(Long memberId, Integer point) {
new MemberException(MemberErrorCode.NOT_FOUND));
member.addPoint(point);
}

public void deleteMember(Long memberId) {

@Override
public void deleteMember(HttpServletRequest request, HttpServletResponse response, Long memberId) {
customLogoutHandler.logout(request, response);
memberRepository.deleteById(memberId);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.withtime.be.withtimebe.global.security.handler;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.withtime.be.withtimebe.domain.auth.service.command.TokenStorageCommandService;
import org.withtime.be.withtimebe.domain.auth.service.query.TokenQueryService;
import org.withtime.be.withtimebe.domain.auth.service.query.TokenStorageQueryService;
import org.withtime.be.withtimebe.global.security.constants.AuthenticationConstants;
import org.withtime.be.withtimebe.global.util.CookieUtil;

@Component
@RequiredArgsConstructor
public class CustomLogoutHandler {

private final TokenStorageCommandService tokenStorageCommandService;
private final TokenStorageQueryService tokenStorageQueryService;
private final TokenQueryService tokenQueryService;

public void logout(HttpServletRequest request, HttpServletResponse response) {
String accessToken = getAccessToken(request);
String refreshToken = getRefreshToken(request);

tokenStorageCommandService.addBlackList(accessToken);
tokenStorageCommandService.addBlackList(refreshToken);

// μΏ ν‚€μ˜ Refresh Token이 λ‹€λ₯Έ 경우λ₯Ό λŒ€λΉ„ν•΄ Redis Refresh도 Black list 처리
Long userId = getUserId(refreshToken);
tokenStorageCommandService.addBlackList(tokenStorageQueryService.getRefreshToken(userId));
tokenStorageCommandService.deleteRefreshToken(userId);

CookieUtil.deleteCookie(request, response, AuthenticationConstants.ACCESS_TOKEN_NAME);
CookieUtil.deleteCookie(request, response, AuthenticationConstants.REFRESH_TOKEN_NAME);
}

private Long getUserId(String token) {
return tokenQueryService.getUserId(token);
}

private String getAccessToken(HttpServletRequest request) {
return CookieUtil.getCookie(request, AuthenticationConstants.ACCESS_TOKEN_NAME);
}

private String getRefreshToken(HttpServletRequest request) {
return CookieUtil.getCookie(request, AuthenticationConstants.REFRESH_TOKEN_NAME);
}}