Nerd @ Work

When Salesforce is life!

[Salesforce / Apex] Can I find out if the current user has access to a record?

Yes you can!

And this is quite simple!
Query the UserRecordAccess object to have instant access to the following informations about a record and an user:

  • HasDeleteAccess: user has delete access on the record
  • HasEditAccess: user has edit access on the record
  • HasTransferAccess: user has transfer access on the record
  • HasReadAccess: user has read access on the record
  • MaxAccessLevel: picklist that tells the maximum access level on the record (None, Read, Edit, Delete, Transfer, All)
  • HasAllAccess: user can share the record

Here is a simple query (on a Case object):

List<UserRecordAccess> accessToRecord = [SELECT RecordId, MaxAccessLevel FROM UserRecordAccess WHERE UserId = :UserInfo.getUserId()  AND RecordId = '500000000000001AAA'];

On API 29.0 and earlier we have few limitations on SOQL:

  • When the running user is querying a user’s access to a set of records, records that the running user does not have read access to are filtered out of the results.
  • When filtering by UserId and RecordId only, you must use SELECT RecordId and optionally one or more of the access level fields:HasReadAccess, HasEditAccess, HasDeleteAccess, HasTransferAccess, and HasAllAccess. You may include MaxAccessLevel.
  • When filtering by UserId, RecordId, and an access level field, you must use SELECT RecordId only.

Quite simple, it has been added since plaftorm version 24.0 but I discovered it few days ago!

[Salesforce / Trailhead] Trailhead MEGA RELEASE (DF15 Edition)

Dreamforce ’15 is coming and with it we expect awesome news from the event.

I won’t be part of it, and this is a super duper sad thing (I REALLY wanted to watch the Foo Fighters live 🙁 ), but this does not stop me from following the event from home.

If the online stuff is not enough, you can do the Get Ready for Dreamforce trailhead module, an interesting and funny module to discover the most important things of the event: agenda, places, social media infos (who to follow to be uptodate), where to get free gadgets (and swag) and some important details about San Francisco (weather, what to pack in your baggage).

I’m not gonna be preset at DF15 but doing this modulo I almost cried thinking of how cool it would be to be there!

…next year Salesforce…I promise…

[sniff … wipe away all tears … pretending nothing happened…]

The next trailhead modules I’ve succesfully passed (I’m quite a maniac about those kinds of gamifications) are CRM Basics, Accounts & Contacts and Leads & Opportunities: these are super basic modules for Salesforce noobs that introduce you in an easy and funny way to the use of the basic standard entities of Salesforce CRM, that is Accounts, Contacts, Leads, Opportunities.

Even if you are an experienced Salesforce Admin/Dev, try these modules: as I always say, there is something new to learn, expecially in things you are sure you master!

The last module added to this MEGA RELEASE is a cool modulo about a feature I promised myself to study but I unfortunately had no time to get deep on: Event Monitoring.

This is a cool new feature that came with Summer ’15 Platform Release: you can extract events that occur on your ORG, using the new EventLogFile object.

An event could be a login, logout, report exportation, Visualforce load, Sandbox creationg/update, API call, etc.

The events can be extracted via REST APIs: if you are not a DEV the modulo will teach you how to make a REST API call.

And if you don’t want to make a REST API call at all, you can download every log files usign the Salesforce Event Log File Browser app:

Here are the supported events (29):

  • Apex Callout
  • Apex Execution
  • Apex SOAP
  • Apex Trigger
  • API
  • Async Report
  • Bulk API
  • Change Set Operation
  • Content Distribution
  • Content Document Link
  • Content Transfer
  • Dashboard
  • Document Attachment Downloads
  • Login
  • Login As
  • Logout
  • MDAPI Operation
  • Multiblock Report
  • Package Install
  • Queued Execution
  • Report
  • Report Export
  • REST API
  • Salesforce1 Adoption (UI Tracking)
  • Sandbox
  • Sites
  • Time-Based Workflow
  • URI
  • Visualforce

One of the best examples that the module points out is the “Monitor of data loss”:
…Imagine that a sales representative leaves your company and joins a major competitor. Later, you find out that your organization is losing deal after deal to this other company. You suspect that your former employee downloaded a report containing leads and shared it with the competition. If you’d been using event monitoring, you could have caught this bad behavior before it cost your company sales.

