feat: 회원 탈퇴(자기 계정 삭제) — Play 정책 대응
- DELETE /api/auth/me: 본인 계정과 모든 데이터 영구 삭제 - 게시판(글/댓글/추천/이미지)·가계부 전체·포인트·결제기록·세션 → 회원 순 삭제 - WithdrawMapper(게시판/포인트/결제/세션) + BackupMapper(가계부) 재사용 - AuthServiceTest 생성자 보강 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
be15f5b85d
commit
8142b8b518
@@ -38,6 +38,8 @@ public class AuthService {
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final com.sb.web.admin.service.AppSettingService appSettingService;
|
||||
private final com.sb.web.auth.mapper.AuthSessionMapper authSessionMapper;
|
||||
private final com.sb.web.auth.mapper.WithdrawMapper withdrawMapper;
|
||||
private final com.sb.web.account.mapper.BackupMapper backupMapper;
|
||||
|
||||
/** 구글 OAuth 클라이언트 ID (ID 토큰 aud 검증용). 미설정 시 구글 로그인 비활성. */
|
||||
@org.springframework.beans.factory.annotation.Value("${app.google-client-id:}")
|
||||
@@ -289,6 +291,50 @@ public class AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원 탈퇴 — 사용자가 소유한 모든 데이터를 삭제하고 회원을 제거한다.
|
||||
* (게시판 글/댓글/추천 · 가계부 전체 · 포인트 · 결제기록 · 세션 → 회원)
|
||||
*/
|
||||
@Transactional
|
||||
public void withdraw(Long memberId, String token) {
|
||||
Member member = memberMapper.findById(memberId);
|
||||
if (member == null) {
|
||||
throw new ApiException(HttpStatus.NOT_FOUND, "회원을 찾을 수 없습니다.");
|
||||
}
|
||||
// 1) 게시판 — 표/댓글/글/이미지 (참조 순서 고려)
|
||||
withdrawMapper.deletePostVotesByMember(memberId);
|
||||
withdrawMapper.deleteCommentVotesByMember(memberId);
|
||||
withdrawMapper.deleteCommentVotesOnMyPosts(memberId);
|
||||
withdrawMapper.deleteCommentVotesOnMyComments(memberId);
|
||||
withdrawMapper.deleteCommentsOnMyPosts(memberId);
|
||||
withdrawMapper.deleteCommentsByAuthor(memberId);
|
||||
withdrawMapper.deletePostVotesOnMyPosts(memberId);
|
||||
withdrawMapper.deletePostTagsOnMyPosts(memberId);
|
||||
withdrawMapper.deletePostsByAuthor(memberId);
|
||||
withdrawMapper.deleteBoardImagesByMember(memberId);
|
||||
// 2) 가계부(계정) 데이터 (복구 삭제와 동일 순서)
|
||||
backupMapper.deleteEntryTags(memberId);
|
||||
backupMapper.deleteEntries(memberId);
|
||||
backupMapper.deleteRecurrings(memberId);
|
||||
backupMapper.deleteBudgets(memberId);
|
||||
backupMapper.deleteBudgetIncome(memberId);
|
||||
backupMapper.deleteQuickEntries(memberId);
|
||||
backupMapper.deleteInvestTrades(memberId);
|
||||
backupMapper.deleteInvestHoldings(memberId);
|
||||
backupMapper.deleteCategories(memberId);
|
||||
backupMapper.deleteTags(memberId);
|
||||
backupMapper.deleteWallets(memberId);
|
||||
// 3) 포인트 / 결제 / 세션
|
||||
withdrawMapper.deletePointHistory(memberId);
|
||||
withdrawMapper.deleteIapPurchases(memberId);
|
||||
withdrawMapper.deleteAuthSessions(memberId);
|
||||
// 4) 회원 삭제
|
||||
memberMapper.deleteById(memberId);
|
||||
// 5) 현재 세션(Redis) 정리
|
||||
logout(token);
|
||||
log.info("[withdraw] member {} ({}) 및 데이터 전체 삭제", memberId, member.getLoginId());
|
||||
}
|
||||
|
||||
/** 만료된 백업 세션 정리 (매일 새벽 4시) */
|
||||
@org.springframework.scheduling.annotation.Scheduled(cron = "0 0 4 * * *")
|
||||
public void cleanupExpiredSessions() {
|
||||
|
||||
Reference in New Issue
Block a user