How to know if a user has a privilege on Object? - sql

I would like to know if a user has a privilege on an object or not.
I'm working on SQL Developer.
When I query manually the table DBA_TAB_PRIVS, I get all the information needed.
However, I need this information to be used in some triggers and functions.
So, I'm writing PL/SQL function that will return 1 if a role has the privilege and 0 otherwise.
CREATE OR REPLACE FUNCTION HAS_PRIVILEGE_ON_OBJECT(rolename IN VARCHAR2,
objectname IN VARCHAR2,
objectowner IN VARCHAR2,
privilegename IN VARCHAR2)
RETURN NUMBER
AS
output NUMBER;
BEGIN
SELECT count(*) INTO output
FROM dba_tab_privs
WHERE grantee = rolename
AND owner = objectowner
AND table_name = objectname
AND privilege = privilegename;
IF output > 0 THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END has_privilege_on_object;
The function doesn't compile and says :
ORA 942 : table or view does not exist.
The user connected has access to the view DBA_TAB_PRIVS since I can query it, but when trying to automate it using a function. It doesn't work.
Any ideas please?

You can use table_privileges:
select * from table_privileges;
This does not require any specific rights from your user.

I'll wager that you have privileges on dba_tab_privs via a role, not via a direct grant. If you want to use a definer's rights stored function, the owner of the function has to have privileges on all the objects granted directly, not via a role.
If you disable roles in your interactive session, can you still query dba_tab_privs? That is, if you do
SQL> set role none;
SQL> select * from dba_tab_privs
do you get the same ORA-00942 error? Assuming that you do
GRANT select any dictionary
TO procedure_owner
will give the procedure_owner user the ability to query any data dictionary table in a stored function. Of course, you could also do a direct grant on just dba_tab_privs.

You currently have access to DBA_TAB_PRIVS through a role. So, executing SQL works fine, but roles are not enabled in the PL/SQL context, so, compilation fails.
Try:
grant select on sys.dba_tab_privs to <user>;
and that should take care of it.

Related

unable to execute sql procedure on oracle live sql

