Compare Zuora managed package permission sets with custom permission sets
You can compare the Zuora managed managed package permission sets with custom permission sets by running the code provided in this article.
- 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);
- 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.
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 snippet
The following code may be run to compare the Zuora managed managed 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;
}
}
}
