I'm at a point within one of my Oracle APEX projects where I need to implement different levels of security for specific individuals for specific applications.
T开发者_开发技巧o start, I created a cartesian containing the information from the user
table, the app
table, and the role
table.
It looks like this:
SELECT
A.user_id, B.app_id, C.role_id
FROM user A, app B, role C
ORDER BY A.user_id ASC, B.app_id ASC, C.role_id ASC
This allows me to return EVERY combination of user
, app
, and role
. w/o using a where clause it returns over 303k rows. currently almost 500 users, 6 roles, and over 100 apps.
when I select from this view for a specific user its returning in approximately 10 ms which is acceptable.
Now, I also have a vw that stores each user's app/role assignment. I've joined this table to the cartesian in the following fashion.
SELECT
A.*,
DECODE(B.app_right_id, null, 0, 1) AS user_access
FROM
vw_user_app_role A -- My cartesian view
LEFT JOIN vw_tbl_user_app_role B
ON A.user_id = B.user_id
AND A.app_id = B.app_id
AND A.role_id = B.role_id
This returns a very usable set of data that resembles
user_id app_id role_id user_access
50 5 1 0
50 10 2 1
50 15 3 1
75 5 1 1
75 10 2 0
75 15 3 0
I'm considering what my next step should be, If I should create a pivot of the data where the app_id would be the row, the role_id would be the columns, and the user_access would be the "data". The "data" would ultimately be rendered as a check box on a website with the appropriate row/column headings.
I'm also considering using a pure ajax/json solution where I will build the json string using pl sql and return the entire string to the client to be processed via jquery.
I'm concerned with the difficulty of the first option (i'm very new to pl sql, and I'm unsure of how to generate a pivot table to be used in this version of oracle (v 10) ) and I'm concerned with the expense of creating an entire json string that will contain so much data.
Any suggestions would be greatly appreciated.
EDIT
I've achieved the pivot table that I desired via the following sql:
SELECT
B.application_nm,
A.user_id,
MAX(DECODE(b.role_name, 'role 1', A.USER_ACCESS, NULL)) "role 1",
MAX(DECODE(b.role_name, 'role 2', A.USER_ACCESS, NULL)) "role 2",
MAX(DECODE(b.role_name, 'role 3', A.USER_ACCESS, NULL)) "role 3",
MAX(DECODE(b.role_name, 'role 4', A.USER_ACCESS, NULL)) "role 4",
MAX(DECODE(b.role_name, 'role 5', A.USER_ACCESS, NULL)) "role 5",
MAX(DECODE(b.role_name, 'role 6', A.USER_ACCESS, NULL)) "role 6"
FROM
vw_user_app_access A LEFT JOIN vw_tbl_app B ON A.app_id = B.app_id
LEFT JOIN vw_tbl_roles C ON A.role_id = C.role_id
GROUP BY B.application_name, A.user_id
ORDER BY A.user_id DESC
Only problem is when in the future we have to add 'role 7'. I have to then go back into this query and add the line MAX(DECODE(b.role_name, 'role 7', A.USER_ACCESS, NULL)) "role 7"
Thinking ahead, this may be an inconvenience, but considering APEX's framework, I would have to go into the report any way to update the number of columns manually i believe.
I'm thinking this may be the "best" solution for now, unless anyone has any other suggestions...
It is possible for an Apex report region based on a dynamic SQL query to return a different number of columns as the query changes. I have set up a simple demo on apex.oracle.com. Type a new column name into the Columns tabular form and press "Add Row", and the Matrix report is re-drawn with an extra column of that name.
You have to:
- Base the report on a function that returns the SQL to be run as a string
- Select the region attribute "Use Generic Column Names (parse query at runtime only)"
- Set the report Headings Type to PL/SQL and then use a function to dynamically return the required column headings as a colon-separated list. Note that this can be different from the column name, although my example uses the same text for both.
If my example isn't clear enough I'll add more info later - I'm out of time now.
精彩评论