I created a procedure
create or replace procedure dba_role
as
user varchar2(200);
ref varchar2(200);
begin
insert into dba_role_privs(grantee,granted_role) (select user as grantee,granted_role from dba_role_privs where grantee=ref);
end;
The procedure is getting created but I'm not able to execute the procedure. I've tried different methods to execute it by passing parameters but nothing worked.
Can anyone please tell how to execute this procedure in oracle live SQL
the parameters to be passed are both strings(varchars)
for example:
I've tried "Execute dba_role('alex','hunter');
The error is
**ORA-06550: line 1, column 7:
**PLS-00306: wrong number or types of arguments in call to 'DBA_ROLE' **
As well as missing the two parameters that you are trying to pass (parameters should appear in brackets immediately following the procedure name, as explained in d r's answer), you can't insert into a DBA view. For one thing, it's not in your schema (unless you are creating your procedure as SYS, which you should never do because SYS is reserved for Oracle internals) and you haven't been granted INSERT privilege, but also because it is defined with multiple joins and unions etc and is therefore not an updatable view. Even it it were, your procedure only specifies two of its seven columns.
Even if you did have privileges and it was updatable and you supplied all of the values, directly updating internal data dictionary tables is unsupported and could damage your database. If you want to grant a privilege to a role you should use the GRANT command:
grant reports_user to hr;
To revoke the grant,
revoke reports_user from hr;
create or replace procedure
dba_role(p_user IN VarChar2, p_ref IN VarChar2) AS
begin
insert into dba_role_privs(grantee, granted_role) (select p_user as grantee, granted_role from dba_role_privs where grantee = p_ref);
end dba_role;
/
Above is how it should be defined - with two VarChar2 parameters. And below is how to call it:
Begin
dba_role('alex', 'hunter');
End;
/
The problem with your code was that user and ref were declared as variables within the scope of the procedure (not as parameters) so, when the procedure was called with parameters (like I did above) then you tryed to pass two parameters to the procedure not accepting any. On the other side, if you call it without parameters (just as dba_role;) then user and ref were both Null.

how to grant all priviledges to all objects(tables, views, procedure, function etc) to a role in oracle

role created:
create role rl_new
want to give all priviledges to all objects like tables, views, procedures, function , etc to that role.
grant all on all_objects to rl_new
what is the right way to give all priviledges to all objects to role?
all_objects is a just a view so, no, that isn't what you want. You'd need to grant access to each object individually. You can use dynamic SQL to make that easier. For example
begin
for t in (select * from user_tables)
loop
execute immediate 'grant all on ' || t.table_name || ' to rl_new';
end loop
end;
Of course, you'd need to do something similar for the different types of objects you want to give grants on.
Going forward, you'll need to include the grants in the scripts that you deploy to create new objects as well.

dbms_metadata.get_ddl not working

I want to get the DDL of Table CARD_TABLE in XT schema
SQL> select dbms_metadata.get_ddl('TABLE','CARD_TABLE','XT') from dual;
ERROR:
ORA-31603: object "CARD_TABLE" of type TABLE not found in
schema "XT"
ORA-06512: at "SYS.DBMS_METADATA", line 5746
ORA-06512: at "SYS.DBMS_METADATA", line 8333
ORA-06512: at line 1
But my select Query works
select count(*) from XT.CARD_TABLE;
count(*)
---------
0
I queried dba_objects it still got the table:
SQL> select owner,object_type from DBA_OBJECTS
where object_name='CARD_TABLE' 2
3 ;
PUBLIC SYNONYM
XT TABLE PARTITION
XT TABLE PARTITION
XT TABLE PARTITION
XT TABLE
XT TABLE PARTITION
VAT TABLE
7 rows selected.
From the dbms_metadata documentation:
If nonprivileged users are granted some form of access to an object in someone else's schema, they will be able to retrieve the grant specification through the Metadata API, but not the object's actual metadata.
So unless you're connected as a privileged user, you can't see the DDL for another user's objects. You would need to connect as SYS, or have the SELECT_CATALOG_ROLE role granted to your user to be able to get XT's object definition.
Even with that role:
In stored procedures, functions, and definers-rights packages, roles (such as SELECT_CATALOG_ROLE) are disabled. Therefore, such a PL/SQL program can only fetch metadata for objects in its own schema. If you want to write a PL/SQL program that fetches metadata for objects in a different schema (based on the invoker's possession of SELECT_CATALOG_ROLE), you must make the program invokers-rights.
If you're calling dbms_metadata from an anonymous PL/SQL block that doesn't matter, but if you're calling it from a procedure you will have to include an AUTHID clause in the procedure declaration, adding AUTHID CURRENT_USER.
grant SELECT_CATALOG_ROLE to <user> with delegate option;
it work for me. Do this after modify procedure
grant SELECT_CATALOG_ROLE to procedure <procedure name>;

Multi-schema select statement doesn't work in PL/SQL procedure?

I'm trying to create a procedure to run multiple PL/SQL statements, but I haven't gotten very far. The select statement works fine if I run it out of a procedure, but if I try to execute it inside one -- it can't find the shttran table. I'm guessing it might be a schema issue, but I have no idea how-to correct. Ideas?
CREATE OR REPLACE PROCEDURE REGREPORTUSER.findUnsent
IS
BEGIN
INSERT INTO regreportuser.maltran (maltran.maltran_key,
maltran.maltran_sent)
SELECT shttran.shttran_id || shttran.shttran_seq_no AS maltran_key,
'No' AS maltran_sent
FROM saturn.shttran -- This is the table it can't find
WHERE TO_DATE (shttran.shttran_activity_date) > SYSDATE - 14
AND shttran.shttran_user = 'WWW2_USER'
AND shttran.shttran_id || shttran.shttran_seq_no NOT IN
(SELECT maltran.maltran_key FROM regreportuser.maltran);
END findUnsent;
Most likely, the problem is that the user that owns the stored procedure, REGREPORTUSER has access to the table saturn.shttran via a role rather than as a direct grant. A definer's rights stored procedure cannot use privileges that are granted to a definer via a role. It can only use privileges granted directly.
You can verify that this is, in fact, the problem by disabling roles in your SQL*Plus session. If you run the command
SQL> set role none;
and then try to execute the SQL statement, you should get the same error. In order to fix the problem, you need to give the grant directly
GRANT SELECT ON saturn.shttran
TO REGREPORTUSER

dba_jobs_running: table or view does not exist when trying to access from procedure

Simply querying running jobs using something like
select * from dba_jobs_running;
works fine when executed in my sqldevelopers SQL console.
However, it does not work, when having exactly the same statement within a procedure.
Compilation fails with
PL/SQL: ORA-00942: table or view does not exist
Any ideas? Is there something like a scope to be considered?
Any suggestions are highly appreciated, thanks in advance :)
You probably need to do a direct GRANT of DBA_JOBS_RUNNING to the user that owns the procedure. Doing a GRANT via a role won't work.... the grant needs to be explicit.
EDIT:
Doing a SELECT from within a procedure requires subtly different permissions to doing a SELECT from outside a procedure (e.g. in SQL-Developer). The user that owns a procedure must have been explicitly granted rights to the table or view... if running a query from outside a view this is not the case (you can be granted the permission through a role for example)
You need to connect as SYS and go:
GRANT SELECT ON SYS.DBA_JOBS_RUNNING TO <user-that-owns-proc>;
Procedures are executed without roles. One way to see if you can run a command in a procedure is to execute:
SQL> set role none;
Role set
You will have the same set of rights as your procedures:
SQL> SELECT * FROM dba_jobs_running;
SELECT * FROM dba_jobs_running
ORA-00942: table or view does not exist
You have to grant select on the view directly to the user:
SQL> -- with dba account
SQL> grant select on dba_jobs_running to a;
Grant succeeded
You will then be able to compile the procedure:
SQL> -- with application schema
SQL> CREATE OR REPLACE PROCEDURE test_dba AS
2 BEGIN
3 FOR cc IN (SELECT * FROM dba_jobs_running) LOOP
4 NULL;
5 END LOOP;
6 END test_dba;
7 /
Procedure created
Is procedure owned by another user? If so have a look at:
Definer and Invoker Rights for stored routines in PL/SQL manual.
Rob