Showing posts with label Apex. Show all posts
Showing posts with label Apex. Show all posts

Sunday, October 20, 2019

Enforce Field-Level Security Permissions for SOQL Queries

This post will explain how to enforce field level security permissions for SOQL queries,

  • In Spring' 19 release salesforce introducing this fantastic feature, WITH_SECURITY_ENFORCED clause, you can use this to enable checking for field- and object-level security permissions on SOQL SELECT queries, including subqueries and cross-object relationships.
  • If you include a field in a SQOL query (Without WITH SECURITY_ENFORCED Clause) and a user doesn’t have access to that field, the field will be returned and can be used by the code without any exception, but the data to that user should not have access.
  • If you use WITH SECURITY_ENFORCED clause for same SOQL Select query, it will throw exception and no data will be returned.
  • The WITH SECURITY_ENFORCED clause is only available in Apex. Using WITH SECURITY_ENFORCED in Apex classes or triggers with an API version earlier than 45.0 is not recommended.

Below are some of the examples.

1. If on the Opportunity object, suppose field-level security for  Stage , Amount, and LeadSource is hidden, it will throw an exception insufficient permissions and no data will return.

String query = ’Select Id, Name, ‘;
if(Schema.sObjectType.Opportunity.fields.Amount.isAccessible()){
query += ‘Amount, ’;
} else{
//Exception handling code will go here
}
if(Schema.sObjectType.Opportunity.fields. LeadSource.isAccessible()){
query += ‘LeadSource, ’;
}
if(Schema.sObjectType.Opportunity.fields.StageName.isAccessible()){
query += ‘StageName, ’;
}
query = query.subString(0, query.length()-2);
query += ‘ FROM Opportunity’;
List<Opportunity> oppty = Database.query(query);
And after this awesome feature introduced, developers need to write below lone of code.
List<Opportunity> oppty = [SELECT Id, Name, LeadSource ,StageName, Amount FROM Opportunity WITH SECURITY_ENFORCED];

2. If field access for Website is hidden, this query throws an exception indicating insufficient permissions.

List<Account> acct = [SELECT Id, parent.Name, parent.Website
FROM Account WITH SECURITY_ENFORCED]

How to use in Apex Method

In below code example, the comparison can be understand that how the field
accessibility were getting checked before introduction of this awesome feature.

Checking field accessibility before this feature:

 if (Schema.SObjectType.Contact.isAccessible()
            && Schema.SObjectType.Contact.fields.Name.isAccessible()
            && Schema.SObjectType.Contact.fields.Secret_Key__c.isAccessible()){
            List results = [SELECT id, Name, Secret_Key__c FROM Contact WHERE Id = :recordId];
            if (!results.isEmpty()) {
                result = results[0];
            }
        } else{
        throw new SecurityException('You don\'t have access to all contact fields'); }

Checking field accessibility after this feature:

try
{
List results = [SELECT id, Name, Secret_Key__c FROM Contact WHERE Id = :recordId 
WITH SECURITY_ENFORCED];
if (!results.isEmpty()) {
result = results[0];
}
}
catch( System.QueryException exception)
{
     throw new SecurityException('You don\'t have access to all contact fields'); }

Wednesday, May 9, 2018

Build URL to display a case using case number instead of Salesforce CaseID

This can be implemented using below code.

Custom label:  
Name: Case_Number_Details

Value: Please enter the valid 8 character Case Number (e.g. 00123456) after the equal sign in the URL above to view the case details.


Visualforce Page:


<apex:page controller="GetCaseByNumber" title="Get Case By Number" showHeader="false">

  <script>

      if ("{!CaseQuery}".length > 0) {

          if ("{!CaseQuery}" != "<apex:outputText value="{!$Label.Case_Number_Details}"/>" && "{!CaseQuery}" != "You Must Supply a Case Number") window.location = "/{!CaseQuery}";

      }

  </script>

  <h1 style="display:block;margin:25px;font-size:16px;">{!CaseQuery}</h1>


</apex:page>


Apex Class:


public class GetCaseByNumber {

    public static String getCaseQuery () {
       String caseNumberDetails = Label.Case_Number_Details;

        string caseNumber = ApexPages.CurrentPage().getParameters().get('CaseNumber');
        List <Case> c = [SELECT Id FROM Case Where CaseNumber =: caseNumber];
        if (c.size()>0) {
            return string.valueOf(c[0].Id);
        }
        else return caseNumberDetails;

    }    

}

Apex test Class:



