Find everything you need to get certified on Fabric—skills challenges, live sessions, exam prep, role guidance, and more.
Get startedGrow your Fabric skills and prepare for the DP-600 certification exam by completing the latest Microsoft Fabric challenge.
HI,
I have a situation where I have a table User.
If AccessAllPortfolioBoards = TRUE, then Table A should have RLS applied to it based on the ID of the user.
If AccessAllPortfolioBoards = FALSE, then Table B should have RLS applied to it based on the ID of the user.
How do I do this? I am stuck as to how to set this up. Do I write some sort of conditional DAX against the tables in different roles?
Thanks in advance.
Solved! Go to Solution.
Hi again @naninamu
Thanks for the clarification, and I'll answer the questions from both your replies.
1. Since the User table has both "User email" and "ID" columns, we can tweak the code to retrieve both the True/False flag and the ID from the relevant row. I adjusted the code to use a slightly different method.
The below RLS expressions grab the relevant row of User and store in a variable UserRow based on User email = UPN. Then the Flag and UserID are extracted from this variable.
-- Filter 'Table A'
VAR UPN =
USERPRINCIPALNAME ()
VAR UserRow =
CALCULATETABLE (
User,
User[User email] = UPN
)
VAR Flag =
SELECTCOLUMNS ( UserRow, User[AccessAllPortfolioBoards] )
VAR UserID =
SELECTCOLUMNS ( UserRow, User[ID] )
VAR Result =
OR (
NOT Flag,
'Table A'[ID] = UserID
)
RETURN
Result
-- Filter 'Table B'
VAR UPN =
USERPRINCIPALNAME ()
VAR UserRow =
CALCULATETABLE (
User,
User[User email] = UPN
)
VAR Flag =
SELECTCOLUMNS ( UserRow, User[AccessAllPortfolioBoards] )
VAR UserID =
SELECTCOLUMNS ( UserRow, User[ID] )
VAR Result =
OR (
Flag,
'Table B'[ID] = UserID
)
RETURN
Result
2. To answer your second post's questions:
The RLS "Filter Expressions" above determine whether a given row of 'Table A' or 'Table B' will be visible. Each expression is evaluated in a row context for each row of the relevant table, and if it returns True, then the row is visible, otherwise it is not visible.
The way I have constructed the expressions is to ensure that:
Taking Mary as an example:
For Table A:
For Table B:
I have attached a modified PBIX, and I suggest testing it out with the different users to verify:
Hope that helps! 🙂
Regards
Thanks for the explanation @naninamu , and sorry for misunderstanding. I realise now I slightly misread your previous post!
So if I've understood it correctly, a given user can either:
(This is essentially the requirement as stated in your first post 🙂 )
To implement this, we can tweak my last model by ensuring a given user is included in only one of the two tables before unioning.
I have slightly reorganised the queries in Power Query to clarify the steps.
The source tables are now:
These are then filtered by
The resulting tables are
These are then unioned into UserEntity.
This ensures a given user appears in only one of the component tables, which are then unioned.
I have updated with User 500 appearing in both tables (with Portfolio = 2, Entity = 2223), but having AccesAllPortfolioBoards = FALSE, so can only view Entity 2223.
This way, we can keep the same simple RLS filter expression.
Let me know if this is the logic you expect 🙂
You're welcome 🙂
Sorry, you're quite right, that last step should have referred to UserEntityFiltered, not UserEntitySource.
Just to ensure the correct file is here, I will replace the uploaded file on the post above.
Glad to help, and all the best!
Regards
Hi again @OwenAuger - I had some questions about your example was hoping you could clarify for me.
1) Take the Table A filter. It should only be filtered where someone has a Portfolio Status of TRUE. Mary has a status of FALSE, thus the FLAG = FALSE. The Table A code says:
VAR Result = OR ( NOT Flag, 'Table A'[Id] = UPN ) RETURN Result
So doesn't "NOT Flag" turn Mary's FALSE into a TRUE? And since OR only needs on TRUE to evaluate to TRUE, doesn't RESULT = TRUE. But for Table A it should be false shouldn't it? - as Mary has a status of FALSE and shouldn't be filtering Table A.
2) Which leads me to my second question - how does the table know what to filter on? As in where does it actually tell the table to filter on the UPN? RESULT is just a TRUE/FALSE, which part of the code actually tells Table A or Table B to filter according to the UPN?
Thanks in advance for helping me out!
Hi again @naninamu
Thanks for the clarification, and I'll answer the questions from both your replies.
1. Since the User table has both "User email" and "ID" columns, we can tweak the code to retrieve both the True/False flag and the ID from the relevant row. I adjusted the code to use a slightly different method.
The below RLS expressions grab the relevant row of User and store in a variable UserRow based on User email = UPN. Then the Flag and UserID are extracted from this variable.
-- Filter 'Table A'
VAR UPN =
USERPRINCIPALNAME ()
VAR UserRow =
CALCULATETABLE (
User,
User[User email] = UPN
)
VAR Flag =
SELECTCOLUMNS ( UserRow, User[AccessAllPortfolioBoards] )
VAR UserID =
SELECTCOLUMNS ( UserRow, User[ID] )
VAR Result =
OR (
NOT Flag,
'Table A'[ID] = UserID
)
RETURN
Result
-- Filter 'Table B'
VAR UPN =
USERPRINCIPALNAME ()
VAR UserRow =
CALCULATETABLE (
User,
User[User email] = UPN
)
VAR Flag =
SELECTCOLUMNS ( UserRow, User[AccessAllPortfolioBoards] )
VAR UserID =
SELECTCOLUMNS ( UserRow, User[ID] )
VAR Result =
OR (
Flag,
'Table B'[ID] = UserID
)
RETURN
Result
2. To answer your second post's questions:
The RLS "Filter Expressions" above determine whether a given row of 'Table A' or 'Table B' will be visible. Each expression is evaluated in a row context for each row of the relevant table, and if it returns True, then the row is visible, otherwise it is not visible.
The way I have constructed the expressions is to ensure that:
Taking Mary as an example:
For Table A:
For Table B:
I have attached a modified PBIX, and I suggest testing it out with the different users to verify:
Hope that helps! 🙂
Regards
Hi @naninamu
Yes, I would suggest creating a single role which contains RLS DAX expressions for both 'Table A' and 'Table B'.
I have attached a simple PBIX to illustrate.
I have assumed that Id corresponds to the User Principal Name returned by USERPRINCIPALNAME ().
In this example, there is a single Role called DynamicRLS with the following expressions to filter the tables:
-- Filter 'Table A'
VAR UPN =
USERPRINCIPALNAME ()
VAR Flag =
LOOKUPVALUE ( User[AccessAllPortfolioBoards], User[Id], UPN )
VAR Result =
OR (
NOT Flag,
'Table A'[Id] = UPN
)
RETURN
Result
-- Filter 'Table B'
VAR UPN =
USERPRINCIPALNAME ()
VAR Flag =
LOOKUPVALUE ( User[AccessAllPortfolioBoards], User[Id], UPN )
VAR Result =
OR (
Flag,
'Table B'[Id] = UPN
)
RETURN
Result
Unfiltered
Vier as user john@test.com (True)
View as user mary@test.com (False)
Please post back if needed.
Regards
Hi @OwenAuger - thank you so much for your reply. It was very helpful!
One thing though is I've realised I've oversimplified my example a little.
The User table actually contains:
While Tables A and B have the [ID] as I stated previously.
So I can check that the USERPRINCIPALNAME() matches the User email in the User table, but I'm having trouble working out how to then grab the corresponding ID in the User Table to filter Tables A or B with.
Would that be some sort of Lookup function? I tried just going 'Table A[ID]' = 'User[ID]' assuming it would just grab the ID of the row filtered by the USERPRINCIPALNAME(), but it didn't work.
Thanks in advance!
Andrew
User | Count |
---|---|
77 | |
75 | |
67 | |
65 | |
47 |
User | Count |
---|---|
108 | |
105 | |
93 | |
83 | |
65 |