Have you ever had loading problems with certain Visual Force pages? When you load it, it works like a charm, but when the customer loads it, it usually go timeout.
Now you can finally measure day by day how VisualForces are being rendered (times opened, viewstates, time required to load, ….).

EventLogFile are exposed 24h after their creation and are available only for 24 h: that is to say you can query / download EventLogFile of yesterday for 24h (till the platform releases the new EventLogFile files).

You can require a 30 days validity for EventLogFile objects (this is not a free feature).

A lot of stuff, uh?

[Salesforce / Revamp] Enable All Trusted IP Ranges for a Salesforce Org

a{color: red !important;}

DISCLAIMER: I’ve just understood you can do this on the profile (without range restrictions). See the “UPDATE” section of this post. This post is still valid as exercise.

Enabling all trusted IP ranges is a must do when developing on a Salesforce Developer ORG and you want to access via metadata API to your code from different locations where your IP can change during time (home, bar, pub, pizza shop, your parent’s house, your parent’s in law house, …).

Thanks to Ray Dehler Enable All Trusted IP Ranges, I’ve done it several times in all Developer ORGs I’ve created since 2011…BTW thanks Ray, you saved me a lot of time!

Unfortunately with Summer ’15 Release this awesome home page component does not work anymore: all home page components that use Javascript cannot work anymore, the Javascript code is blocked and you are forced to use a Visual Force page if you want dynamic behavior.

Apparently it is impossibile to reproduce this home page component using a Visual Force page, these are the main limitations I found while trying to update Ray’s component:

  1. When using a Visual Force home page component with the same Javascript code, Salesforce reloads the loaded “Network Access” component of the iframe on the “parent” location, making it impossibile to load all iframes in one shot
  2. If you use the Visual Force outside the custom component (i.e. loading “/apex/PageName”), due to cross domain restrictions, the iframe is not loaded
  3. Even if you managed to load all iframes on point #1, the corss-domain restriction block you from loading the iframe’s HTML content

Apparently this is impossibile to make it work same as old days.

That’s why I created a simple update of the component to help adding (manually) all ranges:

Click on each “Click to load range” link to open, in a separate window, the “Network Access” page in Edit mode.

This is a way to help developers to load trusted range IPs, faster than writing all ranges by hand.

You can install this unmanaged package clicking on the following button:

Or by installing the following unmanaged package.

This is the GitHub repository with the code and other infos.

If you have a better solution / automation, please share!

UPDATE: I admit, I feel so dumb, but you can simply add the 0.0.0.0-255.255.255.255 range in your Profile (no restrictions apply there), following this section:

[Salesforce / REST APIs] API Request limit on REST header response

Plyaing with Salesforce APIs for a super secret project I came across at this (the red one) response header:

{
    date : "Fri, 31 Jul 2015 22:20:47 GMT",
    set-cookie : -[
       "BrowserId=8gV_vxxxT--xxxi0bg0vug;Path=/;Domain=.salesforce.com;Expires=Tue, 29-Sep-2015 22:20:47 GMT",
    ],
    expires : "Thu, 01 Jan 1970 00:00:00 GMT",
    sforce-limit-info : "api-usage=113/5000000",
    last-modified : "Fri, 24 Jul 2015 12:07:09 GMT",
    content-type : "application/json;charset=UTF-8",
    transfer-encoding : "chunked",
}

This is basically the number of API requests done since this last call, and it can be used to train external systems not to fail when exceeding this limit.

I’m sure this has been there since the beginning of times and it may be documented and, as a Salesforce expert, I should know it, but it is worth an article!

Only thing to know is that the limit is not precise, this is recalculated asynchronously and thus the number may be not the exact current amount.

To test this try my own REST request utility and try to call a simple global describe:

     GET https://[your_instance].salesforce.com/services/data/v34.0/sobjects/
     Headers
     Authorization: Bearer [a_valid_session_id]

[Salesforce/ Lightning] inputLookup: the missing component

Or quick tips on how to implement your own inputLookup Salesforce ligthning component

