I have a dashboard in Workshop that I want to make dynamic based on the user viewing it. For example:
I have a sales object.
User A is from Area A, and User B is from Area B.
I want the dashboard to show only sales data from Area A to users from Area A, and the same for other areas. What’s the best way to do this in Foundry? I was thinking of using a Restricted View with an auxiliary table, but I’m not sure if there’s an easier or better way."
Restricted views are indeed the way to go to provide granular, row level access to the object instances. You can permission the access through use attributes, group membership or organization markings and more, resulting into security policies. In general, you don’t need to use an additional auxiliary table, the data and rules can be read off from upstream transforms resulting into a dataset which gets permissioned away.
For documentation, you can start with [https://www.palantir.com/docs/foundry/object-permissioning/managing-object-security#granular-access-controls-in-the-foundry-ontology](https://Granular access controls in Foundry Ontology).
Bit of a teaser here, but long term, Foundry Ontology will provide security configuration which let’s you encode the security policies directly on the object types, eliminating the needs for a restricted view in between.
I agree with @alieskovsky restricted views are your way to go. However, there are two options you can set this up:
simple: use properties within your data like “Country” or “Customer” to be AND combined with a specific group that should have access to this row. This property based RLS can quickly be applied if you have only few groups. However, if you have many group (I would say 5+) or you expect that groups will change or groups have a very specific scope (like Country + Product Group + Customer) you will go crazy with this.
complex but scalable: Create just one “RLS_ID” array column through your pipeline, that holds all ids (e.g. foundry:user_id) that are allowed to see this row. The restricted view is then just simply doing a “current user:id” is in RLS_ID column.
This RLS_ID array is constructed from two files you maintain either within your use case or centrally in your org.
→ Roles: Defining which combinations of property values describe the scope of a role
→ User Role: which user has which role
Through second approach you can have central team (e.g. in your business/functions) managing the roles and users without having the need to always update restricted view policies. You provide them just the “engine”
Both of the above approaches are indeed correct based on the premise that you want to truly restrict access to the underlying data such that each end user can only see the data for, in this case, their region.
If instead you want something that’s more like a default filter, where the user can explore all of the data, but when they load the page they are only shown what’s in their region, there are ways to accomplish this as well.
In Workshop, you can create a string variable backed by a Multipass property of the current user:
If the regional information you need is actually a property on their account, then you can maybe access it directly as a custom property. Otherwise you’ll need to use the username or id to retrieve the information from wherever you have it available.
The pattern I use most often relies on having a Object Type that models employees or platform users with a property for their Multipass username, but you can also do this with a Typescript function that accesses the User object and reads of the relevant properties from their user profile or from some other source.
Hm @lrhyne, I frequently use your approach to target workshop designs/workflows to specific personas (user groups) by searching “is current user part of specific groups”. However, although restricting access to data only on an application level is technically an option, it is also kinda dangerous imo. If users happen to find their way to e.g. the object explorer, they would have access to all sales. Which is prevented through a restricted view backing the OT.
But for completeness of instructions, if you want to check if a user is member of a defined list of groups you can do the following steps:
create a static string array of “authorized group-ids”
get the array string variable of user → multipass → group ids
create a bool variable → variable transformation with first an array intersection of “authorized group ids” and “current user - all group ids”. And secondly just check if the resulting array is not null.