10 June 2014

Capturing user information on a Visualforce page using Javascript


I was working with a force.com developer who added the Boomerang JavaScript to his organization's pages in order to track browser performance. As a result, when he received a call from a user in Germany claiming that there was a slow down in app performance, he could correlate the Boomerang performance data to the actual user's information. This is a handy tool for tracking app performance in the browser for supporting users.

However, he was having problems querying the user information necessary to correlate the user in Germany to the data he was collecting from the Boomerang script. He needed a way to collect both performance data as well as information about the user.

Visualforce makes this pretty easy already with data binding. Especially since he was also tracking non-Visualforce pages where data binding isn't as easy, I decided to look at other ways to surface that information through JavaScript to make it easy to collect with the Boomerang performance metrics.

There are a couple useful techniques including using the AJAX toolkit, JQuery, and native JavaScript querying cookie information. Okay, the last technique wasn't that successful since we obfuscate user information in the cookie on Visualforce pages but it does become more interesting when adding a performance tracking script to non-Visualforce pages. 

If you want to take a look at the code I wrote for it, you can check it out in my Github repository: https://github.com/atorman/userInfo


03 June 2014

Choose your own adventure with custom permissions



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?

  1. Customers can create permissions for their force.com apps
  2. Customers can create permissions that sync with an authorization directory service like Active Directory or LDAP
  3. IT can store custom metadata about their profiles and permission sets to help categorize them
  4. ISVs (Independent Software Vendors) can create permissions for their apps
  5. 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:
  1. through SOQL using the SetupEntityAccess and CustomPermissions sObjects to answer whether any user has access to a specific or arbitrary custom permission. 
  2. 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)
FROM CustomPermission
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
FROM PermissionSetAssignment
WHERE PermissionSetId
IN (SELECT ParentId
    FROM SetupEntityAccess
    WHERE SetupEntityType = 'CustomPermission')
Query for all SetupEntityAccess rows with custom permissions:

SELECT Id,ParentId,Parent.Name, SetupEntityId FROM SetupEntityAccess
WHERE SetupEntityType='CustomPermission'
AND ParentId
IN (SELECT Id
    FROM PermissionSet
    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 sample app was written by John Brock and can be downloaded from his Github repo: https://github.com/john-brock/Custom-Permissions to jump start your custom permission experience.

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.