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
SOURAV GUHA 9SOURAV GUHA 9 

Automation using Flow/Apex

I have a list of permission sets (PS1-10) and one profile. Below are the steps which I need to execute:
  • First I need to find the users who have this particular profile and PS7
  • Then I need to check if the users having PS7 and this profile have all the permission sets (PS1-10) assigned to them. 
  • If there are less permission sets assigned, then return Missing, if there are more permission sets assigned, return Additional, else return No Change. I need to implement this using either Flow or Apex. 
  • The final output should give me the userID, the permission sets assigned to them and Missing/Additional/No change
Till now I have been doing this manually by querying the PermissionSetAssignment object, then retrieving the Assignee details and the permission sets assigned to the assignee, then manually checking.
 
Thank you
Best Answer chosen by SOURAV GUHA 9
Abdul KhatriAbdul Khatri
Hi Sourav,

Please check the below logic and let me know if this help. You may need to change the profile name as per you requirement or permission set names.

I categorize the return this way
  • Missing And Additional
  • No Chane And Additonal
  • Missing
  • No Change
public class UserService {
    
    private static String profileName = 'System Administrator';
    private static String ps7Name = 'PS7';
    
    private static List<String> ps1_ps10NameList = new List<String>{
        'PS1','PS2','PS3','PS4','PS5','PS6','PS8','PS9','PS10'
    };
    
    
    public static List<UserDetail> getUserPermissionDetails(){

        Map<Id, User> userMap = new Map<Id, User>([SELECT Id
                              	FROM User
                              	WHERE Profile.Name = :profileName
                              		AND Id IN (SELECT AssigneeId 
                                               	FROM PermissionSetAssignment
                                               	WHERE PermissionSet.Name = :ps7Name)]);

        Map<Id, List<String>> permissionSetMap = new Map<Id, List<String>>();
        
        for(PermissionSetAssignment psa : [SELECT AssigneeId, PermissionSet.Name
                                          	FROM PermissionSetAssignment
                                          	WHERE AssigneeId = : userMap.keySet()
                                          		AND (PermissionSet.Name IN :ps1_ps10NameList
                                                     OR PermissionSet.Name NOT IN :ps1_ps10NameList)
                                          	ORDER BY AssigneeId, PermissionSet.Name])
        {
            List<String> tempList = new List<String>();
           	if(permissionSetMap.containsKey(psa.AssigneeId))
                tempList = permissionSetMap.get(psa.AssigneeId);
            
            tempList.add(psa.PermissionSet.Name);
            
            permissionSetMap.put(psa.AssigneeId, tempList);
                
        }

        return evaluateUser(permissionSetMap);
        
    }
    
    
    private static List<UserDetail> evaluateUser(Map<Id, List<String>> permissionSetMap){

        Boolean additional;

		List<UserDetail> userDetailList = new List<UserDetail>();

        List<String> foundList = new List<String>();        
        for(Id id : permissionSetMap.keySet())
        {
			UserDetail ud = new UserDetail();
            additional = false;
            system.debug(permissionSetMap.get(id));
            foundList.clear();

            for(String str : permissionSetMap.get(id)){
            
                if(!ps1_ps10NameList.contains(str)){
                    additional = true;
                }else{
                    foundList.add(str);
                }
            }            
            
            ud.Id = id;
            ud.permissionSetList = permissionSetMap.get(id);
            
            if(additional && ps1_ps10NameList.size() == foundList.size())
                ud.status = 'No Change And Additional';
            else if(additional && ps1_ps10NameList.size() != permissionSetMap.get(id).size())
                ud.status = 'Missing And Additional';
            else if(!additional && ps1_ps10NameList.size() != foundList.size())
                ud.status = 'Missing';
			else if(!additional && ps1_ps10NameList.size() == foundList.size())          
                ud.status = 'No Change';
                
            userDetailList.add(ud);
        }
        
            return userDetailList;
        
    }
    
    public class UserDetail {
        
        public Id id;
        public List<String> permissionSetList;
        public String status;
    } 

}

Let me know if this help or you need to understand the code.

All Answers

Abdul KhatriAbdul Khatri
Hi Sourav,

The part I am confuse is return Additional

What that means?

The way I understood the requirement is this
  • First find the users who have a particular profile and also exist in PS7 Permission Set.
  • Check the above users if these users are also assigned to the permissions sets (PS1-10)
  • Find the users who are missing permission sets, all permission sets.
Now what do you mean by additional 

​​​​​​​Examples would help

