I00N |
Здравствуйте!
Ситуация: пользователю назначена роль SOME_ROLE. Вызов dbms_session.is_role_enabled это подтверждает. В другом сеансе забираем у пользователя роль SOME_ROLE, но dbms_session.is_role_enabled показывает, что роль по-прежнему есть. Только если перелогинится, то получем правильный результат.
Как узнать обладает ли пользователь ролью в данный момент(а не на момент начала сессии) не строя иерархический запрос к dba_role_privs? |
First of all, dbms_session.is_role_enabled HE подтверждает пользователю назначена (I assume by назначена you mean GRANTED) роль SOME_ROLE. SOME_ROLE can be, for example, назначена пользователю but not as default role and therefore dbms_session.is_role_enabled will result in FALSE.
Anyway, if I understood you correctly, dbms_session.is_role_enabled('SOME_ROLE') returns TRUE and you want to find out if SOME_ROLE is still granted to user (directly or indirectly). Then:
Session I
SQL> CREATE OR REPLACE
2 FUNCTION is_role_still_granted(
3 p_role VARCHAR2
4 )
5 RETURN BOOLEAN
6 AUTHID CURRENT_USER
7 IS
8 e_role_not_granted EXCEPTION;
9 PRAGMA EXCEPTION_INIT(e_role_not_granted,-1924);
10 BEGIN
11 IF DBMS_SESSION.IS_ROLE_ENABLED(p_role)
12 THEN
13 BEGIN
14 DBMS_SESSION.SET_ROLE(p_role);
15 RETURN TRUE;
16 EXCEPTION
17 WHEN e_role_not_granted
18 THEN
19 RETURN FALSE;
20 END;
21 ELSE
22 RETURN NULL;
23 END IF;
24 END;
25 /
Function created.
SQL> GRANT EXECUTE ON is_role_still_granted TO u1
2 /
Grant succeeded.
SQL> CREATE ROLE r1
2 /
Role created.
SQL> GRANT r1 TO u1
2 /
Grant succeeded.
SQL>
Session II
SQL> connect u1/u1
Connected.
SQL> SELECT *
2 FROM SESSION_ROLES
3 /
ROLE
------------------------------
R1
SQL> SET SERVEROUTPUT ON
SQL> BEGIN
2 IF DBMS_SESSION.IS_ROLE_ENABLED('R1')
3 THEN
4 DBMS_OUTPUT.PUT_LINE('Yes');
5 ELSE
6 DBMS_OUTPUT.PUT_LINE('No');
7 END IF;
8 END;
9 /
Yes
PL/SQL procedure successfully completed.
SQL> BEGIN
2 IF scott.is_role_still_granted('R1')
3 THEN
4 DBMS_OUTPUT.PUT_LINE('Yes');
5 ELSE
6 DBMS_OUTPUT.PUT_LINE('No');
7 END IF;
8 END;
9 /
Yes
PL/SQL procedure successfully completed.
SQL>
Session I
SQL> REVOKE r1 FROM u1
2 /
Revoke succeeded.
Session II
SQL> SELECT *
2 FROM SESSION_ROLES
3 /
ROLE
------------------------------
R1
SQL> BEGIN
2 IF DBMS_SESSION.IS_ROLE_ENABLED('R1')
3 THEN
4 DBMS_OUTPUT.PUT_LINE('Yes');
5 ELSE
6 DBMS_OUTPUT.PUT_LINE('No');
7 END IF;
8 END;
9 /
Yes
PL/SQL procedure successfully completed.
SQL> BEGIN
2 IF scott.is_role_still_granted('R1')
3 THEN
4 DBMS_OUTPUT.PUT_LINE('Yes');
5 ELSE
6 DBMS_OUTPUT.PUT_LINE('No');
7 END IF;
8 END;
9 /
No
PL/SQL procedure successfully completed.
SQL>
SY.