function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Pathak 1Pathak 1 

Apex trigger to assign a permission set to User

HI , We have Community set up in our org. My req is if a Particular Checkbox is checked on a Contact then It should assign a Permission set to that Community user.

I have written below code but it throws MIXED DML EXCEPTION - 

   
trigger AssignPermissionSet on Contact (after Update)

    {
    
for (contact c :trigger.new) {
        if(c.Is_SUper_User__c == true) {
            
            user u = [SELECT ID from User WHERE ContactId = :c.Id];
            
            PermissionSetAssignment  psa = new PermissionSetAssignment 
            (PermissionSetId = 'XXXXXXXXXXXc94', AssigneeId = U.Id);
            insert psa;
            
        }
    }
}
I have heard to resolve this we have to use Future annotation, But can someone help with the class how should I accomplish this?
 
Best Answer chosen by Pathak 1
Amit Singh 1Amit Singh 1
Hello,

LBK code is not bulkified as there is SOQL inside for loop and DML operation as well. And you are getting error because you can not pass Object inside future method as perameter.
Use below code.
Class.
global class AssignPermissionSet {

  @future 
  static void AssignPermissionSetToUsers (Set<Id> usersId) {
    // Perform long-running code
	List<PermissionSetAssignment> permissionSetList = new List<PermissionSetAssignment>();
	for (User u : [Select Id, Name FROM User Where Id IN : usersId]){ // Add fields as per your requirement...
		PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = 'XXXXXXXXXXXc94', AssigneeId = u.Id);
		permissionSetList.add(psa);
	}
	upsert permissionSetList;
  }
}
Trigger.
trigger AssignPermissionSet on Contact (after Update){
Set<ID> usersId = new Set<Id>();
Set<Id> contactIdsSet = new Set<Id>();
for (contact c :trigger.new) {
    if(c.Is_SUper_User__c == true) {
       contactIdsSet.add(c.Id);
    }
}
For(User usr : [Select Id, Name, From User Where ContactId!=null AND ContactId IN : contactIdsSet]){
	usersId.add(usr.Id);
}
  AssignPermissionSet.AssignPermissionSetToUsers(usersId);
}
Let me know if this helps :)
Thanks!
Amit Singh

 

All Answers

LBKLBK
You need to create a @future method and call it from your trigger.

Here is the class and the trigger you need.

Class
global class AssignPermissionSet {

  @future 
  static void AssignPermissionSetToUsers (List<User> lstUsers) {
    // Perform long-running code
	for (User u : lstUsers){
	PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = 'XXXXXXXXXXXc94', AssigneeId = u.Id);
    upsert psa;
	}
  }
}
Trigger
trigger AssignPermissionSet on Contact (after Update){
List<User> lstUsers = new List<User>();
for (contact c :trigger.new) {
    if(c.Is_SUper_User__c == true) {
      user u = [SELECT ID from User WHERE ContactId = :c.Id];
	  lstUsers.add(u);
    }
  }
  AssignPermissionSet.AssignPermissionSetToUsers(lstUsers);
}
Let me know if this help.

 
Pathak 1Pathak 1
Thanks @LBK - This throws an error - Unsupported parameter type List<User>
LBKLBK
My bad.

@future method accepts only primitive datatypes.

Try these.

APEX Class
global class AssignPermissionSet {

  @future 
  static void AssignPermissionSetToUsers (String[] sUsers) {
    // Perform long-running code
	for (String sUser : sUsers){
	PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = 'XXXXXXXXXXXc94', AssigneeId = (ID)sUser);
    upsert psa;
	}
  }
}
Trigger
trigger AssignPermissionSet on Contact (after Update){
List<String> sUsers = new List<String>();
for (contact c :trigger.new) {
    if(c.Is_SUper_User__c == true) {
      user u = [SELECT ID from User WHERE ContactId = :c.Id];
	  sUsers.add(u);
    }
  }
  AssignPermissionSet.AssignPermissionSetToUsers(sUsers);
}

Let me know if you face any issues with these.
Amit Singh 1Amit Singh 1
Hello,

LBK code is not bulkified as there is SOQL inside for loop and DML operation as well. And you are getting error because you can not pass Object inside future method as perameter.
Use below code.
Class.
global class AssignPermissionSet {

  @future 
  static void AssignPermissionSetToUsers (Set<Id> usersId) {
    // Perform long-running code
	List<PermissionSetAssignment> permissionSetList = new List<PermissionSetAssignment>();
	for (User u : [Select Id, Name FROM User Where Id IN : usersId]){ // Add fields as per your requirement...
		PermissionSetAssignment psa = new PermissionSetAssignment (PermissionSetId = 'XXXXXXXXXXXc94', AssigneeId = u.Id);
		permissionSetList.add(psa);
	}
	upsert permissionSetList;
  }
}
Trigger.
trigger AssignPermissionSet on Contact (after Update){
Set<ID> usersId = new Set<Id>();
Set<Id> contactIdsSet = new Set<Id>();
for (contact c :trigger.new) {
    if(c.Is_SUper_User__c == true) {
       contactIdsSet.add(c.Id);
    }
}
For(User usr : [Select Id, Name, From User Where ContactId!=null AND ContactId IN : contactIdsSet]){
	usersId.add(usr.Id);
}
  AssignPermissionSet.AssignPermissionSetToUsers(usersId);
}
Let me know if this helps :)
Thanks!
Amit Singh

 
This was selected as the best answer
LBKLBK
+ 1 Amit

You can even use the code below to bulkify the SOQL call.
 
trigger AssignPermissionSet on Contact (after Update){
List<String> sUsers = new List<String>();
Map<Id, ID> UserMap = new Map<Id,Id> ([SELECT ContactID, Id FROM User]);
for (contact c :trigger.new) {
    if(c.Is_SUper_User__c == true) {
	  sUsers.add(UserMap.get(c.Id));
    }
  }
  AssignPermissionSet.AssignPermissionSetToUsers(sUsers);
}
And the @future method as it is from my previous response.
 
Pathak 1Pathak 1
Amit n LBK, Both the solution works fine.

@Amit, After changing the method to Public I got the requirement working as required.

Thanks 
Pathak 1Pathak 1
Hey , Also, Can we remove Permission Set if the CheckBox is Unchecked ?
Pathak 1Pathak 1
Hey , Also, Can we remove Permission Set if the CheckBox is Unchecked ?
Viswanath YarramalaViswanath Yarramala
Yes Pathak We can remove. 
Please call insert method into ContactTrigger and User Trigger. 
Pass the Parameters ContactIds in Trigger like as below

Trigger Class:- 
List<Contact> conList = new List<Contact>();
for(Contact c:Trigger.new){
 conList.add(c.id);
}
contactTriggerHandler.assignPermissionSetToUsers(conList);

Apex Class:- 
User-added image