This is a repost of the article I published on Salesforce Developer Blog.

Salesforce Spring ’15 release brought some brand new components ready to be used in your lightning apps. One of the missing components that could be useful for your apps is the input lookup component. The idea is to use a typeahead input field. We are going to user Bootstrap and the Twitter typeahead component.

The idea behind this implementation is that the user will type a search on the input field and the typeahead shows a list of the first 20 items for the given object and search string. On load, the component should also load the initial value of the “name” field for the given object, if an ID value is selected.

This is how the component will look:

For those of you who don’t want to read more and just use the component, jump to the inputLookup github repo.

To ensure proper script loading we will use RequireJS with the trick proposed in this blog post.

Let’s first have a look at the lookupInput component’s markup (github):

<aura:component controller="InputLookupController">
    
    <ltng:require scripts="/resource/RequireJS" afterScriptsLoaded="{!c.initTypeahead}" />
    <aura:handler name="init" value="{!this}" action="{!c.setup}"/>

    <!-- ... -->

    <!-- public attributes -->
    <aura:attribute name="type" type="String" required="true"/>
    <aura:attribute name="value" type="String" />
    <aura:attribute name="className" type="String" />
    <!-- PRIVATE ATTRS -->
    <aura:attribute name="nameValue" type="String"
                    access="PRIVATE"/>
    <aura:attribute name="isLoading" type="Boolean"
                    default="true"
                    access="PRIVATE"/>

    <div class="has-feedback">
        <input id="{!globalId+'_typeahead'}" type="text" 
               value="{!v.nameValue}" class="{!v.className}" 
               onchange="{!c.checkNullValue}" readonly="{!v.isLoading}"/> 
        <span class="glyphicon glyphicon-search form-control-feedback"></span>
    </div>
</aura:component>

It uses the “InputLookupController” Apex class (with required @RemoteActions).

The RequireJS components triggers “c:requireJSLoaded” event that actually makes the component load its bootstrapped Typeahead input field: note the absence of any custom namespace, that is replaced with the “c” default namespace (this is a Spring ’15 feature).

We also have an init method that ensures that all required parameters are set.

This component simply uses a “type” parameters (with the actual API name of the needed SObject) and a “value” parameter that stores the selected ID (or the loading ID).

At first we want to load on initialization (or when the value parameter changes) the content of the input (we want to see the “Name” of the pre-selected SObject and not its ID).

The initialization loading is done using the following “inputLookupController.js” method:

initTypeahead : function(component, event, helper){
        try{
            //first load the current value of the lookup field and then
            //creates the typeahead component
            helper.loadFirstValue(component);
        }catch(ex){
            console.log(ex);
        }
    }

This is the helper part:

loadFirstValue : function(component) {
        //this is necessary to avoid multiple initializations (same event fired again and again)
        if(this.typeaheadInitStatus[component.getGlobalId()]){ 
            return;
        }
        this.typeaheadInitStatus[component.getGlobalId()] = true;
        this.loadValue(component);

    },

    loadValue : function(component, skipTypeaheadLoading){
        this.typeaheadOldValue[component.getGlobalId()] = component.get('v.value');
        var action = component.get("c.getCurrentValue");
        var self = this;
        action.setParams({
            'type' : component.get('v.type'),
            'value' : component.get('v.value'),
        });

        action.setCallback(this, function(a) {
            if(a.error && a.error.length){
                return $A.error('Unexpected error: '+a.error[0].message);
            }
            var result = a.getReturnValue();
            component.set('v.isLoading',false);
            component.set('v.nameValue',result);
            if(!skipTypeaheadLoading) self.createTypeaheadComponent(component);
        });
        $A.enqueueAction(action);
    }

This piece of code simply calls the “InputLookupController.getCurrentValue” remote action that simply preload the selected record’s Name field (if any).

The “typeaheadInitStatus” property (see the full file code) is used to avoid multiple initialization of the component (the “createTypeaheadComponent” method is the method that is used to create the typeahead component: this must be executed only once!).

On the other side the “typeaheadOldValue” stores the current value, in order to understand if the value parameter is changed: this is extremely useful when some other part of the application changes the value parameters and so the component should refresh it’s inner value.

