Redis Cache Status Error Fix

This commit is contained in:
DanielLee
2025-12-09 09:32:33 +09:00
parent df9649fb1b
commit c3245ab79c
24 changed files with 605 additions and 688 deletions

View File

@@ -13,8 +13,7 @@ import org.springframework.stereotype.Component;
/** /**
* 공통코드 캐시 관리 및 초기화 클래스 * 공통코드 캐시 관리 및 초기화 클래스
* *
* <p>애플리케이션 시작 시 공통코드를 Redis 캐시에 미리 로드하고, 캐시 갱신을 관리합니다. * <p>애플리케이션 시작 시 공통코드를 Redis 캐시에 미리 로드하고, 캐시 갱신을 관리합니다. 기존 Redis 데이터와의 호환성 문제로 인한 간헐적 오류를 방지합니다.
* 기존 Redis 데이터와의 호환성 문제로 인한 간헐적 오류를 방지합니다.
*/ */
@Slf4j @Slf4j
@Component @Component
@@ -29,9 +28,8 @@ public class CommonCodeCacheManager {
/** /**
* 애플리케이션 시작 완료 후 공통코드를 Redis 캐시에 미리 로드 * 애플리케이션 시작 완료 후 공통코드를 Redis 캐시에 미리 로드
* *
* <p>이 메서드는 Spring 애플리케이션이 완전히 시작된 후에 자동으로 실행되며, 공통코드 데이터를 Redis * <p>이 메서드는 Spring 애플리케이션이 완전히 시작된 후에 자동으로 실행되며, 공통코드 데이터를 Redis 캐시에 미리 로드하여 초기 조회 시 성능을 최적화합니다.
* 캐시에 미리 로드하여 초기 조회 시 성능을 최적화합니다. 기존 캐시 데이터 호환성 문제를 대비하여 먼저 * 기존 캐시 데이터 호환성 문제를 대비하여 먼저 캐시를 초기화한 후 재로드합니다.
* 캐시를 초기화한 후 재로드합니다.
*/ */
@EventListener(ApplicationReadyEvent.class) @EventListener(ApplicationReadyEvent.class)
public void initializeCommonCodeCache() { public void initializeCommonCodeCache() {
@@ -48,27 +46,18 @@ public class CommonCodeCacheManager {
// 2. DB에서 새로운 데이터 로드 (캐시 미스 상태) // 2. DB에서 새로운 데이터 로드 (캐시 미스 상태)
List<Basic> allCommonCodes = commonCodeService.getFindAll(); List<Basic> allCommonCodes = commonCodeService.getFindAll();
log.info( log.info("✓ 공통코드 {}개를 DB에서 로드하고 Redis 캐시에 저장했습니다.", allCommonCodes.size());
"✓ 공통코드 {}개를 DB에서 로드하고 Redis 캐시에 저장했습니다.",
allCommonCodes.size());
// 3. 로그 출력 (DEBUG 레벨) // 3. 로그 출력 (DEBUG 레벨)
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
allCommonCodes.forEach( allCommonCodes.forEach(
code -> code ->
log.debug( log.debug(" - [{}] {} (ID: {})", code.getCode(), code.getName(), code.getId()));
" - [{}] {} (ID: {})",
code.getCode(),
code.getName(),
code.getId()));
} }
log.info("=== 공통코드 캐시 초기화 완료 ==="); log.info("=== 공통코드 캐시 초기화 완료 ===");
} catch (Exception e) { } catch (Exception e) {
log.warn( log.warn("공통코드 캐시 초기화 중 오류 발생했습니다. 캐시 없이 계속 진행합니다. " + "(첫 번째 조회 시 DB에서 로드되고 캐시됩니다.)", e);
"공통코드 캐시 초기화 중 오류 발생했습니다. 캐시 없이 계속 진행합니다. "
+ "(첫 번째 조회 시 DB에서 로드되고 캐시됩니다.)",
e);
} }
} }
@@ -121,10 +110,31 @@ public class CommonCodeCacheManager {
*/ */
public int getCachedCommonCodeCount() { public int getCachedCommonCodeCount() {
try { try {
List<Basic> cachedCodes = commonCodeService.getFindAll(); // 캐시 오류 시 자동으로 재초기화
return cachedCodes.size(); try {
List<Basic> cachedCodes = commonCodeService.getFindAll();
return cachedCodes.size();
} catch (Exception cacheError) {
log.debug("캐시 조회 중 호환성 오류 감지, 캐시 재초기화 중...: {}", cacheError.getMessage());
// 기존 호환성 문제가 있는 캐시 데이터 강제 제거
try {
var cache = cacheManager.getCache(COMMON_CODES_CACHE_NAME);
if (cache != null) {
cache.clear();
log.debug("✓ 호환되지 않는 캐시 데이터 제거 완료");
}
} catch (Exception clearEx) {
log.debug("캐시 정리 중 예외: {}", clearEx.getMessage());
}
// 재시도
List<Basic> cachedCodes = commonCodeService.getFindAll();
log.info("✓ 캐시 재초기화 완료, 공통코드 {}개 로드됨", cachedCodes.size());
return cachedCodes.size();
}
} catch (Exception e) { } catch (Exception e) {
log.warn("캐시 상태 확인 중 오류 발생: {}", e.getMessage()); log.warn("캐시 상태 확인 중 최종 오류 발생: {}", e.getMessage());
return 0; return 0;
} }
} }

View File

@@ -13,8 +13,6 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.gce.geotiff.GeoTiffReader; import org.geotools.gce.geotiff.GeoTiffReader;
@@ -47,9 +45,8 @@ public class FIleChecker {
return true; return true;
} }
public static boolean verifyFileIntegrity(Path path, String expectedHash) public static boolean verifyFileIntegrity(Path path, String expectedHash)
throws IOException, NoSuchAlgorithmException { throws IOException, NoSuchAlgorithmException {
// 1. 알고리즘 선택 (SHA-256 권장, MD5는 보안상 비추천) // 1. 알고리즘 선택 (SHA-256 권장, MD5는 보안상 비추천)
MessageDigest digest = MessageDigest.getInstance("SHA-256"); MessageDigest digest = MessageDigest.getInstance("SHA-256");
@@ -72,7 +69,6 @@ public class FIleChecker {
return actualHash.equalsIgnoreCase(expectedHash); return actualHash.equalsIgnoreCase(expectedHash);
} }
public static boolean checkTfw(String filePath) { public static boolean checkTfw(String filePath) {
File file = new File(filePath); File file = new File(filePath);
@@ -90,13 +86,13 @@ public class FIleChecker {
lines.add(Double.parseDouble(line.trim())); lines.add(Double.parseDouble(line.trim()));
} }
} }
}catch (IOException ignored) { } catch (IOException ignored) {
return false; return false;
} }
// 2. 6줄이 맞는지 확인 // 2. 6줄이 맞는지 확인
if (lines.size() < 6) { if (lines.size() < 6) {
//System.out.println("유효하지 않은 TFW 파일입니다. (데이터 부족)"); // System.out.println("유효하지 않은 TFW 파일입니다. (데이터 부족)");
return false; return false;
} }
@@ -123,9 +119,9 @@ public class FIleChecker {
if (coverage == null) return false; if (coverage == null) return false;
// 3. GIS 필수 정보(좌표계)가 있는지 확인 // 3. GIS 필수 정보(좌표계)가 있는지 확인
//if (coverage.getCoordinateReferenceSystem() == null) { // if (coverage.getCoordinateReferenceSystem() == null) {
// GeoTIFF가 아니라 일반 TIFF일 수도 있음(이미지는 정상이지만, 좌표계(CRS) 정보가 없습니다.) // GeoTIFF가 아니라 일반 TIFF일 수도 있음(이미지는 정상이지만, 좌표계(CRS) 정보가 없습니다.)
//} // }
return true; return true;
@@ -149,59 +145,57 @@ public class FIleChecker {
String resStr = ""; String resStr = "";
boolean hasDriver = false; boolean hasDriver = false;
// 리눅스/맥용 // 리눅스/맥용
//ProcessBuilder pb = new ProcessBuilder("sh", "-c", "gdalinfo "+filePath+" | grep -i 'Geo'"); // ProcessBuilder pb = new ProcessBuilder("sh", "-c", "gdalinfo "+filePath+" | grep -i 'Geo'");
List<String> command = new ArrayList<>(); List<String> command = new ArrayList<>();
//윈도우용 // 윈도우용
command.add("cmd.exe"); // 윈도우 명령 프롬프트 실행 command.add("cmd.exe"); // 윈도우 명령 프롬프트 실행
command.add("/c"); // 명령어를 수행하고 종료한다는 옵션 command.add("/c"); // 명령어를 수행하고 종료한다는 옵션
//command.add("C:\\Program Files\\QGIS 3.44.4\\bin\\gdalinfo"); // command.add("C:\\Program Files\\QGIS 3.44.4\\bin\\gdalinfo");
command.add("gdalinfo"); command.add("gdalinfo");
command.add(filePath); command.add(filePath);
command.add("|"); command.add("|");
command.add("findstr"); command.add("findstr");
command.add("/i"); command.add("/i");
command.add("Geo"); command.add("Geo");
/* /*
command.add("sh"); // 윈도우 명령 프롬프트 실행 command.add("sh"); // 윈도우 명령 프롬프트 실행
command.add("-c"); // 명령어를 수행하고 종료한다는 옵션 command.add("-c"); // 명령어를 수행하고 종료한다는 옵션
command.add("gdalinfo"); command.add("gdalinfo");
command.add(filePath); command.add(filePath);
command.add("|"); command.add("|");
command.add("grep"); command.add("grep");
command.add("-i"); command.add("-i");
command.add("Geo"); command.add("Geo");
*/ */
ProcessBuilder processBuilder = new ProcessBuilder(command); ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true); processBuilder.redirectErrorStream(true);
try { try {
Process process = processBuilder.start(); Process process = processBuilder.start();
// 인코딩은 윈도우 한글 환경에 맞게 MS949로 지정 // 인코딩은 윈도우 한글 환경에 맞게 MS949로 지정
BufferedReader reader = new BufferedReader( BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
new InputStreamReader(process.getInputStream()));
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
//System.out.println(line); // System.out.println(line);
if( line.contains("Driver: GTiff/GeoTIFF")) { if (line.contains("Driver: GTiff/GeoTIFF")) {
hasDriver = true; hasDriver = true;
break; break;
}
} }
int exitCode = process.waitFor();
} catch (Exception e) {
e.printStackTrace();
} }
int exitCode = process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
return hasDriver; return hasDriver;
} }
} }

