597
database/adb/72_hmm_leave_team_vpd.sql
Normal file
597
database/adb/72_hmm_leave_team_vpd.sql
Normal file
@@ -0,0 +1,597 @@
|
||||
-- ============================================================
|
||||
-- 72_hmm_leave_team_vpd.sql
|
||||
--
|
||||
-- HMM HR leave row security:
|
||||
-- * HMM_HR_MANAGER -> self and directly managed employees
|
||||
-- * HMM_HR_VIEWER -> self only
|
||||
-- * HMM_HR_ADMIN -> all rows when the role is explicitly assigned
|
||||
--
|
||||
-- Run as ADMIN after the HMM access-management schema is installed.
|
||||
-- This script is idempotent and never stores a plain bearer token.
|
||||
-- ============================================================
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
SET ECHO OFF
|
||||
SET FEEDBACK ON
|
||||
SET DEFINE OFF
|
||||
|
||||
ALTER SESSION DISABLE PARALLEL DML;
|
||||
|
||||
PROMPT === 1. Ensuring HMM roles and demo role assignments ===
|
||||
MERGE INTO hmm_access_roles dst
|
||||
USING (
|
||||
SELECT 1 role_id, 'HMM_HR_VIEWER' role_name,
|
||||
'HMM employee self-service leave access' description,
|
||||
'PUBLIC' max_sensitivity_level FROM dual
|
||||
UNION ALL
|
||||
SELECT 2, 'HMM_HR_MANAGER',
|
||||
'HMM manager access to self and direct reports',
|
||||
'INTERNAL' FROM dual
|
||||
UNION ALL
|
||||
SELECT 3, 'HMM_HR_ADMIN',
|
||||
'HMM HR administrator full leave access',
|
||||
'CONFIDENTIAL' FROM dual
|
||||
) src
|
||||
ON (dst.role_name = src.role_name)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
dst.description = src.description,
|
||||
dst.max_sensitivity_level = src.max_sensitivity_level,
|
||||
dst.active_yn = 'Y',
|
||||
dst.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
role_id, role_name, description, max_sensitivity_level,
|
||||
active_yn, created_at, updated_at
|
||||
) VALUES (
|
||||
src.role_id, src.role_name, src.description, src.max_sensitivity_level,
|
||||
'Y', SYSTIMESTAMP, SYSTIMESTAMP
|
||||
);
|
||||
|
||||
MERGE INTO hmm_employee_access_roles dst
|
||||
USING (
|
||||
SELECT e.employee_id, r.role_id
|
||||
FROM hmm_hr_employees e
|
||||
JOIN hmm_access_roles r ON r.role_name = 'HMM_HR_MANAGER'
|
||||
WHERE e.employee_code = 'E1001'
|
||||
AND e.employment_status = 'ACTIVE'
|
||||
) src
|
||||
ON (dst.employee_id = src.employee_id AND dst.role_id = src.role_id)
|
||||
WHEN NOT MATCHED THEN INSERT (employee_id, role_id, created_at)
|
||||
VALUES (src.employee_id, src.role_id, SYSTIMESTAMP);
|
||||
|
||||
MERGE INTO hmm_employee_access_roles dst
|
||||
USING (
|
||||
SELECT e.employee_id, r.role_id
|
||||
FROM hmm_hr_employees e
|
||||
JOIN hmm_access_roles r ON r.role_name = 'HMM_HR_VIEWER'
|
||||
WHERE e.manager_employee_id = (
|
||||
SELECT manager.employee_id
|
||||
FROM hmm_hr_employees manager
|
||||
WHERE manager.employee_code = 'E1001'
|
||||
)
|
||||
AND e.employment_status = 'ACTIVE'
|
||||
) src
|
||||
ON (dst.employee_id = src.employee_id AND dst.role_id = src.role_id)
|
||||
WHEN NOT MATCHED THEN INSERT (employee_id, role_id, created_at)
|
||||
VALUES (src.employee_id, src.role_id, SYSTIMESTAMP);
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT === 2. Ensuring protected leave objects and columns ===
|
||||
DECLARE
|
||||
PROCEDURE ensure_object(
|
||||
p_object_name IN VARCHAR2,
|
||||
p_description IN VARCHAR2
|
||||
) AS
|
||||
v_object_id NUMBER;
|
||||
BEGIN
|
||||
BEGIN
|
||||
SELECT object_id
|
||||
INTO v_object_id
|
||||
FROM hmm_access_objects
|
||||
WHERE owner = 'ADMIN'
|
||||
AND object_name = p_object_name;
|
||||
|
||||
UPDATE hmm_access_objects
|
||||
SET enabled_yn = 'Y',
|
||||
description = p_description,
|
||||
ords_path = 'cb-ords/cb-object-query/admin/' || LOWER(p_object_name)
|
||||
WHERE object_id = v_object_id;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
SELECT NVL(MAX(object_id), 0) + 1
|
||||
INTO v_object_id
|
||||
FROM hmm_access_objects;
|
||||
|
||||
INSERT INTO hmm_access_objects (
|
||||
object_id, owner, object_name, ords_path, enabled_yn, description
|
||||
) VALUES (
|
||||
v_object_id,
|
||||
'ADMIN',
|
||||
p_object_name,
|
||||
'cb-ords/cb-object-query/admin/' || LOWER(p_object_name),
|
||||
'Y',
|
||||
p_description
|
||||
);
|
||||
END;
|
||||
|
||||
FOR c IN (
|
||||
SELECT column_name
|
||||
FROM user_tab_columns
|
||||
WHERE table_name = p_object_name
|
||||
ORDER BY column_id
|
||||
) LOOP
|
||||
MERGE INTO hmm_access_object_columns dst
|
||||
USING (
|
||||
SELECT v_object_id object_id, c.column_name column_name
|
||||
FROM dual
|
||||
) src
|
||||
ON (
|
||||
dst.object_id = src.object_id
|
||||
AND dst.column_name = src.column_name
|
||||
)
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
column_id, object_id, column_name, sensitive_yn,
|
||||
sensitivity_level, redaction_method
|
||||
) VALUES (
|
||||
(SELECT NVL(MAX(column_id), 0) + 1 FROM hmm_access_object_columns),
|
||||
src.object_id,
|
||||
src.column_name,
|
||||
'N',
|
||||
'PUBLIC',
|
||||
'NONE'
|
||||
);
|
||||
END LOOP;
|
||||
END;
|
||||
BEGIN
|
||||
ensure_object(
|
||||
'HMM_LEAVE_BALANCES',
|
||||
'HMM employee leave balance protected by employee hierarchy'
|
||||
);
|
||||
ensure_object(
|
||||
'HMM_LEAVE_REQUESTS',
|
||||
'HMM employee leave requests protected by employee hierarchy'
|
||||
);
|
||||
END;
|
||||
/
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT === 3. Ensuring role permission rules ===
|
||||
DECLARE
|
||||
PROCEDURE ensure_permission(
|
||||
p_role_name IN VARCHAR2,
|
||||
p_target_name IN VARCHAR2,
|
||||
p_rule_type IN VARCHAR2
|
||||
) AS
|
||||
v_role_id NUMBER;
|
||||
v_perm_id NUMBER;
|
||||
BEGIN
|
||||
SELECT role_id
|
||||
INTO v_role_id
|
||||
FROM hmm_access_roles
|
||||
WHERE role_name = p_role_name
|
||||
AND active_yn = 'Y';
|
||||
|
||||
BEGIN
|
||||
SELECT perm_id
|
||||
INTO v_perm_id
|
||||
FROM hmm_access_permissions
|
||||
WHERE role_id = v_role_id
|
||||
AND target_name = p_target_name
|
||||
AND action_name = 'SELECT';
|
||||
|
||||
UPDATE hmm_access_permissions
|
||||
SET permission_effect = 'ALLOW'
|
||||
WHERE perm_id = v_perm_id;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
SELECT cb_permission_seq.NEXTVAL
|
||||
INTO v_perm_id
|
||||
FROM dual;
|
||||
|
||||
INSERT INTO hmm_access_permissions (
|
||||
perm_id, role_id, target_name, action_name, permission_effect
|
||||
) VALUES (
|
||||
v_perm_id, v_role_id, p_target_name, 'SELECT', 'ALLOW'
|
||||
);
|
||||
END;
|
||||
|
||||
DELETE FROM hmm_access_permission_rules
|
||||
WHERE perm_id = v_perm_id;
|
||||
|
||||
INSERT INTO hmm_access_permission_rules (
|
||||
rule_id, perm_id, rule_column, rule_type, rule_value
|
||||
) VALUES (
|
||||
cb_permission_rule_seq.NEXTVAL,
|
||||
v_perm_id,
|
||||
'EMPLOYEE_ID',
|
||||
p_rule_type,
|
||||
NULL
|
||||
);
|
||||
END;
|
||||
BEGIN
|
||||
ensure_permission('HMM_HR_VIEWER', 'HMM_LEAVE_BALANCES', 'SELF');
|
||||
ensure_permission('HMM_HR_VIEWER', 'HMM_LEAVE_REQUESTS', 'SELF');
|
||||
ensure_permission('HMM_HR_MANAGER', 'HMM_LEAVE_BALANCES', 'MANAGED_TEAM');
|
||||
ensure_permission('HMM_HR_MANAGER', 'HMM_LEAVE_REQUESTS', 'MANAGED_TEAM');
|
||||
ensure_permission('HMM_HR_ADMIN', 'HMM_LEAVE_BALANCES', 'ALL');
|
||||
ensure_permission('HMM_HR_ADMIN', 'HMM_LEAVE_REQUESTS', 'ALL');
|
||||
END;
|
||||
/
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT === 4. Creating secure HMM access context ===
|
||||
CREATE OR REPLACE PACKAGE hmm_access_ctx_pkg AUTHID DEFINER AS
|
||||
PROCEDURE clear_user;
|
||||
PROCEDURE set_user_by_bearer(p_bearer_token IN VARCHAR2);
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE PACKAGE BODY hmm_access_ctx_pkg AS
|
||||
PROCEDURE clear_user AS
|
||||
BEGIN
|
||||
DBMS_SESSION.SET_CONTEXT('HMM_ACCESS_CTX', 'EMPLOYEE_ID', NULL);
|
||||
DBMS_SESSION.SET_CONTEXT('HMM_ACCESS_CTX', 'EMPLOYEE_CODE', NULL);
|
||||
DBMS_SESSION.SET_CONTEXT('HMM_ACCESS_CTX', 'TEAM_ID', NULL);
|
||||
END;
|
||||
|
||||
PROCEDURE set_user_by_bearer(p_bearer_token IN VARCHAR2) AS
|
||||
v_employee_id hmm_hr_employees.employee_id%TYPE;
|
||||
v_employee_code hmm_hr_employees.employee_code%TYPE;
|
||||
v_team_id hmm_hr_employees.team_id%TYPE;
|
||||
BEGIN
|
||||
IF p_bearer_token IS NULL OR TRIM(p_bearer_token) IS NULL THEN
|
||||
clear_user;
|
||||
RAISE_APPLICATION_ERROR(-20101, 'Bearer token is required');
|
||||
END IF;
|
||||
|
||||
SELECT e.employee_id,
|
||||
e.employee_code,
|
||||
e.team_id
|
||||
INTO v_employee_id,
|
||||
v_employee_code,
|
||||
v_team_id
|
||||
FROM hmm_access_bearer_tokens t
|
||||
JOIN hmm_hr_employees e
|
||||
ON e.employee_id = t.employee_id
|
||||
WHERE t.key_hash = STANDARD_HASH(p_bearer_token, 'SHA256')
|
||||
AND t.revoked_at IS NULL
|
||||
AND t.expires_at > CAST(SYSTIMESTAMP AS TIMESTAMP)
|
||||
AND e.employment_status = 'ACTIVE';
|
||||
|
||||
DBMS_SESSION.SET_CONTEXT(
|
||||
'HMM_ACCESS_CTX', 'EMPLOYEE_ID', TO_CHAR(v_employee_id)
|
||||
);
|
||||
DBMS_SESSION.SET_CONTEXT(
|
||||
'HMM_ACCESS_CTX', 'EMPLOYEE_CODE', v_employee_code
|
||||
);
|
||||
DBMS_SESSION.SET_CONTEXT(
|
||||
'HMM_ACCESS_CTX', 'TEAM_ID', TO_CHAR(v_team_id)
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN
|
||||
clear_user;
|
||||
RAISE_APPLICATION_ERROR(-20102, 'Invalid or expired bearer token');
|
||||
WHEN TOO_MANY_ROWS THEN
|
||||
clear_user;
|
||||
RAISE_APPLICATION_ERROR(-20103, 'Bearer token mapping is not unique');
|
||||
END;
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE CONTEXT hmm_access_ctx USING hmm_access_ctx_pkg;
|
||||
|
||||
PROMPT === 5. Creating the HMM leave VPD filter ===
|
||||
CREATE OR REPLACE FUNCTION hmm_leave_vpd_filter(
|
||||
p_schema IN VARCHAR2,
|
||||
p_object IN VARCHAR2
|
||||
) RETURN VARCHAR2
|
||||
AUTHID DEFINER
|
||||
AS
|
||||
v_employee_id NUMBER;
|
||||
v_target VARCHAR2(128);
|
||||
v_allow_predicate VARCHAR2(32767);
|
||||
v_deny_predicate VARCHAR2(32767);
|
||||
v_permission_clause VARCHAR2(32767);
|
||||
|
||||
FUNCTION quote_literal(p_value IN VARCHAR2) RETURN VARCHAR2 IS
|
||||
BEGIN
|
||||
RETURN '''' || REPLACE(NVL(p_value, ''), '''', '''''') || '''';
|
||||
END;
|
||||
|
||||
FUNCTION safe_column(p_column_name IN VARCHAR2) RETURN VARCHAR2 IS
|
||||
v_column VARCHAR2(128);
|
||||
v_count NUMBER;
|
||||
BEGIN
|
||||
v_column := DBMS_ASSERT.SIMPLE_SQL_NAME(UPPER(TRIM(p_column_name)));
|
||||
|
||||
SELECT COUNT(*)
|
||||
INTO v_count
|
||||
FROM all_tab_columns
|
||||
WHERE owner = UPPER(p_schema)
|
||||
AND table_name = UPPER(p_object)
|
||||
AND column_name = v_column;
|
||||
|
||||
RETURN CASE WHEN v_count = 1 THEN v_column ELSE NULL END;
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN NULL;
|
||||
END;
|
||||
|
||||
PROCEDURE append_and(p_clause IN VARCHAR2) IS
|
||||
BEGIN
|
||||
IF p_clause IS NULL THEN
|
||||
v_permission_clause := NULL;
|
||||
ELSIF v_permission_clause IS NULL THEN
|
||||
v_permission_clause := '(' || p_clause || ')';
|
||||
ELSE
|
||||
v_permission_clause := v_permission_clause || ' AND (' || p_clause || ')';
|
||||
END IF;
|
||||
END;
|
||||
|
||||
PROCEDURE append_permission(
|
||||
p_effect IN VARCHAR2,
|
||||
p_clause IN VARCHAR2
|
||||
) IS
|
||||
BEGIN
|
||||
IF p_clause IS NULL THEN
|
||||
RETURN;
|
||||
END IF;
|
||||
|
||||
IF p_effect = 'DENY' THEN
|
||||
IF v_deny_predicate IS NULL THEN
|
||||
v_deny_predicate := '(' || p_clause || ')';
|
||||
ELSE
|
||||
v_deny_predicate := v_deny_predicate || ' OR (' || p_clause || ')';
|
||||
END IF;
|
||||
ELSIF v_allow_predicate IS NULL THEN
|
||||
v_allow_predicate := '(' || p_clause || ')';
|
||||
ELSE
|
||||
v_allow_predicate := v_allow_predicate || ' OR (' || p_clause || ')';
|
||||
END IF;
|
||||
END;
|
||||
BEGIN
|
||||
BEGIN
|
||||
v_employee_id := TO_NUMBER(
|
||||
SYS_CONTEXT('HMM_ACCESS_CTX', 'EMPLOYEE_ID')
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN '1 = 0';
|
||||
END;
|
||||
|
||||
IF v_employee_id IS NULL OR p_schema IS NULL OR p_object IS NULL THEN
|
||||
RETURN '1 = 0';
|
||||
END IF;
|
||||
|
||||
v_target := UPPER(TRIM(p_object));
|
||||
IF v_target NOT IN ('HMM_LEAVE_BALANCES', 'HMM_LEAVE_REQUESTS') THEN
|
||||
RETURN '1 = 0';
|
||||
END IF;
|
||||
|
||||
FOR permission_row IN (
|
||||
SELECT DISTINCT
|
||||
p.perm_id,
|
||||
NVL(UPPER(TRIM(p.permission_effect)), 'ALLOW') permission_effect
|
||||
FROM (
|
||||
SELECT er.role_id
|
||||
FROM hmm_employee_access_roles er
|
||||
WHERE er.employee_id = v_employee_id
|
||||
UNION
|
||||
SELECT gr.role_id
|
||||
FROM hmm_access_group_members gm
|
||||
JOIN hmm_access_groups g
|
||||
ON g.group_id = gm.group_id
|
||||
AND g.active_yn = 'Y'
|
||||
JOIN hmm_group_access_roles gr
|
||||
ON gr.group_id = gm.group_id
|
||||
WHERE gm.employee_id = v_employee_id
|
||||
) effective_role
|
||||
JOIN hmm_access_roles role
|
||||
ON role.role_id = effective_role.role_id
|
||||
AND role.active_yn = 'Y'
|
||||
JOIN hmm_access_permissions p
|
||||
ON p.role_id = role.role_id
|
||||
AND p.target_name = v_target
|
||||
AND p.action_name = 'SELECT'
|
||||
ORDER BY p.perm_id
|
||||
) LOOP
|
||||
v_permission_clause := NULL;
|
||||
|
||||
FOR rule_row IN (
|
||||
SELECT UPPER(TRIM(rule_type)) rule_type,
|
||||
UPPER(TRIM(rule_column)) rule_column,
|
||||
rule_value
|
||||
FROM hmm_access_permission_rules
|
||||
WHERE perm_id = permission_row.perm_id
|
||||
ORDER BY rule_id
|
||||
) LOOP
|
||||
DECLARE
|
||||
v_column VARCHAR2(128);
|
||||
v_clause VARCHAR2(32767);
|
||||
BEGIN
|
||||
v_column := safe_column(NVL(rule_row.rule_column, 'EMPLOYEE_ID'));
|
||||
v_clause := NULL;
|
||||
|
||||
IF rule_row.rule_type = 'ALL' THEN
|
||||
v_clause := '1 = 1';
|
||||
ELSIF rule_row.rule_type = 'SELF' AND v_column IS NOT NULL THEN
|
||||
v_clause := v_column
|
||||
|| ' = TO_NUMBER(SYS_CONTEXT(''HMM_ACCESS_CTX'', ''EMPLOYEE_ID''))';
|
||||
ELSIF rule_row.rule_type = 'MANAGED_TEAM' AND v_column IS NOT NULL THEN
|
||||
v_clause := v_column || ' IN ('
|
||||
|| 'SELECT employee.employee_id '
|
||||
|| 'FROM ADMIN.HMM_HR_EMPLOYEES employee '
|
||||
|| 'WHERE employee.employee_id = '
|
||||
|| 'TO_NUMBER(SYS_CONTEXT(''HMM_ACCESS_CTX'', ''EMPLOYEE_ID'')) '
|
||||
|| 'OR employee.manager_employee_id = '
|
||||
|| 'TO_NUMBER(SYS_CONTEXT(''HMM_ACCESS_CTX'', ''EMPLOYEE_ID''))'
|
||||
|| ')';
|
||||
ELSIF rule_row.rule_type = '='
|
||||
AND v_column IS NOT NULL
|
||||
AND rule_row.rule_value IS NOT NULL THEN
|
||||
v_clause := 'TO_CHAR(' || v_column || ') = '
|
||||
|| quote_literal(rule_row.rule_value);
|
||||
ELSIF rule_row.rule_type IN ('!=', '<>')
|
||||
AND v_column IS NOT NULL
|
||||
AND rule_row.rule_value IS NOT NULL THEN
|
||||
v_clause := 'TO_CHAR(' || v_column || ') <> '
|
||||
|| quote_literal(rule_row.rule_value);
|
||||
END IF;
|
||||
|
||||
IF v_clause IS NULL THEN
|
||||
v_permission_clause := NULL;
|
||||
EXIT;
|
||||
END IF;
|
||||
append_and(v_clause);
|
||||
END;
|
||||
END LOOP;
|
||||
|
||||
append_permission(
|
||||
permission_row.permission_effect,
|
||||
v_permission_clause
|
||||
);
|
||||
END LOOP;
|
||||
|
||||
IF v_allow_predicate IS NULL THEN
|
||||
RETURN '1 = 0';
|
||||
END IF;
|
||||
|
||||
IF v_deny_predicate IS NULL THEN
|
||||
RETURN v_allow_predicate;
|
||||
END IF;
|
||||
|
||||
RETURN '((' || v_allow_predicate || ') AND NOT ('
|
||||
|| v_deny_predicate || '))';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RETURN '1 = 0';
|
||||
END;
|
||||
/
|
||||
|
||||
SHOW ERRORS PACKAGE hmm_access_ctx_pkg
|
||||
SHOW ERRORS PACKAGE BODY hmm_access_ctx_pkg
|
||||
SHOW ERRORS FUNCTION hmm_leave_vpd_filter
|
||||
|
||||
PROMPT === 6. Attaching context-sensitive VPD policies ===
|
||||
DECLARE
|
||||
PROCEDURE replace_policy(p_object_name IN VARCHAR2) AS
|
||||
BEGIN
|
||||
BEGIN
|
||||
DBMS_RLS.DROP_POLICY(
|
||||
object_schema => 'ADMIN',
|
||||
object_name => p_object_name,
|
||||
policy_name => 'HMM_LEAVE_SCOPE_POLICY'
|
||||
);
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
IF SQLCODE != -28102 THEN
|
||||
RAISE;
|
||||
END IF;
|
||||
END;
|
||||
|
||||
DBMS_RLS.ADD_POLICY(
|
||||
object_schema => 'ADMIN',
|
||||
object_name => p_object_name,
|
||||
policy_name => 'HMM_LEAVE_SCOPE_POLICY',
|
||||
function_schema => 'ADMIN',
|
||||
policy_function => 'HMM_LEAVE_VPD_FILTER',
|
||||
statement_types => 'SELECT',
|
||||
update_check => FALSE,
|
||||
enable => TRUE,
|
||||
policy_type => DBMS_RLS.CONTEXT_SENSITIVE
|
||||
);
|
||||
END;
|
||||
BEGIN
|
||||
replace_policy('HMM_LEAVE_BALANCES');
|
||||
replace_policy('HMM_LEAVE_REQUESTS');
|
||||
END;
|
||||
/
|
||||
|
||||
PROMPT === 7. Recording backoffice descriptions ===
|
||||
MERGE INTO hmm_access_vpd_filter_notes dst
|
||||
USING (
|
||||
SELECT 'ADMIN' function_owner,
|
||||
'HMM_LEAVE_VPD_FILTER' function_name,
|
||||
'Builds self, managed-team, and administrator leave predicates from HMM roles and access rules.'
|
||||
description
|
||||
FROM dual
|
||||
) src
|
||||
ON (
|
||||
dst.function_owner = src.function_owner
|
||||
AND dst.function_name = src.function_name
|
||||
)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
dst.description = src.description,
|
||||
dst.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
function_owner, function_name, description, updated_at
|
||||
) VALUES (
|
||||
src.function_owner, src.function_name, src.description, SYSTIMESTAMP
|
||||
);
|
||||
|
||||
MERGE INTO hmm_access_vpd_policy_notes dst
|
||||
USING (
|
||||
SELECT 'ADMIN' object_owner,
|
||||
object_name,
|
||||
'HMM_LEAVE_SCOPE_POLICY' policy_name,
|
||||
'Restricts leave rows to self, direct reports, or explicit HR administrator access.'
|
||||
description
|
||||
FROM (
|
||||
SELECT 'HMM_LEAVE_BALANCES' object_name FROM dual
|
||||
UNION ALL
|
||||
SELECT 'HMM_LEAVE_REQUESTS' FROM dual
|
||||
)
|
||||
) src
|
||||
ON (
|
||||
dst.object_owner = src.object_owner
|
||||
AND dst.object_name = src.object_name
|
||||
AND dst.policy_name = src.policy_name
|
||||
)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
dst.description = src.description,
|
||||
dst.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
object_owner, object_name, policy_name, description, updated_at
|
||||
) VALUES (
|
||||
src.object_owner, src.object_name, src.policy_name,
|
||||
src.description, SYSTIMESTAMP
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
PROMPT === 8. Deployment inventory ===
|
||||
SELECT object_name, object_type, status
|
||||
FROM user_objects
|
||||
WHERE object_name IN (
|
||||
'HMM_ACCESS_CTX',
|
||||
'HMM_ACCESS_CTX_PKG',
|
||||
'HMM_LEAVE_VPD_FILTER'
|
||||
)
|
||||
ORDER BY object_name, object_type;
|
||||
|
||||
SELECT object_name, policy_name, function, sel, enable, policy_type
|
||||
FROM all_policies
|
||||
WHERE object_owner = 'ADMIN'
|
||||
AND object_name IN ('HMM_LEAVE_BALANCES', 'HMM_LEAVE_REQUESTS')
|
||||
AND policy_name = 'HMM_LEAVE_SCOPE_POLICY'
|
||||
ORDER BY object_name;
|
||||
|
||||
SELECT e.employee_code, r.role_name
|
||||
FROM hmm_employee_access_roles er
|
||||
JOIN hmm_hr_employees e ON e.employee_id = er.employee_id
|
||||
JOIN hmm_access_roles r ON r.role_id = er.role_id
|
||||
WHERE r.role_name IN ('HMM_HR_VIEWER', 'HMM_HR_MANAGER')
|
||||
ORDER BY e.employee_code, r.role_name;
|
||||
|
||||
SELECT r.role_name,
|
||||
p.target_name,
|
||||
pr.rule_column,
|
||||
pr.rule_type
|
||||
FROM hmm_access_permissions p
|
||||
JOIN hmm_access_roles r ON r.role_id = p.role_id
|
||||
JOIN hmm_access_permission_rules pr ON pr.perm_id = p.perm_id
|
||||
WHERE p.target_name IN ('HMM_LEAVE_BALANCES', 'HMM_LEAVE_REQUESTS')
|
||||
ORDER BY r.role_name, p.target_name;
|
||||
|
||||
PROMPT === HMM leave team VPD ready ===
|
||||
Reference in New Issue
Block a user