private class GetCaseByNumberTest {
    
    static testmethod void TestAccdata(){ 
        Profile prof = [select id from profile where name='System Administrator'];    
        User us      = new User(alias = 'tuser', email='TestUser@testingorg.com',    
                                emailencodingkey='UTF-8', lastname='TestingUser', languagelocalekey='en_US', 
                                localesidkey='en_US', profileid = prof.Id,   
                                timezonesidkey='America/Los_Angeles', username='TestUser@testingorg.com');
        insert us;  
        System.runAs (us) { 
            Account ac = new Account(Name    ='Test', OwnerId  =us.Id);            
            insert ac;
            
            
            Contact cn  = new Contact (FirstName  = 'Test', LastName = 'Test',AccountId = ac.Id,email='testcase@org.com');
            insert cn;
            
            Test.startTest();
            string RTID = [select id from RecordType where SobjectType = 'Case' and Name = 'Support Case'].Id;
            System.assertNotEquals(null,RTID);
            
            case c = new Case(AccountId=ac.Id ,ContactId =  cn.Id,Status='New',Origin='Phone',RecordTypeId = RTID,Subject = 'TestCase',Description ='Test',Product_Type__c = 'My Product);
            
            insert c;
            PageReference myVfPage = Page.getCaseByNumber;
            Test.setCurrentPage(myVfPage);
           ApexPages.currentPage().getParameters().put('CaseNumber',ApexPages.currentPage().getParameters().get(c.CaseNumber));
            
            GetCaseByNumber controller = new GetCaseByNumber();
            GetCaseByNumber.getCaseQuery();
            
            Test.stopTest();
            
        }

    }



Friday, November 10, 2017

How to Convert String to sObject using Apex in Salesforce

Below is the sample code can be used to Convert String to sObject using Apex.

String str = 'Account';
sObject objct = Schema.getGlobalDescribe().get(str).newSObject();
objct.put('Name', 'My Account');
objct.put('Description', 'Description of My Account');
System.debug('sObject - ' + objct);
Below is the output of this code.

SOQL Query to Get the CreatedBy and LastModifiedBy User Name


Below SOQL query can be used to get the CreatedBy and LastModifiedBy User Name


SELECT Id, Name, CreatedBy.FirstName, CreatedBy.LastName, CreatedBy.Name, LastModifiedBy.FirstName, LastModifiedBy.LastName, LastModifiedBy.Name FROM Object__c

Note: Object__c, you can replace for the object you want to get these data.

Tuesday, October 31, 2017

AuraHandledException

From Apex class:

 @AuraEnabled
    public static List<Account> fetchAccount() {
        throw new AuraHandledException('User-defined error');

    }

From client-side controller:

doInit: function(component, event, helper) {
        var action = component.get('c.fetchAccount');
        action.setParams({ firstName : cmp.get("v.firstName") });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set('v.Accounts', response.getReturnValue());
            }
            else if (component.isValid() && state === "ERROR") {
                console.log("Error Message: ", response.getError()[0].message);
            }
        });
        $A.enqueueAction(action);
    }


How to Select All Fields with SOQL in Apex

1. Query All Fields for a Known Record ID:

ID recordId = '5001a00000CgCE2';

DescribeSObjectResult describeResult = recordId.getSObjectType().getDescribe();

List<String> fieldNames = new List<String>( describeResult.fields.getMap().keySet() );

String query =
  ' SELECT ' +
      String.join( fieldNames, ',' ) +
  ' FROM ' +
      describeResult.getName() +
  ' WHERE ' +
      ' id = :recordId ' +
  ' LIMIT 1 '
;

// return generic list of sobjects or typecast to expected type
List<SObject> records = Database.query( query );

System.debug( records );

2. Query All Fields for All Records

The same concept as above but we don’t have a specific record ID, so we need to determine the sobjectype by explicitly specifying the object we’ll query on.

// without an ID, simply specify the object to then derive the sobject type
DescribeSObjectResult describeResult = Account.getSObjectType().getDescribe();

List<String> fieldNames = new List<String>( describeResult.fields.getMap().keySet() );

String query =
  ' SELECT ' +
      String.join( fieldNames, ',' ) +
  ' FROM ' +
      describeResult.getName()
;

// return generic list of sobjects or typecast to expected type
List<SObject> records = Database.query( query );

System.debug( records );

Friday, October 13, 2017

JavaScript in Strict Mode

