/
Apex Script-Driven Configuration Guide (FDM)

Apex Script-Driven Configuration Guide (FDM)

This documentation explains how Salesforce org admins can successfully set up Cuneiform® for CRM using our collection of Apex scripts. These scripts perform most of the point-and-click configuration required in a fraction of the time spent declaratively performing the same activities.

APPLIES TO | CUNEIFORM FOR CRM FIELD AND DATA MANAGEMENT

Once installed, Cuneiform for CRM requires some manual configuration to enable profiling against your org’s Salesforce objects. This page contains Apex Scripts that automate most of these activities – reducing configuration time to under ten (10) minutes – vs. the thirty (30) minutes configuration takes manually.

If you’re unfamiliar with how to execute Apex Scripts – please consider completing Salesforce’s Developer Console Basics Trailhead Trail. The trail will teach the skills necessary to execute these scripts.

Please visit our Declarative Configuration guide for step-by-step instructions on setting up your Salesforce org to support Cuneiform for CRM. It includes detailed walkthroughs on creating and securing the Connected App that Cuneiform for CRM uses to profile Salesforce Objects and metadata. Use the guide to review Cuneiform for CRM’s configuration requirements.

Apex Script-Driven Configuration Guide

Complete the activities outlined in the following seven (7) steps to finish your Cuneiform for CRM: Field and Data Management configuration using our Apex configuration scripts. Once you’ve completed the configuration, you can verify it using the Cuneiform for CRM: Control Panel.

 

Expand the element below to open the Apex script for this configuration step.

/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Anonymous Apex to create our Self-Signed Certificate * Actions performed by this script: * * * [1:] Verify that our Cuneiform for CRM: Self-Signed Certifciate Exists * * [2:] If it does not -- then create the certificate * * This script was created to run before exercising the Control Panel to validate the installation. * It automates the configuration steps described in the Cuneiform for Salesforce product documentation * via https://jira-peernova.atlassian.net/wiki/spaces/CFCPD/pages/2598993921 * * See https://help.salesforce.com/s/articleView?id=sf.security_keys_creating.htm&type=5 * for details on the necessary object and security permissions required to create self-signed * certificcates and execute this script successfully. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ // Initialize local variables HttpRequest req; HttpResponse res; String retrieveCertificateXML; String certificateXML; // Initialize the visual formatting variables String spacer = ' '; String bdr = '---------------------------------------------------------------------------------------------------------------------------------'; // Initialize success messages (so we don't have to repeat them) String successLine1 = spacer + 'Nice work! Please visit'; String successLine2 = spacer + 'https://peernova.link/cuneiform/fdm/setup/step-002'; String successLine3 = spacer + 'to complete the next configuration step: Create the Connected App Permission-Set.'; System.debug(bdr); System.debug(spacer + 'Cuneiform for CRM: Field and Data Management: Certificate Creation Script'); System.debug(spacer + 'Create the Cuneiform for CRM: Self-Signed Certificate in Your Salesforce Org.'); // Initialize the ConnectedApp details String certificateYear = String.valueOf(Datetime.now().year() + 2); // Initialize the XML document used to create the certificate certificateXML = '<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><env:Header><SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata"><sessionId>{0}</sessionId></SessionHeader></env:Header><env:Body><createMetadata xmlns="http://soap.sforce.com/2006/04/metadata"><metadata xsi:type="Certificate"><fullName>Cuneiform_for_CRM_Self_Signed_Certificate</fullName><caSigned>false</caSigned><encryptedWithPlatformEncryption>false</encryptedWithPlatformEncryption><expirationDate>{1}-01-01T00:00:00.000Z</expirationDate><keySize>4096</keySize><masterLabel>Cuneiform for CRM: Self-Signed Certificate</masterLabel><privateKeyExportable>true</privateKeyExportable></metadata></createMetadata></env:Body></env:Envelope>'; // Initialize the xml document containing the read-request details retrieveCertificateXML = '<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><env:Header><SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata"><sessionId>{0}</sessionId></SessionHeader></env:Header><env:Body><readMetadata xmlns="http://soap.sforce.com/2006/04/metadata"><type>Certificate</type><fullNames>Cuneiform_for_CRM_Self_Signed_Certificate</fullNames></readMetadata></env:Body></env:Envelope>'; retrieveCertificateXML = String.format(retrieveCertificateXML, new String[] { UserInfo.getSessionId() }); // Initialize the httpRequest to verify the certificate exists req = new HttpRequest(); req.setEndpoint(Url.getOrgDomainUrl().toExternalForm() + '/services/Soap/m/60.0'); req.setMethod('POST'); req.setHeader('Content-Type', 'text/xml'); req.setHeader('SOAPAction', '""'); req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId()); req.setBody(retrieveCertificateXML); // Process the httpRequest res = new Http().send(req); // Check if the certificate already exists if (res.getBody().contains('<records xsi:type="Certificate"><fullName>Cuneiform_for_CRM_Self_Signed_Certificate</fullName>')) { System.debug(bdr); System.debug(spacer + 'We found a self-signed certificate with the API Name'); System.debug(spacer + '[Cuneiform_for_CRM_Self_Signed_Certificate] in this Salesforce org.'); System.debug(spacer); System.debug(successLine1); System.debug(successLine2); System.debug(successLine3); System.debug(bdr); } else { // Otherwise, let's create the certificate certificateXML = String.format(certificateXML, new String[] { UserInfo.getSessionId(), certificateYear }); // Apply the certificate details to the request and process it req.setBody(certificateXML); // Process the httpRequest res = new Http().send(req); // Check the response and audit / output the results to the end-user if (!res.getBody().contains('<success>true</success>')) { System.debug(bdr); System.debug(spacer + 'We were unable to create the Cuneiform for CRM: Self-Signed Certificate. Please review the error response for details.'); System.debug(spacer + 'Metadata API Error Response:'); System.debug(spacer); System.debug(res.getBody().mid(res.getBody().indexOf('<errors>'), res.getBody().indexOf('</errors>') - (res.getBody().indexOf('<errors>') - 9))); System.debug(spacer); System.debug(spacer + 'Please review Metadata API Error Response, and try again. Verify that you have access'); System.debug(spacer + 'and permission to create Metadata via the Metadata API, and that the Cuneiform for CRM'); System.debug(spacer + 'Self-Signed Certificate does not already exist in your Org.'); } else { System.debug(spacer + 'The Self-Signed Certificate was successfully created.'); System.debug(spacer); System.debug(successLine1); System.debug(successLine2); System.debug(successLine3); } System.debug(bdr); }