View File

@@ -45,198 +45,197 @@ public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
@ExceptionHandler(EntityNotFoundException.class) @ExceptionHandler(EntityNotFoundException.class)
public ApiResponseDto<String> handlerEntityNotFoundException( public ApiResponseDto<String> handlerEntityNotFoundException(
EntityNotFoundException e, HttpServletRequest request) { EntityNotFoundException e, HttpServletRequest request) {
log.warn("[EntityNotFoundException] resource :{} ", e.getMessage()); log.warn("[EntityNotFoundException] resource :{} ", e.getMessage());
String codeName = "NOT_FOUND_DATA"; String codeName = "NOT_FOUND_DATA";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf("UNPROCESSABLE_ENTITY"), HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf("UNPROCESSABLE_ENTITY"), HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(HttpMessageNotReadableException.class) @ExceptionHandler(HttpMessageNotReadableException.class)
public ApiResponseDto<String> handleUnreadable( public ApiResponseDto<String> handleUnreadable(
HttpMessageNotReadableException e, HttpServletRequest request) { HttpMessageNotReadableException e, HttpServletRequest request) {
log.warn("[HttpMessageNotReadableException] resource :{} ", e.getMessage()); log.warn("[HttpMessageNotReadableException] resource :{} ", e.getMessage());
String codeName = "BAD_REQUEST"; String codeName = "BAD_REQUEST";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.NOT_FOUND) @ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(NoSuchElementException.class) @ExceptionHandler(NoSuchElementException.class)
public ApiResponseDto<String> handlerNoSuchElementException( public ApiResponseDto<String> handlerNoSuchElementException(
NoSuchElementException e, HttpServletRequest request) { NoSuchElementException e, HttpServletRequest request) {
log.warn("[NoSuchElementException] resource :{} ", e.getMessage()); log.warn("[NoSuchElementException] resource :{} ", e.getMessage());
String codeName = "NOT_FOUND_DATA"; String codeName = "NOT_FOUND_DATA";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf("NOT_FOUND"), HttpStatus.valueOf("NOT_FOUND"),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class) @ExceptionHandler(IllegalArgumentException.class)
public ApiResponseDto<String> handlerIllegalArgumentException( public ApiResponseDto<String> handlerIllegalArgumentException(
IllegalArgumentException e, HttpServletRequest request) { IllegalArgumentException e, HttpServletRequest request) {
log.warn("[handlerIllegalArgumentException] resource :{} ", e.getMessage()); log.warn("[handlerIllegalArgumentException] resource :{} ", e.getMessage());
String codeName = "BAD_REQUEST"; String codeName = "BAD_REQUEST";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
@ExceptionHandler(DataIntegrityViolationException.class) @ExceptionHandler(DataIntegrityViolationException.class)
public ApiResponseDto<String> handlerDataIntegrityViolationException( public ApiResponseDto<String> handlerDataIntegrityViolationException(
DataIntegrityViolationException e, HttpServletRequest request) { DataIntegrityViolationException e, HttpServletRequest request) {
log.warn("[DataIntegrityViolationException] resource :{} ", e.getMessage()); log.warn("[DataIntegrityViolationException] resource :{} ", e.getMessage());
String codeName = "DATA_INTEGRITY_ERROR"; String codeName = "DATA_INTEGRITY_ERROR";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf("UNPROCESSABLE_ENTITY"), HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
ErrorLogDto.LogErrorLevel.CRITICAL, ErrorLogDto.LogErrorLevel.CRITICAL,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf("UNPROCESSABLE_ENTITY"), HttpStatus.valueOf("UNPROCESSABLE_ENTITY"),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class) @ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResponseDto<String> handlerMethodArgumentNotValidException( public ApiResponseDto<String> handlerMethodArgumentNotValidException(
MethodArgumentNotValidException e, HttpServletRequest request) { MethodArgumentNotValidException e, HttpServletRequest request) {
log.warn("[MethodArgumentNotValidException] resource :{} ", e.getMessage()); log.warn("[MethodArgumentNotValidException] resource :{} ", e.getMessage());
String codeName = "BAD_REQUEST"; String codeName = "BAD_REQUEST";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.UNAUTHORIZED) @ResponseStatus(HttpStatus.UNAUTHORIZED)
@ExceptionHandler(AccessDeniedException.class) @ExceptionHandler(AccessDeniedException.class)
public ApiResponseDto<String> handlerAccessDeniedException( public ApiResponseDto<String> handlerAccessDeniedException(
AccessDeniedException e, HttpServletRequest request) { AccessDeniedException e, HttpServletRequest request) {
log.warn("[AccessDeniedException] resource :{} ", e.getMessage()); log.warn("[AccessDeniedException] resource :{} ", e.getMessage());
String codeName = "UNAUTHORIZED"; String codeName = "UNAUTHORIZED";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.ERROR, ErrorLogDto.LogErrorLevel.ERROR,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.BAD_GATEWAY) @ResponseStatus(HttpStatus.BAD_GATEWAY)
@ExceptionHandler(HttpServerErrorException.BadGateway.class) @ExceptionHandler(HttpServerErrorException.BadGateway.class)
public ApiResponseDto<String> handlerHttpServerErrorException( public ApiResponseDto<String> handlerHttpServerErrorException(
HttpServerErrorException e, HttpServletRequest request) { HttpServerErrorException e, HttpServletRequest request) {
log.warn("[HttpServerErrorException] resource :{} ", e.getMessage()); log.warn("[HttpServerErrorException] resource :{} ", e.getMessage());
String codeName = "BAD_GATEWAY"; String codeName = "BAD_GATEWAY";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.CRITICAL, ErrorLogDto.LogErrorLevel.CRITICAL,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
@ExceptionHandler(IllegalStateException.class) @ExceptionHandler(IllegalStateException.class)
public ApiResponseDto<String> handlerIllegalStateException( public ApiResponseDto<String> handlerIllegalStateException(
IllegalStateException e, HttpServletRequest request) { IllegalStateException e, HttpServletRequest request) {
log.warn("[IllegalStateException] resource :{} ", e.getMessage()); log.warn("[IllegalStateException] resource :{} ", e.getMessage());
String codeName = "UNPROCESSABLE_ENTITY"; String codeName = "UNPROCESSABLE_ENTITY";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MemberException.DuplicateMemberException.class) @ExceptionHandler(MemberException.DuplicateMemberException.class)
public ApiResponseDto<String> handlerDuplicateMemberException( public ApiResponseDto<String> handlerDuplicateMemberException(
MemberException.DuplicateMemberException e, HttpServletRequest request) { MemberException.DuplicateMemberException e, HttpServletRequest request) {
log.warn("[DuplicateMemberException] resource :{} ", e.getMessage()); log.warn("[DuplicateMemberException] resource :{} ", e.getMessage());
String codeName = ""; String codeName = "";
@@ -254,115 +253,112 @@ public class GlobalExceptionHandler {
} }
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf("BAD_REQUEST"), HttpStatus.valueOf("BAD_REQUEST"),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf("BAD_REQUEST"), HttpStatus.valueOf("BAD_REQUEST"),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MemberException.MemberNotFoundException.class) @ExceptionHandler(MemberException.MemberNotFoundException.class)
public ApiResponseDto<String> handlerMemberNotFoundException( public ApiResponseDto<String> handlerMemberNotFoundException(
MemberException.MemberNotFoundException e, HttpServletRequest request) { MemberException.MemberNotFoundException e, HttpServletRequest request) {
log.warn("[MemberNotFoundException] resource :{} ", e.getMessage()); log.warn("[MemberNotFoundException] resource :{} ", e.getMessage());
String codeName = "NOT_FOUND_USER"; String codeName = "NOT_FOUND_USER";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf("BAD_REQUEST"), HttpStatus.valueOf("BAD_REQUEST"),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf("BAD_REQUEST"), HttpStatus.valueOf("BAD_REQUEST"),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.CONFLICT) @ResponseStatus(HttpStatus.CONFLICT)
@ExceptionHandler(DuplicateKeyException.class) @ExceptionHandler(DuplicateKeyException.class)
public ApiResponseDto<String> handlerDuplicateKeyException( public ApiResponseDto<String> handlerDuplicateKeyException(
DuplicateKeyException e, HttpServletRequest request) { DuplicateKeyException e, HttpServletRequest request) {
log.warn("[DuplicateKeyException] resource :{} ", e.getMessage()); log.warn("[DuplicateKeyException] resource :{} ", e.getMessage());
String codeName = "DUPLICATE_DATA"; String codeName = "DUPLICATE_DATA";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf("CONFLICT"), HttpStatus.valueOf("CONFLICT"),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf("CONFLICT"), HttpStatus.valueOf("CONFLICT"),
errorLog.getId()); errorLog.getId());
} }
@ExceptionHandler(BadCredentialsException.class) @ExceptionHandler(BadCredentialsException.class)
public ResponseEntity<ApiResponseDto<String>> handleBadCredentials( public ResponseEntity<ApiResponseDto<String>> handleBadCredentials(
BadCredentialsException e, HttpServletRequest request BadCredentialsException e, HttpServletRequest request) {
) {
log.warn("[BadCredentialsException] resource : {} ", e.getMessage()); log.warn("[BadCredentialsException] resource : {} ", e.getMessage());
String codeName = "UNAUTHORIZED"; String codeName = "UNAUTHORIZED";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.WARNING, ErrorLogDto.LogErrorLevel.WARNING,
e.getStackTrace()); e.getStackTrace());
ApiResponseDto<String> body = ApiResponseDto<String> body =
ApiResponseDto.createException( ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
return ResponseEntity return ResponseEntity.status(HttpStatus.UNAUTHORIZED) // 🔥 여기서 401 지정
.status(HttpStatus.UNAUTHORIZED) // 🔥 여기서 401 지정 .body(body);
.body(body);
} }
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(RuntimeException.class) @ExceptionHandler(RuntimeException.class)
public ApiResponseDto<String> handlerRuntimeException( public ApiResponseDto<String> handlerRuntimeException(
RuntimeException e, HttpServletRequest request) { RuntimeException e, HttpServletRequest request) {
log.warn("[RuntimeException] resource :{} ", e.getMessage()); log.warn("[RuntimeException] resource :{} ", e.getMessage());
String codeName = "INTERNAL_SERVER_ERROR"; String codeName = "INTERNAL_SERVER_ERROR";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.CRITICAL, ErrorLogDto.LogErrorLevel.CRITICAL,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@@ -372,36 +368,36 @@ public class GlobalExceptionHandler {
String codeName = "INTERNAL_SERVER_ERROR"; String codeName = "INTERNAL_SERVER_ERROR";
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, request,
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
ErrorLogDto.LogErrorLevel.CRITICAL, ErrorLogDto.LogErrorLevel.CRITICAL,
e.getStackTrace()); e.getStackTrace());
return ApiResponseDto.createException( return ApiResponseDto.createException(
ApiResponseCode.getCode(codeName), ApiResponseCode.getCode(codeName),
ApiResponseCode.getMessage(codeName), ApiResponseCode.getMessage(codeName),
HttpStatus.valueOf(codeName), HttpStatus.valueOf(codeName),
errorLog.getId()); errorLog.getId());
} }
/** /**
* 에러 로그 테이블 저장 로직 * 에러 로그 테이블 저장 로직
* *
* @param request : request * @param request : request
* @param errorCode : 정의된 enum errorCode * @param errorCode : 정의된 enum errorCode
* @param httpStatus : HttpStatus 값 * @param httpStatus : HttpStatus 값
* @param logErrorLevel : WARNING, ERROR, CRITICAL * @param logErrorLevel : WARNING, ERROR, CRITICAL
* @param stackTrace : 에러 내용 * @param stackTrace : 에러 내용
* @return : insert하고 결과로 받은 Entity * @return : insert하고 결과로 받은 Entity
*/ */
private ErrorLogEntity saveErrorLogData( private ErrorLogEntity saveErrorLogData(
HttpServletRequest request, HttpServletRequest request,
ApiResponseCode errorCode, ApiResponseCode errorCode,
HttpStatus httpStatus, HttpStatus httpStatus,
ErrorLogDto.LogErrorLevel logErrorLevel, ErrorLogDto.LogErrorLevel logErrorLevel,
StackTraceElement[] stackTrace) { StackTraceElement[] stackTrace) {
Long userid = null; Long userid = null;
@@ -415,35 +411,35 @@ public class GlobalExceptionHandler {
* 만든 CustomUserDetails 타입인가? 체크 * 만든 CustomUserDetails 타입인가? 체크
*/ */
if (request.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth if (request.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth
&& auth.getPrincipal() instanceof CustomUserDetails customUserDetails) { && auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
// audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기 // audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기
userid = customUserDetails.getMember().getId(); userid = customUserDetails.getMember().getId();
} }
String stackTraceStr = String stackTraceStr =
Arrays.stream(stackTrace) Arrays.stream(stackTrace)
.map(StackTraceElement::toString) .map(StackTraceElement::toString)
.collect(Collectors.joining("\n")) .collect(Collectors.joining("\n"))
.substring(0, Math.min(stackTrace.length, 255)); .substring(0, Math.min(stackTrace.length, 255));
ErrorLogEntity errorLogEntity = ErrorLogEntity errorLogEntity =
new ErrorLogEntity( new ErrorLogEntity(
request.getRequestURI(), request.getRequestURI(),
ApiLogFunction.getEventType(request), ApiLogFunction.getEventType(request),
logErrorLevel, logErrorLevel,
String.valueOf(httpStatus.value()), String.valueOf(httpStatus.value()),
errorCode.getText(), errorCode.getText(),
stackTraceStr, stackTraceStr,
userid, userid,
ZonedDateTime.now()); ZonedDateTime.now());
return errorLogRepository.save(errorLogEntity); return errorLogRepository.save(errorLogEntity);
} }
@ExceptionHandler(CustomApiException.class) @ExceptionHandler(CustomApiException.class)
public ResponseEntity<ApiResponseDto<String>> handleCustomApiException( public ResponseEntity<ApiResponseDto<String>> handleCustomApiException(
CustomApiException e, HttpServletRequest request) { CustomApiException e, HttpServletRequest request) {
log.warn("[CustomApiException] resource : {}", e.getMessage()); log.warn("[CustomApiException] resource : {}", e.getMessage());
String codeName = e.getCodeName(); String codeName = e.getCodeName();
@@ -453,11 +449,11 @@ public class GlobalExceptionHandler {
ApiResponseCode apiCode = ApiResponseCode.getCode(codeName); ApiResponseCode apiCode = ApiResponseCode.getCode(codeName);
ErrorLogEntity errorLog = ErrorLogEntity errorLog =
saveErrorLogData( saveErrorLogData(
request, apiCode, status, ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace()); request, apiCode, status, ErrorLogDto.LogErrorLevel.WARNING, e.getStackTrace());
ApiResponseDto<String> body = ApiResponseDto<String> body =
ApiResponseDto.createException(apiCode, message, status, errorLog.getId()); ApiResponseDto.createException(apiCode, message, status, errorLog.getId());
return new ResponseEntity<>(body, status); return new ResponseEntity<>(body, status);
} }

View File

@@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator; import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.Duration; import java.time.Duration;
import java.util.List;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
@@ -81,15 +82,21 @@ public class RedisConfig {
cacheObjectMapper.registerModule(new JavaTimeModule()); cacheObjectMapper.registerModule(new JavaTimeModule());
cacheObjectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); cacheObjectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
cacheObjectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); cacheObjectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 알 수 없는 타입에 대해 더 유연하게 처리
cacheObjectMapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
cacheObjectMapper.findAndRegisterModules(); cacheObjectMapper.findAndRegisterModules();
// 타입 정보 포함 - JAVA_LANG_OBJECT로 제한적으로 적용 // 타입 정보 포함 - JAVA_LANG_OBJECT로 제한적으로 적용
// 호환성 문제 해결을 위해 더 많은 타입 허용
PolymorphicTypeValidator ptv = PolymorphicTypeValidator ptv =
BasicPolymorphicTypeValidator.builder() BasicPolymorphicTypeValidator.builder()
.allowIfSubType("com.kamco.cd.kamcoback") .allowIfSubType("com.kamco.cd.kamcoback")
.allowIfSubType("org.springframework.data.domain") .allowIfSubType("org.springframework.data.domain")
.allowIfSubType("java.util") .allowIfSubType("java.util")
.allowIfSubType("java.time") .allowIfSubType("java.time")
.allowIfSubType("java.lang")
.allowIfBaseType(List.class)
.allowIfBaseType("com.kamco.cd.kamcoback.code.dto.CommonCodeDto$Basic")
.build(); .build();
cacheObjectMapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT); cacheObjectMapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT);

View File

@@ -29,30 +29,29 @@ public class SecurityConfig {
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable()) // CSRF 보안 기능 비활성화 http.csrf(csrf -> csrf.disable()) // CSRF 보안 기능 비활성화
.sessionManagement( .sessionManagement(
sm -> sm ->
sm.sessionCreationPolicy( sm.sessionCreationPolicy(
SessionCreationPolicy.STATELESS)) // 서버 세션 만들지 않음, 요청은 JWT 인증 SessionCreationPolicy.STATELESS)) // 서버 세션 만들지 않음, 요청은 JWT 인증
.formLogin(form -> form.disable()) // react에서 로그인 요청 관리 .formLogin(form -> form.disable()) // react에서 로그인 요청 관리
.httpBasic(basic -> basic.disable()) // 기본 basic 인증 비활성화 JWT 인증사용 .httpBasic(basic -> basic.disable()) // 기본 basic 인증 비활성화 JWT 인증사용
.logout(logout -> logout.disable()) // 기본 로그아웃 비활성화 JWT는 서버 상태가 없으므로 로그아웃 처리 필요 없음 .logout(logout -> logout.disable()) // 기본 로그아웃 비활성화 JWT는 서버 상태가 없으므로 로그아웃 처리 필요 없음
.authenticationProvider( .authenticationProvider(
customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용 customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용
.authorizeHttpRequests( .authorizeHttpRequests(
auth -> auth ->
auth.requestMatchers( auth.requestMatchers(
"/api/auth/signin", "/api/auth/signin",
"/api/auth/refresh", "/api/auth/refresh",
"/swagger-ui/**", "/swagger-ui/**",
"/v3/api-docs/**") "/v3/api-docs/**")
.permitAll() .permitAll()
.anyRequest() .anyRequest()
.authenticated()) .authenticated())
.addFilterBefore( .addFilterBefore(
jwtAuthenticationFilter, jwtAuthenticationFilter,
UsernamePasswordAuthenticationFilter UsernamePasswordAuthenticationFilter
.class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장. .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장.
; ;
return http.build(); return http.build();
@@ -60,7 +59,7 @@ public class SecurityConfig {
@Bean @Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration)
throws Exception { throws Exception {
return configuration.getAuthenticationManager(); return configuration.getAuthenticationManager();
} }

View File

@@ -6,11 +6,8 @@ import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
@SecurityScheme( @SecurityScheme(
name = "BearerAuth", name = "BearerAuth",
type = SecuritySchemeType.HTTP, type = SecuritySchemeType.HTTP,
scheme = "bearer", scheme = "bearer",
bearerFormat = "JWT" bearerFormat = "JWT")
) public class SwaggerConfig {}
public class SwaggerConfig {
}

View File

@@ -64,22 +64,22 @@ public class ApiLogFunction {
} }
public static String getRequestBody( public static String getRequestBody(
HttpServletRequest servletRequest, ContentCachingRequestWrapper contentWrapper) { HttpServletRequest servletRequest, ContentCachingRequestWrapper contentWrapper) {
StringBuilder resultBody = new StringBuilder(); StringBuilder resultBody = new StringBuilder();
// GET, form-urlencoded POST 파라미터 // GET, form-urlencoded POST 파라미터
Map<String, String[]> paramMap = servletRequest.getParameterMap(); Map<String, String[]> paramMap = servletRequest.getParameterMap();
String queryParams = String queryParams =
paramMap.entrySet().stream() paramMap.entrySet().stream()
.map(e -> e.getKey() + "=" + String.join(",", e.getValue())) .map(e -> e.getKey() + "=" + String.join(",", e.getValue()))
.collect(Collectors.joining("&")); .collect(Collectors.joining("&"));
resultBody.append(queryParams.isEmpty() ? "" : queryParams); resultBody.append(queryParams.isEmpty() ? "" : queryParams);
// JSON Body // JSON Body
if ("POST".equalsIgnoreCase(servletRequest.getMethod()) if ("POST".equalsIgnoreCase(servletRequest.getMethod())
&& servletRequest.getContentType() != null && servletRequest.getContentType() != null
&& servletRequest.getContentType().contains("application/json")) { && servletRequest.getContentType().contains("application/json")) {
try { try {
// json인 경우는 Wrapper를 통해 가져오기 // json인 경우는 Wrapper를 통해 가져오기
resultBody.append(getBodyData(contentWrapper)); resultBody.append(getBodyData(contentWrapper));
@@ -91,8 +91,8 @@ public class ApiLogFunction {
// Multipart form-data // Multipart form-data
if ("POST".equalsIgnoreCase(servletRequest.getMethod()) if ("POST".equalsIgnoreCase(servletRequest.getMethod())
&& servletRequest.getContentType() != null && servletRequest.getContentType() != null
&& servletRequest.getContentType().startsWith("multipart/form-data")) { && servletRequest.getContentType().startsWith("multipart/form-data")) {
resultBody.append("multipart/form-data request"); resultBody.append("multipart/form-data request");
} }

View File

@@ -31,19 +31,19 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
@Override @Override
public boolean supports( public boolean supports(
MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) { MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
// ApiResponseDto를 반환하는 경우에만 적용 // ApiResponseDto를 반환하는 경우에만 적용
return returnType.getParameterType().equals(ApiResponseDto.class); return returnType.getParameterType().equals(ApiResponseDto.class);
} }
@Override @Override
public Object beforeBodyWrite( public Object beforeBodyWrite(
Object body, Object body,
MethodParameter returnType, MethodParameter returnType,
MediaType selectedContentType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpRequest request,
ServerHttpResponse response) { ServerHttpResponse response) {
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest(); HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
ContentCachingRequestWrapper contentWrapper = (ContentCachingRequestWrapper) servletRequest; ContentCachingRequestWrapper contentWrapper = (ContentCachingRequestWrapper) servletRequest;
@@ -57,15 +57,16 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
Long userid = null; Long userid = null;
/** /**
* servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth * servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth 이 요청이
* 이 요청이 JWT 인증을 통과한 요청인가? 그리고 Spring Security Authentication 객체가 UsernamePasswordAuthenticationToken 타입인가? 체크 * JWT 인증을 통과한 요청인가? 그리고 Spring Security Authentication 객체가
* UsernamePasswordAuthenticationToken 타입인가? 체크
*/ */
/** /**
* auth.getPrincipal() instanceof CustomUserDetails customUserDetails * auth.getPrincipal() instanceof CustomUserDetails customUserDetails principal 안에 들어있는 객체가 내가
* principal 안에 들어있는 객체가 내가 만든 CustomUserDetails 타입인가? 체크 * 만든 CustomUserDetails 타입인가? 체크
*/ */
if (servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth if (servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth
&& auth.getPrincipal() instanceof CustomUserDetails customUserDetails) { && auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
// audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기 // audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기
userid = customUserDetails.getMember().getId(); userid = customUserDetails.getMember().getId();
@@ -76,15 +77,15 @@ public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
// TODO: menuUid 를 동적으로 가져오게끔 해야함 // TODO: menuUid 를 동적으로 가져오게끔 해야함
AuditLogEntity log = AuditLogEntity log =
new AuditLogEntity( new AuditLogEntity(
userid, userid,
ApiLogFunction.getEventType(servletRequest), ApiLogFunction.getEventType(servletRequest),
ApiLogFunction.isSuccessFail(apiResponse), ApiLogFunction.isSuccessFail(apiResponse),
"MU_01_01", "MU_01_01",
ip, ip,
servletRequest.getRequestURI(), servletRequest.getRequestURI(),
requestBody, requestBody,
apiResponse.getErrorLogUid()); apiResponse.getErrorLogUid());
// tb_audit_log 테이블 저장 // tb_audit_log 테이블 저장
auditLogRepository.save(log); auditLogRepository.save(log);
} }

View File

@@ -3,12 +3,6 @@ package com.kamco.cd.kamcoback.mapsheet;
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto; import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
import com.kamco.cd.kamcoback.code.service.CommonCodeService; import com.kamco.cd.kamcoback.code.service.CommonCodeService;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.config.api.ApiResponseDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FilesDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FoldersDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDepthDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFoldersDto;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngService; import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@@ -63,7 +57,6 @@ public class MapSheetMngApiController {
return ApiResponseDto.ok(mapSheetMngService.findMapSheetMngList(searchReq)); return ApiResponseDto.ok(mapSheetMngService.findMapSheetMngList(searchReq));
} }
/** /**
* @param hstUidList * @param hstUidList
* @return * @return

View File

@@ -9,9 +9,7 @@ import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDepthDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFoldersDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFoldersDto;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto; import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngFileCheckerService; import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngFileCheckerService;
import com.kamco.cd.kamcoback.mapsheet.service.MapSheetMngService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@@ -19,11 +17,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -93,26 +88,22 @@ public class MapSheetMngFileCheckerApiController {
return ApiResponseDto.createOK(mapSheetMngFileCheckerService.getFilesDepthAll(srchDto)); return ApiResponseDto.createOK(mapSheetMngFileCheckerService.getFilesDepthAll(srchDto));
} }
@Operation(summary = "영상데이터관리 > 영상파일 동기화", description = "영상파일 동기화") @Operation(summary = "영상데이터관리 > 영상파일 동기화", description = "영상파일 동기화")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "동기화 성공", description = "동기화 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = CommonCodeDto.Basic.class))), schema = @Schema(implementation = CommonCodeDto.Basic.class))),
@ApiResponse(responseCode = "404", description = "동기화 할수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "동기화 할수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PostMapping("/sync-process") @PostMapping("/sync-process")
public ApiResponseDto<ImageryDto.SyncReturn> syncProcess( public ApiResponseDto<ImageryDto.SyncReturn> syncProcess(
@RequestBody @Valid ImageryDto.searchReq searchReq) { @RequestBody @Valid ImageryDto.searchReq searchReq) {
return ApiResponseDto.ok(mapSheetMngFileCheckerService.syncProcess(searchReq)); return ApiResponseDto.ok(mapSheetMngFileCheckerService.syncProcess(searchReq));
} }
} }

View File

@@ -1,8 +1,6 @@
package com.kamco.cd.kamcoback.mapsheet.dto; package com.kamco.cd.kamcoback.mapsheet.dto;
import com.kamco.cd.kamcoback.config.enums.EnumType;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.UUID; import java.util.UUID;
@@ -10,10 +8,8 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import org.hibernate.annotations.ColumnDefault;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
public class ImageryDto { public class ImageryDto {
@@ -43,7 +39,9 @@ public class ImageryDto {
@NotNull @NotNull
private Integer mngYyyy; private Integer mngYyyy;
public Pageable toPageable() {return PageRequest.of(page, size);} public Pageable toPageable() {
return PageRequest.of(page, size);
}
} }
@Schema(name = "ImageryDto", description = "영상관리파일 검색 리턴") @Schema(name = "ImageryDto", description = "영상관리파일 검색 리턴")
@@ -94,7 +92,4 @@ public class ImageryDto {
private int tfwErrCnt; private int tfwErrCnt;
private int tifErrCnt; private int tifErrCnt;
} }
} }

View File

@@ -11,7 +11,6 @@ import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDepthDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFoldersDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFoldersDto;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto; import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.postgres.core.MapSheetMngFileCheckerCoreService; import com.kamco.cd.kamcoback.postgres.core.MapSheetMngFileCheckerCoreService;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -302,9 +301,7 @@ public class MapSheetMngFileCheckerService {
} }
} }
public ImageryDto.SyncReturn syncProcess(ImageryDto.searchReq searchReq) { public ImageryDto.SyncReturn syncProcess(ImageryDto.searchReq searchReq) {
return mapSheetMngFileCheckerCoreService.syncProcess(searchReq); return mapSheetMngFileCheckerCoreService.syncProcess(searchReq);
} }
} }

View File

@@ -2,15 +2,10 @@ package com.kamco.cd.kamcoback.mapsheet.service;
import static java.lang.String.CASE_INSENSITIVE_ORDER; import static java.lang.String.CASE_INSENSITIVE_ORDER;
import com.kamco.cd.kamcoback.common.utils.NameValidator;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FilesDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FilesDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FolderDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.FoldersDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDepthDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDepthDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto; import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFilesDto;
import com.kamco.cd.kamcoback.mapsheet.dto.FileDto.SrchFoldersDto;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService; import com.kamco.cd.kamcoback.postgres.core.MapSheetMngCoreService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@@ -42,8 +37,6 @@ public class MapSheetMngService {
private final MapSheetMngCoreService mapSheetMngCoreService; private final MapSheetMngCoreService mapSheetMngCoreService;
public FilesDto getFilesAll(SrchFilesDto srchDto) { public FilesDto getFilesAll(SrchFilesDto srchDto) {
String dirPath = srchDto.getDirPath(); String dirPath = srchDto.getDirPath();
@@ -236,7 +229,4 @@ public class MapSheetMngService {
public MapSheetMngDto.DmlReturn updateExceptUseInference(@Valid List<Long> hstUidList) { public MapSheetMngDto.DmlReturn updateExceptUseInference(@Valid List<Long> hstUidList) {
return mapSheetMngCoreService.updateExceptUseInference(hstUidList); return mapSheetMngCoreService.updateExceptUseInference(hstUidList);
} }
} }

View File

@@ -30,139 +30,138 @@ public class AdminApiController {
@Operation(summary = "회원가입", description = "회원가입") @Operation(summary = "회원가입", description = "회원가입")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "회원가입 성공", description = "회원가입 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Long.class))), schema = @Schema(implementation = Long.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PostMapping("/join") @PostMapping("/join")
public ApiResponseDto<Long> saveMember( public ApiResponseDto<Long> saveMember(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "회원가입", description = "회원가입",
required = true, required = true,
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = MembersDto.AddReq.class))) schema = @Schema(implementation = MembersDto.AddReq.class)))
@RequestBody @RequestBody
@Valid @Valid
MembersDto.AddReq addReq) { MembersDto.AddReq addReq) {
return ApiResponseDto.createOK(adminService.saveMember(addReq)); return ApiResponseDto.createOK(adminService.saveMember(addReq));
} }
@Operation(summary = "역할 추가", description = "uuid 기준으로 역할 추가") @Operation(summary = "역할 추가", description = "uuid 기준으로 역할 추가")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "역할 추가", description = "역할 추가",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = UUID.class))), schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PostMapping("/roles/add") @PostMapping("/roles/add")
public ApiResponseDto<UUID> saveRoles( public ApiResponseDto<UUID> saveRoles(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "역할 추가", description = "역할 추가",
required = true, required = true,
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = MembersDto.RolesDto.class))) schema = @Schema(implementation = MembersDto.RolesDto.class)))
@RequestBody @RequestBody
@Valid @Valid
MembersDto.RolesDto rolesDto) { MembersDto.RolesDto rolesDto) {
adminService.saveRoles(rolesDto); adminService.saveRoles(rolesDto);
return ApiResponseDto.createOK(rolesDto.getUuid()); return ApiResponseDto.createOK(rolesDto.getUuid());
} }
@Operation(summary = "역할 삭제", description = "uuid 기준으로 역할 삭제") @Operation(summary = "역할 삭제", description = "uuid 기준으로 역할 삭제")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "역할 삭제", description = "역할 삭제",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = UUID.class))), schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@DeleteMapping("/roles/rm") @DeleteMapping("/roles/rm")
public ApiResponseDto<UUID> deleteRoles( public ApiResponseDto<UUID> deleteRoles(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "역할 삭제", description = "역할 삭제",
required = true, required = true,
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = MembersDto.RolesDto.class))) schema = @Schema(implementation = MembersDto.RolesDto.class)))
@RequestBody @RequestBody
@Valid @Valid
MembersDto.RolesDto rolesDto) { MembersDto.RolesDto rolesDto) {
adminService.deleteRoles(rolesDto); adminService.deleteRoles(rolesDto);
return ApiResponseDto.createOK(rolesDto.getUuid()); return ApiResponseDto.createOK(rolesDto.getUuid());
} }
@Operation(summary = "상태 수정", description = "상태 수정") @Operation(summary = "상태 수정", description = "상태 수정")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "상태 수정", description = "상태 수정",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = UUID.class))), schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PatchMapping("{uuid}/status") @PatchMapping("{uuid}/status")
public ApiResponseDto<UUID> updateStatus( public ApiResponseDto<UUID> updateStatus(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "상태 수정", description = "상태 수정",
required = true, required = true,
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = MembersDto.StatusDto.class))) schema = @Schema(implementation = MembersDto.StatusDto.class)))
@PathVariable UUID uuid, @PathVariable
@RequestBody UUID uuid,
@Valid @RequestBody @Valid MembersDto.StatusDto statusDto) {
MembersDto.StatusDto statusDto) {
adminService.updateStatus(uuid, statusDto); adminService.updateStatus(uuid, statusDto);
return ApiResponseDto.createOK(uuid); return ApiResponseDto.createOK(uuid);
} }
@Operation(summary = "회원 탈퇴", description = "회원 탈퇴") @Operation(summary = "회원 탈퇴", description = "회원 탈퇴")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "회원 탈퇴", description = "회원 탈퇴",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = UUID.class))), schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@DeleteMapping("/delete/{uuid}") @DeleteMapping("/delete/{uuid}")
public ApiResponseDto<UUID> deleteAccount(@PathVariable UUID uuid) { public ApiResponseDto<UUID> deleteAccount(@PathVariable UUID uuid) {
adminService.deleteAccount(uuid); adminService.deleteAccount(uuid);
@@ -171,18 +170,18 @@ public class AdminApiController {
@Operation(summary = "비밀번호 초기화", description = "비밀번호 초기화") @Operation(summary = "비밀번호 초기화", description = "비밀번호 초기화")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "비밀번호 초기화", description = "비밀번호 초기화",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Long.class))), schema = @Schema(implementation = Long.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PatchMapping("/{memberId}/password") @PatchMapping("/{memberId}/password")
public ApiResponseDto<Long> resetPassword(@PathVariable Long memberId) { public ApiResponseDto<Long> resetPassword(@PathVariable Long memberId) {
adminService.resetPassword(memberId); adminService.resetPassword(memberId);

View File

@@ -47,24 +47,24 @@ public class AuthController {
@Operation(summary = "로그인", description = "사번으로 로그인하여 액세스/리프레시 토큰을 발급.") @Operation(summary = "로그인", description = "사번으로 로그인하여 액세스/리프레시 토큰을 발급.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "로그인 성공", description = "로그인 성공",
content = @Content(schema = @Schema(implementation = TokenResponse.class))), content = @Content(schema = @Schema(implementation = TokenResponse.class))),
@ApiResponse( @ApiResponse(
responseCode = "401", responseCode = "401",
description = "ID 또는 비밀번호 불일치", description = "ID 또는 비밀번호 불일치",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
public ApiResponseDto<TokenResponse> signin( public ApiResponseDto<TokenResponse> signin(
@io.swagger.v3.oas.annotations.parameters.RequestBody( @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "로그인 요청 정보", description = "로그인 요청 정보",
required = true) required = true)
@RequestBody @RequestBody
SignInRequest request, SignInRequest request,
HttpServletResponse response) { HttpServletResponse response) {
Authentication authentication = Authentication authentication =
authenticationManager.authenticate( authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())); new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
String username = authentication.getName(); // UserDetailsService 에서 사용한 username String username = authentication.getName(); // UserDetailsService 에서 사용한 username
@@ -73,17 +73,17 @@ public class AuthController {
// Redis에 RefreshToken 저장 (TTL = 7일) // Redis에 RefreshToken 저장 (TTL = 7일)
refreshTokenService.save( refreshTokenService.save(
username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs()); username, refreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
// HttpOnly + Secure 쿠키에 RefreshToken 저장 // HttpOnly + Secure 쿠키에 RefreshToken 저장
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, refreshToken) ResponseCookie.from(refreshCookieName, refreshToken)
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs())) .maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ApiResponseDto.ok(new TokenResponse(accessToken)); return ApiResponseDto.ok(new TokenResponse(accessToken));
@@ -93,15 +93,16 @@ public class AuthController {
@Operation(summary = "토큰 재발급", description = "리프레시 토큰으로 새로운 액세스/리프레시 토큰을 재발급합니다.") @Operation(summary = "토큰 재발급", description = "리프레시 토큰으로 새로운 액세스/리프레시 토큰을 재발급합니다.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "재발급 성공", description = "재발급 성공",
content = @Content(schema = @Schema(implementation = TokenResponse.class))), content = @Content(schema = @Schema(implementation = TokenResponse.class))),
@ApiResponse( @ApiResponse(
responseCode = "401", responseCode = "401",
description = "만료되었거나 유효하지 않은 리프레시 토큰", description = "만료되었거나 유효하지 않은 리프레시 토큰",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))) content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
}) })
public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response) throws AccessDeniedException { public ResponseEntity<TokenResponse> refresh(String refreshToken, HttpServletResponse response)
throws AccessDeniedException {
if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) { if (refreshToken == null || !jwtTokenProvider.isValidToken(refreshToken)) {
throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다."); throw new AccessDeniedException("만료되었거나 유효하지 않은 리프레시 토큰 입니다.");
} }
@@ -119,17 +120,17 @@ public class AuthController {
// Redis 갱신 // Redis 갱신
refreshTokenService.save( refreshTokenService.save(
username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs()); username, newRefreshToken, jwtTokenProvider.getRefreshTokenValidityInMs());
// 쿠키 갱신 // 쿠키 갱신
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, newRefreshToken) ResponseCookie.from(refreshCookieName, newRefreshToken)
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs())) .maxAge(Duration.ofMillis(jwtTokenProvider.getRefreshTokenValidityInMs()))
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ResponseEntity.ok(new TokenResponse(newAccessToken)); return ResponseEntity.ok(new TokenResponse(newAccessToken));
@@ -139,11 +140,12 @@ public class AuthController {
@Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(리프레시 토큰 삭제)합니다.") @Operation(summary = "로그아웃", description = "현재 사용자의 토큰을 무효화(리프레시 토큰 삭제)합니다.")
@ApiResponses({ @ApiResponses({
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "로그아웃 성공", description = "로그아웃 성공",
content = @Content(schema = @Schema(implementation = Void.class))) content = @Content(schema = @Schema(implementation = Void.class)))
}) })
public ApiResponseDto<ResponseEntity<Object>> logout(Authentication authentication, HttpServletResponse response) { public ApiResponseDto<ResponseEntity<Object>> logout(
Authentication authentication, HttpServletResponse response) {
if (authentication != null) { if (authentication != null) {
String username = authentication.getName(); String username = authentication.getName();
// Redis에서 RefreshToken 삭제 // Redis에서 RefreshToken 삭제
@@ -152,19 +154,17 @@ public class AuthController {
// 쿠키 삭제 (Max-Age=0) // 쿠키 삭제 (Max-Age=0)
ResponseCookie cookie = ResponseCookie cookie =
ResponseCookie.from(refreshCookieName, "") ResponseCookie.from(refreshCookieName, "")
.httpOnly(true) .httpOnly(true)
.secure(refreshCookieSecure) .secure(refreshCookieSecure)
.path("/") .path("/")
.maxAge(0) .maxAge(0)
.sameSite("Strict") .sameSite("Strict")
.build(); .build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return ApiResponseDto.createOK(ResponseEntity.noContent().build()); return ApiResponseDto.createOK(ResponseEntity.noContent().build());
} }
public record TokenResponse(String accessToken) { public record TokenResponse(String accessToken) {}
}
} }

View File

@@ -31,40 +31,40 @@ public class MembersApiController {
@Operation(summary = "회원정보 목록", description = "회원정보 조회") @Operation(summary = "회원정보 목록", description = "회원정보 조회")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "200", responseCode = "200",
description = "검색 성공", description = "검색 성공",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = Page.class))), schema = @Schema(implementation = Page.class))),
@ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@GetMapping @GetMapping
public ApiResponseDto<Page<Basic>> getMemberList( public ApiResponseDto<Page<Basic>> getMemberList(
@ParameterObject MembersDto.SearchReq searchReq) { @ParameterObject MembersDto.SearchReq searchReq) {
return ApiResponseDto.ok(membersService.findByMembers(searchReq)); return ApiResponseDto.ok(membersService.findByMembers(searchReq));
} }
@Operation(summary = "회원정보 수정", description = "회원정보 수정") @Operation(summary = "회원정보 수정", description = "회원정보 수정")
@ApiResponses( @ApiResponses(
value = { value = {
@ApiResponse( @ApiResponse(
responseCode = "201", responseCode = "201",
description = "회원정보 수정", description = "회원정보 수정",
content = content =
@Content( @Content(
mediaType = "application/json", mediaType = "application/json",
schema = @Schema(implementation = UUID.class))), schema = @Schema(implementation = UUID.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
}) })
@PutMapping("/{uuid}") @PutMapping("/{uuid}")
public ApiResponseDto<UUID> updateMember( public ApiResponseDto<UUID> updateMember(
@PathVariable UUID uuid, @RequestBody MembersDto.UpdateReq updateReq) { @PathVariable UUID uuid, @RequestBody MembersDto.UpdateReq updateReq) {
membersService.updateMember(uuid, updateReq); membersService.updateMember(uuid, updateReq);
return ApiResponseDto.createOK(uuid); return ApiResponseDto.createOK(uuid);
} }

View File

@@ -28,21 +28,19 @@ public class MembersDto {
private String email; private String email;
private String status; private String status;
private String roleName; private String roleName;
@JsonFormatDttm @JsonFormatDttm private ZonedDateTime createdDttm;
private ZonedDateTime createdDttm; @JsonFormatDttm private ZonedDateTime updatedDttm;
@JsonFormatDttm
private ZonedDateTime updatedDttm;
public Basic( public Basic(
Long id, Long id,
UUID uuid, UUID uuid,
String employeeNo, String employeeNo,
String name, String name,
String email, String email,
String status, String status,
String roleName, String roleName,
ZonedDateTime createdDttm, ZonedDateTime createdDttm,
ZonedDateTime updatedDttm) { ZonedDateTime updatedDttm) {
this.id = id; this.id = id;
this.uuid = uuid; this.uuid = uuid;
this.employeeNo = employeeNo; this.employeeNo = employeeNo;

View File

@@ -1,7 +1,5 @@
package com.kamco.cd.kamcoback.postgres.core; package com.kamco.cd.kamcoback.postgres.core;
import com.kamco.cd.kamcoback.common.utils.FIleChecker;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngRepository; import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngRepository;
@@ -124,8 +122,4 @@ public class MapSheetMngCoreService {
throw new RuntimeException("File search error", e); throw new RuntimeException("File search error", e);
} }
} }
} }

View File

@@ -2,23 +2,7 @@ package com.kamco.cd.kamcoback.postgres.core;
import com.kamco.cd.kamcoback.common.utils.FIleChecker; import com.kamco.cd.kamcoback.common.utils.FIleChecker;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto; import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngFileCheckerRepository; import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngFileCheckerRepository;
import com.kamco.cd.kamcoback.postgres.repository.mapsheet.MapSheetMngRepository;
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@@ -35,36 +19,35 @@ public class MapSheetMngFileCheckerCoreService {
@Value("{spring.profiles.active}") @Value("{spring.profiles.active}")
private String activeEnv; private String activeEnv;
public ImageryDto.SyncReturn syncProcess(ImageryDto.searchReq searchReq) { public ImageryDto.SyncReturn syncProcess(ImageryDto.searchReq searchReq) {
String flag = "SUCCESS"; String flag = "SUCCESS";
int syncCnt = 0; int syncCnt = 0;
int tfwErrCnt = 0; int tfwErrCnt = 0;
int tifErrCnt = 0; int tifErrCnt = 0;
//대상파일목록 가저오기 // 대상파일목록 가저오기
Page<ImageryDto.SyncDto> pageImagerySyncDto = mapSheetMngFileCheckerRepository.findImagerySyncList(searchReq); Page<ImageryDto.SyncDto> pageImagerySyncDto =
mapSheetMngFileCheckerRepository.findImagerySyncList(searchReq);
for (ImageryDto.SyncDto dto : pageImagerySyncDto.getContent()) { for (ImageryDto.SyncDto dto : pageImagerySyncDto.getContent()) {
boolean isTfwFile = true; boolean isTfwFile = true;
isTfwFile = FIleChecker.checkTfw(dto.getMiddlePath()+dto.getFilename()); isTfwFile = FIleChecker.checkTfw(dto.getMiddlePath() + dto.getFilename());
boolean isGdalInfoTiffFile = true; boolean isGdalInfoTiffFile = true;
isGdalInfoTiffFile = FIleChecker.cmmndGdalInfo(dto.getCogMiddlePath()+dto.getCogFilename()); isGdalInfoTiffFile = FIleChecker.cmmndGdalInfo(dto.getCogMiddlePath() + dto.getCogFilename());
//isGdalInfoTiffFile = FIleChecker.cmmndGdalInfo("D:/kamco_cog/36713/36713073_cog.tif"); // isGdalInfoTiffFile = FIleChecker.cmmndGdalInfo("D:/kamco_cog/36713/36713073_cog.tif");
syncCnt = syncCnt + 1; syncCnt = syncCnt + 1;
if( !isTfwFile )tfwErrCnt = tfwErrCnt + 1; if (!isTfwFile) tfwErrCnt = tfwErrCnt + 1;
if( !isGdalInfoTiffFile )tifErrCnt = tifErrCnt + 1; if (!isGdalInfoTiffFile) tifErrCnt = tifErrCnt + 1;
// 예: 특정 작업 수행 // 예: 특정 작업 수행
// someService.process(dto); // someService.process(dto);
} }
if( tfwErrCnt > 0 || tifErrCnt > 0 )flag = "ERROR"; if (tfwErrCnt > 0 || tifErrCnt > 0) flag = "ERROR";
return new ImageryDto.SyncReturn(flag, syncCnt, tfwErrCnt, tifErrCnt); return new ImageryDto.SyncReturn(flag, syncCnt, tfwErrCnt, tifErrCnt);
} }
} }

View File

@@ -41,12 +41,12 @@ public class MembersCoreService {
public Long saveMembers(MembersDto.AddReq addReq) { public Long saveMembers(MembersDto.AddReq addReq) {
if (membersRepository.existsByEmployeeNo(addReq.getEmployeeNo())) { if (membersRepository.existsByEmployeeNo(addReq.getEmployeeNo())) {
throw new MemberException.DuplicateMemberException( throw new MemberException.DuplicateMemberException(
MemberException.DuplicateMemberException.Field.EMPLOYEE_NO, addReq.getEmployeeNo()); MemberException.DuplicateMemberException.Field.EMPLOYEE_NO, addReq.getEmployeeNo());
} }
if (membersRepository.existsByEmail(addReq.getEmail())) { if (membersRepository.existsByEmail(addReq.getEmail())) {
throw new MemberException.DuplicateMemberException( throw new MemberException.DuplicateMemberException(
MemberException.DuplicateMemberException.Field.EMAIL, addReq.getEmail()); MemberException.DuplicateMemberException.Field.EMAIL, addReq.getEmail());
} }
MemberEntity memberEntity = new MemberEntity(); MemberEntity memberEntity = new MemberEntity();
@@ -66,7 +66,7 @@ public class MembersCoreService {
*/ */
public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) { public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) {
MemberEntity memberEntity = MemberEntity memberEntity =
membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException()); membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
if (StringUtils.isNotBlank(memberEntity.getEmployeeNo())) { if (StringUtils.isNotBlank(memberEntity.getEmployeeNo())) {
memberEntity.setEmployeeNo(updateReq.getEmployeeNo()); memberEntity.setEmployeeNo(updateReq.getEmployeeNo());
@@ -93,13 +93,13 @@ public class MembersCoreService {
public void saveRoles(MembersDto.RolesDto rolesDto) { public void saveRoles(MembersDto.RolesDto rolesDto) {
MemberEntity memberEntity = MemberEntity memberEntity =
membersRepository membersRepository
.findByUUID(rolesDto.getUuid()) .findByUUID(rolesDto.getUuid())
.orElseThrow(() -> new MemberNotFoundException()); .orElseThrow(() -> new MemberNotFoundException());
if (memberRoleRepository.findByUuidAndRoleName(rolesDto)) { if (memberRoleRepository.findByUuidAndRoleName(rolesDto)) {
throw new MemberException.DuplicateMemberException( throw new MemberException.DuplicateMemberException(
MemberException.DuplicateMemberException.Field.DEFAULT, "중복된 역할이 있습니다."); MemberException.DuplicateMemberException.Field.DEFAULT, "중복된 역할이 있습니다.");
} }
MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId(); MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId();
@@ -120,9 +120,9 @@ public class MembersCoreService {
*/ */
public void deleteRoles(MembersDto.RolesDto rolesDto) { public void deleteRoles(MembersDto.RolesDto rolesDto) {
MemberEntity memberEntity = MemberEntity memberEntity =
membersRepository membersRepository
.findByUUID(rolesDto.getUuid()) .findByUUID(rolesDto.getUuid())
.orElseThrow(() -> new MemberNotFoundException()); .orElseThrow(() -> new MemberNotFoundException());
MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId(); MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId();
memberRoleEntityId.setMemberUuid(rolesDto.getUuid()); memberRoleEntityId.setMemberUuid(rolesDto.getUuid());
@@ -142,9 +142,7 @@ public class MembersCoreService {
*/ */
public void updateStatus(UUID uuid, MembersDto.StatusDto statusDto) { public void updateStatus(UUID uuid, MembersDto.StatusDto statusDto) {
MemberEntity memberEntity = MemberEntity memberEntity =
membersRepository membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
.findByUUID(uuid)
.orElseThrow(() -> new MemberNotFoundException());
memberEntity.setStatus(statusDto.getStatus()); memberEntity.setStatus(statusDto.getStatus());
memberEntity.setUpdatedDttm(ZonedDateTime.now()); memberEntity.setUpdatedDttm(ZonedDateTime.now());
@@ -158,9 +156,7 @@ public class MembersCoreService {
*/ */
public void deleteAccount(UUID uuid) { public void deleteAccount(UUID uuid) {
MemberEntity memberEntity = MemberEntity memberEntity =
membersRepository membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException());
.findByUUID(uuid)
.orElseThrow(() -> new MemberNotFoundException());
MemberArchivedEntityId memberArchivedEntityId = new MemberArchivedEntityId(); MemberArchivedEntityId memberArchivedEntityId = new MemberArchivedEntityId();
memberArchivedEntityId.setUserId(memberEntity.getId()); memberArchivedEntityId.setUserId(memberEntity.getId());
@@ -193,10 +189,10 @@ public class MembersCoreService {
*/ */
public void resetPassword(Long id) { public void resetPassword(Long id) {
MemberEntity memberEntity = MemberEntity memberEntity =
membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException()); membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException());
String salt = String salt =
BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim()); BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim());
// 패스워드 암호화, 초기 패스워드 고정 // 패스워드 암호화, 초기 패스워드 고정
String hashedPassword = BCrypt.hashpw(password, salt); String hashedPassword = BCrypt.hashpw(password, salt);

View File

@@ -1,14 +1,10 @@
package com.kamco.cd.kamcoback.postgres.repository.mapsheet; package com.kamco.cd.kamcoback.postgres.repository.mapsheet;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto; import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.Optional;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
public interface MapSheetMngFileCheckerRepositoryCustom { public interface MapSheetMngFileCheckerRepositoryCustom {
Page<ImageryDto.SyncDto> findImagerySyncList(ImageryDto.@Valid searchReq searchReq); Page<ImageryDto.SyncDto> findImagerySyncList(ImageryDto.@Valid searchReq searchReq);
} }

View File

@@ -29,7 +29,6 @@ public class MapSheetMngFileCheckerRepositoryImpl extends QuerydslRepositorySupp
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
} }
@Override @Override
public Page<ImageryDto.SyncDto> findImagerySyncList(ImageryDto.@Valid searchReq searchReq) { public Page<ImageryDto.SyncDto> findImagerySyncList(ImageryDto.@Valid searchReq searchReq) {
@@ -41,53 +40,44 @@ public class MapSheetMngFileCheckerRepositoryImpl extends QuerydslRepositorySupp
} }
List<ImageryDto.SyncDto> foundContent = List<ImageryDto.SyncDto> foundContent =
queryFactory queryFactory
.select( .select(
Projections.constructor( Projections.constructor(
ImageryDto.SyncDto.class, ImageryDto.SyncDto.class,
imageryEntity.id, imageryEntity.id,
imageryEntity.year, imageryEntity.year,
imageryEntity.scene50k, imageryEntity.scene50k,
imageryEntity.scene5k, imageryEntity.scene5k,
imageryEntity.middlePath, imageryEntity.middlePath,
imageryEntity.cogMiddlePath, imageryEntity.cogMiddlePath,
imageryEntity.filename, imageryEntity.filename,
imageryEntity.cogFilename, imageryEntity.cogFilename,
mapSheetMngHstEntity.hstUid mapSheetMngHstEntity.hstUid))
) .from(imageryEntity)
) .leftJoin(mapSheetMngHstEntity)
.from(imageryEntity) .on(
.leftJoin(mapSheetMngHstEntity).on( imageryEntity
imageryEntity.year.eq(mapSheetMngHstEntity.mngYyyy) .year
.and(imageryEntity.scene5k.eq(mapSheetMngHstEntity.mapSheetNum.stringValue()))) .eq(mapSheetMngHstEntity.mngYyyy)
.where(whereBuilder) .and(imageryEntity.scene5k.eq(mapSheetMngHstEntity.mapSheetNum.stringValue())))
.offset(pageable.getOffset()) .where(whereBuilder)
.limit(pageable.getPageSize()) .offset(pageable.getOffset())
//.orderBy(mapSheetMngEntity.createdDttm.desc()) .limit(pageable.getPageSize())
.fetch(); // .orderBy(mapSheetMngEntity.createdDttm.desc())
.fetch();
Long countQuery = Long countQuery =
queryFactory queryFactory
.select(imageryEntity.id.count()) .select(imageryEntity.id.count())
.from(imageryEntity) .from(imageryEntity)
.where(whereBuilder) .where(whereBuilder)
.fetchOne(); .fetchOne();
return new PageImpl<>(foundContent, pageable, countQuery); return new PageImpl<>(foundContent, pageable, countQuery);
} }
private NumberExpression<Integer> rowNum() { private NumberExpression<Integer> rowNum() {
return Expressions.numberTemplate( return Expressions.numberTemplate(
Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate); Integer.class, "row_number() over(order by {0} desc)", mapSheetMngHstEntity.createdDate);
} }
} }

View File

@@ -1,6 +1,5 @@
package com.kamco.cd.kamcoback.postgres.repository.mapsheet; package com.kamco.cd.kamcoback.postgres.repository.mapsheet;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@@ -14,6 +13,4 @@ public interface MapSheetMngRepositoryCustom {
Page<MapSheetMngDto.MngDto> findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq); Page<MapSheetMngDto.MngDto> findMapSheetMngList(MapSheetMngDto.@Valid searchReq searchReq);
Optional<MapSheetMngHstEntity> findMapSheetMngHstInfo(Long hstUid); Optional<MapSheetMngHstEntity> findMapSheetMngHstInfo(Long hstUid);
} }

View File

@@ -1,12 +1,10 @@
package com.kamco.cd.kamcoback.postgres.repository.mapsheet; package com.kamco.cd.kamcoback.postgres.repository.mapsheet;
import static com.kamco.cd.kamcoback.postgres.entity.QImageryEntity.imageryEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx50kEntity.mapInkx50kEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx50kEntity.mapInkx50kEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapInkx5kEntity.mapInkx5kEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngEntity.mapSheetMngEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity; import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetMngHstEntity.mapSheetMngHstEntity;
import com.kamco.cd.kamcoback.mapsheet.dto.ImageryDto;
import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto; import com.kamco.cd.kamcoback.mapsheet.dto.MapSheetMngDto;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity; import com.kamco.cd.kamcoback.postgres.entity.MapSheetMngHstEntity;
import com.querydsl.core.BooleanBuilder; import com.querydsl.core.BooleanBuilder;
@@ -141,7 +139,6 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport
return new PageImpl<>(foundContent, pageable, countQuery); return new PageImpl<>(foundContent, pageable, countQuery);
} }
@Override @Override
public Optional<MapSheetMngHstEntity> findMapSheetMngHstInfo(Long hstUid) { public Optional<MapSheetMngHstEntity> findMapSheetMngHstInfo(Long hstUid) {
return Optional.ofNullable( return Optional.ofNullable(
@@ -169,7 +166,4 @@ public class MapSheetMngRepositoryImpl extends QuerydslRepositorySupport
"{0} like '%" + searchReq.getSearchValue() + "%'", "{0} like '%" + searchReq.getSearchValue() + "%'",
mapSheetMngHstEntity.mapSheetNum)); mapSheetMngHstEntity.mapSheetNum));
} }
} }