JavaScript code that runs in a browser can access a user's private information. To protect this information, LockerService requires you to use ECMAScript (ES5) strict mode, and enforces it in your code. This mode makes it easier to write secure JavaScript. A few code tweaks to comply with ES5 can substantially reduce the need for checking data at runtime.

Here’s a simple example of how strict mode prevents JavaScript from traversing the call-stack and modifying other functions. Without strict mode, the following function would have returned the name of the function that called primaryFunction().

JavaScript code:
function primaryFunction() {
  'use strict'
  console.log("The function calling the current method is: “+ primaryFunction.caller.name);
}
function callerFunction() {
  return primaryFunction(); 
}
callerFunction();

Output:
Uncaught TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
at primaryFunction (<anonymous>:3:72) at callerFunction (<anonymous>:6:10) at <anonymous>:8:1

Strict mode restricts access to several other entities. When it is enforced, you can no longer reference the window object through the JavaScript variable this, for example. These restrictions eliminate a lot of potential security vulnerabilities.

Monday, April 17, 2017

List of Annotations in Salesforce Apex

Usually Annotation means which will specifies the behavior or modifies the way how the particular class or method behaves in salesforce. Based on annotations the functionality or behavior and usage of particular class or method we can simply identify.

Each annotation will starts with '@' symbol and followed by name of the annotation
To declare a method/class with annotations it must be declared immediately before method/class

List of Available Annotations in Apex:


  • @isTest
  • @InvocableMethod
  • @InvocableVariable
  • @future
  • @AuraEnabled
  • @ReadOnly
  • @RemoteAction
  • @TestSetup
  • @TestVisible
  • @Deprecated

Apex REST annotations:

  • @RestResource(urlMapping='/yourUrl')
  • @HttpDelete
  • @HttpGet
  • @HttpPatch
  • @HttpPost
  • @HttpPut

How To Allow Only Numbers in Phone Number Field in Visual Force Page

If your trying to restrict your phone number field to accept only Numbers in visual force page you can use the below simple JavaScript code to achieve this easily.
<script>

function isNumber(evt) {
        evt = (evt) ? evt : window.event;
        var charCode = (evt.which) ? evt.which : evt.keyCode;
        if (charCode > 31 && (charCode < 48 || charCode > 57)) {
            return false;
        }
}

</script>

<apex:inputfield value="{!c.Phone__c}" id="boPhone" onkeypress="return isNumber(event)"/>

Friday, April 14, 2017

What is difference between JavaScript Remoting and Remote Objects

JavaScript Remoting and Remote Objects offer similar features, and both are useful tools for creating dynamic, responsive pages. They have some important differences that you should consider before choosing which to use.

In general, Remote Objects is well-suited to pages that need to perform only simple Create-Read-Update-Delete, or “CRUD”, object access. JavaScript Remoting is better suited to pages that access higher-level server actions. Remote Objects lets you get up and running quickly without a lot of ceremony, while JavaScript Remoting is suited for more complex applications that require some up front API-style design work.

Visualforce Remote Objects:

1. Makes basic “CRUD” object access easy
2. Doesn’t require any Apex code
3. Supports minimal server-side application logic
4. Doesn’t provide automatic relationship traversals; you must look up related objects yourself

JavaScript Remoting:

1. Requires both JavaScript and Apex code
2. Supports complex server-side application logic
3. Handles complex object relationships better
4. Uses network connections (even) more efficiently

What is difference between JavaScript Remoting and 

The <apex:actionFunction> component also lets you call controller action methods through JavaScript.
In general, <apex:actionFunction> is easier to use and requires less code, while JavaScript remoting offers more flexibility.

Here are some specific differences between the two.
The <apex:actionFunction> tag:

 1. lets you specify rerender targets
 2. submits the form
 3. doesn’t require you to write any JavaScript
JavaScript remoting:

1. lets you pass parameters
2. provides a callback
3. requires you to write some JavaScript

How to check If Chatter is enabled or not for current Org using APEX

Below code can be used to check if chatter is enabled or not for
current org by finding the "FeedItem" is exists or not in org.

Map<String,Schema.SObjectType> globaldesc = Schema.getGlobalDescribe(); 
if(globaldesc.containsKey('FeedItem')){
   system.debug('Enabled!');
}
else{
   system.debug('Disabled!');
}

Thursday, April 13, 2017

How to find out which fields are changed on the record

elwo is the code which can used to identify which field is changed on the record using sobject methods.

public  class FieldsController {
   list<string> listAPIfields = new list<string>();
            Map <String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
            Map <String, Schema.SObjectField> fieldMap = schemaMap.get('Account').getDescribe().fields.getMap();
            for(Schema.SObjectField sfield : fieldMap.Values()){
                 schema.describefieldresult dfield = sfield.getDescribe();
                 if(dfield.isUpdateable()){
                    listAPIfields.add(dfield.getname());
                 }
            }
            system.debug('****listAPIfields'+listAPIfields);
            for(Account objAccount:lstNew){
                sobject sobjNew = objAccount;
                sobject sobjOld = mpOld.get(objAccount.id);
                for(string strfield:listAPIfields){
                    if(sobjNew.get(strfield)!=sobjOld.get(strfield)){
                        system.debug('***********FIELD MODIFIED'+strfield);
                    }
                }
            }
            }

What is Skinny Tables and how does it applied on For Large Data Volumes

Salesforce creates skinny tables to contain frequently used fields and to avoid joins, and it keeps the skinny tables in sync with their source tables when the source tables are modified. To enable skinny tables, contact Salesforce.com Customer Support.
For each object table, Salesforce maintains other, separate tables at the database level for standard and custom fields. This separation ordinarily necessitates a join when a query contains both kinds of fields. A skinny table contains both kinds of fields and does not include soft-deleted records.
This table shows an Account view, a corresponding database table, and a skinny table that would speed up Account queries.

Need to contact Salesforce Customer Support or your Account Manager to enable skinny tables.

It can be created on custom objects, and on Account, Contact, Opportunity, Lead, and Case objects. 


This table shows an Account view, a corresponding database table, and a skinny table that would speed up  Account queries.                                                                                                           
Skinny tables can contain the following types of fields.
  • Checkbox
  • Date
  • Date and time
  • Email
  • Number
  • Percent
  • Phone picklist
  • Picklist (multi-select)
  • Text
  • Text area
  • Text area (long)
  • URL

Skinny table can speed up queries. Instead of using a date range like 01/01/11 to 12/31/11—which entails an expensive, repeated computation to create an annual or year-to-date report—you can use a skinny table to include a Year field and to filter on Year = '2011'.
  • Skinny tables can contain a maximum of 100 columns.
  • Skinny tables cannot contain fields from other objects.
  • Skinny tables are not copied to sandbox organizations. To have production skinny tables activated in a sandbox organization, contact salesforce.com Customer Support.

Tuesday, April 11, 2017

Salesforce record Id 15 digit 18 digit conversion

Salesforce record Id uniquely identifies each record in salesforcce. Salesforce record Id can either be 15 digit or 18 digit. 15 digit salesforce record  id is case sensitive and 18 digit salesforce record id is case insensitive. Every record in salesforce is identified by unique record Id in every salesforce organization.
15 digit case-sensitive version is referenced in the UI and also visible in browser
18 digit case-insensitive version which is referenced through the API
The last 3 digits of the 18 digit Id is a checksum of the capitalization of the first 15 characters, this Id length was created as a workaround to legacy system which were not compatible with case-sensitive Ids. The API will accept the 15 digit Id as input but will always return the 18 digit Id.

Visualforce Code:

<apex:page controller="idConvertor">
    <apex:form >
        <apex:pageBlock >
        <apex:pageMessages id="showmsg"></apex:pageMessages>
            <apex:pageBlockButtons >
                <apex:commandButton value="Convert" action="{!convert}"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection >
            <apex:inputText value="{!inputId}" label="Input Id:"/>
            <apex:outPutText value="{!outputId}" label="Output Id:"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Apex Code:
public with sharing class idConvertor {
    public String inputId{get;set;}
    public String outputId{get;set;}
public PageReference convert(){
       outputId = convertId(inputId);
        return null;
    }

    String convertId(String inputId){
        string suffix = '';
        integer flags;
        try{
            for (integer i = 0; i < 3; i++) {
                flags = 0;
                for (integer j = 0; j < 5; j++) {
                    string c = inputId.substring(i * 5 + j,i * 5 + j + 1);
                    if (c.toUpperCase().equals(c) && c >= 'A' && c <= 'Z') {
                        flags = flags + (1 << j);
                    }
                }
                if (flags <= 25) {
                    suffix += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.substring(flags,flags+1);
                }else{
                    suffix += '012345'.substring(flags - 26, flags-25);
                }
            }
        }
        catch(Exception exc){
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.ERROR,'Please enter Valid 15 digit Id'));
        }
        String outputId = inputId+suffix;
        return outputId;
    }
}