Compare Zuora managed package permission sets with custom permission sets
Learn how to compare Zuora managed package permission sets with custom permission sets using Apex code.
- Open the Developer Console and select File > New > Apex Class.Alternatively, go to Setup and create a new Apex class.
- Name the class PermissionSetCopyUtil.If you use a different name, ensure to update the class name in the code snippet provided in this article.
- Paste the code snippet provided in this article into the new class and click Save.
- In the Developer Console, click Debug > Execute Anonymous Window and paste the following code based on your requirement:
- To view the comparison of the permission sets in the log, use the following code. In the following code, replace 'source' with the API name of the source permission set and 'target' with the API name of the target permission set.
PermissionSetCopyUtil.copyPermissions('source','target',false);
- To view the comparison of the permission sets in the log and update the changes, use the following code. In the following code, replace 'source' with the API name of the source permission set and 'target' with the API name of the target permission set.
PermissionSetCopyUtil.copyPermissions('source','target',true);
Note: In the above Replace 'source' with the actual API name of the source permission set and 'target' with the actual API name of the target permission set.Code snippetThe following code may be run to compare the Zuora managedmanaged package permission sets with custom permission sets./** * @description Utility class to copy permissions from one permission set to another */ public with sharing class PermissionSetCopyUtil { /** * @description Copies permissions from source permission set to target permission set. * This utility only adds permissions to the target permission set and never removes any existing permissions. * @param sourcePermSetName API NAME of the source permission set * @param targetPermSetName API NAME of the target permission set * @param performDML When False:Permissions can be reviewed in the log.Nothing will be updated. When True: Permissions will be updated. * @return Result containing success status and any error messages */ public static CopyResult copyPermissions(string sourcePermSetName, string targetPermSetName,Boolean performDML) { CopyResult result = new CopyResult(); try { // Validate input parameters if (String.isBlank(sourcePermSetName) || String.isBlank(targetPermSetName)) { return new CopyResult(false, 'Permission Set names cannot be blank'); } // Single optimized query to get both permission sets Map<String, PermissionSet> permSetMap = new Map<String, PermissionSet>(); for (PermissionSet ps : [SELECT Id, Name FROM PermissionSet WHERE Name IN (:sourcePermSetName, :targetPermSetName)]) { permSetMap.put(ps.Name, ps); } // Validate both permission sets exist PermissionSet sourcePermSet = permSetMap.get(sourcePermSetName); if (sourcePermSet == null) { return new CopyResult(false, 'Source Permission Set not found: ' + sourcePermSetName); } PermissionSet targetPermSet = permSetMap.get(targetPermSetName); if (targetPermSet == null) { return new CopyResult(false, 'Target Permission Set not found: ' + targetPermSetName); } // Prevent copying to the same permission set if (sourcePermSet.Id == targetPermSet.Id) { return new CopyResult(false, 'Source and target permission sets cannot be the same'); } // Copy object permissions result.objectPermissionResults = copyObjectPermissions(sourcePermSet.Id, targetPermSet.Id,performDML); // Copy field permissions result.fieldPermissionResults = copyFieldPermissions(sourcePermSet.Id, targetPermSet.Id,performDML); // Copy class access result.classAccessResults = copyClassAccess(sourcePermSet.Id, targetPermSet.Id,performDML); result.success = true; result.message = 'Permission copy completed successfully'; System.debug(JSON.serialize(result)); } catch (Exception e) { System.debug(e.getStackTraceString()); System.debug(e.getMessage()); result.success = false; result.message = 'Error copying permissions: ' + e.getMessage(); System.debug(JSON.serialize(result)); } return result; } /** * @description Copies object permissions from source to target permission set * @param sourcePermSetId Source permission set ID * @param targetPermSetId Target permission set ID * @param performDML When False:Permissions can be reviewed in the log.Nothing will be updated. When True: Permissions will be updated. * @return List of results for each object permission copied */ private static List<PermissionResult> copyObjectPermissions(Id sourcePermSetId, Id targetPermSetId,Boolean performDML) { List<PermissionResult> results = new List<PermissionResult>(); // Query source object permissions List<ObjectPermissions> sourceObjectPerms = [ SELECT Id, SObjectType, PermissionsCreate, PermissionsRead, PermissionsEdit, PermissionsDelete, PermissionsViewAllRecords, PermissionsModifyAllRecords FROM ObjectPermissions WHERE ParentId = :sourcePermSetId ]; // Query existing target object permissions for upsert operation Map<String, ObjectPermissions> targetObjectPermsMap = new Map<String, ObjectPermissions>(); for (ObjectPermissions op : [ SELECT Id, SObjectType, PermissionsCreate, PermissionsRead, PermissionsEdit, PermissionsDelete, PermissionsViewAllRecords, PermissionsModifyAllRecords FROM ObjectPermissions WHERE ParentId = :targetPermSetId ]) { targetObjectPermsMap.put(op.SObjectType, op); } // Prepare object permissions to upsert List<ObjectPermissions> objectPermsToUpsert = new List<ObjectPermissions>(); for (ObjectPermissions sourceObjPerm : sourceObjectPerms) { // Check if object permission already exists in target ObjectPermissions targetObjPerm = targetObjectPermsMap.get(sourceObjPerm.SObjectType); if (targetObjPerm == null) { // Create new object permission targetObjPerm = new ObjectPermissions( ParentId = targetPermSetId, SObjectType = sourceObjPerm.SObjectType, PermissionsCreate = sourceObjPerm.PermissionsCreate, PermissionsRead = sourceObjPerm.PermissionsRead, PermissionsEdit = sourceObjPerm.PermissionsEdit, PermissionsDelete = sourceObjPerm.PermissionsDelete, PermissionsViewAllRecords = sourceObjPerm.PermissionsViewAllRecords, PermissionsModifyAllRecords = sourceObjPerm.PermissionsModifyAllRecords ); results.add(new PermissionResult(sourceObjPerm.SObjectType, 'Created')); } else { Boolean isUpdated = false; if(sourceObjPerm.PermissionsCreate != targetObjPerm.PermissionsCreate){ System.debug('Object Name: ' + sourceObjPerm.SObjectType + ' Source Create Permission : ' + sourceObjPerm.PermissionsCreate + ' Target Create Permission : ' + targetObjPerm.PermissionsCreate); targetObjPerm.PermissionsCreate = targetObjPerm.PermissionsCreate || sourceObjPerm.PermissionsCreate; isUpdated = true; } if(sourceObjPerm.PermissionsRead != targetObjPerm.PermissionsRead){ System.debug('Object Name: ' + sourceObjPerm.SObjectType + ' Source Read Permission : ' + sourceObjPerm.PermissionsRead + ' Target Read Permission : ' + targetObjPerm.PermissionsRead); targetObjPerm.PermissionsRead = targetObjPerm.PermissionsRead || sourceObjPerm.PermissionsRead; isUpdated = true; } if(sourceObjPerm.PermissionsEdit != targetObjPerm.PermissionsEdit){ System.debug('Object Name: ' + sourceObjPerm.SObjectType + ' Source Edit Permission : ' + sourceObjPerm.PermissionsEdit + ' Target Edit Permission : ' + targetObjPerm.PermissionsEdit); targetObjPerm.PermissionsEdit = targetObjPerm.PermissionsEdit || sourceObjPerm.PermissionsEdit; isUpdated = true; } if(sourceObjPerm.PermissionsDelete != targetObjPerm.PermissionsDelete){ System.debug('Object Name: ' + sourceObjPerm.SObjectType + ' Source Delete Permission : ' + sourceObjPerm.PermissionsDelete + ' Target Delete Permission : ' + targetObjPerm.PermissionsDelete); targetObjPerm.PermissionsDelete = targetObjPerm.PermissionsDelete || sourceObjPerm.PermissionsDelete; isUpdated = true; } if(sourceObjPerm.PermissionsViewAllRecords != targetObjPerm.PermissionsViewAllRecords){ System.debug('Object Name: ' + sourceObjPerm.SObjectType + ' Source View All Permission : ' + sourceObjPerm.PermissionsViewAllRecords + ' Target View All Permission : ' + targetObjPerm.PermissionsViewAllRecords); targetObjPerm.PermissionsViewAllRecords = targetObjPerm.PermissionsViewAllRecords || sourceObjPerm.PermissionsViewAllRecords; isUpdated = true; } if(sourceObjPerm.PermissionsModifyAllRecords != targetObjPerm.PermissionsModifyAllRecords){ System.debug('Object Name: ' + sourceObjPerm.SObjectType + ' Source Modify All Permission : ' + sourceObjPerm.PermissionsModifyAllRecords + ' Target Modify All Permission : ' + targetObjPerm.PermissionsModifyAllRecords); targetObjPerm.PermissionsModifyAllRecords = targetObjPerm.PermissionsModifyAllRecords || sourceObjPerm.PermissionsModifyAllRecords; isUpdated = true; } if(isUpdated){ results.add(new PermissionResult(sourceObjPerm.SObjectType, 'Updated')); } } objectPermsToUpsert.add(targetObjPerm); } // Upsert object permissions if (performDML && !objectPermsToUpsert.isEmpty()) { upsert objectPermsToUpsert; } return results; } /** * @description Copies field permissions from source to target permission set * @param sourcePermSetId Source permission set ID * @param targetPermSetId Target permission set ID * @param performDML When False:Permissions can be reviewed in the log.Nothing will be updated. When True: Permissions will be updated. * @return List of results for each field permission copied */ private static List<PermissionResult> copyFieldPermissions(Id sourcePermSetId, Id targetPermSetId,Boolean performDML) { List<PermissionResult> results = new List<PermissionResult>(); // Query source field permissions List<FieldPermissions> sourceFieldPerms = [ SELECT Id, Field, PermissionsRead, PermissionsEdit, SobjectType FROM FieldPermissions WHERE ParentId = :sourcePermSetId ]; // Query existing target field permissions for upsert operation Map<String, FieldPermissions> targetFieldPermsMap = new Map<String, FieldPermissions>(); for (FieldPermissions fp : [ SELECT Id, Field, PermissionsRead, PermissionsEdit, SobjectType FROM FieldPermissions WHERE ParentId = :targetPermSetId ]) { targetFieldPermsMap.put(fp.Field, fp); } // Prepare field permissions to upsert List<FieldPermissions> fieldPermsToUpsert = new List<FieldPermissions>(); for (FieldPermissions sourceFieldPerm : sourceFieldPerms) { // Check if field permission already exists in target FieldPermissions targetFieldPerm = targetFieldPermsMap.get(sourceFieldPerm.Field); if (targetFieldPerm == null) { // Create new field permission targetFieldPerm = new FieldPermissions( ParentId = targetPermSetId, Field = sourceFieldPerm.Field, SobjectType = sourceFieldPerm.SobjectType, PermissionsRead = sourceFieldPerm.PermissionsRead, PermissionsEdit = sourceFieldPerm.PermissionsEdit ); results.add(new PermissionResult(sourceFieldPerm.Field, 'Created')); } else { Boolean isUpdated = false; if(targetFieldPerm.PermissionsRead != sourceFieldPerm.PermissionsRead){ System.debug('Field Name: ' + targetFieldPerm.Field + ' Source Read Permission : ' + sourceFieldPerm.PermissionsRead + ' Target Read Permission : ' + targetFieldPerm.PermissionsRead); targetFieldPerm.PermissionsRead = targetFieldPerm.PermissionsRead || sourceFieldPerm.PermissionsRead; } if(targetFieldPerm.PermissionsEdit != sourceFieldPerm.PermissionsEdit){ System.debug('Field Name: ' + targetFieldPerm.Field + ' Source Edit Permission : ' + sourceFieldPerm.PermissionsEdit + ' Target Edit Permission : ' + targetFieldPerm.PermissionsEdit); targetFieldPerm.PermissionsEdit = targetFieldPerm.PermissionsEdit || sourceFieldPerm.PermissionsEdit; } // Update existing field permission - only add permissions, never remove them if(isUpdated){ results.add(new PermissionResult(sourceFieldPerm.Field, 'Updated')); } } fieldPermsToUpsert.add(targetFieldPerm); } // Upsert field permissions if (performDML && !fieldPermsToUpsert.isEmpty()) { Database.upsert(fieldPermsToUpsert,false); } return results; } /** * @description Copies Apex class access from source to target permission set * @param sourcePermSetId Source permission set ID * @param targetPermSetId Target permission set ID * @param performDML When False:Permissions can be reviewed in the log.Nothing will be updated. When True: Permissions will be updated. * @return List of results for each class access copied */ private static List<PermissionResult> copyClassAccess(Id sourcePermSetId, Id targetPermSetId,Boolean performDML) { List<PermissionResult> results = new List<PermissionResult>(); // Query source class access List<SetupEntityAccess> sourceClassAccess = [ SELECT Id, SetupEntityId, SetupEntityType FROM SetupEntityAccess WHERE ParentId = :sourcePermSetId AND SetupEntityType = 'ApexClass' ]; // Query existing target class access for upsert operation Map<Id, SetupEntityAccess> targetClassAccessMap = new Map<Id, SetupEntityAccess>(); for (SetupEntityAccess sea : [ SELECT Id, SetupEntityId, SetupEntityType FROM SetupEntityAccess WHERE ParentId = :targetPermSetId AND SetupEntityType = 'ApexClass' ]) { targetClassAccessMap.put(sea.SetupEntityId, sea); } // Query class names for better reporting Map<Id, String> classNames = new Map<Id, String>(); for (ApexClass cls : [SELECT Id, Name FROM ApexClass WHERE Id IN (SELECT SetupEntityId FROM SetupEntityAccess WHERE ParentId = :sourcePermSetId AND SetupEntityType = 'ApexClass')]) { classNames.put(cls.Id, cls.Name); } // Prepare class access to insert List<SetupEntityAccess> classAccessToInsert = new List<SetupEntityAccess>(); for (SetupEntityAccess sourceAccess : sourceClassAccess) { // Check if class access already exists in target if (!targetClassAccessMap.containsKey(sourceAccess.SetupEntityId)) { // Create new class access SetupEntityAccess targetAccess = new SetupEntityAccess( ParentId = targetPermSetId, SetupEntityId = sourceAccess.SetupEntityId //SetupEntityType = 'ApexClass' ); classAccessToInsert.add(targetAccess); String className = classNames.containsKey(sourceAccess.SetupEntityId) ? classNames.get(sourceAccess.SetupEntityId) : String.valueOf(sourceAccess.SetupEntityId); results.add(new PermissionResult(className, 'Created')); } } // Insert class access if (performDML && !classAccessToInsert.isEmpty()) { insert classAccessToInsert; } return results; } /** * @description Class to hold the result of a permission copy operation */ public class CopyResult { @AuraEnabled public Boolean success { get; set; } @AuraEnabled public String message { get; set; } @AuraEnabled public List<PermissionResult> objectPermissionResults { get; set; } @AuraEnabled public List<PermissionResult> fieldPermissionResults { get; set; } @AuraEnabled public List<PermissionResult> classAccessResults { get; set; } @AuraEnabled public List<PermissionResult> pageAccessResults { get; set; } public CopyResult() { this.success = false; this.objectPermissionResults = new List<PermissionResult>(); this.fieldPermissionResults = new List<PermissionResult>(); this.classAccessResults = new List<PermissionResult>(); this.pageAccessResults = new List<PermissionResult>(); } public CopyResult(Boolean success, String message) { this(); this.success = success; this.message = message; } } /** * @description Class to hold the result of a single permission copy operation */ public class PermissionResult { @AuraEnabled public String name { get; set; } @AuraEnabled public String status { get; set; } public PermissionResult(String name, String status) { this.name = name; this.status = status; } } }