Execute this Anonymous Apex script to create the Cuneiform for CRM: Self-Signed Certificate. Use our step-by-step guide if you are unfamiliar with executing Apex Scripts via the Salesforce Developer Console.

 

Expand the element below to open the Apex script for this configuration step.

/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Anonymous Apex to create our Connected App Permission-Set * Actions performed by this script: * * * [1:] Verify that our Connected App permission-set exists * * [2:] If it does not -- then create the Connected App permission-set * * This script was created to run before exercising the Control Panel to validate the installation. * It automates the configuration steps described in the Cuneiform for Salesforce product documentation * via https://jira-peernova.atlassian.net/wiki/spaces/CFCPD/pages/2596798483/ * * See https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_permissionset.htm * for details on the necessary object and security permissions required to create a permission-set * and execute this script successfully. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ // Initialize local variables List<PermissionSet> adminPermSet; String adminPermSetApiName; List<PermissionSet> permSetValidation; String permSetLabel; String permSetApiName; String permSetDesc; Boolean permSetSessionActivationRequired; PermissionSet permSet; Boolean exceptionOccurred; DmlException caughtException; // Default constants we use in our script for layout and testing / debugging purposes Boolean testException = false; String spacer = ' '; String border = '---------------------------------------------------------------------------------------------------------------------------------'; String testExceptionMessage = 'This is a test exception to verify that the script can handle exceptions.'; // Initialize success messages (so we don't have to repeat them) String successLine1 = spacer + 'Nice work! Please visit'; String successLine2 = spacer + 'https://peernova.link/cuneiform/fdm/setup/step-003'; String successLine3 = spacer + 'to complete the next configuration step: Create the Administrative Permission-Set Group.'; // Initialize script constants (do not change these values) adminPermSetApiName = 'Cuneiform_for_CRM_Administrative_User'; permSetLabel = 'Cuneiform for CRM: Connected App Assignment'; permSetApiName = 'Cuneiform_for_CRM_Connected_App_Assignment'; permSetDesc = 'This permission set supports administrative access to PeerNova\'s Cuneiform for CRM application. It provides users access to the Connected App that brokers Salesforce API requests.'; permSetSessionActivationRequired = false; System.debug(border); System.debug(spacer + 'Cuneiform for CRM: Field and Data Management: Configuration Apex Script'); System.debug(spacer + '1. Verify that the Connected App Permission-Set exists.'); // First, let's verify that our Administrative Permission-Set exists (verifying we're installed) adminPermSet = [SELECT Id FROM PermissionSet WHERE Name = :adminPermSetApiName]; // Was a valid Permission Set found? if (adminPermSet.size() == 0) { // Output that the permission-set was not found -- and needs to be verified System.debug(border); System.debug(spacer + 'We could not verify your Cuneiform for CRM: Field and Data Management installation.'); System.debug(border); System.debug(spacer + 'The Administrative Permission-Set "' + adminPermSetApiName + '" was not found.'); System.debug(spacer + 'Please ensure that Cuneiform for CRM is installed and that you have system administrator'); System.debug(spacer + 'level access to complete the installation.'); System.debug(spacer); System.debug(spacer + 'You can install Cuneiform for CRM by opening our appexchange listing at'); System.debug(spacer + 'https://peernova.link/cuneiform/install/fdm/appexchange'); System.debug(spacer + 'Click on the "Get It Now" button to install Cuneiform for CRM: Field and Data Management.'); System.debug(border); } else { // First, let's verify that our Connected App permission-set exists permSetValidation = [SELECT Id FROM PermissionSet WHERE Name = :permSetApiName]; // Was a valid Permission Set found? if (permSetValidation.size() <> 0) { // Output that the permission-set was verified and already exists System.debug(border); System.debug(spacer + 'The Permission-Set "' + permSetApiName + '" was successfully verified.'); System.debug(spacer); System.debug(successLine1); System.debug(successLine2); System.debug(successLine3); System.debug(border); // Otherwise, let's create one } else { // If not -- then let's create one permSet = new PermissionSet(); // Default the permission-set with the values we've defined permSet.Name = permSetApiName; permSet.Label = permSetLabel; permSet.Description = permSetDesc; permSet.HasActivationRequired = permSetSessionActivationRequired; // Create the permission-set try { // Test to see if we should throw an exception if (testException) { throw new DmlException(testExceptionMessage); // Otherwise, insert the permission-set } else { insert permSet; exceptionOccurred = false; } } catch (DmlException e) { caughtException = e; exceptionOccurred = true; } // Output that the permission-set was verified and already exists System.debug(border); System.debug(spacer + 'The Permission-Set "' + permSetApiName + '" was not found; attempting to create it.'); // Did an exception occur? if (exceptionOccurred) { System.debug(spacer + 'An error occurred while attempting to create the Permission-Set [' + permSetApiName + '].'); System.debug(spacer + 'Error Message: ' + caughtException.getMessage()); System.debug(border); System.debug(spacer + caughtException.getStackTraceString()); System.debug(border); System.debug(spacer + 'DML exceptions often occur because of rights or access permissions. Please verify that'); System.debug(spacer + 'the user executing this script has the necessary rights to create a permission-set.'); System.debug(spacer + 'Try executing this script again once you have addressed the root cause of this exception.'); } else { System.debug(spacer + 'The Permission-Set "' + permSetApiName + '" was successfully created.'); System.debug(spacer); System.debug(successLine1); System.debug(successLine2); System.debug(successLine3); } System.debug(border); } }