To achieve this simply see the “inputLookupRenderer.js” file:

rerender : function(component, helper){
        this.superRerender();
        //if value changes, triggers the loading method
        if(helper.typeaheadOldValue[component.getGlobalId()] !== component.get('v.value')){
            helper.loadValue(component,true);
        }
    }

This method is called every time the component is rerendered (e.g. when one of its parameters changes), and it constantly evaluates if the “value” parameter has changed since the last set; if this is true then we load again the component, without re-contructing it (“skipTypeaheadLoading” parameters of the loadValue function).

The typeahead is a simple porting of the Twitter Typeahead component with some changes, the most important of which is the call to the remote action that search (using SOSL) for all SObjects given the search term (“substringMatcher” function of the helper file):

// . . . 
    substringMatcher : function(component) {
        //usefull to escape chars for regexp calculation
        function escapeRegExp(str) {
          return str.replace(/[-[]/{}()*+?.^$|]/g, "$&");
        }

        return function findMatches(q, cb) {
            q = escapeRegExp(q);
            var action = component.get("c.searchSObject");
            var self = this;

            action.setParams({
                'type' : component.get('v.type'),
                'searchString' : q,
            });

            action.setCallback(this, function(a) {
                if(a.error && a.error.length){
                    return $A.error('Unexpected error: '+a.error[0].message);
                }
                var result = a.getReturnValue();

                var matches, substrRegex;

                // an array that will be populated with substring matches
                var matches = [];

                // regex used to determine if a string contains the substring `q`
                var substrRegex = new RegExp(q, 'i');
                var strs = JSON.parse(result);
                // iterate through the pool of strings and for any string that
                // contains the substring `q`, add it to the `matches` array
                $.each(strs, function(i, str) {
                    if (substrRegex.test(str.value)) {
                        // the typeahead jQuery plugin expects suggestions to a
                        // JavaScript object, refer to typeahead docs for more info
                        matches.push({ value: str.value , id: str.id});
                    }
                });
                if(!strs || !strs.length){

                    $A.run(function(){
                        component.set('v.value', null);
                    });
                }
                cb(matches);
            });
            $A.run(function(){
                $A.enqueueAction(action);
            });
        };
    }
    // . . .

This “complex” code is used to push the results from the “searchSObject” remote action to the typeahead result set picklist.

Finally you can add the component in your lightning app:

<aura:application >

    <aura:attribute name="id" type="String" default="" access="GLOBAL"/>
    <aura:attribute name="objNew" type="Contact" default="{'sobjectType':'Contact',  
                                                       'Id':null}" />

    <!-- ... -->

    <div class="well">
        <div class="panel panel-primary">
            <div class="panel-heading">Existent sobject</div>
            <div class="panel-body">
                <div class="form-horizontal" >
                    <div class="form-group">
                        <label class="col-sm-2 control-label">Contact</label>
                        <div class="col-sm-8">
                            <c:inputLookup type="Contact"  
                                         value="{!v.id}"
                                         className="form-control "/>
                        </div>
                    </div>
                    <div class="form-group has-feedback">
                        <label class="col-sm-2 control-label">Loaded contact</label>
                        <div class="col-sm-8 ">
                            <ui:inputText value="{!v.id}" 
                                          class="form-control"
                                          placeholder="Change id value"/>
                         </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="panel panel-primary">
            <div class="panel-heading">New sobject</div>
            <div class="panel-body">
                <div class="form-horizontal" >
                  <div class="form-group">
                    <label class="col-sm-2 control-label">Contact</label>
                    <div class="col-sm-8">
                      <c:inputLookup type="{!v.objNew.sobjectType}"
                                    value="{!v.objNew.Id}"  
                                    className="form-control "/>
                      </div>
                  </div>
                 <div class="form-group has-feedback">
                    <label class="col-sm-2 control-label">New contact</label>
                    <div class="col-sm-8 ">
                        <ui:inputText value="{!v.objNew.Id}" 
                                      class="form-control"
                                      placeholder="Change id value"/>
                     </div>
                  </div>
                </div>
            </div>
        </div>
    </div>

