289 lines
11 KiB
Java
289 lines
11 KiB
Java
package com.cloudhandson.vpdbackoffice.domain.probe;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
public record ProbeResult(
|
|
ProbeStatus status,
|
|
List<String> columns,
|
|
List<Map<String, Object>> rows,
|
|
int rowCount,
|
|
List<String> maskedColumns,
|
|
String errorCode,
|
|
String errorMessage,
|
|
String requestHeaders,
|
|
String requestPayload,
|
|
String responseHeaders,
|
|
String responseBody,
|
|
String vpdPredicate,
|
|
String effectiveSql,
|
|
SqlExecutionEvidence executionEvidence,
|
|
String executionEvidenceMessage,
|
|
List<SqlExecutionCandidate> executionCandidates,
|
|
FgaExecutionEvidence fgaExecutionEvidence,
|
|
String fgaExecutionEvidenceMessage
|
|
) {
|
|
|
|
public ProbeResult(
|
|
ProbeStatus status,
|
|
List<String> columns,
|
|
List<Map<String, Object>> rows,
|
|
int rowCount,
|
|
List<String> maskedColumns,
|
|
String errorCode,
|
|
String errorMessage,
|
|
String requestHeaders,
|
|
String requestPayload,
|
|
String responseHeaders,
|
|
String responseBody
|
|
) {
|
|
this(
|
|
status,
|
|
columns,
|
|
rows,
|
|
rowCount,
|
|
maskedColumns,
|
|
errorCode,
|
|
errorMessage,
|
|
requestHeaders,
|
|
requestPayload,
|
|
responseHeaders,
|
|
responseBody,
|
|
null,
|
|
null,
|
|
null,
|
|
null,
|
|
List.of(),
|
|
null,
|
|
null
|
|
);
|
|
}
|
|
|
|
public ProbeResult(
|
|
ProbeStatus status,
|
|
List<String> columns,
|
|
List<Map<String, Object>> rows,
|
|
int rowCount,
|
|
List<String> maskedColumns,
|
|
String errorCode,
|
|
String errorMessage,
|
|
String requestHeaders,
|
|
String requestPayload,
|
|
String responseHeaders,
|
|
String responseBody,
|
|
String vpdPredicate,
|
|
String effectiveSql
|
|
) {
|
|
this(
|
|
status,
|
|
columns,
|
|
rows,
|
|
rowCount,
|
|
maskedColumns,
|
|
errorCode,
|
|
errorMessage,
|
|
requestHeaders,
|
|
requestPayload,
|
|
responseHeaders,
|
|
responseBody,
|
|
vpdPredicate,
|
|
effectiveSql,
|
|
null,
|
|
null,
|
|
List.of(),
|
|
null,
|
|
null
|
|
);
|
|
}
|
|
|
|
public static ProbeResult blocked(ProbeStatus status, String errorCode, String errorMessage) {
|
|
return blocked(status, errorCode, errorMessage, null, null, null, null);
|
|
}
|
|
|
|
public static ProbeResult blocked(
|
|
ProbeStatus status,
|
|
String errorCode,
|
|
String errorMessage,
|
|
String requestHeaders,
|
|
String requestPayload,
|
|
String responseHeaders,
|
|
String responseBody
|
|
) {
|
|
return new ProbeResult(
|
|
status,
|
|
List.of(),
|
|
List.of(),
|
|
0,
|
|
List.of(),
|
|
errorCode,
|
|
errorMessage,
|
|
requestHeaders,
|
|
requestPayload,
|
|
responseHeaders,
|
|
responseBody
|
|
);
|
|
}
|
|
|
|
public boolean successLike() {
|
|
return status == ProbeStatus.SUCCESS || status == ProbeStatus.VPD_DENY_EMPTY_RESULT;
|
|
}
|
|
|
|
public boolean hasSqlTrace() {
|
|
return effectiveSql != null && !effectiveSql.isBlank();
|
|
}
|
|
|
|
public ProbeResult withSqlTrace(String predicate, String sql) {
|
|
return new ProbeResult(
|
|
status,
|
|
columns,
|
|
rows,
|
|
rowCount,
|
|
maskedColumns,
|
|
errorCode,
|
|
errorMessage,
|
|
requestHeaders,
|
|
requestPayload,
|
|
responseHeaders,
|
|
responseBody,
|
|
predicate,
|
|
sql,
|
|
executionEvidence,
|
|
executionEvidenceMessage,
|
|
executionCandidates,
|
|
fgaExecutionEvidence,
|
|
fgaExecutionEvidenceMessage
|
|
);
|
|
}
|
|
|
|
public boolean hasExecutionEvidence() {
|
|
return executionEvidence != null && executionEvidence.sqlId() != null
|
|
&& !executionEvidence.sqlId().isBlank();
|
|
}
|
|
|
|
public ProbeResult withExecutionEvidence(
|
|
SqlExecutionEvidence evidence,
|
|
String unavailableMessage
|
|
) {
|
|
return withExecutionEvidence(evidence, unavailableMessage, List.of());
|
|
}
|
|
|
|
public ProbeResult withExecutionEvidence(
|
|
SqlExecutionEvidence evidence,
|
|
String unavailableMessage,
|
|
List<SqlExecutionCandidate> candidates
|
|
) {
|
|
return new ProbeResult(
|
|
status,
|
|
columns,
|
|
rows,
|
|
rowCount,
|
|
maskedColumns,
|
|
errorCode,
|
|
errorMessage,
|
|
requestHeaders,
|
|
requestPayload,
|
|
responseHeaders,
|
|
responseBody,
|
|
vpdPredicate,
|
|
effectiveSql,
|
|
evidence,
|
|
unavailableMessage,
|
|
candidates == null ? List.of() : List.copyOf(candidates),
|
|
fgaExecutionEvidence,
|
|
fgaExecutionEvidenceMessage
|
|
);
|
|
}
|
|
|
|
public boolean hasExecutionCandidates() {
|
|
return executionCandidates != null && !executionCandidates.isEmpty();
|
|
}
|
|
|
|
public boolean hasFgaExecutionEvidence() {
|
|
return fgaExecutionEvidence != null && fgaExecutionEvidence.sqlText() != null
|
|
&& !fgaExecutionEvidence.sqlText().isBlank();
|
|
}
|
|
|
|
public ProbeResult withFgaExecutionEvidence(
|
|
FgaExecutionEvidence evidence,
|
|
String unavailableMessage
|
|
) {
|
|
return new ProbeResult(
|
|
status,
|
|
columns,
|
|
rows,
|
|
rowCount,
|
|
maskedColumns,
|
|
errorCode,
|
|
errorMessage,
|
|
requestHeaders,
|
|
requestPayload,
|
|
responseHeaders,
|
|
responseBody,
|
|
vpdPredicate,
|
|
effectiveSql,
|
|
executionEvidence,
|
|
executionEvidenceMessage,
|
|
executionCandidates,
|
|
evidence,
|
|
unavailableMessage
|
|
);
|
|
}
|
|
|
|
public String title() {
|
|
return switch (status) {
|
|
case SUCCESS -> "권한에 따라 데이터를 볼 수 있습니다.";
|
|
case VPD_DENY_EMPTY_RESULT -> "현재 권한으로 볼 수 있는 행이 없습니다.";
|
|
case TOKEN_NOT_FOUND -> "DB에 등록되지 않은 토큰입니다.";
|
|
case TOKEN_INACTIVE -> "만료되었거나 회수된 토큰입니다.";
|
|
case INVALID_TOKEN -> "입력한 토큰 정보가 일치하지 않습니다.";
|
|
case OBJECT_DISABLED -> "검증 대상이 비활성 상태입니다.";
|
|
case OBJECT_NOT_ACCESSIBLE -> "현재 권한으로 이 대상에 접근할 수 없습니다.";
|
|
case VPD_FILTER_ERROR -> "이 객체에 연결된 별도 VPD Filter가 실행되지 않습니다.";
|
|
case ORDS_PATH_NOT_FOUND -> "검증 대상의 ORDS 경로를 찾지 못했습니다.";
|
|
case ORDS_NOT_CONFIGURED -> "ORDS 연결 주소가 아직 설정되지 않았습니다.";
|
|
case ORDS_UNAVAILABLE -> "ORDS 서버에 연결할 수 없습니다.";
|
|
case ORDS_TIMEOUT -> "ORDS 응답을 기다리다 시간이 초과되었습니다.";
|
|
case INVALID_ORDS_RESPONSE -> "ORDS 응답 형식을 해석할 수 없습니다.";
|
|
case UNKNOWN_ERROR -> "검증 중 예상하지 못한 문제가 발생했습니다.";
|
|
};
|
|
}
|
|
|
|
public String plainSummary() {
|
|
return switch (status) {
|
|
case SUCCESS -> "토큰의 사용자와 역할을 기준으로 VPD가 적용되었고, 허용된 데이터 " + rowCount
|
|
+ "개가 반환되었습니다.";
|
|
case VPD_DENY_EMPTY_RESULT -> "호출은 정상 처리됐지만 VPD가 현재 사용자에게 허용한 행은 0개입니다. 권한 규칙과 실제 데이터가 맞지 않으면 정상 결과이며 오류가 아닐 수 있습니다.";
|
|
case TOKEN_NOT_FOUND -> "입력한 원문과 일치하는 등록 기록이 현재 DB에 없습니다. 예전에 발급한 값이거나 다른 환경의 토큰일 수 있습니다.";
|
|
case TOKEN_INACTIVE -> "토큰은 DB에 있지만 만료되었거나 관리자가 회수해 더 이상 사용자 권한을 증명할 수 없습니다.";
|
|
case INVALID_TOKEN -> "화면에서 선택한 정보와 입력한 토큰 원문이 서로 다릅니다.";
|
|
case OBJECT_DISABLED -> "선택한 객체가 검증 대상으로 활성화되어 있지 않아 ORDS 호출을 시작하지 않았습니다.";
|
|
case OBJECT_NOT_ACCESSIBLE -> "토큰은 확인됐지만 ORDS 또는 DB가 이 객체에 대한 접근을 거부했습니다.";
|
|
case VPD_FILTER_ERROR -> "토큰과 사용자 권한은 확인됐지만, 대상 객체의 VPD 함수가 DB 오류를 내어 행 필터를 계산하지 못했습니다.";
|
|
case ORDS_PATH_NOT_FOUND -> "권한 판단 전 단계에서 실제 ORDS 주소와 등록된 객체 경로가 일치하지 않았습니다.";
|
|
case ORDS_NOT_CONFIGURED -> "백오피스가 호출할 ORDS 기준 주소가 없어 권한 검증을 시작하지 못했습니다.";
|
|
case ORDS_UNAVAILABLE -> "권한 판단 전 단계에서 ORDS 서버 또는 네트워크에 연결하지 못했습니다.";
|
|
case ORDS_TIMEOUT -> "ORDS가 제한 시간 안에 응답하지 않아 권한 결과를 확인하지 못했습니다.";
|
|
case INVALID_ORDS_RESPONSE -> "ORDS 호출은 끝났지만 rows/items 배열이 없는 응답이라 권한 결과로 표시하지 못했습니다.";
|
|
case UNKNOWN_ERROR -> "토큰, 권한, ORDS 중 어느 단계의 문제인지 기술 상세를 확인해야 합니다.";
|
|
};
|
|
}
|
|
|
|
public String nextAction() {
|
|
return switch (status) {
|
|
case SUCCESS -> "반환된 행과 마스킹 컬럼이 예상한 범위인지 확인하세요. 다르면 권한 화면의 행·열 규칙을 조정한 뒤 다시 검증하세요.";
|
|
case VPD_DENY_EMPTY_RESULT -> "유효 권한 화면에서 사용자에게 직접 또는 그룹으로 상속된 역할과 행 규칙을 확인하세요.";
|
|
case TOKEN_NOT_FOUND -> "토큰 화면에서 현재 환경의 사용자에게 새 토큰을 발급하고, 한 번만 표시되는 원문을 복사해 다시 검증하세요.";
|
|
case TOKEN_INACTIVE -> "토큰 화면에서 활성 토큰을 새로 발급한 뒤 다시 검증하세요.";
|
|
case INVALID_TOKEN -> "복사한 원문이 맞는지 확인하고, 원문을 잃었다면 새 토큰을 발급하세요.";
|
|
case OBJECT_DISABLED -> "보호 객체를 활성화하고 권한을 등록한 뒤 다시 검증하세요.";
|
|
case OBJECT_NOT_ACCESSIBLE -> "유효 권한과 ORDS handler의 대상 객체가 같은지 확인하세요.";
|
|
case VPD_FILTER_ERROR -> "토큰이나 권한을 바꾸지 말고 DB 보호 연결에서 이 객체의 Filter를 확인하세요. 일반 권한 객체라면 권한체계 자동 Filter로 복구하세요.";
|
|
case ORDS_PATH_NOT_FOUND -> "보호 객체의 ORDS 경로와 실제 module/template 경로를 맞춘 뒤 다시 실행하세요.";
|
|
case ORDS_NOT_CONFIGURED -> "설정에서 ORDS 기준 주소를 등록한 뒤 백오피스를 재시작하세요.";
|
|
case ORDS_UNAVAILABLE, ORDS_TIMEOUT -> "권한 설정을 바꾸지 말고 먼저 ORDS 실행 상태, 주소와 네트워크를 확인하세요.";
|
|
case INVALID_ORDS_RESPONSE -> "ORDS handler가 rows 또는 items 배열을 반환하는지 확인하세요.";
|
|
case UNKNOWN_ERROR -> "아래 기술 상세의 오류 코드와 응답을 확인한 뒤 해당 단계부터 점검하세요.";
|
|
};
|
|
}
|
|
}
|