Execute this Anonymous Apex script to create the Cuneiform for CRM: Connected App Assignment permission set. Use our step-by-step guide if you are unfamiliar with executing Apex Scripts via the Salesforce Developer Console.

 

Expand the element below to open the Apex script for this configuration step.

/** * ─────────────────────────────────────────────────────────────────────────────────────────────────┐ * Anonymous Apex to create our Administrative Permission-Set Group * Actions performed by this script: * * * [1:] Verify that our Administrative Permission-Set Group exists * * [2:] If it does not -- then create the Administrative Permission-Set Group * * [3:] Associate the Connected App Permission-Set with the Administrative Permission-Set Group * * This script was created to run before exercising the Control Panel to validate the installation. * It automates the configuration steps described in the Cuneiform for Salesforce product documentation * via https://jira-peernova.atlassian.net/wiki/spaces/CFCPD/pages/2596798483/ * * See https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_permissionsetgroup.htm * and https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_permissionsetgroupcomponent.htm * for details on the necessary object and security permissions required to create a permission-set group, * associate a permission-set, and and execute this script successfully. * ─────────────────────────────────────────────────────────────────────────────────────────────────┘ */ // Initialize local variables String permSetGroupLabel; String permSetGroupApiName; String permSetGroupDesc; Boolean permSetGroupSessionActivationRequired; List<PermissionSet> adminPermSet; String adminPermSetApiName; List<PermissionSetGroup> adminPermSetGroup; PermissionSetGroup permSetGroup; Boolean exceptionOccurred; DmlException caughtException; // Default constants we use in our script for layout and testing / debugging purposes Boolean testException = false; String spacer = ' '; String border = '---------------------------------------------------------------------------------------------------------------------------------'; String testExceptionMessage = 'This is a test exception to verify that the script can handle exceptions.'; // Initialize success messages (so we don't have to repeat them) String successLine1 = spacer + 'Nice work! Please visit'; String successLine2 = spacer + 'https://peernova.link/cuneiform/fdm/setup/step-004'; String successLine3 = spacer + 'to complete the next permission-set group configuration step: Assign Permission-Sets and Users.'; // Initialize local variables (do not change these values) adminPermSetApiName = 'Cuneiform_for_CRM_Administrative_User'; permSetGroupLabel = 'Cuneiform for CRM: Administrators'; permSetGroupApiName = 'Cuneiform_for_CRM_Administrators'; permSetGroupDesc = 'This permission set group manages the collection of permission sets required to support administrative access to Cuneiform for CRM. Org Admins can assign this group to users that should have profiling capabilities within their Salesforce Org.'; permSetGroupSessionActivationRequired = false; System.debug(border); System.debug(spacer + 'Cuneiform for CRM: Field and Data Management: Configuration Apex Script'); System.debug(spacer + '2. Verify that the Administrative Permission-Set Group exists.'); // First, let's verify that our Administrative Permission-Set exists (verifying we're installed) adminPermSet = [SELECT Id FROM PermissionSet WHERE Name = :adminPermSetApiName]; // Was a valid Permission Set found? if (adminPermSet.size() == 0) { // Output that the permission-set was not found -- and needs to be verified System.debug(border); System.debug(spacer + 'The Administrative Permission-Set "' + adminPermSetApiName + '" was not found.'); System.debug(spacer + 'Please ensure that Cuneiform for CRM is installed and that you have system administrator'); System.debug(spacer + 'level access to complete the installation.'); System.debug(spacer); System.debug(spacer + 'You can install Cuneiform for CRM by opening our appexchange listing at'); System.debug(spacer + 'https://peernova.link/cuneiform/install/fdm/appexchange'); System.debug(spacer + 'Click on the "Get It Now" button to install Cuneiform for CRM: Field and Data Management.'); System.debug(border); } else { // Next, let's see if our Permission-Set Group exists adminPermSetGroup = [SELECT Id FROM PermissionSetGroup WHERE DeveloperName = :permSetGroupApiName]; // Was the administrative permission-set group found? if (adminPermSetGroup.size() > 0) { // If so, output that the permission-set group and its configuration was verified System.debug(border); System.debug(spacer + 'The Permission-Set Group [' + permSetGroupApiName + '] was successfully verified.'); System.debug(spacer); System.debug(successLine1); System.debug(successLine2); System.debug(successLine3); System.debug(border); } else { // If not -- then let's create one permSetGroup = new PermissionSetGroup(); // Default the permission-set with the values we've defined permSetGroup.DeveloperName = permSetGroupApiName; permSetGroup.MasterLabel = permSetGroupLabel; permSetGroup.Description = permSetGroupDesc; permSetGroup.HasActivationRequired = permSetGroupSessionActivationRequired; // Create the permission-set try { // Test to see if we should throw an exception if (testException) { throw new DmlException(testExceptionMessage); // Otherwise, insert the permission-set } else { // Insert the permission-set insert permSetGroup; // Audit that no exceptions took place exceptionOccurred = false; } } catch (DmlException e) { caughtException = e; exceptionOccurred = true; } // Output that the permission-set was verified and already exists System.debug(border); System.debug(' The Permission-Set Group [' + permSetGroupApiName + '] was not found; attempting to create it.'); if (exceptionOccurred) { System.debug(spacer + 'An error occurred while attempting to create the Permission-Set Group [' + permSetGroupApiName + '].'); System.debug(spacer + 'Error Message: ' + caughtException.getMessage()); System.debug(border); System.debug(spacer + caughtException.getStackTraceString()); System.debug(border); System.debug(spacer + 'DML exceptions often occur because of rights or access permissions. Please verify that'); System.debug(spacer + 'the user executing this script has the necessary rights to create a permission-set.'); System.debug(spacer + 'Try executing this script again once you have addressed the root cause of this exception.'); } else { System.debug(spacer + 'The Permission-Set Group [' + permSetGroupApiName + '] was successfully created.'); System.debug(spacer); System.debug(successLine1); System.debug(successLine2); System.debug(successLine3); } System.debug(border); } }