</aura:application>

We have two components, the first one ‘s value is grabbed directly from the “?id=XXXX” query string parameters, while the second one has no value on load:

Finally you can easily test that everytime you change the “value” input text, the inputLookup component loads it’s new “name” field, while if you search for a Contact on the component and select a record, the value input is set with the new value.

You brand new custom input lookup component is served!

[Salesforce / Apex] Integer vs Double math expressions

This is a quick post about some findings about how math expressions are handled by Apex engine, arisen from the developments of a personal package to reproduce Salesforce Formulas in Apex (and even more).

For those out there that are super expert on this field of programming, this post may seem simplicistic and “obvious”, but I think this could help a lot of guys out there that had the same problem!

Take this expression:

Double aValue = 1 / 5 * 5;

Since elementary school I learned that I could play with fractions, and in this particular example you simply reduce the 5 in the second member of the “/” operator with the third member after the “*” operator.

What’s the result?

It’s absolutely 1!

Wrong!

At first I thought I was the first to find an incredible bug, but after a while, thinking about how Java works, I understood the reason.

Try to execute this other statemanet:

Double aValue = 5 * 1 / 5;

What’s the result?

It is correctly 1.

The reason is how the “/” operator calculates:

  • If at least one operand is double/decimal, the operation is calculated in decimal style; that’s why 1.0/10 = 0.1 and 1.0/10*10 = 1 as expected
  • If both operands are integer numbers, the operation is done in the interger set of values, so 1 / 10 = 0 and the order of execution matters; that’s wky 1 / 10 * 10 = 0 and 10 * 1 / 10 = 1

In both cases the type of the result variable (Double aValue) does not affect the result, so aValue evaluates to “0.0” or “1.0”, that is a simple conversion from the integer result to a its double value.

[Salesforce / Apex / VisualForce] Getting rid of the “Save & New” button

In some circumstances the “Save & New” button on the standard layout is not desired.

This is an idea (there are others of this kind) to make this optional on layouts, but unfortunately it’s been freezed for years.

The simpler solution was to execute some javascript on a hone page component in order to hide every button that has the “save_new” name:
Remove Save & New button of the standard edit page.

With Summer ’15 you cannot use anymore custom home page components that contains script tags, so the hack is not valid anymore: if you try to create/edit an HTML Area Custom Component you get this info message:

This component contains code that is no longer supported. For security reasons, in Summer ’15 we will start removing non-supported code from HTML Area home page components. As a result, this component may stop working properly.

If you want to use JavaScript or other advanced HTML elements in your home page component, we recommend that you create a Visualforce Area component instead.

I had to find a solution for a client, and the “New” button override was the way.

The button I’m talking about is this one (on the Editing standard layout):

You simply have to override the “New” button on your selected objects, creating for each object a Visual Force page with a standard Controller and the following extension:

<apex:page standardController="Account" extensions="SObjectNewActionOverrideController" action="{!onLoadPage}">
</apex:page>

public class SObjectNewActionOverrideController {
    public String debug{get;Set;}
    private String SObjectPrefix = null;
    public SObjectNewActionOverrideController(ApexPages.StandardController controller){
        this.SObjectPrefix = controller.getRecord().getSObjectType().getDescribe().getKeyPrefix();
        
    }
    public PageReference onLoadPage(){
        this.debug = JSON.serializePretty(ApexPages.currentPage().getParameters());
        String retURL = ApexPages.currentPage().getParameters().get('retURL');
        //these are the conditions to understand that this is actually a "new" page
        //that comes from a previously "save" page in which the user clicked on "Save & New"
        if(ApexPages.currentPage().getParameters().get('save_new')=='1' 
           && retURL != null
           && retURL.startsWith('/'+SObjectPrefix)
           && retURL.indexOf('/', 4) < 0
           && !retURL.contains('?')
           && retURL.length() >= 15){
               PageReference pg = new PAgeReference(retURL);
               pg.setRedirect(true);
               return pg;
           }else{
               PageReference pg = new PAgeReference('/'+this.SObjectPrefix+'/e');
               for(String key : ApexPages.currentPage().getParameters().keyset()){
                   if(key == 'save_new' || key == 'sfdc.override') continue;
                   pg.getParameters().put(key, ApexPages.currentPage().getParameters().get(key));
               }
               //https://mindfiresfdcprofessionals.wordpress.com/2013/07/10/override-standard-button-in-specific-condition/
               pg.getParameters().put('nooverride','1');
               pg.setRedirect(true);
               return pg;
           }
    }
}

