You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AdminUserBanService.unbanUser()가 사용하는 findActiveBan(long userId)는 UserBanRepository.findByBannedUserIdAndIsExpiredFalseAndExpiredAtAfter(...)(Optional<UserBan> 반환, 단일 결과를 기대)를 호출합니다.
user_ban 테이블에는 "유저당 활성 차단 1건" 제약이 DB 레벨에 없고, 차단 생성 시 중복 방지 로직도 check-then-act 방식입니다.
privatevoidvalidateNotAlreadyBanned(longuserId) {
if (userBanRepository.existsByBannedUserIdAndIsExpiredFalseAndExpiredAtAfter(userId, ZonedDateTime.now(UTC))) {
thrownewCustomException(ErrorCode.ALREADY_BANNED_USER);
}
}
두 관리자가 동시에 같은 유저를 차단하면, 두 요청 모두 existsBy... 체크를 통과한 뒤 각자 UserBan을 저장할 수 있어(트랜잭션 격리/락 없음) 같은 유저에게 활성 차단이 2건 생길 수 있습니다. 이 상태에서 관리자가 해당 유저의 차단을 해제하려고 하면 findByBannedUserIdAndIsExpiredFalseAndExpiredAtAfter가 2건을 반환하게 되어 Spring Data가 IncorrectResultSizeDataAccessException을 던지고, 차단 해제 요청이 실패합니다.
(#845/#846 쿼리 플랜 개선 작업 중 유사한 패턴 — SiteUserFilterRepositoryImpl.searchRestrictedUsers의 배치조회에서도 같은 원인으로 크래시가 날 수 있다는 리뷰를 받아 그쪽은 이미 수정했습니다. 이 이슈는 그 수정 범위에 포함되지 않은 언밴 플로우 쪽입니다.)
재현 방법(선택)
같은 유저에 대해 거의 동시에 관리자 제재(ban) API를 2번 호출(또는 user_ban에 같은 banned_user_id로 활성 행을 2건 직접 insert)
어떤 버그인가요
AdminUserBanService.unbanUser()가 사용하는findActiveBan(long userId)는UserBanRepository.findByBannedUserIdAndIsExpiredFalseAndExpiredAtAfter(...)(Optional<UserBan>반환, 단일 결과를 기대)를 호출합니다.user_ban테이블에는 "유저당 활성 차단 1건" 제약이 DB 레벨에 없고, 차단 생성 시 중복 방지 로직도 check-then-act 방식입니다.두 관리자가 동시에 같은 유저를 차단하면, 두 요청 모두
existsBy...체크를 통과한 뒤 각자UserBan을 저장할 수 있어(트랜잭션 격리/락 없음) 같은 유저에게 활성 차단이 2건 생길 수 있습니다. 이 상태에서 관리자가 해당 유저의 차단을 해제하려고 하면findByBannedUserIdAndIsExpiredFalseAndExpiredAtAfter가 2건을 반환하게 되어 Spring Data가IncorrectResultSizeDataAccessException을 던지고, 차단 해제 요청이 실패합니다.(#845/#846 쿼리 플랜 개선 작업 중 유사한 패턴 —
SiteUserFilterRepositoryImpl.searchRestrictedUsers의 배치조회에서도 같은 원인으로 크래시가 날 수 있다는 리뷰를 받아 그쪽은 이미 수정했습니다. 이 이슈는 그 수정 범위에 포함되지 않은 언밴 플로우 쪽입니다.)재현 방법(선택)
user_ban에 같은banned_user_id로 활성 행을 2건 직접 insert)IncorrectResultSizeDataAccessException발생, 차단 해제 실패참고할만한 자료(선택)
src/main/java/com/example/solidconnection/admin/service/AdminUserBanService.java(validateNotAlreadyBanned,findActiveBan,unbanUser)src/main/java/com/example/solidconnection/siteuser/repository/UserBanRepository.javasrc/main/resources/db/migration/V40__create_user_ban_table.sql(유저별 활성 차단 유일성을 보장하는 제약 없음)개선 방향 제안(참고)
user_ban에 "유저당 활성 차단 1건" 제약을 DB 레벨에서 강제(예: 부분 유니크 인덱스/애플리케이션 락)하거나, 차단 생성 시 비관적 락/유니크 제약 위반 처리로 race를 막기findActiveBan을Optional<UserBan>대신List<UserBan>으로 조회해 여러 건이 있어도 안전하게 처리(예: 모두 해제하거나 최신 건만 해제)하도록 방어적으로 수정