add: common에 audit, constants 추가

This commit is contained in:
UNGGU0704
2025-06-11 17:24:47 +09:00
parent 483ba6c8c3
commit 13d5c97594
12 changed files with 617 additions and 0 deletions
@@ -0,0 +1,13 @@
package com.ktds.hi.common.audit;
/**
* 감사 액션 열거형
*/
public enum AuditAction {
CREATE,
UPDATE,
DELETE,
ACCESS,
LOGIN,
LOGOUT
}
@@ -0,0 +1,29 @@
package com.ktds.hi.common.audit;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 감사 로그 엔티티
*/
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AuditLog {
private Long id;
private String entityType;
private String entityId;
private AuditAction action;
private String oldValues;
private String newValues;
private String userId;
private String userAgent;
private String ipAddress;
private LocalDateTime timestamp;
}
@@ -0,0 +1,11 @@
package com.ktds.hi.common.audit;
/**
* 감사 로그 리포지토리 인터페이스
*/
public interface AuditLogRepository {
void save(AuditLog auditLog);
AuditLog findById(Long id);
}
@@ -0,0 +1,105 @@
package com.ktds.hi.common.audit;
import com.ktds.hi.common.repository.AuditLogRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Map;
/**
* 감사 로거
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class AuditLogger {
private final AuditLogRepository auditLogRepository;
public void logCreate(Object entity) {
AuditLog auditLog = AuditLog.builder()
.entityType(entity.getClass().getSimpleName())
.entityId(extractEntityId(entity))
.action(AuditAction.CREATE)
.newValues(extractEntityInfo(entity))
.userId(getCurrentUserInfo())
.ipAddress(getClientInfo())
.timestamp(LocalDateTime.now())
.build();
auditLogRepository.save(auditLog);
log.info("감사 로그 기록 - CREATE: {}", auditLog);
}
public void logUpdate(Object entity, Map<String, Object> oldValues, Map<String, Object> newValues) {
AuditLog auditLog = AuditLog.builder()
.entityType(entity.getClass().getSimpleName())
.entityId(extractEntityId(entity))
.action(AuditAction.UPDATE)
.oldValues(oldValues.toString())
.newValues(newValues.toString())
.userId(getCurrentUserInfo())
.ipAddress(getClientInfo())
.timestamp(LocalDateTime.now())
.build();
auditLogRepository.save(auditLog);
log.info("감사 로그 기록 - UPDATE: {}", auditLog);
}
public void logDelete(Object entity) {
AuditLog auditLog = AuditLog.builder()
.entityType(entity.getClass().getSimpleName())
.entityId(extractEntityId(entity))
.action(AuditAction.DELETE)
.oldValues(extractEntityInfo(entity))
.userId(getCurrentUserInfo())
.ipAddress(getClientInfo())
.timestamp(LocalDateTime.now())
.build();
auditLogRepository.save(auditLog);
log.info("감사 로그 기록 - DELETE: {}", auditLog);
}
public void logAccess(String entityType, String entityId) {
AuditLog auditLog = AuditLog.builder()
.entityType(entityType)
.entityId(entityId)
.action(AuditAction.ACCESS)
.userId(getCurrentUserInfo())
.ipAddress(getClientInfo())
.timestamp(LocalDateTime.now())
.build();
auditLogRepository.save(auditLog);
log.debug("감사 로그 기록 - ACCESS: {}", auditLog);
}
private String extractEntityId(Object entity) {
// 리플렉션을 사용하여 ID 필드 추출
try {
return entity.getClass().getMethod("getId").invoke(entity).toString();
} catch (Exception e) {
return "unknown";
}
}
private String extractEntityInfo(Object entity) {
// 엔티티 정보를 JSON 형태로 변환
return entity.toString();
}
private String getCurrentUserInfo() {
// 현재 사용자 정보 반환
return "system"; // 실제 구현에서는 SecurityContext에서 가져옴
}
private String getClientInfo() {
// 클라이언트 IP 정보 반환
return "127.0.0.1"; // 실제 구현에서는 HttpServletRequest에서 가져옴
}
}
@@ -0,0 +1,26 @@
package com.ktds.hi.common.audit;
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import java.util.Optional;
/**
* JPA Auditing을 위한 사용자 정보 제공자
*/
@Component
public class CustomAuditorAware implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return Optional.of("system");
}
return Optional.of(authentication.getName());
}
}
@@ -0,0 +1,22 @@
package com.ktds.hi.common.constants;
import java.time.Duration;
/**
* 캐시 관련 상수
*/
public class CacheConstants {
public static final Duration DEFAULT_TTL = Duration.ofHours(1);
public static final Duration SHORT_TTL = Duration.ofMinutes(15);
public static final Duration LONG_TTL = Duration.ofHours(24);
public static final String USER_CACHE_PREFIX = "user:";
public static final String STORE_CACHE_PREFIX = "store:";
public static final String REVIEW_CACHE_PREFIX = "review:";
public static final String RECOMMENDATION_CACHE_PREFIX = "recommend:";
private CacheConstants() {
// 유틸리티 클래스
}
}
@@ -0,0 +1,20 @@
package com.ktds.hi.common.constants;
/**
* 에러 코드 상수
*/
public class ErrorCode {
public static final String INVALID_REQUEST = "INVALID_REQUEST";
public static final String UNAUTHORIZED = "UNAUTHORIZED";
public static final String FORBIDDEN = "FORBIDDEN";
public static final String NOT_FOUND = "NOT_FOUND";
public static final String DUPLICATE_RESOURCE = "DUPLICATE_RESOURCE";
public static final String BUSINESS_RULE_VIOLATION = "BUSINESS_RULE_VIOLATION";
public static final String EXTERNAL_SERVICE_ERROR = "EXTERNAL_SERVICE_ERROR";
public static final String INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR";
private ErrorCode() {
// 유틸리티 클래스
}
}
@@ -0,0 +1,20 @@
package com.ktds.hi.common.constants;
/**
* 메시지 코드 상수
*/
public class MessageCode {
public static final String SUCCESS_CREATE = "성공적으로 생성되었습니다";
public static final String SUCCESS_UPDATE = "성공적으로 수정되었습니다";
public static final String SUCCESS_DELETE = "성공적으로 삭제되었습니다";
public static final String INVALID_INPUT = "입력값이 올바르지 않습니다";
public static final String DUPLICATE_USERNAME = "이미 사용중인 아이디입니다";
public static final String DUPLICATE_NICKNAME = "이미 사용중인 닉네임입니다";
public static final String INVALID_CREDENTIALS = "아이디 또는 비밀번호가 일치하지 않습니다";
public static final String ACCESS_DENIED = "접근 권한이 없습니다";
private MessageCode() {
// 유틸리티 클래스
}
}
@@ -0,0 +1,19 @@
package com.ktds.hi.common.constants;
/**
* 보안 관련 상수
*/
public class SecurityConstants {
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String BEARER_PREFIX = "Bearer ";
public static final String TOKEN_TYPE_ACCESS = "access";
public static final String TOKEN_TYPE_REFRESH = "refresh";
public static final long ACCESS_TOKEN_EXPIRE_TIME = 30 * 60 * 1000L; // 30분
public static final long REFRESH_TOKEN_EXPIRE_TIME = 7 * 24 * 60 * 60 * 1000L; // 7일
private SecurityConstants() {
// 유틸리티 클래스
}
}