Hello!
I'm currently developing a reactive application and managing user permissions based on roles. I’ve created 8 roles and need to configure what users can see. Setting access to screens is straightforward with the roles section, but I’m facing challenges when it comes to hiding/showing parts of the UI based on roles.
Currently, I use a data action at the start of each screen to output boolean variables such as IsITAdmin to define roles. However, this approach requires repeating the same data action on each screen and block, which doesn’t seem efficient.
I was thinking of creating a server action and calling it on every screen, but I am not sure in which event I should call it (initialize, ready, or render).
I have looked around the forum and I can see different approaches (e.g., using JavaScript to check a role), but I am wondering what is the most common approach.
My questions are:
Has anyone implemented a similar setup, or does anyone have advice on best practices for this scenario?
Thank you,
Andrea
Hi @Andrea Caselli ,
Its a really awesome bunch of questions.
There are many ways to resolve the scenario but speaking of Optimized solution i can suggest the below idea. Try to implement both the points to improve performance.
1. Use DataAction to retrieve server data, So that you can display a loader or temporary widget till the time its loaded fully (By Using DataAction.IsDataFetched property). This answers point 3 that UI data is loaded only after the role confirmation is obtained from server.
2. Inside DataAction use a server action to retrieve data and increase the Server action cache time so that the data is retrieved fast on the second block/action hit.
This method allows to ensure a server check is made and its executed on loading of the page/block.
Hi @Jerome Rajadurai J
Thank you for your reply! That's definitely a more refined approach than mine and if I will decide in the end to continue using the Data Action approach I will definitely refine it by using your suggestions. Thanks!
Hi Andrea,
Assuming that your roles - or role assignments to be more specific - are not constantly changing one way to is to modify the existing UserInfo block (if using the default application templates). The default UserInfo block is part of the individual default layouts. In its standard configuration it calls a GetUserName client action in the OnInitialize handler of the block which in turn refreshes the GetUserNameFromServer data action.
You can hook into that data action and retrieve additional information like the assigned roles. Since you need the roles for UI visibility you would return a boolean value for each individual role. like AppIsManager, AppIsAdmin, AppIsOperator asf.
The default UserInfo block sets a client variable username to the retrieved username from the server. You would have to create additional client variables for your roles.
But take note that - at least from my perspective - the default UserInfo block has a design flaw. Storing the result of the username takes place in the same client action (GetUsername) where the data action is refreshed. Data refreshing is an asynchronous task, so it is not ensured that the data is already retrieved when assigning the result to the client variables.
A better option is to add an OnAfterFetch action to the GetUserNameFromServer data action and make all client variable assignments there.
In your UI you would use the Client variables to enable certain elements, but you have to make sure to do a proper role checking in your server/service actions as well.
Best
Stefan
Hi @Stefan Weber
This is another interesting approach that I didn't consider. I need to decide if I want to potentially expose my UI to users who are capable of manipulating client variables. I definitely need to do, as you said, a proper role checking in server actions.
Thank you for your reply!
Yes. That is exactly the point to consider. But everything on the client side can be changed. Either in local storage or by directly modifying the javascript code or its result. That is why UI manipulation is not a security measurement.
@Andrea Caselli
Is using a data action for each screen and block the right approach to manage UI visibility based on roles?
How can I optimize this process to avoid redundancy and improve efficiency?
What is the best way to securely manage role-based UI visibility?
If I create a server action for role checking, in which event (initialize, ready, render) should I call it?
Recommended Approach
Create a Server Action for Role Checking:
Call the Server Action on Session Start:
Use Session Variables or Client Variables:
Bind UI Elements to Role Variables:
Hi, Stefan
I was looking for a safe and high-performance solution to control UI visibility role-based and came across your solution here.
I implemented it this way (especially with the assignment after the OnAfterFetch event) and it works great.
In addition, I created a client action as a function that does nothing but evaluate the client variables and then return the Boolean result (simple if with assignment). I can now use this function for each screen and screen element (for example containers) to control the visibility.
This also creates the advantage that when the roles are changed or new additional roles are added, this can be converted centrally in the global client action.
And in addition the client variables can also be used for defining classes on elements (for to make them invisible for example) :
If( Client.Has_readOnly = True,"display-none","")
Thus, one control per screen is omitted and the end user authorizations can be queried stably by the client variables over the duration of the session.
Great solution!! Thank you for that!
Christine