Monday, August 14, 2017

Salesforce Security: Concepts

Salesforce Security Layers

  1. Organization: Login IP ranges, Login hours; when where how can a user login to the org
  2. Object: Object-level security; what action can a user have on a specific object
  3. Field: Field-level security; what field can a user read/edit
  4. Record: Sharing; what records can a user access

From an architect’s perspective, data access in Salesforce falls into 2 main categories:

  • Object-level access, which includes field-level access
  • Record-level access

Profiles and Permission Sets determine the object level security access to each object in Salesforce.

Read object-level security doesn't give Read access to all account records, it only gives the ability to read account records.

Profiles

A profile contains the baseline permissions of a user, and each user is assigned only 1 profile. It defines a user’s ability to peform different functions, access records, and the way the records are displayed. Profiles are tied to a user license.

Enhanced profile user interface lets you search for any setting and it can take you to this setting page. This can be set up in Setup —> User Management Settings.

Permission Set

A permission set is a collection of permissions that can be assigned to a user extending users’ functional access without changing their profiles. Users can have only one profile but they can have multiple permission sets.

Permission Set Group (PSG): It is a collection of permission sets. Users with a PSG receive the combined permissions of all the permission sets in the group. You can also remove individual permissions from a group with the muting feature, to further customize the group. Please note that a PSG can only contain 1 muting permission set that is created within the group.

A profile doesn’t provide the appropriate mechanism for scalable permission assignment. Permission sets and PSG are used to avoid the creation of many different profiles that are only slightly different.

List of permissions that are missing in a permission set

  • Page layout assignment
  • Login hours and Login IP ranges
  • Desktop client access
  • Session settings
  • Password policies
  • Delegated Authentication
  • 2-factor authentication with SSO
  • Organization-wide email addresses are assignable by profiles only
  • Default record type per object
  • Profile specific search layouts

Record Ownership

Every record must be owned by a single user or queue. The owner has access to the record, based on the object settings of the owner’s profile. Queue members and users higher in a role hierarchy can access queues from list views and take ownership of records in a queue.

Record ownership and full access are synonymous and interchangeable and provide the user with the highest level of access to a record.

Sharing (record-level access)

Record-level access determines which records a user can see for a specific object. Object-level security should allow to access this record.

  • Organization-Wide Defaults
  • Role Hierarchy
  • Sharing Rules
  • Manual Sharing
  • Team Sharing
  • Territory Hierarchy Access

For each object, the View All and Modify All permissions ignore sharing rules and settings.

View All Data and Modify All Data administrative permissions apply to all objects’ records.

Organization-wide Defaults (OWD)

OWD sharing settings specify the default level of access users have to each others’ records. OWD are the only way to restrict record access. You use OWD settings to lock down your data to the most restrictive level, and then use other sharing tools to selectively give access to other users. For each object, the OWD can be:

  • Private
  • Public read only
  • Public read/write
  • Public read/write/transfer: available for cases and leads
  • Public full access: available for campaigns
  • Controlled by parent

Role Hierarchy

Users can access the data of all the users directly below them in the hierarchy (subordinates) using the Grant Access Using Hierachies option. Managers gain as much access as their subordinates. This access applies to records owned by users, as well as records shared with them.

Public Group

A public group is a collection of individual users, roles, territories, and so on, that all have a function in common.

Groups can be nested (group A nested into group B), but keep in mind that nesting has an impact on group maintenance and performance due to group membership calculation. Don’t nest more than 5 levels. As a best practice, keep the total number of public groups for an organization to 100,000.

Sharing Rules

They allow for exceptions to OWD settings and the role hierarchy that give additional users access to records they don’t own. There are 2 types of sharing rules:

  1. Ownership-based: records are shared following criteria based on their owner. For example, share all opportunities owned by user A with Group B. As a best practice, keep the number of ownership-based rules per object to 1000.
  2. Criteria-based: they provide access to records based on the record’s field values.

Manual Sharing

Gives user the flexibility to share specific records with users that need to see them. To grant access to a record, you must be one of the following users:

  • The record owner
  • A user in a role above in the hierarchy
  • Any user granted Full Access to the record
  • An administrator

Team Sharing

For accounts, opportunities and cases, record owners can use teams to allow other users access to their records. The record owner adds team members and specifies the level of access each team member has to the record, so that some team members can have read-only access and others can have read-write access. The record owner can also specify a role for each team member.

Share This:    Facebook Twitter

Sunday, August 13, 2017

Using Dynamic Apex to retrieve Picklist Values

USECASE: Fetch the picklist values from Industry field of Account sObject.

List<SelectOption> options = new List<SelectOption>();

Schema.DescribeFieldResult fieldResult = Account.Industry.getDescribe();
List<Schema.PicklistEntry> picklistEntries = fieldResult.getPicklistValues();

for (Schema.PicklistEntry picklistEntry : picklistEntries) {
    options.add(new SelectOption(picklistEntry.getLabel(), picklistEntry.getValue()));
}

return options;

OR

List<SelectOption> options = new List<SelectOption>();

Map<String, Schema.SObjectField> fieldMap = Account.getSObjectType().getDescribe().fields.getMap();
List<Schema.PicklistEntry> picklistEntries = fieldMap.get('Industry').getDescribe().getPickListValues();

for (Schema.PicklistEntry picklistEntry : picklistEntries) {
    options.add(new SelectOption(picklistEntry.getLabel(), picklistEntry.getValue()));
}

return options;