The code simply does a redirect to the “previously” edited record if we are coming from a save operation (and user clicks on “Save & New”), getting rid to the “New” action of the “Save & New”, or simply goes to the standard edit page (the retURL is evaluated: if it is not an object ID then goes to the New action).

As stated in the code, there are other places in which the user clicks on a “New” button but the “save_new” parameter is still passed by Salesforce (I don’t understand the reason though), but this time the user should see the “New” page.

These buttons are the “New” button on the Sobject main page (e.g. /001/o page):

And the related lists:

Comments and alternative solutions are really appreciated!

[Salesforce / Trailhead] The beginning of your Force.com journey

a{color:red !important;}

Few days ago the Salesforce team released 4 new Trailhead modules, and I decided finally to have a look at it…with my style.

What is my style?

I may say “all in” or “all or nothing” style.

I decided to do all the modules and see which topics were covered (and how deeply).

With year of Force.com development it’s been quite easy for me to complete in few hours all the modules, but I haven’t earned all the points available (I did some mistakes when answering to questions) and I must admint I also learned something (expecially in modules I don’t play a lot in my job).

After 16 modules I have to say this is a really good starting point to start learning the basics of the Force.com platform, and sometimes the documentation goes deeper than you could expect, covering important aspects that sometimes you find out only after months of “real world” practice.

The Trailhead modules page lists all the modules in alphabetical order, but you can follow the 3 steps on the Trailhead main page to have a better study order.

Recently some cool modules have been added:

  • Process Automation: you learn the basics of process automation and the new Process Builder and Visual Workflows tools, cool ways to get your complex processes up and running in few clicks!
  • Chatter Basics: this useful module teaches the basics of setting up Chatter on your org to improve social collaboration
  • Lightning Components: this is my favorite modulo above all, I love Lightning Components and can’t wait to see them out of the Beta stage. Learn base and advanced aspects of this new powerful framework
  • Visualforce Mobile: learn how to create slick and smooth visualforce pages on the Salesforce1 mobile platform

This is the complete list of available modules:

And (awesomely) these are “can’t wait” upcoming modules:

  • Reports & Dashboards: Build real-time reports and charts to visualize key business metrics
  • Apex Integration Services: Integrate with external apps using Apex REST and SOAP services
  • Asynchronous Apex: Write more efficient Apex code with asynchronous processing
  • Visualforce & JavaScript: Use JavaScript to enhance and customize your Visualforce pages
  • App Deployment: Learn best practices for team app development and lifecycle management

Stay tuned for more modules!

I’m gonna definitely suggest all my Company’s interns to start learning Force.com using Trailhead, a funny and awesome way to learn the Force!

And once for all:

[Salesforce / SSO] Implementing Delegated SSO

a{color:red !important;}

Playing with code is cool, but playing with useless stuff is even better 🙂

Ok, I’m kidding, I just want to say that sometimes you have to get your hands dirty to understand what lies underneath things and try to build useless stuff to see simple “Hello world!” appear!

This is the case of Delegated SSO.

Few weeks ago with Paolo (a colleage of mine), I was checking deeper on Salesforce SSO, trying to figure out from the docs how to implement it.

The first thing that came across my eyes was the difference between Delegated and Federated SSO.
It wans’t that clear at that time, that’s why Paolo played with the code for some time and did a cool thing that I reproduced in the following Github repo.

Federated SSO is done using well known protocols such as SAML, granting a secure identity provisioning: with Microsoft ADFS you can use your own company domain to log on your Salesforce CRMs as well.

Which is the problem with this kind of SSO?

To implement its bases you don’t need a single line of code.

Too bad we are dirty men that like to play with mud!

That’s why this post!

