The upcoming Summer '14 release notes
came out late last week. There were over 330 pages of new features and goodness. However, my favorite feature being announced by far is Custom Permissions (page 172 if you're interested).
What makes this feature one of the coolest ones I've worked on so far is that it enables customers and partners to define their own permissions while enabling administrators to still assign them the same way they assign any other permission on a profile or permission set.
Why use it?
- Customers can create permissions for their force.com apps
- Customers can create permissions that sync with an authorization directory service like Active Directory or LDAP
- IT can store custom metadata about their profiles and permission sets to help categorize them
- ISVs (Independent Software Vendors) can create permissions for their apps
- Scope Connected apps by retrieving only those permissions assigned to a user for that app without querying for all permissions assigned to the user for the organization
How does this work?
Often times, a salesforce developer will want to create an access check in their code that enables them to differentiate which users can access specific pieces of custom functionality. For instance, only administrators should be allowed access to the Permissioner tab and Visualforce page or only sales managers should be allowed to print the sales commission report.
There are a variety of ways to create access checks on the salesforce platform. You can re-use an existing access control such as a tab setting or Visualforce page access. However, for everything else, a salesforce developer would have to create something completely custom.
In the past, this has meant creating custom settings which are hierarchical in nature and administered separately from the rest of a user’s permissions. As a result, custom settings do not follow any of the normal behaviors associated with profile or permission set permissions like the ability for an administrator to easily assign them.
Custom permissions enable developers to define new access checks that can be assigned to users the same way as any other user permission: through the user’s permission set or profile. This enables developers to focus on their code, while enabling administrators to manage custom permissions the same way as they manage standard user, object, field, and other kinds of permissions for users. That way the administrator can use point-and-click whereas the developer can use code.
There are two ways custom permission access can be queried in Summer '14 to determine if a user has access:
- through SOQL using the SetupEntityAccess and CustomPermissions sObjects to answer whether any user has access to a specific or arbitrary custom permission.
- through the standard Connected Apps flow and the identity service to answer what specific custom permissions the current user has when they authenticate into their connected app.
Usage 1: Use SOQL to determine access with the API
In setup, create a custom permission under Build | Develop | Custom Permissions.
Query in Workbench
using a Developer Edition organization in Summer '14 for all permission sets assigned the 'Approver' permission:
SELECT Id, DeveloperName,
(select Id, Parent.Name, Parent.Profile.Name from SetupEntityAccessItems)
WHERE DeveloperName = 'Approver'
Query for all permission sets and profiles with custom permissions:
SELECT Assignee.Name, PermissionSet.Id, PermissionSet.Profile.Name, PermissionSet.isOwnedByProfile, PermissionSet.Label
IN (SELECT ParentId
WHERE SetupEntityType = 'CustomPermission')
Query for all SetupEntityAccess rows with custom permissions:
SELECT Id,ParentId,Parent.Name, SetupEntityId FROM SetupEntityAccess
IN (SELECT Id
WHERE isOwnedByProfile = false)
Usage 2: Check access to using Apex
I've heard this use case frequently from customers. Rather than receive an insufficient privileges message after clicking on a button, you can choose whether to display the button based on the user's assigned custom permissions, thereby preventing users from getting an insufficient privilege message after the event.
We determine the permissions that a user has been assigned by first querying all of the Setup Entity Access rows tied to the user’s assigned permission sets where there is at least one row of type ‘CustomPermission’:
access =[SELECT SetupEntityId FROM SetupEntityAccess WHERE SetupEntityType='CustomPermission' AND ParentId IN (SELECT PermissionSetId FROM PermissionSetAssignment WHERE AssigneeId=:userId)];
This usage pattern is more powerful than straight SOQL because it can string the multiple queries together into something that answers whether the user has access to specific custom permissions.
This feature will be in Developer Preview in Summer '14 which means it will automatically be enabled for all Developer Edition organizations for people to play with and provide feedback for what they want to see.