Share This:    Facebook Twitter

DescribeSObjectResult: Check whether the object is Custom or Standard


List<String> allCustomObjsList = new List<string>();
List<String> allStandardObjsList = new List<string>();

for(Schema.SobjectType obj : Schema.getGlobalDescribe().values()) {
    Schema.DescribeSobjectResult objResult = obj.getDescribe();
    if(objResult.isCustom()) {
        String strObjName =objResult.getname();
        allCustomObjsList.add(strObjName);
    }
    else {
        String strObjName =objResult.getname();
        allStandardObjsList.add(strObjName);
    }
}

System.debug('Custom Objects List: ' +allCustomObjsList);
System.debug('Standard Objects List: ' +allStandardObjsList);

If you need to check for a specific object, execute the below code:
Schema.DescribeSObjectResult describeAccount = Schema.sObjectType.Account;
System.debug(describeAccount.isCustom());

Similarly you can use other methods for describing sObjects, the list of which can be found below:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_sobject_describe.htm

Share This:    Facebook Twitter

Fetch recordType Name and recordTypeId without SOQL

To avoid SOQL Limit we can use dynamic apex to get RecordTypeId. We can get a particular RecordTypeId of a particular sObject or get all recordTypeid of one sobejct in a map.

global class RecordTypeUtils {
    
    //Method to get the recordTypeId 
    public static Id recordTypeId(string obj,string recName){
        Id recTypeId;
        if(obj!= null && recName != null){
            recTypeId= Schema.getGlobalDescribe().get(obj).getDescribe().getRecordTypeInfosByName().get(recName).getRecordTypeId();
        }  
        return recTypeId;  
    }
    
    //Method to get the map of recordType Name as key and recordTypeId as value 
    public static Map<String,Id> recordTypeMap(string obj){
        Map<String,Id> recTypeNameWithIdMap=new Map<String,Id>();
        if(obj!= null){
            for(Schema.RecordTypeInfo recInfo : Schema.getGlobalDescribe().get(obj).getDescribe().getRecordTypeInfosByName().values()){
                recTypeNameWithIdMap.put(recInfo.getName(),recInfo.getRecordTypeId());
            }
        }
        return recTypeNameWithIdMap;
    } 
}

I created a record type "NewLabel" on Account object. Enter the below Apex code in Execute Anonymous window and check the output:

Map<String,Id> recTypeIdMap=RecordTypeUtils.recordTypeMap('Account');
System.debug(recTypeIdMap);
Id recId=RecordTypeUtils.recordTypeId('Account','NewLabel');
System.debug(recId);

Id recordTypeId = Schema.SObjectType.Account.getRecordTypeInfosByName().get('NewLabel').getRecordTypeId(); 
System.debug(recordTypeId);

Note that values of recId and recordTypeId in your output is same.

Check the link below to check a utility class that performs the query against the RecordType object
https://interactiveties.com/blog/2016/recordtype-utility-class.php
Share This:    Facebook Twitter

Saturday, August 12, 2017

Apex: Get sObject details using ID

Id id = 'a0M7F000000qXgg';
Schema.sObjectType objType = id.getSObjectType();
Schema.DescribeSObjectResult objDescribe = objType.getDescribe();

System.debug(objDescribe.getName());

Similarly, you can get other sObject details using the methods described in the link below:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_sobject_describe.htm
Share This:    Facebook Twitter

Total Pageviews

My Social Profiles

View Sonal's profile on LinkedIn

Tags

__proto__ $Browser Access Grants Accessor properties Admin Ajax AllowsCallouts Apex Apex Map Apex Sharing AssignmentRuleHeader AsyncApexJob Asynchronous Auth Provider AWS Callbacks Connected app constructor Cookie CPU Time CSP Trusted Sites CSS Custom settings CustomLabels Data properties Database.Batchable Database.BatchableContext Database.query Describe Result Destructuring Dynamic Apex Dynamic SOQL Einstein Analytics enqueueJob Enterprise Territory Management Enumeration escapeSingleQuotes featured Flows geolocation getGlobalDescribe getOrgDefaults() getPicklistValues getRecordTypeId() getRecordTypeInfosByName() getURLParameters Google Maps Governor Limits hasOwnProperty() Heap Heap Size IIFE Immediately Invoked Function Expression Interview questions isCustom() Javascript Javascript Array jsForce Lightning Lightning Components Lightning Events lightning-record-edit-form lightning:combobox lightning:icon lightning:input lightning:select LockerService Lookup LWC Manual Sharing Map Modal Module Pattern Named Credentials NodeJS OAuth Object.freeze() Object.keys() Object.preventExtensions() Object.seal() Organization Wide Defaults Override PDF Reader Performance performance.now() Permission Sets Picklist Platform events Popup Postman Primitive Types Profiles Promise propertyIsEnumerable() prototype Query Selectivity Queueable Record types Reference Types Regex Regular Expressions Relationships Rest API Rest Operator Revealing Module Pattern Role Hierarchy Salesforce Salesforce Security Schema.DescribeFieldResult Schema.DescribeSObjectResult Schema.PicklistEntry Schema.SObjectField Schema.SObjectType Security Service Components Shadow DOM Sharing Sharing Rules Singleton Slots SOAP API SOAP Web Services SOQL SOQL injection Spread Operator Star Rating stripInaccessible svg svgIcon Synchronous this Token Triggers uiObjectInfoApi Upload Files VSCode Web Services XHR
Scroll To Top