With Delegated SSO you need 2 actors:

  • An Identity provider (e.g. your Domain server)
  • The Salesforce ORG in which you want to be logged in without remembering username/password

The first wall you splash into is the fact the you have your ORG to be enabled to Delegated SSO: this should be enabled by Salesforce support, so you need a way to contact support (if you’re not using an ORG with built in support).

After your ORG is enabled to Delegated SSO, this is where the config has to be enabled in your “delegated” ORG:

The Delegated Gateway URL contains the URL of the webservice of the “delegating” server.

Then you have to enable the Is Single Sign-On Enabled flag in the Administrative Permissions section of your users’ profile.

This is where we got our hands dirty while making out research: why not using a Salesforce ORG as the identity provider?

Challenge accepted!

What happens with delegated SSO? When you try to log in into your delegated ORG, Salesforce at first try to access the “Delegated SSO” webservice: if this accept the request, than you are automatically logged in; if the server gives a KO, than the ORG checks for username/password to be correct.

This is the message that the delegated ORG sends to the identity provider:

<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope
   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <Authenticate xmlns="urn:authentication.soap.sforce.com">
         <username>[email protected]</username>
         <password>myPassword99</password>
         <sourceIp>1.2.3.4</sourceIp>
      </Authenticate>
   </soapenv:Body>
</soapenv:Envelope>

It basically asks for a user/password couple with a source IP, and receives this response:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope 
   xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <AuthenticateResult xmlns="urn:authentication.soap.sforce.com">
         <Authenticated>false</Authenticated>
      </AuthenticateResult>
   </soapenv:Body>
</soapenv:Envelope>

The Authenticated field conveys the OK/KO result.

You can use the password field to host a unique and temporary token to make the connection more secure.

To log-in from your identity provider page, use this example page (see the /apex/DelegateLogin page):

Each of this users is a delegated user on another ORG, that is stored in the DelegatedUser__c SObject:

It stores Username and Remote ORG ID, because it is used to create the login URL to make the authentication go smootly for the user:

public PageReference delegateAuthentication(){
 String password = generateGUID();
 insert new DelegatedToken__c(Token__c = password, 
         Username__c = this.usr.DelegatedUsername__c,
         RequestIP__c = getCurrentIP());
 String url = 'https://login.salesforce.com/login.jsp?'
    +'un='+EncodingUtil.urlEncode(this.usr.DelegatedUsername__c, 'utf8')
    +'&orgId='+this.usr.Delegated_ORG_ID__c 
    +'&pw='+EncodingUtil.urlEncode(password, 'utf8')
    +'&rememberUn=0&jse=0';
 //you can also setup a startURL, logoutURL and ssoStartPage parameters to enhance usre experience
 PageReference page = new PageReference(url);
 page.setRedirect(false);
 return page;
}

This way you can request a login action for every user you have stored in your objects (this case has the same ORG but you can have wathever ORG you want, no limits); the token is stored in a DelegatedToken__c SObject that is used to handle temporary tokens, usernames and IPs: this way, when the delegated ORG asks our ORG with this infos, our webservice can succesfully authenticate the requesting user.

This is done through the public webservice exposed by the RESTDelegatedAuthenticator class:

    @HttpPost
    global static void getOpenCases() {
        RestResponse response = RestContext.response;
        response.statusCode = 200;
        response.addHeader('Content-Type', 'application/xml');
        Boolean authResult = false;
        try{
            Dom.Document doc = new DOM.Document(); 
            doc.load(RestContext.request.requestBody.toString());  
            DOM.XMLNode root = doc.getRootElement();
            Map<String,String> requestValues = walkThrough(root);
            
            
            authResult = checkCredentials(requestValues.get('username'), 
                                          requestValues.get('password'),
                                          requestValues.get('sourceIp'));
        }catcH(Exception e){
            insert new Log__c(Description__c = e.getStackTraceString()+'n'+e.getMessage(), 
                       Request__c = RestContext.request.requestBody.toString());
        }finally{
            insert new Log__c(Description__c = 'Result:'+authResult, 
                       Request__c = RestContext.request.requestBody.toString());
        }
        String soapResp = '<?xml version="1.0" encoding="UTF-8"?>'
            +'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">'
            +'<soapenv:Body>'
            +'<authenticateresult xmlns="urn:authentication.soap.sforce.com">'
            +'<authenticated>'+authResult+'</Authenticated>'
            +'</AuthenticateResult>'
            +'</soapenv:Body>'
            +'</soapenv:Envelope>';
        response.responseBody = Blob.valueOf(soapResp);
    }