Thanks
SOURAV GUHA 9SOURAV GUHA 9
Additional means if the user has PS7 and any other permission set assigned to him, apart from PS1-10. Thank
SOURAV GUHA 9SOURAV GUHA 9
There can be one more scenario. where the user has PS7, contains some of the permission sets in PS1-10 but not all (hence Missing), but also contains permission sets other than PS1-10. This scenario will be very rare in our system, but still as an edge case can be marked as Other.
Thanks
SOURAV GUHA 9SOURAV GUHA 9
Apologies If I was not clear before, but this automation is to identify the users who have PS7 and exactly 10 permission sets (PS1-10). They should not have any other permission sets. All the users having PS7 and this profile, should have exactly PS1-10 permissions, any more permissions will mark them as additional. 
Thanks
Abdul KhatriAbdul Khatri
Hi Sourav,

Please check the below logic and let me know if this help. You may need to change the profile name as per you requirement or permission set names.

I categorize the return this way
  • Missing And Additional
  • No Chane And Additonal
  • Missing
  • No Change
public class UserService {
    
    private static String profileName = 'System Administrator';
    private static String ps7Name = 'PS7';
    
    private static List<String> ps1_ps10NameList = new List<String>{
        'PS1','PS2','PS3','PS4','PS5','PS6','PS8','PS9','PS10'
    };
    
    
    public static List<UserDetail> getUserPermissionDetails(){

        Map<Id, User> userMap = new Map<Id, User>([SELECT Id
                              	FROM User
                              	WHERE Profile.Name = :profileName
                              		AND Id IN (SELECT AssigneeId 
                                               	FROM PermissionSetAssignment
                                               	WHERE PermissionSet.Name = :ps7Name)]);

        Map<Id, List<String>> permissionSetMap = new Map<Id, List<String>>();
        
        for(PermissionSetAssignment psa : [SELECT AssigneeId, PermissionSet.Name
                                          	FROM PermissionSetAssignment
                                          	WHERE AssigneeId = : userMap.keySet()
                                          		AND (PermissionSet.Name IN :ps1_ps10NameList
                                                     OR PermissionSet.Name NOT IN :ps1_ps10NameList)
                                          	ORDER BY AssigneeId, PermissionSet.Name])
        {
            List<String> tempList = new List<String>();
           	if(permissionSetMap.containsKey(psa.AssigneeId))
                tempList = permissionSetMap.get(psa.AssigneeId);
            
            tempList.add(psa.PermissionSet.Name);
            
            permissionSetMap.put(psa.AssigneeId, tempList);
                
        }

        return evaluateUser(permissionSetMap);
        
    }
    
    
    private static List<UserDetail> evaluateUser(Map<Id, List<String>> permissionSetMap){

        Boolean additional;

		List<UserDetail> userDetailList = new List<UserDetail>();

        List<String> foundList = new List<String>();        
        for(Id id : permissionSetMap.keySet())
        {
			UserDetail ud = new UserDetail();
            additional = false;
            system.debug(permissionSetMap.get(id));
            foundList.clear();

            for(String str : permissionSetMap.get(id)){
            
                if(!ps1_ps10NameList.contains(str)){
                    additional = true;
                }else{
                    foundList.add(str);
                }
            }            
            
            ud.Id = id;
            ud.permissionSetList = permissionSetMap.get(id);
            
            if(additional && ps1_ps10NameList.size() == foundList.size())
                ud.status = 'No Change And Additional';
            else if(additional && ps1_ps10NameList.size() != permissionSetMap.get(id).size())
                ud.status = 'Missing And Additional';
            else if(!additional && ps1_ps10NameList.size() != foundList.size())
                ud.status = 'Missing';
			else if(!additional && ps1_ps10NameList.size() == foundList.size())          
                ud.status = 'No Change';
                
            userDetailList.add(ud);
        }
        
            return userDetailList;
        
    }
    
    public class UserDetail {
        
        public Id id;
        public List<String> permissionSetList;
        public String status;
    } 

}

Let me know if this help or you need to understand the code.
This was selected as the best answer
SOURAV GUHA 9SOURAV GUHA 9
Hello Abdul,
Thanks a lot for the code. Would you mind providing an elaborate explanation for the logic, it would help a beginner developer like myself to grasp the concepts.
Thanks again.
Abdul KhatriAbdul Khatri
Hi Sourav,

Is the code doing what you are looking for, If yes can you please mark it a best Answer.

Here is the explanation.
  • The first SOQL is to get the relevant users that are part of the profile and PS7
  • Second SOQL is to get all the PermissionSets assigned to the above users order by user and ther permissionssets
  • Then I loop around them looking the level of permissionset matching them against the required ones making a decision of those four scenarios mentioned above.
  • I stored the results in the map by userid, list of permission set, status.
  • I used the inner class to store the results
I hope this will help