Monday, December 25, 2017

Custom Permissions : Way to control user access to different functionality in Salesforce

Problem Statement

There is a very common scenario in which admin has to configure different validation rules, workflow rules which fires based on User Id or Profile Id.

Consider below mentioned scenarios:
  • Position (Custom Object) records can be closed by user belonging to specific profile.
  • You have created a VF page where you display specific section to users based on profile. 

In both scenarios, you have to check for profile Id in validation rule as well as in VF (to rendered specific section).





Now after some time if you have to enable the above mentioned functionality to new profile or to specific user then, you have to modify the validation rule as well as your VF page code.

Solution

You can use custom permission for these kind of scenarios.

Custom permission is just a record which can be referenced in validation rule, workflow rules, VF, Apex etc. You can assign custom permission to profile or permission set (similar way in which we assign VF page and Apex class).

Now you can check custom permission in validation rules and VF by using global $Permission variable.

Steps to use custom permission and use as per above scenario:
  • Create custom permission (Navigate to Set Up--> Develop--> Custom Permissions).
  • Create new custom permission.

  • Add custom permission to profile or permission set(navigate to Enable custom permission section).

  • Modify the validation rule to and VF to refer custom permission instead of profile id.



So custom permission help us to control different functionality in salesforce to different users. If you have to enable functionality for single user then add custom permission to permission set and then add that permission set to user.

Alternate Approach

All admins/developers were using custom setting to control functionality for different users but after launch of custom permission, jobs of developer or admin will be easy.

Custom Permission in Apex

You can use below static method to find out list of user who have permission for custom permission:


public static List<User> findUsersWithCustomPermission(String customPermissionname)
{
    List<user> userList = new List<User>();
Set<Id> permissionSetIds = new Set<Id>();
    for (SetupEntityAccess access : [ SELECT ParentId FROM SetupEntityAccess 
WHERE SetupEntityId IN ( SELECT Id FROM CustomPermission 
            WHERE DeveloperName = :name)]) {
        permissionSetIds.add(access.ParentId);
    }
if(permissionSetIds.size()>0){
userList = [SELECT Username FROM User 
WHERE Id IN (SELECT AssigneeId FROM PermissionSetAssignment
WHERE PermissionSetId IN :permissionSetIds)];
}
    return userList;
}

Hope this will help!!!

Saturday, December 16, 2017

Insufficient Privileges : How to troubleshoot record access issue in Salesforce

"Insufficient Privileges" is common error which appears on user interface if user tries to access/edit a record. As we know that apart from OWD and profile, record can be shared by using sharing rules, role hierarchy, manual sharing or apex sharing.



If some user report this kind of issue, then instead of checking all sharing options, we can directly run below query to check what kind of access that user have for given record.

SELECT RecordId, HasReadAccess, HasTransferAccess, MaxAccessLevel, HasAllAccess, HasDeleteAccess, HasEditAccess FROM UserRecordAccess  WHERE UserId = “005xxxxxxxxx”AND RecordId = “001xxxxxxxx”

Where 005xxxxxxxxx is user id and  001xxxxxxxx is record Id.

HasAllAccess Indicates whether a user has all access–read, edit, delete, and transfer—to the record (true) or not (false).
HasReadAccess, HasEditAccess , HasDeleteAccess ,HasTransferAccess return Boolean value.
MaxAccessLevel return access level like None, read, Edit,Delete,Transfer and All.


This query will help to understand whether user has access to record or not. After that you can check different options (sharing rules, role, apex sharing etc.) to find out why that user is not having access to record.

Hope this will help!!!

Tuesday, December 12, 2017

Formatting and Localizing dates in javascript in Lightning

Date formatting in javascript

AuraLocalizationService JavaScript API provides methods for localizing dates and formatting.

Use the formatDate() to format date by providing format string as second argument.

formatDate (String | Number | Date date, String formatString)

Use $A.localizationService to use the methods in AuraLocalizationService.

Below are few examples of format string and their output:

var now = new Date();
var dateString = "2017-12-12";

// Returns date in the format "Dec 12, 2017"
console.log($A.localizationService.formatDate(dateString));

// Returns date in the format "2017 12 12"
console.log($A.localizationService.formatDate(dateString, "YYYY MM DD"));

// Returns date in the format "December 12 2017, 11:03:47 PM"
console.log($A.localizationService.formatDate(now, "MMMM DD YYYY, hh:mm:ss a"));

// Returns date in the format "Dec 12 2017, 11:03:57 PM"
console.log($A.localizationService.formatDate(now, "MMM DD YYYY, hh:mm:ss a"));

Refer below link for more details:
tokens supported in format string

Localization

Lightning framework provides client-side localization support on input/output elements. This helps in customize the date and time format.

For example, below code will display date in Europe/Berlin timezone (Dec 13, 2017 2:17:08 AM)

<aura:component>
    <ui:outputDateTime value="2017-12-13T02:17:08.997Z"  timezone="Europe/Berlin" />
</aura:component>

To customize date and time format use, lightning:formattedDateTime.

The attributes on lightning:formattedDateTime helps you to control formatting at a granular level. For example, you need to display the date using the MM/DD/YYYY format, then use below code:

<lightning:formattedDateTime value="{!v.datetimeValue}" timeZone="Europe/Berlin" year="numeric" month="numeric" day="numeric"/>


datetimeValue can be set in controller code either in doInit or any other function as mentioned below:

var date = new Date();
component.set("v.datetimeValue", date)

Locale Information on client side controller

  • $A.get("$Locale.timezone")  : This will return timezone like Europe/Paris, Europe/Berlin etc.
  • $A.get("$Locale.currency") : This will return org currency locale like "$", "¥" etc.

Hope this will help!!!!