This webservice simply checks the incoming SOAP XML request, extracts the fields on the request and tests its values with the checkCredentials() method.

If the token is not expired you’ll be succesfully redirected to the new ORG logged as the user you wanted to.

A good practice is to use custom domains: you can thus replace “login.salesforce.com” with your “My Domain” of the corresponding ORG (you can also add a new field on the DelegatedUser__c SObject.

To enable public webservice, you simlpy need to create a new Site:

Then click on your Site, click the button “Public Access Setting” and add the RESTDelegatedAuthenticator to the Apex classes accessible by this public profile.

The comple code is right here in this Github repository.

May the Force.com be with you!

[Salesforce / RemoteAction] Using Date fields on a RemoteAction (PITA ALERT!)

I’ve just come through a bug on the Date field handling for Visual Force @RemoteAction.

We want to pass to a remote action a list of SObjects to be handled correctly.

This is the controller that hosts the @RemoteAction method:

public class MyController(){
   @RemoteAction
   public String doAction(List<contact> contacts){
      return 'All is ok!';
   }
}

This is the JS on the VF page:

function action(){
   var contact1 = {"LastName":"Smith",
                   "FirstName":"John",
                   "Phone" : "999-999-999"};
   var contact2 = {"LastName":"Brown",
                   "FirstName":"Mike",
                   "Phone" : "123-456-789"};
   var contactList= [contact1, contact2];
   Visualforce.remoting.Manager.invokeAction(
              '{!$RemoteAction.MyController.doAction}', 
              accList || [],
                function(result, event){
                    if(event.status){
                        alert(result);
                    }else{
                        //generic event error
                        alert(event.message);
                    }
                },{escape: false, timeout: 120000});
}

This runs perfectly.

But let’s add a Date field on the JS part:

function action(){
   var contact1 = {"LastName":"Smith",
                   "FirstName":"John",
                   "BirthDate":"1980-01-01",
                   "Phone" : "999-999-999"};
   var contact2 = {"LastName":"Brown",
                   "FirstName":"Mike",
                   "BirthDate":"1982-11-21",
                   "Phone" : "123-456-789"};
   var contactList= [contact1, contact2];
   Visualforce.remoting.Manager.invokeAction(
              '{!$RemoteAction.MyController.doAction}', 
              contactList || [],
                function(result, event){
                    if(event.status){
                        alert(result);
                    }else{
                        //generic event error
                        alert(event.message);
                    }
                },{escape: false, timeout: 120000});
}

And all messes up, stating that you are passing an incorrect type to MyController.doAction(List).

The problem is related to how the Date type serialization is done when invoking the Remote Action (it is apparently a bug not fixed yet).

The solution is to pass a serialized version of the JS array and deserialize it with Apex:

public class MyController(){
   @RemoteAction
   public String doAction(String serializedContacts){
      List<contact> contacts = (List<contact>)JSON.deserialize(objList,List<contact>.class);
      return 'All is ok!';
   }
}
function action(){
   var contact1 = {"LastName":"Smith",
                   "FirstName":"John",
                   "BirthDate":"1980-01-01",
                   "Phone" : "999-999-999"};
   var contact2 = {"LastName":"Brown",
                   "FirstName":"Mike",
                   "BirthDate":"1982-11-21",
                   "Phone" : "123-456-789"};
   var contactList= [contact1, contact2];
   Visualforce.remoting.Manager.invokeAction(
              '{!$RemoteAction.MyController.doAction}', 
              JSON.stringify(contactList || []),
                function(result, event){
                    if(event.status){
                        alert(result);
                    }else{
                        //generic event error
                        alert(event.message);
                    }
                },{escape: false, timeout: 120000});
}

Remember: don’t mess with JSON serialization!

Page 23 of 26

Powered by WordPress & Theme by Anders Norén