So lets say 100, 200, 400, 600 are company_ids and there are 6 administrators who each have their company_ids. The owner of the table User_Info is Admin who is also the owner of other tables and can view, edit, delete, update any tables, procedures, or anything. Has all rights.
Now Admin has created users MKarki and other such in the User_Info table with respective company_ids.
There are other tables inserted using Admin's account in Oracle 10g like customer, employee, shipment and so on. Each of those table have "Company_ID" as a foreign key.
A user when logs into their own session can insert, update, delete the records from the table customer, employee or any other based on the company_id it belongs to. MKarki cannot select, insert, update, or delete records which has company_id 200 (this one is already taken care of).
Example: So the User_Info table has these columns:
Company_ID F_Name L_Name Username Owner Level_Of_Security
100 Mala Karki MKarki Admin 5
100 Piya Karki PKarki Admin 5
200 Giya Khadka GKhadka Admin 5
Now customer table looks like this:
CUS_ID Company_ID F_Na L_Na Owner Sec_Level
23 100 Hor Loki MKarki 4
22 100 Bholu Kam PKarki 4
34 200 Golu Pop GKhadka 4
Based on the tables above: When MKarki logs into her own Oracle account and executes the Select statement: Select * from Customer. She should be able to view all records that have company_Id 100. (This is what I need to know as how this can be implemented???)
So now if PKarki logs into oracle 10g then she should be able to see both of the customer values for company_ID 100 even if one belongs to MKarki since PKarki is also from same company ID.
Now we need to implement a security policy function for the above business policy.
The environment is Oracle 10g and it is for Virtual Private Database
I am unable to get any rows even after setting the context with package, package body, and procedure. (No rows selected or "Error: Policy predicate has errors" if I tweak the Sys_Context a little bit)
I have also created the context with package like this:
Create or replace Context CompAdmin USING Pac_Comp_Adm;
Create or Replace Package Pac_Comp_Adm IS Procedure Get_Company_ID; END; /
Create or Replace PACKAGE BODY Pac_Comp_Adm
IS PROCEDURE Get_Company_ID IS V_Company_ID Number;
BEGIN
Select Company_ID INTO V_Company_ID FROM User_Info
Where Company_ID = SYS_CONTEXT('USERENV','SESSION_USER');
DBMS_SESSION.SET_CONTEXT('COMPADMIN','Company_ID', V_Company_ID); EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END; END; /
Create or Replace FUNCTION Helo_Comp_ID ( P_SCHEMA_NAME IN varchar2, P_OBJECT_NAME IN varchar2)
Return varchar2 IS V_Hello Varchar2(300);
BEGIN If User = 'ADMIN'
then V_Hello := '';
Else
V_Hello:='SYS_CONTEXT('||q'['CompAdmin']'||
','||q'['Company_ID']'||')
='||q'['Company_ID']';
END IF;
RETURN V_Hello;
END; /
After this I am setting the policies using the function above as follows:
exec DBMS_RLS.ADD_Policy ('ADMIN','CUSTOMER','Row_Upper_Sec','ADMIN','Helo_Comp_ID','SELECT,INSERT,UPDATE,DELETE');
Best Answer
According to the question, all you need to do is attach a predicate on the query to customer table as shown below.
Right? If yes, you have to create a function which should return a predicate as:
Well, I have done a small demo for your requirement. I have created
doramail
as anADMIN
user who owns the tablesuser_info
,customer
and a function calledHello_Comp_ID
.Since the user
MKarki
belongs tocompany_id
100 he only can see records wherecompany_id
is 100.In your case there might be problem in returned predicate. You can change:
To this:
If you are still having trouble then you can view the predicate being attached to your query using
explain plan
command. And then you can change the predicate(if there are any logical/syntactical errors in the predicate) in the function.