Execute this Anonymous Apex script to create the Cuneiform for CRM: Administrators permission-set group. Use our step-by-step guide if you are unfamiliar with executing Apex Scripts via the Salesforce Developer Console.

 

Expand the element below to open the Apex script for this configuration step.

// Initialize local variables String permSetGroupApiName; List<PermissionSet> adminPermSet; String adminPermSetApiName; List<PermissionSet> connectedAppPermSet; String connectedAppPermSetApiName; List<PermissionSetGroup> adminPermSetGroup; List<PermissionSetGroupComponent> adminPermSetGroupComponents; List<PermissionSetGroupComponent> permSetGroupComponents; List<Id> adminPermSetIds; List<Id> sourcePermSetIds; List<Id> targetPermSetIds; Boolean exceptionOccurred; DmlException caughtException; Boolean hasUser; // Default constants we use in our script for layout and testing / debugging purposes Boolean testException = false; String spacer = ' '; String bdr = '---------------------------------------------------------------------------------------------------------------------------------'; String testExceptionMessage = 'This is a test exception.'; // Initialize local variables (do not change these values) adminPermSetApiName = 'Cuneiform_for_CRM_Administrative_User'; connectedAppPermSetApiName = 'Cuneiform_for_CRM_Connected_App_Assignment'; permSetGroupApiName = 'Cuneiform_for_CRM_Administrators'; hasUser = false; System.debug(bdr); System.debug(spacer + 'Cuneiform for CRM: Field and Data Management: Configuration Apex Script'); System.debug(spacer + '3. Verify that the Administrative Group\'s required permission-set assignments exist.'); // First, let's verify that our Administrative Permission-Set exists (verifying we're installed) adminPermSet = [SELECT Id FROM PermissionSet WHERE Name = :adminPermSetApiName]; // Was a valid Permission Set found? if (adminPermSet.size() == 0) { // Output that the permission-set was not found -- and needs to be verified System.debug(bdr); System.debug(spacer + 'The Administrative Permission-Set "' + adminPermSetApiName + '" was not found.'); System.debug(spacer + 'Please ensure that Cuneiform for CRM is installed and that you have admin-level access.'); System.debug(spacer); System.debug(spacer + 'You can install Cuneiform for CRM by opening our appexchange listing at'); System.debug(spacer + 'https://peernova.link/cuneiform/install/fdm/appexchange'); System.debug(spacer + 'Click on the "Get It Now" button to install Cuneiform for CRM: Field and Data Management.'); System.debug(bdr); } else { // Next, let's see if our Permission-Set Group and ConnectedApp permission-set exists adminPermSetGroup = [SELECT Id FROM PermissionSetGroup WHERE DeveloperName = :permSetGroupApiName]; connectedAppPermSet = [SELECT Id FROM PermissionSet WHERE Name = :connectedAppPermSetApiName]; // Was the administrative permission-set group found? if (adminPermSetGroup.size() == 0 || connectedAppPermSet.size() == 0) { if (adminPermSetGroup.size() == 0) { System.debug(bdr); System.debug(spacer + 'The Permission-Set Group "' + permSetGroupApiName + '" was not found.'); System.debug(bdr); } if (connectedAppPermSet.size() == 0) { System.debug(bdr); System.debug(spacer + 'The Connected App permission-set "' + connectedAppPermSetApiName + '" was not found.'); System.debug(bdr); } } else { // Create the source permission-set collection and add the connected-app / admin ids sourcePermSetIds = new List<Id>(); sourcePermSetIds.add(connectedAppPermSet[0].Id); sourcePermSetIds.add(adminPermSet[0].Id); // Retrieve the permission-set group assignments -- so we can verify the connected app and admin permission-sets adminPermSetGroupComponents = [SELECT Id, PermissionSetId FROM PermissionSetGroupComponent WHERE PermissionSetGroupId = :adminPermSetGroup[0].Id AND PermissionSetId IN :sourcePermSetIds]; // Initialize the Id list adminPermSetIds = new List<Id>(); // Create a list of the permission-set Ids that are already associated with the administrative permission-set group for (PermissionSetGroupComponent thisComponent: adminPermSetGroupComponents) { adminPermSetIds.add(thisComponent.PermissionSetId); } targetPermSetIds = new List<Id>(); // Now, which permission-sets are missing from the administrative permission-set group? for (Id sourceId: sourcePermSetIds) { if (adminPermSetIds.contains(sourceId) == false) { targetPermSetIds.add(sourceId); } } // If we have permission-sets to add -- then let's add them if (targetPermSetIds.size() != 0) { // If not -- then let's back-fill the missing associations permSetGroupComponents = new List<PermissionSetGroupComponent>(); // Create component records for the missing associations for (Id thisTargetId : targetPermSetIds) { permSetGroupComponents.add( new PermissionSetGroupComponent( PermissionSetId = thisTargetId, PermissionSetGroupId = adminPermSetGroup[0].Id ) ); } } // Create the permission-set try { // Test to see if we should throw an exception if (testException) { throw new DmlException(testExceptionMessage); // Otherwise, insert the permission-set } else { // Insert the permission-set group permission-set assignments (if necessary) if (permSetGroupComponents != null) { insert permSetGroupComponents; } // Audit that no exceptions took place exceptionOccurred = false; } } catch (DmlException e) { caughtException = e; exceptionOccurred = true; } // Output that the permission-set was verified and already exists System.debug(bdr); if (permSetGroupComponents == null) { System.debug(spacer + 'The permission-set assignments for the Group [' + permSetGroupApiName + '] were successfully verified.'); } else { System.debug(spacer + 'The permission-set assignments for the Group [' + permSetGroupApiName + '] were not found.'); } if (exceptionOccurred) { System.debug(spacer + 'An error occurred while attempting to create the permission-set assignments for the Group [' + permSetGroupApiName + '].'); System.debug(spacer + 'Error Message: ' + caughtException.getMessage()); System.debug(bdr); System.debug(spacer + caughtException.getStackTraceString()); System.debug(bdr); System.debug(spacer + 'DML exceptions often occur because of rights or access permissions. Please verify that'); System.debug(spacer + 'the user executing this script has the necessary rights to create a permission-set.'); System.debug(spacer + 'Try executing this script again once you have addressed the root cause of this exception.'); } else { if (permSetGroupComponents != null) { System.debug(spacer + 'The missing permission-set assignments were successfully created.'); } System.debug(spacer); System.debug(spacer + 'Nice work! Please visit'); System.debug(spacer + 'https://peernova.link/cuneiform/fdm/setup/step-005'); System.debug(spacer + 'to complete the next permission-set configuration step: Assigning-Users.'); } System.debug(bdr); } }

