Monday, February 18, 2019

Using Emoji in Salesforce

Nowadays, emoji is widely used from mobile device messaging, email, until more serious business applications such as Salesforce. If you don't have emoji keyboard, you can copy varieties of emoji from the internet, one of the most famous is

As per this article 5 Ways You Can Use Emoji, you can use emoji in Salesforce, from:
- Chatter Post
- Validation Rules
- Help text
- Formula field
- Picklist values
- Field value
- List view

Emoji in Salesforce works in both Lightning and Chatter.


Tuesday, February 5, 2019

Einstein Analytics: Security Predicate for CSV file

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 security predicate for Dataset created from CSV file. By default, when you load CSV file to create a new dataset, the security predicate will be empty, which mean everyone has access to the dataset can see all rows.

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

<dataset column> <operator> <value>

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

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

You can use and and or logic 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.

How to create exceptions?
This mean, a group of Salesforce users should not be impacted by security predicate. One of the simple ideas is to add unique values, such as User Role Id, or User Profile Id, or custom field from 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, only see data the same with user Territory. In this scenario, Territory is a custom field in user object and also available in the Dataset.
1. Get the Profile Id of Executive Profile
2. Add Profile Id from (1) as a column to all rows in CSV file before loading to Einstein Analytics
3. Load the CSV file to Einstein Analytics
4. Edit the dataset created and create security predicate as follow

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

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

Using the same method, you can add Role as 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 duplicate the columns in CSV file 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 dataset security predicate by edit the dataset and enter 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 is 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).

If you replace data for an existing dataset, the security dataset defined will be stayed, including when you restore from the previous dataset.


Page-level ad