Pages

Tuesday, February 5, 2019

Einstein Analytics: Security Predicate setting

Einstein Analytics supports security predicates, a robust row-level security feature that enables you to model many different types of access controls on datasets. Einstein Analytics also supports sharing inheritance, to synchronize with sharing that’s configured in Salesforce, subject to certain limitations. If you use sharing inheritance, you must also set a security predicate to take over in situations when sharing settings can’t be honored.

This blog will discuss setting up a security predicate for a Dataset created from the CSV file. By default, when you load the CSV file to create a new dataset, the security predicate will be empty, which means everyone who has access to the dataset can see all rows.

We can build a security predicate even for CSV files that do not originally come from Salesforce, as long as there is an identifier that links between CSV files with Salesforce data. We can build a security predicate after the dataset is created in Einstein Analytics.

Syntax
<dataset column> <operator> <value>

Examples
'UserId' == "$User.Id"
  • UserId is the API name of the dataset
  • == is the operator
  • $User.Id this is the current Salesforce User ID when opening the dashboard or lens

If you check the above basic syntax again, then change the syntax to "$User.Id" == 'UserId', this syntax becomes invalid and will be rejected by the system. Even if the values are the same, the security predicate must always start with the dataset column and not the other way around.

You can use and && and or || logical operators in the security predicate
(‘Expected_Revenue’ > 4000 || ‘Stage Name’ == "Closed Won") && ‘isDeleted’ != "False"

Consider the following requirements for the predicate expression:
  • The expression is case-sensitive.
  • The expression cannot exceed 1,000 characters.
  • There must be at least one space between the dataset column and the operator, between the operator and the value, and before and after logical operators. This expression is not valid: ‘Revenue’>100. It must have spaces like this: ‘Revenue’ > 100.
  • Support string and numeric values, but not Boolean
  • If you are using custom fields in the user object, make sure the Insights Security User has read permission to the custom fields

How to create exceptions?
This means that a security predicate should not impact a group of Salesforce users. One simple idea is to add unique values, such as User Role ID, User Profile ID, or a custom field from the User object, to the dataset security predicate and to the data itself.

Scenario: All users with Profile = Executive are allowed to see all data; otherwise, they can only see data the same as user Territory. In this scenario, Territory is a custom field in the user object and is also available in the Dataset.
1. Get the Profile ID of the Executive Profile
2. Add Profile ID from (1) as a column to all rows in the CSV file before loading to Einstein Analytics
3. Load the CSV file to Einstein Analytics
4. Edit the dataset created and create a security predicate as follows

'Territory' == "$User.Territory__c" || 'Executive_ProfileId' == "$User.ProfileId"

The first part (in purple) allows users to see only data where the Territory in the dataset is the same as the Territory defined in the user object.
The second part (in green) allows all users with Executive Profile to see all data; that's why we use logic (||).


Using the same method, you can add Role as an exception too, just add another column and fill the Role Id to all rows. However, if you need to define more than 1 profile or 1 role, you need to keep duplicating the columns in the CSV file and add use || as the exception, e.g., 'Territory' == "$User.Territory__c" || 'Executive_ProfileId' == "$User.ProfileId" || 'Strategy_ProfileId' == "$User.ProfileId", I know this is not a pretty solution, but it works.


You can define a dataset security predicate by editing the dataset and entering a valid Security Predicate.

The system will check and reject if the security predicate syntax is invalid, such as "$User.Id" == 'UserId' (wrong order), also if the value does not exist, such as: 'UserId' == "$User.Field__c" (Field__c field does not exist in User object). However, the system will not validate and not reject if the column name does not exist, such as: 'UserField' == "$User.Id" (UserField does not exist in the dataset column).

Note:
1. If you replace data for an existing dataset, the security dataset defined will stay, including when you restore from the previous dataset. This also includes if you change the Security Predicate value in the dataflow register node, the security predicate in the dataset regenerate will stay, so you need to manually update it in the dataset.

2. Dataset column <dataset column> <operator> <value> could be a multi-value, for example: 'AccountTeam.UserId' == "$User.Id"
AccountTeam.UserId is a Lookup Multiple Values that result from an augment node, from User to Account Team. This security predicate allows any users in the Account Team for the ability to see the dataset rows.


Logical Operators
  • && for logical AND, for example: 'Stage Name' == "Closed Won" && 'isDeleted' != "False"
  • || for logical OR, for example: 'Expected_Revenue' > 4000 || 'Stage Name' == "Closed Won"


Comparison Operators
  • == : Equals, for example: 'Stage Name' == "Closed Won"
  • != : Not equals, for example: 'isDeleted' != "False"
  • < : Less than, for example: 'Revenue' < 100
  • <= : Less or equal
  • > : Greater than
  • >= : Greater or equal
in : true if the left operand exists in the list of strings substituted for a multivalue picklist (field value), for example: 'Demog' in ["$User.Demographic__c"]
In this example, Demographic__c is of type multiPicklistField. During evaluation, the multivalue picklist field is substituted by a list of strings, with 1 string per user-selected item.
Comma-separated lists are not supported within the square-bracket construct.


8 comments:

  1. Hi,
    I have flatter my dataset on Account in receipe. Now i need to check if the logged in User account is in that Heirachy than he should get access of the same Account. On security predicate i am trying to give the below formula but dataset is not returning any record. Can you please help me in identifying the issue with this

    'Id' == "$User.AccountId" || 'View_All_Data__c' == "$User.View_All_Data__c" ||
    "$User.AccountId" in 'ParentId_flatten_multiField'

    ReplyDelete
    Replies
    1. I think sec predicate does not support "in", try to change to ==

      Delete
  2. I have a requirement to use User related contact value in Security Predicate in Einstein Analytics. For every user, there will be a contact (Role Code) and I need to pull that value in Security Predicate.



    Instead of going with the Automated process and pulling the value on the User record, is there any way where I can directly pull child field value from the user in security Predicates (eg: $User.Contact.Role_Code__c)



    Can you please suggest how to achieve this?

    ReplyDelete
    Replies
    1. What do you mean with "child field value from the user"?

      Delete
    2. I mean, Contact is the child of User. Is there any way where I can directly pull Contact field value from the user (which is the child of user) in security Predicates

      Delete
    3. oh, never try that, what is the result of using "$User.Contact.Role_Code__c"

      Delete
  3. Hi, I want to define a Security Predicate where Logged-in users can see None record in the Dashboard. can you please suggest how to achieve this?

    'User.UserId' == "$User.Id" || 'User.Acc.Owner.Role.Roles' == "$User.UserRoleId" || 'User.Team.Role.Roles' == "$User.UserRoleId" || '$BEGEO_Security.BE_GEO_NAME' == "$None"

    ReplyDelete
    Replies
    1. what is None here mean? is it a value? or just a blank?

      Delete