로그인 및 인증 관련 엔티티, 레포지토리 개선:
eapim-portal CI (from elink-portal-common) / build (push) Has been cancelled
eapim-portal CI (from elink-portal-common) / build (push) Has been cancelled
- 실패 사유/로그인 유형 코드 필드 추가(UserLog) - 만료 인증번호 일괄 삭제 레포지토리 메서드 추가 - UUID v7 적용(TwoFactorAuth) - PK 정렬 효율 개선 - 인증번호 실패 사유 코드 추가(AuthNumberException)
This commit is contained in:
@@ -23,6 +23,8 @@ public interface AppRequestRepository extends BaseRepository<AppRequest, String>
|
||||
|
||||
List<AppRequest> findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List<AppRequestType> types, List<ApprovalState> approvalStates);
|
||||
|
||||
List<AppRequest> findAllByOrgAndTypeIsInAndApprovalIsNull(PortalOrg org, List<AppRequestType> types);
|
||||
|
||||
int countAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List<AppRequestType> types, List<ApprovalState> approvalStates);
|
||||
|
||||
Optional<AppRequest> findByIdAndOrg(String id, PortalOrg org);
|
||||
|
||||
@@ -88,7 +88,11 @@ public class PortalUser extends Auditable implements Serializable, com.eactive.e
|
||||
@Comment("로그인실패횟수")
|
||||
private Integer loginFailureCount;
|
||||
|
||||
@Column(name = "password_change_date")
|
||||
// PASSWORD_CHANGE_DATE 컬럼은 VARCHAR2(14) yyyyMMddHHmmss 문자열이다.
|
||||
// LocalDateTime 을 그대로 바인딩하면 27자로 변환되어 ORA-12899(값 초과)가 발생하므로
|
||||
// 14자 문자열로 변환하는 컨버터를 적용한다.
|
||||
@Column(name = "password_change_date", length = 14)
|
||||
@Convert(converter = com.eactive.eai.data.converter.LocalDateTimeToStringConverter14.class)
|
||||
@Comment("비밀번호변경일시")
|
||||
private LocalDateTime passwordChangeDate;
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ public class TwoFactorAuth {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", length = 36, nullable = false)
|
||||
@GenericGenerator(name = "uuid-gen", strategy = "uuid2")
|
||||
// UUID v7(타임스탬프 기반, 시간순 정렬) — PK 인덱스 삽입 지역성 개선. 기존 v4 행과 컬럼 호환.
|
||||
@GenericGenerator(name = "uuid-gen", strategy = "com.eactive.apim.portal.jpa.UuidV7Generator")
|
||||
@GeneratedValue(generator = "uuid-gen", strategy = GenerationType.IDENTITY)
|
||||
private String id;
|
||||
|
||||
|
||||
+10
@@ -2,7 +2,9 @@ package com.eactive.apim.portal.portaluser.repository;
|
||||
|
||||
import com.eactive.apim.portal.portaluser.entity.TwoFactorAuth;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface TwoFactorAuthRepository extends JpaRepository<TwoFactorAuth, String> {
|
||||
@@ -12,6 +14,14 @@ public interface TwoFactorAuthRepository extends JpaRepository<TwoFactorAuth, St
|
||||
|
||||
void deleteAllByRecipientKey(String recipientKey);
|
||||
|
||||
/**
|
||||
* 만료된 인증번호 레코드를 일괄 삭제한다. (정리 스케줄러용)
|
||||
* expires_on 은 LocalDateTimeToStringConverter14(yyyyMMddHHmmss) 로 저장되며,
|
||||
* 해당 포맷은 사전식 정렬이 시간순과 일치하므로 문자열 < 비교가 곧 시간 비교다.
|
||||
*/
|
||||
@Modifying
|
||||
int deleteAllByExpiresAtBefore(LocalDateTime threshold);
|
||||
|
||||
// 아래 두 메서드는 recipient(암호화 컬럼) 기반이라 신뢰할 수 없음 — 신규 코드에서는 RecipientKey 버전을 사용할 것.
|
||||
@Deprecated
|
||||
Optional<TwoFactorAuth> findByRecipient(String recipientKey);
|
||||
|
||||
@@ -1,7 +1,37 @@
|
||||
package com.eactive.apim.portal.portaluser.service;
|
||||
|
||||
public class AuthNumberException extends RuntimeException{
|
||||
/**
|
||||
* 인증번호(2FA/이메일/SMS) 검증·발송 실패 예외.
|
||||
*
|
||||
* <p>기존에는 메시지 문자열만 있었으나, 감사 로그에서 실패 사유(만료/불일치/미존재)를
|
||||
* 코드로 구분해야 하므로 {@link Reason} 을 추가했다. 기존 메시지 전용 생성자는 유지되며
|
||||
* 이 경우 {@code reason == null} 이다(하위호환).</p>
|
||||
*/
|
||||
public class AuthNumberException extends RuntimeException {
|
||||
|
||||
/** 실패 사유 분류 */
|
||||
public enum Reason {
|
||||
/** 저장된 인증번호가 없음(미발송/이미 소비/스케줄러 정리) */
|
||||
NOT_FOUND,
|
||||
/** 유효시간 초과 */
|
||||
EXPIRED,
|
||||
/** 인증번호 불일치 */
|
||||
MISMATCH
|
||||
}
|
||||
|
||||
private final Reason reason;
|
||||
|
||||
public AuthNumberException(String message) {
|
||||
super(message);
|
||||
this.reason = null;
|
||||
}
|
||||
|
||||
public AuthNumberException(String message, Reason reason) {
|
||||
super(message);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Reason getReason() {
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,4 +45,12 @@ public class UserLog {
|
||||
@Column(name = "success", nullable = false)
|
||||
private boolean success;
|
||||
|
||||
/** 실패 사유 코드 (LoginFailureReason). 성공 행은 null */
|
||||
@Column(name = "failure_reason", length = 64)
|
||||
private String failureReason;
|
||||
|
||||
/** 로그인 유형 코드 (LoginType: NORMAL/TWO_FACTOR/SIGNUP_AUTO). 실패 행·과거 행은 null */
|
||||
@Column(name = "login_type", length = 32)
|
||||
private String loginType;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user