我想向桌面客户的经理授予更新权,但仅限于经理所在的客户。
例如我有一个表Custumer,我使用命令CREATE USER创建了一个用户“Jean”,所以我希望“Jean”可以修改它所管理的所有客户。
答案 0 :(得分:-1)
我找到了RLS的这个例子,但是为了满足您的简单USER要求而编辑为时已晚。此示例适用于具有许多可能从组织树继承的各种ROLES的用户。但我希望你明白这个想法?
BEGIN
DBMS_RLS.DROP_POLICY (object_schema => 'CHS',
object_name => 'CASE_FILE',
policy_name => 'CASE_FILE_READ');
DBMS_RLS.DROP_POLICY (object_schema => 'CHS',
object_name => 'CASE_FILE',
policy_name => 'CASE_FILE_WRITE');
DBMS_RLS.DROP_POLICY (object_schema => 'CHS',
object_name => 'CASE_FILE',
policy_name => 'CASE_FILE_REGISTER');
END;
CREATE OR REPLACE PACKAGE chs_security_policies AS
ROLE_CRUM CONSTANT VARCHAR2(5) := 'CRUM';
ROLE_CRUO CONSTANT VARCHAR2(5) := 'CRUO';
ROLE_HOU CONSTANT VARCHAR2(5) := 'HOU';
ROLE_DCO CONSTANT VARCHAR2(5) := 'DCO';
ROLE_SA CONSTANT VARCHAR2(5) := 'SA';
ROLE_CA CONSTANT VARCHAR2(5) := 'CA';
CHS_ORG_TREE CONSTANT CHAR(5) := 'CHS01';
READ_ACCESS CONSTANT INTEGER := 63;
WRITE_ACCESS CONSTANT INTEGER := 42;
INSERT_ACCESS CONSTANT INTEGER := 64;
ORG_CASCADE CONSTANT INTEGER := 2060;
CASE_SPECIFIC CONSTANT INTEGER := 48;
QUARANTINED_ACCESS CONSTANT INTEGER := 128;
FINALISED_ACCESS CONSTANT INTEGER := 256;
READ_ONLY CONSTANT INTEGER := 21;
READ_CASE_ORG_UNITS CONSTANT INTEGER := 16;
READ_GROUP_ORG_UNITS CONSTANT INTEGER := 4;
READ_WORLD_ORG_UNITS CONSTANT INTEGER := 1;
FUNCTION case_file_read (i_schema IN VARCHAR2, i_object IN VARCHAR2)
RETURN VARCHAR2;
FUNCTION case_file_write (i_schema IN VARCHAR2, i_object IN VARCHAR2)
RETURN VARCHAR2;
FUNCTION case_file_register (i_schema IN VARCHAR2, i_object IN VARCHAR2)
RETURN VARCHAR2;
FUNCTION case_file_filter (i_schema IN VARCHAR2, i_object IN VARCHAR2, i_access_requested INTEGER)
RETURN VARCHAR2;
FUNCTION check_case_access (i_case_file_id IN INTEGER, i_mgr_org_unit IN INTEGER, i_dco_person_id in varchar2)
RETURN INTEGER
DETERMINISTIC;
FUNCTION default_priv_mask (i_person_id in varchar2)
RETURN INTEGER
DETERMINISTIC;
FUNCTION decode_role (i_case_file_id IN INTEGER, i_mgr_org_unit IN INTEGER, i_dco_person_id in varchar2)
RETURN VARCHAR2
DETERMINISTIC;
FUNCTION check_proxy_access (i_case_file_id IN case_file.case_file_id%type
, i_dco_person_id IN case_file.dco_person_id%type
, i_mgr_org_unit IN case_file.mgr_org_unit%type
, i_proxy_person_id IN case_file.dco_person_id%type)
RETURN INTEGER
DETERMINISTIC;
END chs_security_policies;
CREATE OR REPLACE PACKAGE BODY chs_security_policies AS
FUNCTION case_file_read (i_schema IN VARCHAR2, i_object IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
RETURN case_file_filter(i_schema, i_object, READ_ACCESS);
END case_file_read;
FUNCTION case_file_write (i_schema IN VARCHAR2, i_object IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
RETURN case_file_filter(i_schema, i_object, WRITE_ACCESS);
END case_file_write;
FUNCTION case_file_register (i_schema IN VARCHAR2, i_object IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
RETURN case_file_filter(i_schema, i_object, INSERT_ACCESS);
END case_file_register;
FUNCTION case_file_filter (i_schema IN VARCHAR2, i_object IN VARCHAR2, i_access_requested INTEGER)
RETURN VARCHAR2
IS
o_filter_predicate VARCHAR2(200) := '';
BEGIN
CASE lower(i_object)
WHEN 'case_file' THEN
o_filter_predicate :=
'BITAND(chs_security_policies.check_case_access(case_file_id, mgr_org_unit, dco_person_id), '||i_access_requested||') <> 0 ';
WHEN 'case_file_h' THEN
o_filter_predicate :=
'BITAND(chs_security_policies.check_case_access(case_file_id, mgr_org_unit, dco_person_id), '||i_access_requested||') <> 0 ';
END CASE;
RETURN o_filter_predicate;
END case_file_filter;
FUNCTION check_proxy_access (i_case_file_id IN case_file.case_file_id%type
, i_dco_person_id IN case_file.dco_person_id%type
, i_mgr_org_unit IN case_file.mgr_org_unit%type
, i_proxy_person_id IN case_file.dco_person_id%type)
RETURN INTEGER
DETERMINISTIC
IS
o_has_access INTEGER := 0;
v_prev_person varchar2(8) := SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER');
BEGIN
dbms_session.set_identifier(i_proxy_person_id);
IF BITAND(check_case_access(i_case_file_id, i_mgr_org_unit, i_dco_person_id), READ_ACCESS) <> 0
THEN
o_has_access := 1;
END IF;
dbms_session.set_identifier(v_prev_person);
RETURN o_has_access;
END check_proxy_access;
FUNCTION check_case_access(i_case_file_id in INTEGER, i_mgr_org_unit in INTEGER, i_dco_person_id in varchar2)
RETURN INTEGER
DETERMINISTIC
IS
o_access_granted INTEGER := 0;
v_curr_person varchar2(8) := SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER');
v_single_priv INTEGER := 0;
v_profile_org_unit INTEGER := 0;
v_quarantine_ok varchar2(1);
v_finalise_ok varchar2(1);
v_is_participant varchar2(1);
v_local_role access_role.role_code%type;
cursor user_privs is
select
d.priv_id,
b.org_unit_id,
c.role_code
from
access_user a
,access_profile b
,access_role c
,access_role_priv d
,access_priv e
where
a.person_id = v_curr_person
and a.active_flag = 'Y'
and b.person_id = a.person_id
and c.role_code = b.role_code
and d.role_code = b.role_code
and e.priv_id = d.priv_id
;
BEGIN
IF v_curr_person is null
THEN
RETURN 0;
END IF;
select
case
when exists
(select
*
from
complainant a
where
a.case_file_id = i_case_file_id
and a.person_id = v_curr_person
and a.active_flag = 'Y'
)
then 'Y'
else 'N'
end
into
v_is_participant
from
dual
;
IF v_is_participant = 'Y'
THEN
RETURN 0;
END IF;
select
case
when exists
(select
*
from
respondent a
where
a.case_file_id = i_case_file_id
and a.person_id = v_curr_person
and a.person_type <> 'U'
and a.active_flag = 'Y'
)
then 'Y'
else 'N'
end
into
v_is_participant
from
dual
;
IF v_is_participant = 'Y'
THEN
RETURN 0;
END IF;
v_quarantine_ok := 'N';
v_finalise_ok := 'N';
open user_privs;
loop
fetch user_privs into v_single_priv,
v_profile_org_unit,
v_local_role;
exit when user_privs%notfound;
IF v_single_priv = QUARANTINED_ACCESS
THEN
v_quarantine_ok := 'Y';
continue;
END IF;
IF v_single_priv = FINALISED_ACCESS
THEN
v_finalise_ok := 'Y';
continue;
END IF;
IF bitand(v_single_priv, ORG_CASCADE) <> 0
THEN
select
case
when i_mgr_org_unit in (
select
a.org_unit_child
from
org_rel a
connect by nocycle
a.org_rel_type_code = CHS_ORG_TREE and
prior
a.org_unit_child = a.org_unit_parent
start with
a.org_unit_child = v_profile_org_unit
and a.org_rel_type_code = CHS_ORG_TREE)
then v_single_priv
else 0
end
into
v_single_priv
from
dual
;
END IF;
IF bitand(v_single_priv, CASE_SPECIFIC) <> 0
THEN
IF v_local_role = 'CA'
THEN
select
case
when exists
(select
*
from
case_assistant a
where
a.case_file_id = i_case_file_id
and a.case_assistant_id = v_curr_person
and sysdate between a.access_from and a.access_to
)
then v_single_priv
else 0
end
into
v_single_priv
from
dual
;
IF v_single_priv <> 0
THEN
v_quarantine_ok := 'Y';
END IF;
ELSE
IF v_curr_person <> i_dco_person_id
THEN
v_single_priv := 0;
END IF;
END IF;
END IF;
o_access_granted := (o_access_granted + v_single_priv - bitand(o_access_granted, v_single_priv));
end loop;
close user_privs;
IF o_access_granted = 0 THEN
RETURN o_access_granted;
END IF;
IF (v_quarantine_ok = 'N' AND (i_dco_person_id <> v_curr_person
OR BITAND(o_access_granted,CASE_SPECIFIC) = 0)) THEN
select
case
when exists
(select
*
from
quarantine a
where
a.case_file_id = i_case_file_id
and a.active_flag = 'Y'
)
then 0
else o_access_granted
end
into
o_access_granted
from
dual
;
END IF;
IF o_access_granted = 0 THEN
RETURN o_access_granted;
END IF;
IF v_finalise_ok = 'N' THEN
select
case
when exists
(select
*
from
finalise a
where
a.case_file_id = i_case_file_id
)
then 0
else o_access_granted
end
into
o_access_granted
from
dual
;
END IF;
IF v_finalise_ok = 'Y' THEN
select
case
when exists
(select
*
from
finalise a
where
a.case_file_id = i_case_file_id
)
then BITAND(o_access_granted, READ_ONLY)
else o_access_granted
end
into
o_access_granted
from
dual
;
END IF;
RETURN o_access_granted;
END check_case_access;
FUNCTION decode_role(i_case_file_id IN INTEGER, i_mgr_org_unit IN INTEGER, i_dco_person_id in varchar2)
RETURN VARCHAR2
DETERMINISTIC
IS
v_curr_person varchar2(8) := SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER');
v_access_granted INTEGER := 0;
o_role_used access_role.role_code%type;
BEGIN
v_access_granted := check_case_access(i_case_file_id, i_mgr_org_unit, i_dco_person_id);
IF BITAND(v_access_granted, READ_CASE_ORG_UNITS ) <> 0 THEN
IF v_curr_person = i_dco_person_id THEN
o_role_used := ROLE_DCO;
ELSE
o_role_used := ROLE_CA;
END IF;
ELSE
IF BITAND(v_access_granted, READ_GROUP_ORG_UNITS) <> 0 THEN
o_role_used := ROLE_HOU;
ELSE
IF BITAND(v_access_granted, READ_WORLD_ORG_UNITS) <> 0 THEN
select
case
when exists
(select
*
from
access_profile a
where
a.person_id = v_curr_person
and a.role_code = ROLE_CRUM
)
then ROLE_CRUM
else ROLE_CRUO
end
into
o_role_used
from
dual
;
END IF;
END IF;
END IF;
RETURN o_role_used;
END decode_role;
FUNCTION default_priv_mask(i_person_id in varchar2)
RETURN INTEGER
DETERMINISTIC
IS
o_access_available INTEGER := 0;
v_single_priv INTEGER := 0;
cursor user_privs is
select
d.priv_id
from
access_user a
,access_profile b
,access_role c
,access_role_priv d
,access_priv e
where
a.person_id = i_person_id
and a.active_flag = 'Y'
and b.person_id = a.person_id
and c.role_code = b.role_code
and d.role_code = b.role_code
and e.priv_id = d.priv_id
;
BEGIN
open user_privs;
loop
fetch user_privs into v_single_priv;
exit when user_privs%notfound;
o_access_available := (o_access_available + v_single_priv - bitand(o_access_available, v_single_priv));
end loop;
close user_privs;
RETURN o_access_available;
END default_priv_mask;
END chs_security_policies;
/
BEGIN
DBMS_RLS.ADD_POLICY (object_schema => 'CHS',
object_name => 'CASE_FILE',
policy_name => 'CASE_FILE_READ',
function_schema => 'CHS',
statement_types => 'SELECT',
policy_function => 'chs_security_policies.case_file_read');
DBMS_RLS.ADD_POLICY (object_schema => 'CHS',
object_name => 'CASE_FILE',
policy_name => 'CASE_FILE_WRITE',
function_schema => 'CHS',
statement_types => 'UPDATE,DELETE',
policy_function => 'chs_security_policies.case_file_write');
DBMS_RLS.ADD_POLICY (object_schema => 'CHS',
object_name => 'CASE_FILE',
policy_name => 'CASE_FILE_REGISTER',
function_schema => 'CHS',
statement_types => 'INSERT',
policy_function => 'chs_security_policies.case_file_register');
END;