There are two main ways to implement row-level security in a universe. One is via a Security Profile; the other is via @variable('BOUSER')
.
If the security is to be applied at a group level (that is, all members of a group should have the same condition applied), then a Security Profile is appropriate. This is covered in Chapter 17 of the IDT User Guide. At a high level, the steps are:
- From IDT, launch the Security Editor
- Select the universe, and create either a Data Security Profile or a Business Security Profile (read the docs for the differences between the two, but one is that with the DSP, you will write a WHERE condition; with the BSP, you select objects and define a condition)
- Once the Security Profile is created, select the group or groups that it should apply to
- Repeat the above for each group that should have a restriction applied
The other method for applying row-level security is only applicable when the data source includes a table that has a mapping of BO user IDs to the values that they may have access to. For example, let's say you have a security table in your data source that looks like this:
user_id region
------- ------
U123 NE
U123 SE
U321 W
and your fact table looks like:
pk region value
__ ______ _____
1 NE 3
2 W 4
You can apply security such that user U123 only sees the "NE" row, and user U321 only sees the "W" row. You would join the two tables on region (security.region=fact.region
), then create a new mandatory filter on security.user_id=@variable('BOUSER')
. This will force the filter to be applied to all queries.
Note that both of the above methods work by adding conditions to the query's WHERE condition. If your users have permission to view and edit the query's SQL, they will be above to override the filtering logic. To ensure security, users should be denied this right.