How to change/update the profile of a User in Salesforce from apex code

It's my first blog writing, so ignore all the grammatical errors here :)

A user profile update is not allowed through apex code generally and it through error 
FIELD_INTEGRITY_EXCEPTION, Cannot change profile for current user: Profile ID.

It can be achieve by Http callout. How to do this, its pretty simple. There are 2 way to do this:

1st: If we have community or a site enabled in our sf org. It's  3-4 step process.

  • Create a visualforce page and assign a controller to it. Make this page public through guest user permissions.
  • Define an action in apex:page tag.  which will be called when ever this page executes
  • In controller : action: write the code to update the profileId. It works.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
public void callPublicSite(){

     String remoteURL = 'https://testing.force.com/ProfileUpdate?userId=' userId+'&profileId='+profileIdToUpdate;

     HttpRequest httpRequest = new HttpRequest();
     httpRequest.setMethod('GET');
     httpRequest.setEndpoint(remoteURL);
     HttpResponse httpResponse = new Http().send(httpRequest);

} 

Here "ProfileUpdate" is the public page . which is executes , whenever callPublicSite method is called. Hence result , it do the Http callout and execute public page with given parameters.

Page Controller






1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public void doProfileUpdate()
{     
   try
   {
      String userId = ApexPages.currentPage().getParameters().get('userId');
      String profileId = ApexPages.currentPage().getParameters().get('profileId');
      update new User(Id=userId,ProfileId = profileId);
   }
   Catch(Exception e)
   {
     System.debug('::::user profile not update'+e);
   }
}


Page Code





1
2
<apex:page controller="ProfileUpdateController" action="{!doProfileUpdate}">
</apex:page>


2nd way to do this :  If the sf org don't have enabled site or community, then we have to make a http callout to restful class.

Note : Remote URL use like this if namespace is enabled in org:
String remoteURL = 'https://na34.salesforce.com/services/apexrest/namespace/ProfileUpdate?_HttpMethod=PATCH';

Http callout code
don't mix the "selectProfile" method in restful class. keep where you want to execute your business logic.
For Current user this solution won't work.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public void selectProfile(){
String remoteURL = 'https://na34.salesforce.com/services/apexrest/namespaceHereifAvailable/ProfileUpdate?_HttpMethod=PATCH';
         String userId = '005e877812882' //userid
        HTTPRequest httpRequest = new HTTPRequest();
        httpRequest.setMethod('POST');
        httpRequest.setHeader('Authorization', 'OAuth '+UserInfo.getSessionId());
        httpRequest.setHeader('Content-Type', 'application/json');
        httpRequest.setBody('{"userId":"'+userId+'","profileId":"'+commProfileId+'"}');
        httpRequest.setEndpoint(remoteURL);
        HTTPResponse res = new Http().send(httpRequest);
        System.debug('BODY: '+res.getBody());
        System.debug('STATUS:'+res.getStatus());
        System.debug('STATUS_CODE:'+res.getStatusCode());
        return null;

     }


Restful apex class code

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@RestResource(urlMapping='/ProfileUpdate/*')
global with sharing class ProfileUpdate {

    @HttpPatch
    global static String updateProfile(String  profileId, String userId) {
        
        update new User(Id=userId,ProfileId = profileId);
           
        return 'Profile Updated';
      }

}


This all is done because when callout is responded , it do all action with admin profile.


Let me know , if it helped you or if you have any question regarding this.

Comments


  1. string userId='005Q003000P5TGsZZA';
    string profileIdToUpdate ='00e37600000MbmuqAC';
    String remoteURL = 'https://cs3.salesforce.com/services/apexrest/ProfileUpdateRest?userId='+userId+'&profileId='+profileIdToUpdate;

    HTTPRequest httpRequest = new HTTPRequest();
    httpRequest.setHeader('Authorization', 'OAuth '+UserInfo.getSessionId());
    httpRequest.setHeader('Content-Type', 'application/json');
    httpRequest.setMethod('GET');
    ;
    httpRequest.setMethod('GET');
    httpRequest.setEndpoint(remoteURL);
    HTTPResponse httpResponse = new Http().send(httpRequest);






    @RestResource(urlMapping='/ProfileUpdateRest/*')
    global with sharing class ProfileUpdaterest {

    @HttpGet

    global static String updateProfile() {

    String userId = RestContext.request.params.get('userId');
    String profileId = RestContext.request.params.get('profileId');


    update new User(Id=userId,ProfileId = profileId);

    return 'Profile Updated';
    }

    }





    Tried the second approach but getting same integrity exception. I am making http callout to restful class using dev console. Could you please check if correct. Or profile can be updated using 2nd approach??

    ReplyDelete
    Replies
    1. please have a look again. i have updated my post.

      Delete
  2. is your page is public either using community or site ?

    ReplyDelete
  3. Hi Ankush
    I'm trying the second approach, what is the meaning of "Before this we should have get the token and establish the connection." & how to get this token. Right now I'm getting the error "Status Code 401".

    Thanks in Advance
    Arun

    ReplyDelete
    Replies
    1. No need of token, As we are doing both action in same org. Use SessionId as Oauth token. Refer the code again. I made few changes.

      Delete
  4. @Ankush,
    I am trying the same internally, Want to see if I create a lightniing component and that can resolve this.

    Lightning component will have a check boxes, based on selection from current user, the profile will be changed to selected one for the same logged in user.

    ReplyDelete
  5. I have a queueable class where I am trying to update user profile when contact is updated in community.I am also facing the same error.Want to try out the workaround that u have provided.

    But want to know how to call doProfileUpdate method in callPublicSite method?

    ReplyDelete

Post a Comment

Popular posts from this blog

Deep Dive into Salesforce to Salesforce Connection

File Migration from One Salesforce Org to Another Org using Skyvia