fix #557: guide permission-driven VPD flow
This commit is contained in:
@@ -5,8 +5,15 @@
|
||||
<nav th:replace="~{fragments/layout :: nav}"></nav>
|
||||
<main class="container py-4">
|
||||
<div class="page-title">
|
||||
<h1>ORDS 조회 Handler 생성</h1>
|
||||
<p>VPD가 적용된 TABLE/VIEW를 ORDS HTTP 경로로 서빙하기 위한 조회 Handler를 등록합니다.</p>
|
||||
<h1>ORDS 조회 대상 등록</h1>
|
||||
<p>이 화면은 DB 객체를 HTTP로 연결할 경로만 등록합니다. 누가 어떤 행을 볼 수 있는지는 권한 규칙과 VPD에서 결정합니다.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<strong>벡터 지식자료 검색 흐름:</strong>
|
||||
문서를 청크로 나누고 기술 태그를 붙인 뒤 전용 ORDS 검색을 등록합니다.
|
||||
그 다음 <a href="/permissions">권한 관리</a>에서 <code>특정 기술 태그</code>를 여러 개 추가하면
|
||||
태그 중 하나라도 맞는 청크만 검색됩니다.
|
||||
</div>
|
||||
|
||||
<section th:replace="~{fragments/layout :: architectureStrip('ords')}"></section>
|
||||
@@ -15,7 +22,8 @@
|
||||
<div class="alert alert-danger" th:if="${errorMessage}" th:text="${errorMessage}"></div>
|
||||
|
||||
<section class="content-band">
|
||||
<h2>조회 Handler 대상 추가</h2>
|
||||
<h2>조회 대상 추가 (예제 Handler)</h2>
|
||||
<p class="section-subtitle">DB 객체 하나를 하나의 조회 Handler로 연결하는 예제입니다. 대상 추가 후 Handler를 생성하면 VPD context 설정과 기본 SELECT가 포함된 PL/SQL이 만들어지며, 소스 보기에서 실제 업무에 맞게 수정할 수 있습니다.</p>
|
||||
<form method="post" action="/objects" class="form-grid">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<input type="hidden" name="owner" required>
|
||||
@@ -32,15 +40,40 @@
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
ORDS Path
|
||||
<input class="form-control" name="ordsPath" placeholder="DB 객체 선택 시 자동 입력" required>
|
||||
ORDS Path (자동)
|
||||
<input class="form-control" name="ordsPath" data-ords-path-input
|
||||
placeholder="DB 객체 선택 시 자동 입력" readonly required>
|
||||
<span class="form-hint">
|
||||
객체를 선택하면 예제용 module/template 경로가 자동으로 입력됩니다. 비워 제출해도 서버가 같은 규칙으로 채웁니다.
|
||||
<label class="form-check form-check-inline ms-2">
|
||||
<input class="form-check-input" type="checkbox" data-ords-path-edit>
|
||||
<span class="form-check-label">고급: 직접 수정</span>
|
||||
</label>
|
||||
</span>
|
||||
</label>
|
||||
<label>
|
||||
조회 대상 설명
|
||||
<input class="form-control" name="description" maxlength="200"
|
||||
placeholder="예: 기술 태그 권한이 적용된 지식자료 검색">
|
||||
</label>
|
||||
<button class="btn btn-primary" type="submit">대상 추가</button>
|
||||
</form>
|
||||
<div class="alert alert-info mt-3 mb-0">
|
||||
<strong>생성되는 예제 흐름:</strong>
|
||||
<code>cb_ords_handler_pkg.set_vpd_context(:auth_header)</code>로 토큰의 사용자·역할 컨텍스트를 넣고,
|
||||
선택한 한 테이블에 <code>SELECT ... FROM OWNER.TABLE</code>을 실행한 뒤 JSON으로 반환합니다.
|
||||
이것은 유일한 사용 방식이 아니라 시작점이며, Handler 소스와 ORDS 메타데이터에서 수정할 수 있습니다.
|
||||
컬럼 민감도·마스킹은 이 화면에서 다루지 않고 <a href="/permissions">권한 관리의 원문 표시 허용 컬럼</a>에서 별도로 설정합니다.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-band">
|
||||
<h2>조회 Handler 대상 목록</h2>
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<h2>조회 대상 목록</h2>
|
||||
<p class="section-subtitle">ORDS Path와 Handler 상태를 관리합니다. 접근 권한은 이 표에서 만들지 않습니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm align-middle">
|
||||
<thead>
|
||||
@@ -48,6 +81,7 @@
|
||||
<th>ID</th>
|
||||
<th>Owner</th>
|
||||
<th>Object</th>
|
||||
<th>설명</th>
|
||||
<th>ORDS Path</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
@@ -58,6 +92,16 @@
|
||||
<td th:text="${object.objectId()}">1</td>
|
||||
<td th:text="${object.owner()}">ADMIN</td>
|
||||
<td th:text="${object.objectName()}">CB_V_SEARCH_DOCUMENTS</td>
|
||||
<td>
|
||||
<form method="post" action="/objects/description" class="inline-form">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<input type="hidden" name="objectId" th:value="${object.objectId()}">
|
||||
<input class="form-control form-control-sm" name="description" maxlength="200"
|
||||
th:value="${object.description()}" placeholder="짧은 설명">
|
||||
<button class="btn btn-sm btn-outline-primary" type="submit">저장</button>
|
||||
</form>
|
||||
<small class="text-muted" th:text="${object.descriptionOrDefault()}">조회 대상 설명</small>
|
||||
</td>
|
||||
<td>
|
||||
<form method="post" action="/objects/ords-path" class="inline-form">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
@@ -67,7 +111,10 @@
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<div class="action-stack">
|
||||
<div class="action-stack" th:if="${object.objectName() == 'CB_VECTOR_SEARCH_DOCUMENTS'}">
|
||||
<span class="text-info small">전용 벡터 Handler 사용<br>(SQL 29, EMBEDDING 미노출)</span>
|
||||
</div>
|
||||
<div class="action-stack" th:unless="${object.objectName() == 'CB_VECTOR_SEARCH_DOCUMENTS'}">
|
||||
<form method="post" action="/objects/ords-handler" class="inline-form">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<input type="hidden" name="objectId" th:value="${object.objectId()}">
|
||||
@@ -87,74 +134,24 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="5" class="policy-source-cell">
|
||||
<details class="column-policy-panel">
|
||||
<summary>기본 컬럼 민감도/마스킹 정책</summary>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Column</th>
|
||||
<th>민감도</th>
|
||||
<th>마스킹</th>
|
||||
<th>상태</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="column : ${columnsByObject[object.objectId()]}">
|
||||
<td>
|
||||
<span th:text="${column.columnName()}">CONTENTS</span>
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"
|
||||
th:form="${'column-policy-form-' + column.columnId()}">
|
||||
<input type="hidden" name="columnId" th:value="${column.columnId()}"
|
||||
th:form="${'column-policy-form-' + column.columnId()}">
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-select form-select-sm" name="sensitivityLevel"
|
||||
th:form="${'column-policy-form-' + column.columnId()}">
|
||||
<option value="PUBLIC" th:selected="${column.sensitivityLevel() == 'PUBLIC'}">PUBLIC</option>
|
||||
<option value="INTERNAL" th:selected="${column.sensitivityLevel() == 'INTERNAL'}">INTERNAL</option>
|
||||
<option value="CONFIDENTIAL" th:selected="${column.sensitivityLevel() == 'CONFIDENTIAL'}">CONFIDENTIAL</option>
|
||||
<option value="RESTRICTED" th:selected="${column.sensitivityLevel() == 'RESTRICTED'}">RESTRICTED</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-select form-select-sm" name="redactionMethod"
|
||||
th:form="${'column-policy-form-' + column.columnId()}">
|
||||
<option value="NONE" th:selected="${column.redactionMethod() == 'NONE'}">NONE</option>
|
||||
<option value="NULLIFY" th:selected="${column.redactionMethod() == 'NULLIFY'}">NULLIFY</option>
|
||||
<option value="PARTIAL" th:selected="${column.redactionMethod() == 'PARTIAL'}">PARTIAL</option>
|
||||
<option value="FULL" th:selected="${column.redactionMethod() == 'FULL'}">FULL</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge"
|
||||
th:classappend="${column.sensitive()} ? ' text-bg-warning' : ' text-bg-secondary'"
|
||||
th:text="${column.policyLabel()}">PUBLIC/NONE</span>
|
||||
</td>
|
||||
<td>
|
||||
<form method="post" action="/objects/column-policy"
|
||||
th:id="${'column-policy-form-' + column.columnId()}"></form>
|
||||
<button class="btn btn-sm btn-outline-primary" type="submit"
|
||||
th:form="${'column-policy-form-' + column.columnId()}">저장</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:if="${#lists.isEmpty(columnsByObject[object.objectId()])}">
|
||||
<td colspan="5" class="text-muted">등록된 컬럼 정책이 없습니다.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</details>
|
||||
<div th:id="${'handler-source-' + object.objectId()}" class="text-muted small">
|
||||
<td colspan="6" class="policy-source-cell">
|
||||
<div class="object-handler-explainer">
|
||||
<strong>이 대상에서 자동으로 연결되는 것</strong>
|
||||
<span>토큰 헤더 → VPD context 설정 → 선택한 단일 테이블의 기본 SELECT → JSON 응답</span>
|
||||
<small>행 접근은 권한 규칙/VPD가 담당합니다. 원문 표시 예외는 권한 관리 Step 4에서 여러 컬럼을 등록하세요.</small>
|
||||
</div>
|
||||
<div th:if="${object.objectName() != 'CB_VECTOR_SEARCH_DOCUMENTS'}"
|
||||
th:id="${'handler-source-' + object.objectId()}" class="text-muted small">
|
||||
소스 보기를 누르면 기본 Handler PL/SQL이 표시됩니다.
|
||||
</div>
|
||||
<div th:if="${object.objectName() == 'CB_VECTOR_SEARCH_DOCUMENTS'}" class="text-muted small">
|
||||
전용 벡터 검색 Handler는 SQL 29에서 등록합니다.
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</th:block>
|
||||
<tr th:if="${#lists.isEmpty(objects)}">
|
||||
<td colspan="5" class="text-muted">등록된 조회 Handler 대상이 없습니다.</td>
|
||||
<td colspan="6" class="text-muted">등록된 조회 Handler 대상이 없습니다.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Reference in New Issue
Block a user