Execute this Anonymous Apex script to create these permission set assignments. Use our step-by-step guide if you are unfamiliar with executing Apex Scripts via the Salesforce Developer Console.

 

Expand the element below to open the Apex script for this configuration step.

// Initialize local variables String permSetGroupApiName; List<PermissionSet> adminPermSet; String adminPermSetApiName; List<PermissionSetGroup> adminPermSetGroup; List<PermissionSetAssignment> adminUserAssignment; Boolean exceptionOccurred; DmlException caughtException; Boolean hasPermissionSets; Boolean hasUser; // Default constants we use in our script for layout and testing / debugging purposes Boolean testException = false; String spacer = ' '; String bdr = '---------------------------------------------------------------------------------------------------------------------------------'; String testExceptionMessage = 'This is a test exception.'; // Initialize local variables (do not change these values) adminPermSetApiName = 'Cuneiform_for_CRM_Administrative_User'; permSetGroupApiName = 'Cuneiform_for_CRM_Administrators'; hasPermissionSets = false; hasUser = false; System.debug(bdr); System.debug(spacer + 'Cuneiform for CRM: Field and Data Management: Configuration Apex Script'); System.debug(spacer + '4. Provide User Access to the Administrative Permission-Set Group.'); // First, let's verify that our Administrative Permission-Set exists (verifying we're installed) adminPermSet = [SELECT Id FROM PermissionSet WHERE Name = :adminPermSetApiName]; // Was a valid Permission Set found? if (adminPermSet.size() == 0) { // Output that the permission-set was not found -- and needs to be verified System.debug(bdr); System.debug(spacer + 'The Administrative Permission-Set "' + adminPermSetApiName + '" was not found.'); System.debug(spacer + 'Please ensure that Cuneiform for CRM is installed and that you have admin-level access.'); System.debug(spacer); System.debug(spacer + 'You can install Cuneiform for CRM by opening our appexchange listing at'); System.debug(spacer + 'https://peernova.link/cuneiform/install/fdm/appexchange'); System.debug(spacer + 'Click on the "Get It Now" button to install Cuneiform for CRM: Field and Data Management.'); System.debug(bdr); } else { // Next, let's see if our Permission-Set Group and ConnectedApp permission-set exists adminPermSetGroup = [SELECT Id FROM PermissionSetGroup WHERE DeveloperName = :permSetGroupApiName]; // Audit if we couldn't find the administrative permission-set group if (adminPermSetGroup.size() == 0) { System.debug(bdr); System.debug(spacer + 'The Permission-Set Group "' + permSetGroupApiName + '" was not found.'); System.debug(bdr); } else { // Verify that the current user is associated with the administrative permission-set group adminUserAssignment = [SELECT Id FROM PermissionSetAssignment WHERE AssigneeId = :UserInfo.getUserId() AND PermissionSetGroupId = :adminPermSetGroup[0].Id]; if (adminUserAssignment.size() != 0) { System.debug(bdr); System.debug(spacer + 'The current user is already assigned to the Permission-Set Group "' + permSetGroupApiName + '".'); System.debug(spacer); System.debug(spacer + 'Nice work! Please visit'); System.debug(spacer + 'https://peernova.link/cuneiform/fdm/setup/step-006'); System.debug(spacer + 'to complete the next configuration step: Creating the Connected App.'); System.debug(bdr); } else { // Create the permission-set assignment try { // Test to see if we should throw an exception if (testException) { throw new DmlException(testExceptionMessage); } else { // Create the permission-set assignment insert new PermissionSetAssignment( AssigneeId = UserInfo.getUserId(), PermissionSetGroupId = adminPermSetGroup[0].Id ); // Audit that no exceptions took place exceptionOccurred = false; } } catch (DmlException e) { caughtException = e; exceptionOccurred = true; } // Output that the permission-set was verified and already exists System.debug(bdr); if (exceptionOccurred) { System.debug(spacer + 'An error occurred while attempting to create the permission-set assignment for the Group [' + permSetGroupApiName + '].'); System.debug(spacer + 'Error Message: ' + caughtException.getMessage()); System.debug(bdr); System.debug(spacer + caughtException.getStackTraceString()); System.debug(bdr); System.debug(spacer + 'DML exceptions often occur because of rights or access permissions. Please verify that'); System.debug(spacer + 'the user executing this script has the necessary rights to create a permission-set.'); System.debug(spacer + 'Try executing this script again once you have addressed the root cause of this exception.'); } else { System.debug(spacer + 'The current user was successfully assigned to the Permission-Set Group "' + permSetGroupApiName + '".'); System.debug(spacer); System.debug(spacer + 'Nice work! Please visit'); System.debug(spacer + 'https://peernova.link/cuneiform/fdm/setup/step-006'); System.debug(spacer + 'to complete the next configuration step: Creating the Connected App.'); } System.debug(bdr); } } }

Execute this Anonymous Apex script to create your user assignment. Use our step-by-step guide if you are unfamiliar with executing Apex Scripts via the Salesforce Developer Console.

 

Expand the element below to open the Apex script for this configuration step.

// Initialize local variables HttpRequest req; HttpResponse res; String connectedAppXML; String appConsumerKey; // Initialize the visual formatting variables String spacer = ' '; String bdr = '---------------------------------------------------------------------------------------------------------------------------------'; System.debug(bdr); System.debug(spacer + 'Cuneiform for CRM: Field and Data Management: Configuration Apex Script'); System.debug(spacer + '5. Create the Cuneiform for CRM: Connected App in Your Salesforce Org.'); // Initialize the ConnectedApp details String selfSignedCertificateApiName = 'Cuneiform_for_CRM_Self_Signed_Certificate'; String appApiName = 'Cuneiform_for_CRM_Connected_App'; String appLabel = 'Cuneiform for CRM: Connected App'; String appEmail = 'cuneiform.sf@peernova.com'; String appPermSet = 'Cuneiform for CRM: Connected App Assignment'; String appDescription = 'This Connected App is leveraged by the PeerNova: Cuneiform for CRM application to provide secure access to Salesforce REST APIs. We leverage REST APIs to monitor and profile data and metadata in this org.'; String appIconUrl = 'https://lh6.googleusercontent.com/3b6tVui747u3ty6d98JfkXTJCF5unEj6W2oOMs-upvatI0-ydNTA3k1b6Z1cJZOXQ8A=w2400'; String appLogoUrl = 'https://lh6.googleusercontent.com/ykSeeKgrxYndJj37ia2PoGx9-czBfgSk4jsTpYfUKG96l9k-Bp-NTfhdsNxyyC4hyIQ=w2400'; // Initialize local variables List<String> idSegments; Long epochTime; String epochTimeString; String orgId; String output; Double reverseCalc; // Initialize the idList idSegments = new List<String>(); // First, let's retrieve epochTime for today epochTime = Datetime.now().getTime(); epochTimeString = String.valueOf(epochTime); // Next, let's retrieve the orgId for this Org orgId = [SELECT Id FROM Organization LIMIT 1][0].Id; // Next, build-out the appConsumerKey for our ConnectedApp reverseCalc = Math.random(); if (reverseCalc < 0.5) { idSegments.add(epochTimeString.substring(0, 2).reverse()); } else { idSegments.add(epochTimeString.substring(0, 2)); } idSegments.add(EncodingUtil.convertToHex(Crypto.generateAesKey(256)).substring(6)); idSegments.add(orgId.substring(0, 3)); // Section Two of the ConnectedApp's Consumer Key reverseCalc = Math.random(); if (reverseCalc < 0.5) { idSegments.add(epochTimeString.substring(3, 5).reverse()); } else { idSegments.add(epochTimeString.substring(3, 5)); } idSegments.add(EncodingUtil.convertToHex(Crypto.generateAesKey(256)).substring(6)); idSegments.add(orgId.substring(4, 10)); // Section Three of the ConnectedApp's Consumer Key reverseCalc = Math.random(); if (reverseCalc < 0.5) { idSegments.add(epochTimeString.substring(6, 8).reverse()); } else { idSegments.add(epochTimeString.substring(6, 8)); } idSegments.add(orgId.substring(11, 13)); idSegments.add(EncodingUtil.convertToHex(Crypto.generateAesKey(256)).substring(6)); // Section Four of the ConnectedApp's Consumer Key reverseCalc = Math.random(); if (reverseCalc < 0.5) { idSegments.add(epochTimeString.substring(9, 12).reverse()); } else { idSegments.add(epochTimeString.substring(9, 12)); } idSegments.add(orgId.substring(14, 18)); idSegments.add(EncodingUtil.convertToHex(Crypto.generateAesKey(256)).substring(6)); // Join the shuffled elements into a single-string output = String.join(idSegments, ''); // Automatically trim this string down to 255 characters maximum appConsumerKey = output.substring(0, 255); // Initialize the xml document containing our connectedApp metadata connectedAppXML = '<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><env:Header><SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata"><sessionId>{0}</sessionId></SessionHeader></env:Header><env:Body><createMetadata xmlns="http://soap.sforce.com/2006/04/metadata"><metadata xsi:type="ConnectedApp"><fullName>{1}</fullName><label>{2}</label><contactEmail>{3}</contactEmail><description>{4}</description><iconUrl>{5}</iconUrl><logoUrl>{6}</logoUrl><oauthConfig><callbackUrl>https://cuneiform-crm.peernova.io</callbackUrl><consumerKey>{7}</consumerKey><isAdminApproved>true</isAdminApproved><isClientCredentialEnabled>false</isClientCredentialEnabled><isConsumerSecretOptional>false</isConsumerSecretOptional><isPkceRequired>true</isPkceRequired><isIntrospectAllTokens>false</isIntrospectAllTokens><isNamedUserJwtEnabled>false</isNamedUserJwtEnabled><isSecretRequiredForRefreshToken>true</isSecretRequiredForRefreshToken><oauthClientCredentialUser /><scopes>Api</scopes><scopes>Full</scopes><scopes>RefreshToken</scopes></oauthConfig><oauthPolicy><ipRelaxation>ENFORCE</ipRelaxation><refreshTokenPolicy>specific_lifetime:2:HOURS</refreshTokenPolicy></oauthPolicy><permissionSetName>{8}</permissionSetName><sessionPolicy><sessionTimeout>15</sessionTimeout></sessionPolicy></metadata></createMetadata></env:Body></env:Envelope>'; connectedAppXML = String.format(connectedAppXML, new String[] { UserInfo.getSessionId(), appApiName, appLabel, appEmail, appDescription, appIconUrl, appLogoUrl, appConsumerKey, appPermSet }); // Initialize the httpRequest to create the ConnectedApp req = new HttpRequest(); req.setEndpoint(Url.getOrgDomainUrl().toExternalForm() + '/services/Soap/m/60.0'); req.setMethod('GET'); req.setHeader('Content-Type', 'text/xml'); req.setHeader('SOAPAction', '""'); req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId()); req.setBody(connectedAppXML); // Process the httpRequest res = new Http().send(req); // Check the response and audit / output the results to the end-user if (!res.getBody().contains('<success>true</success>')) { System.debug(bdr); System.debug(spacer + 'We were unable to create the Cuneiform for CRM: Connected App. Please review the error response for details.'); System.debug(spacer + 'Metadata API Error Response:'); System.debug(spacer); System.debug(res.getBody().mid(res.getBody().indexOf('<errors>'), res.getBody().indexOf('</errors>') - (res.getBody().indexOf('<errors>') - 9))); System.debug(spacer); System.debug(spacer + 'Please review Metadata API Error Response, and try again. Verify that you have access'); System.debug(spacer + 'and permission to create Metadata via the Metadata API, and that the Cuneiform for CRM'); System.debug(spacer + 'Connected App does not already exist in your Org.'); System.debug(bdr); } else { // Initialize the metadata container properties Metadata.DeployContainer mdContainer = new Metadata.DeployContainer(); Metadata.CustomMetadata configProfileRecord = new Metadata.CustomMetadata(); // Create the Configuration Wrapper to get the Active Metadata Used for the Environment pnova__Active_Configuration__mdt activeConfigProfile = [SELECT Id, pnova__Active_Configuration_Profile__r.DeveloperName FROM pnova__Active_Configuration__mdt WHERE DeveloperName = 'Active_Configuration' LIMIT 1]; pnova__Configuration_Profile__mdt configProfile = [SELECT Id, DeveloperName, pnova__Certificate_Unique_Name__c, pnova__ConnectedApp_Label__c, pnova__ConnectedApp_Consumer_Key__c FROM pnova__Configuration_Profile__mdt WHERE DeveloperName = :activeConfigProfile.pnova__Active_Configuration_Profile__r.DeveloperName LIMIT 1]; // Initialize the name of the metadata we're going to process configProfileRecord.fullName = 'pnova__Configuration_Profile__mdt.pnova__' + configProfile.DeveloperName; configProfileRecord.label = 'Production'; Metadata.CustomMetadataValue connectedAppLabelField = new Metadata.CustomMetadataValue(); connectedAppLabelField.field = 'pnova__ConnectedApp_Label__c'; connectedAppLabelField.value = appLabel; configProfileRecord.values.add(connectedAppLabelField); Metadata.CustomMetadataValue consumerKeyField = new Metadata.CustomMetadataValue(); consumerKeyField.field = 'pnova__ConnectedApp_Consumer_Key__c'; consumerKeyField.value = appConsumerKey; configProfileRecord.values.add(consumerKeyField); Metadata.CustomMetadataValue certApiNameField = new Metadata.CustomMetadataValue(); certApiNameField.field = 'pnova__Certificate_Unique_Name__c'; certApiNameField.value = selfSignedCertificateApiName; configProfileRecord.values.add(certApiNameField); // Add the metadata to the container -- and process it mdContainer.addMetadata(configProfileRecord); Id jobId = Metadata.Operations.enqueueDeployment(mdContainer, null); System.debug(bdr); System.debug(spacer + 'The Cuneiform for CRM: Connected App was successfully created.'); System.debug(spacer + '-- see JobId: ' + jobId + ' for metadata deployment details.'); System.debug(spacer); System.debug(spacer + 'Nice Work! We have updated the Configuration Profile with the Connected App details.'); System.debug(spacer); System.debug(spacer + 'Please follow our remaining installation instructions via'); System.debug(spacer + 'https://peernova.link/cuneiform/fdm/setup/step-007'); System.debug(spacer + 'to enable digital signatures for your Connected App (the final step).'); System.debug(bdr); }

Execute this Anonymous Apex script to create the Connected App. Use our step-by-step guide if you are unfamiliar with executing Apex Scripts via the Salesforce Developer Console.

 

Expand the element below to open the Apex script for this configuration step.

// Initialize local variables HttpRequest req; HttpResponse res; String headerXML; String updateHeaderXML; String closeXML; String sessionHeaderXML; String connectedAppXML; String certificateXML; String retrieveCertificateXML; String retrieveConnectedAppXML; String updateConnectedAppXML; String updateContainerXML; String digitalCertificateXML; String updateResponseXML; String certContent; // Default the ConnectedApp Name String connectedAppName = 'Cuneiform_for_CRM_Connected_App'; // Initialize the visual formatting variables String spacer = ' '; String bdr = '---------------------------------------------------------------------------------------------------------------------------------'; System.debug(bdr); System.debug(spacer + 'Cuneiform for CRM: Field and Data Management: Configuration Apex Script'); System.debug(spacer + '6. Associate Your Self-Signed Certificate to the Connected App.'); // Initialize the xml document containing the read-request details headerXML = '<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://soap.sforce.com/2006/04/metadata">'; updateHeaderXML = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://soap.sforce.com/2006/04/metadata">'; sessionHeaderXML = '<soapenv:Header><tns:SessionHeader><tns:sessionId>{0}</tns:sessionId></tns:SessionHeader></soapenv:Header><soapenv:Body>'; retrieveCertificateXML = '<tns:readMetadata><type>Certificate</type><fullNames>Cuneiform_for_CRM_Self_Signed_Certificate</fullNames></tns:readMetadata>'; retrieveConnectedAppXML = '<tns:readMetadata><type>ConnectedApp</type><fullNames>' + connectedAppName + '</fullNames></tns:readMetadata>'; updateContainerXML = '<updateMetadata xmlns="http://soap.sforce.com/2006/04/metadata"><metadata xsi:type="ConnectedApp">{0}</metadata></updateMetadata>'; closeXML = '</soapenv:Body></soapenv:Envelope>'; // Seed the user's session for authentication sessionHeaderXML = String.format(sessionHeaderXML, new String[] {UserInfo.getSessionId()}); retrieveCertificateXML = headerXML + sessionHeaderXML + retrieveCertificateXML + closeXML; retrieveConnectedAppXML = headerXML + sessionHeaderXML + retrieveConnectedAppXML + closeXML; // Initialize the httpRequest to verify and retrieve the certificate req = new HttpRequest(); req.setEndpoint(Url.getOrgDomainUrl().toExternalForm() + '/services/Soap/m/60.0'); req.setMethod('GET'); req.setHeader('SOAPAction', '""'); req.setHeader('Content-Type', 'text/xml'); req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId()); req.setBody(retrieveCertificateXML); // Process the httpRequest res = new Http().send(req); certificateXML = res.getBody(); // Confirm that the certificate already exists if (!certificateXML.contains('<fullName>Cuneiform_for_CRM_Self_Signed_Certificate</fullName>')) { System.debug(bdr); System.debug(spacer + 'We were unable to verify the [Cuneiform for CRM: Self-Signed Certificate] exists.'); System.debug(spacer + 'Please check [Certificate and Key Management] within Salesforce Setup and'); System.debug(spacer + 'Manually verify that the certificate exists.'); System.debug(spacer); System.debug(spacer + 'If you need to create the certificate, please visit '); System.debug(spacer + 'https://peernova.link/cuneiform/fdm/setup/step-000'); System.debug(spacer + 'and execute the Anonymous Apex script to create the certificate.'); System.debug(bdr); } else { // Update the request and validate the ConnectedApp was found req.setBody(retrieveConnectedAppXML); // Execute the request res = new Http().send(req); connectedAppXML = res.getBody(); // Confirm that the connectedApp already exists if (!connectedAppXML.contains('<fullName>' + connectedAppName + '</fullName>')) { System.debug(bdr); System.debug(spacer + 'We were unable to verify the [Cuneiform for CRM: Connected App] exists.'); System.debug(spacer + 'Please check [Connected Apps] within Salesforce Setup'); System.debug(spacer + 'and manually verify that the Connected App exists.'); System.debug(spacer); System.debug(spacer + 'If you need to create the Connected App, please visit '); System.debug(spacer + 'https://peernova.link/cuneiform/fdm/setup/step-006'); System.debug(spacer + 'and execute the Anonymous Apex script to create the Connected App.'); System.debug(bdr); } else { // Retrieve the certificate content and append it to the connectedApp definition certContent = certificateXML.substringBetween('<content>', '</content>'); digitalCertificateXML = '<certificate>' + certContent + '</certificate></oauthConfig>'; connectedAppXML = connectedAppXML.replace('</oauthConfig>', digitalCertificateXML).substringBetween('<result><records xsi:type="ConnectedApp">', '</records>'); // Create the connectedApp update details and set the request updateConnectedAppXML = updateHeaderXML + sessionHeaderXML + updateContainerXML + closeXML; updateConnectedAppXML = String.format(updateConnectedAppXML, new String[] {connectedAppXML}); req.setBody(updateConnectedAppXML); // Execute the request res = new Http().send(req); updateResponseXML = res.getBody(); // Confirm that we were able to update the ConnectedApp if (updateResponseXML.contains('<success>true</success>')) { System.debug(bdr); System.debug(spacer + 'The Cuneiform for CRM: Connected App was successfully updated. Please'); System.debug(spacer + 'examine the Connected App to verify the digital certificate was added.'); System.debug(spacer); System.debug(spacer + 'Nice Work! We have updated the Connected App to include the digital'); System.debug(spacer + 'certificate. You are now ready to validate your configuration.'); System.debug(spacer); System.debug(spacer + 'Please follow our remaining installation instructions via'); System.debug(spacer + 'https://peernova.link/cuneiform/fdm/setup/verify'); System.debug(spacer + 'to verify your configuration via our Control Panel.'); System.debug(bdr); } else { System.debug(bdr); System.debug(spacer + 'We were unable to update the Cuneiform for CRM: Connected App. Please review the error response for details.'); System.debug(spacer + 'Metadata API Error Response:'); System.debug(spacer); System.debug(updateResponseXML.mid(updateResponseXML.indexOf('<errors>'), updateResponseXML.indexOf('</errors>') - (updateResponseXML.indexOf('<errors>') - 9))); System.debug(spacer); System.debug(spacer + 'Please review Metadata API Error Response, and try again. Verify that you have access'); System.debug(spacer + 'and permission to update Metadata via the Metadata API, and that the Cuneiform for CRM'); System.debug(spacer + 'Connected App already exists in your Org.'); System.debug(bdr); } } }

Execute this Anonymous Apex script to assign your self-signed certificate to the Connected App. Use our step-by-step guide if you are unfamiliar with executing Apex Scripts via the Salesforce Developer Console.


Congratulations! You’ve completed the configuration tasks (wasn’t that fast?). Now, please visit Verifying Your Configuration with the Control Panel to confirm that the app is correctly configured.