Skip to content

Commit

Permalink
feat: add sample data mechanism for packaged installations (#40)
Browse files Browse the repository at this point in the history
* feat: add sample data import for packaged installations

* fix: format sfdx-project.json
  • Loading branch information
muenzpraeger authored Nov 18, 2024
1 parent 7568eaf commit ee63f3b
Show file tree
Hide file tree
Showing 13 changed files with 273 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<CustomApplication xmlns="http://soap.sforce.com/2006/04/metadata">
<brand>
<headerColor>#0070D2</headerColor>
<shouldOverrideOrgTheme>false</shouldOverrideOrgTheme>
</brand>
<formFactors>Small</formFactors>
<formFactors>Large</formFactors>
<isNavAutoTempTabsDisabled>true</isNavAutoTempTabsDisabled>
<isNavPersonalizationDisabled>true</isNavPersonalizationDisabled>
<isNavTabPersistenceDisabled>false</isNavTabPersistenceDisabled>
<isOmniPinnedViewEnabled>false</isOmniPinnedViewEnabled>
<label>Sample Data Import</label>
<navType>Standard</navType>
<tabs>Import</tabs>
<uiType>Lightning</uiType>
<utilityBar>Sample_Data_Import_UtilityBar</utilityBar>
</CustomApplication>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
<flexiPageRegions>
<name>utilityItems</name>
<type>Region</type>
</flexiPageRegions>
<flexiPageRegions>
<name>backgroundComponents</name>
<type>Background</type>
</flexiPageRegions>
<masterLabel>Sample Data Import UtilityBar</masterLabel>
<template>
<name>one:utilityBarTemplateDesktop</name>
<properties>
<name>isLeftAligned</name>
<value>true</value>
</properties>
</template>
<type>UtilityBar</type>
</FlexiPage>
3 changes: 3 additions & 0 deletions cc-base-app/main/default/lwc/sampleData/sampleData.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.container {
text-align: center;
}
10 changes: 10 additions & 0 deletions cc-base-app/main/default/lwc/sampleData/sampleData.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<template>
<div class="container">
<lightning-button
onclick={handleOnClick}
label="Import sample data"
disabled={isImportActive}
></lightning-button>
<lightning-spinner lwc:if={isImportActive}></lightning-spinner>
</div>
</template>
31 changes: 31 additions & 0 deletions cc-base-app/main/default/lwc/sampleData/sampleData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { LightningElement } from 'lwc';
import Toast from 'lightning/toast';
import importData from '@salesforce/apex/DataTreeImporter.importData';
import generateData from '@salesforce/apex/SampleDataGenerator.generateData';

export default class SampleData extends LightningElement {
isImportActive = false;

handleOnClick() {
this.isImportActive = true;
importData().then(() => {
generateData()
.then(() => {
this.isImportActive = false;
Toast.show({
label: 'Success',
message: 'Sample data imported successfully',
variant: 'success'
});
})
.catch((error) => {
this.isImportActive = false;
Toast.show({
label: 'Error',
message: error.body.message,
variant: 'error'
});
});
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<application>Coral_Cloud</application>
<visible>true</visible>
</applicationVisibilities>
<applicationVisibilities>
<application>Sample_Data_Import</application>
<visible>true</visible>
</applicationVisibilities>
<fieldPermissions>
<editable>true</editable>
<field>Account.AccountNumber</field>
Expand Down Expand Up @@ -641,6 +645,10 @@
<tab>Guest_Review__c</tab>
<visibility>Visible</visibility>
</tabSettings>
<tabSettings>
<tab>Import</tab>
<visibility>Visible</visibility>
</tabSettings>
<tabSettings>
<tab>Session__c</tab>
<visibility>Visible</visibility>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<RemoteSiteSetting xmlns="http://soap.sforce.com/2006/04/metadata">
<description>Access to sample data in GitHub</description>
<disableProtocolSecurity>false</disableProtocolSecurity>
<isActive>true</isActive>
<url>https://raw.githubusercontent.com</url>
</RemoteSiteSetting>
6 changes: 6 additions & 0 deletions cc-base-app/main/default/tabs/Import.tab-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<CustomTab xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Import</label>
<lwcComponent>sampleData</lwcComponent>
<motif>Custom37: Bridge</motif>
</CustomTab>
84 changes: 84 additions & 0 deletions cc-base-app/main/setup/classes/DataTreeImporter.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
public class DataTreeImporter {

Check warning on line 1 in cc-base-app/main/setup/classes/DataTreeImporter.cls

View workflow job for this annotation

GitHub Actions / scratch-org-test

Apex classes should declare a sharing model if DML or SOQL is used

Detect classes declared without explicit sharing mode if DML methods are used. This forces the developer to take access restrictions into account before modifying objects. ApexSharingViolations (Priority: 3, Ruleset: Security) https://pmd.github.io/pmd-6.55.0/pmd_rules_apex_security.html#apexsharingviolations
static String githubContacts = 'https://raw.githubusercontent.com/trailheadapps/coral-cloud/main/data/data-Contact.json';
static String githubExperience = 'https://raw.githubusercontent.com/trailheadapps/coral-cloud/main/data/data-Experience__c.json';
static String githubGuestReview = 'https://raw.githubusercontent.com/trailheadapps/coral-cloud/main/data/data-Guest_Review__c.json';
static String githubCase = 'https://raw.githubusercontent.com/trailheadapps/coral-cloud/main/data/data-Case.json';

public class SObjectTree {
public List<SObject> records;
}

@AuraEnabled
public static void importData() {
try {
// Parse JSON data into a list of ObjectData
List<Contact> contacts = (List<Contact>) fetchJsonFromGitHub(
githubContacts
);

List<Experience__c> experiences = (List<Experience__c>) fetchJsonFromGitHub(
githubExperience
);

List<Guest_Review__c> reviews = (List<Guest_Review__c>) fetchJsonFromGitHub(
githubGuestReview
);
List<Case> cases = (List<Case>) fetchJsonFromGitHub(githubCase);

insert contacts;

Check warning on line 28 in cc-base-app/main/setup/classes/DataTreeImporter.cls

View workflow job for this annotation

GitHub Actions / scratch-org-test

Validate CRUD permission before SOQL/DML operation

The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. Since Apex runs by default in system mode not having proper permissions checks results in escalation of privilege and may produce runtime errors. This check forces you to handle such scenarios. Since Winter '23 (API Version 56) you can enforce user mode for database operations by using `WITH USER_MODE` in SOQL. This makes Apex to respect Field-level security (FLS) and object permissions of the running user. When using user mode, no violation is reported by this rule. By default, the rule allows access checks can be performed using system Apex provisions such as `DescribeSObjectResult.isAccessible/Createable/etc.`, the SOQL `WITH SECURITY_ENFORCED` clause, or using the open source [Force.com ESAPI](https://github.com/forcedotcom/force-dot-com-esapi) class library. Because it is common to use authorization facades to assist with this task, the rule also allows configuration of regular expression-based patterns for the methods used to authorize each type of CRUD operation. These pattern are configured via the following properties: * `createAuthMethodPattern`/`createAuthMethodTypeParamIndex` - a pattern for the method used for create authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for create. * `readAuthMethodPattern`/`readAuthMethodTypeParamIndex` - a pattern for the method used for read authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for read. * `updateAuthMethodPattern`/`updateAuthMethodTypeParamIndex` - a pattern for the method used for update authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for update. * `deleteAuthMethodPattern`/`deleteAuthMethodTypeParamIndex` - a pattern for the method used for delete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for delete. * `undeleteAuthMethodPattern`/`undeleteAuthMethodTypeParamIndex` - a pattern for the method used for undelete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for undelete. * `mergeAuthMethodPattern`/`mergeAuthMethodTypeParamIndex` - a pattern for the method used for merge authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for merge. The following example shows how the rule can be configured for the [sirono-common](https://github.com/SCWells72/sirono-common) [`AuthorizationUtil`](https://github.com/SCWells72/sirono-common#authorization-utilities) class: ```xml <rule ref="category/apex/security.xml/ApexCRUDViolation" message="Validate CRUD permission before SOQL/DML operation"> <priority>3</priority> <properties> <property name="createAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Createable|Upsertable)"/> <property name="readAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Accessible"/> <property name="updateAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Updateable|Upsertable)"/> <property name="deleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Deletable"/> <property name="undeleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Undeletable"/> <property name="mergeAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Mergeable"/> </properties> </rule> ``` Note: This rule will produce false positives for VF getter methods. In VF getters the access permission check happens automatically and is not needed explicitly. However, the rule can't reliably determine whether a getter is a VF getter or not and reports a violation in any case. In such cases, the violation should be [suppressed](pmd_userdocs_suppressing_warnings.html). ApexCRUDViolation (Priority
insert experiences;

Check warning on line 29 in cc-base-app/main/setup/classes/DataTreeImporter.cls

View workflow job for this annotation

GitHub Actions / scratch-org-test

Validate CRUD permission before SOQL/DML operation

The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. Since Apex runs by default in system mode not having proper permissions checks results in escalation of privilege and may produce runtime errors. This check forces you to handle such scenarios. Since Winter '23 (API Version 56) you can enforce user mode for database operations by using `WITH USER_MODE` in SOQL. This makes Apex to respect Field-level security (FLS) and object permissions of the running user. When using user mode, no violation is reported by this rule. By default, the rule allows access checks can be performed using system Apex provisions such as `DescribeSObjectResult.isAccessible/Createable/etc.`, the SOQL `WITH SECURITY_ENFORCED` clause, or using the open source [Force.com ESAPI](https://github.com/forcedotcom/force-dot-com-esapi) class library. Because it is common to use authorization facades to assist with this task, the rule also allows configuration of regular expression-based patterns for the methods used to authorize each type of CRUD operation. These pattern are configured via the following properties: * `createAuthMethodPattern`/`createAuthMethodTypeParamIndex` - a pattern for the method used for create authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for create. * `readAuthMethodPattern`/`readAuthMethodTypeParamIndex` - a pattern for the method used for read authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for read. * `updateAuthMethodPattern`/`updateAuthMethodTypeParamIndex` - a pattern for the method used for update authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for update. * `deleteAuthMethodPattern`/`deleteAuthMethodTypeParamIndex` - a pattern for the method used for delete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for delete. * `undeleteAuthMethodPattern`/`undeleteAuthMethodTypeParamIndex` - a pattern for the method used for undelete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for undelete. * `mergeAuthMethodPattern`/`mergeAuthMethodTypeParamIndex` - a pattern for the method used for merge authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for merge. The following example shows how the rule can be configured for the [sirono-common](https://github.com/SCWells72/sirono-common) [`AuthorizationUtil`](https://github.com/SCWells72/sirono-common#authorization-utilities) class: ```xml <rule ref="category/apex/security.xml/ApexCRUDViolation" message="Validate CRUD permission before SOQL/DML operation"> <priority>3</priority> <properties> <property name="createAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Createable|Upsertable)"/> <property name="readAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Accessible"/> <property name="updateAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Updateable|Upsertable)"/> <property name="deleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Deletable"/> <property name="undeleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Undeletable"/> <property name="mergeAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Mergeable"/> </properties> </rule> ``` Note: This rule will produce false positives for VF getter methods. In VF getters the access permission check happens automatically and is not needed explicitly. However, the rule can't reliably determine whether a getter is a VF getter or not and reports a violation in any case. In such cases, the violation should be [suppressed](pmd_userdocs_suppressing_warnings.html). ApexCRUDViolation (Priority

Experience__c experience = [
SELECT Id
FROM Experience__c
WHERE Name = 'Tropical Snorkel Adventure'
];

Check warning on line 35 in cc-base-app/main/setup/classes/DataTreeImporter.cls

View workflow job for this annotation

GitHub Actions / scratch-org-test

Validate CRUD permission before SOQL/DML operation

The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. Since Apex runs by default in system mode not having proper permissions checks results in escalation of privilege and may produce runtime errors. This check forces you to handle such scenarios. Since Winter '23 (API Version 56) you can enforce user mode for database operations by using `WITH USER_MODE` in SOQL. This makes Apex to respect Field-level security (FLS) and object permissions of the running user. When using user mode, no violation is reported by this rule. By default, the rule allows access checks can be performed using system Apex provisions such as `DescribeSObjectResult.isAccessible/Createable/etc.`, the SOQL `WITH SECURITY_ENFORCED` clause, or using the open source [Force.com ESAPI](https://github.com/forcedotcom/force-dot-com-esapi) class library. Because it is common to use authorization facades to assist with this task, the rule also allows configuration of regular expression-based patterns for the methods used to authorize each type of CRUD operation. These pattern are configured via the following properties: * `createAuthMethodPattern`/`createAuthMethodTypeParamIndex` - a pattern for the method used for create authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for create. * `readAuthMethodPattern`/`readAuthMethodTypeParamIndex` - a pattern for the method used for read authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for read. * `updateAuthMethodPattern`/`updateAuthMethodTypeParamIndex` - a pattern for the method used for update authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for update. * `deleteAuthMethodPattern`/`deleteAuthMethodTypeParamIndex` - a pattern for the method used for delete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for delete. * `undeleteAuthMethodPattern`/`undeleteAuthMethodTypeParamIndex` - a pattern for the method used for undelete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for undelete. * `mergeAuthMethodPattern`/`mergeAuthMethodTypeParamIndex` - a pattern for the method used for merge authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for merge. The following example shows how the rule can be configured for the [sirono-common](https://github.com/SCWells72/sirono-common) [`AuthorizationUtil`](https://github.com/SCWells72/sirono-common#authorization-utilities) class: ```xml <rule ref="category/apex/security.xml/ApexCRUDViolation" message="Validate CRUD permission before SOQL/DML operation"> <priority>3</priority> <properties> <property name="createAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Createable|Upsertable)"/> <property name="readAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Accessible"/> <property name="updateAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Updateable|Upsertable)"/> <property name="deleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Deletable"/> <property name="undeleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Undeletable"/> <property name="mergeAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Mergeable"/> </properties> </rule> ``` Note: This rule will produce false positives for VF getter methods. In VF getters the access permission check happens automatically and is not needed explicitly. However, the rule can't reliably determine whether a getter is a VF getter or not and reports a violation in any case. In such cases, the violation should be [suppressed](pmd_userdocs_suppressing_warnings.html). ApexCRUDViolation (Priority

List<Guest_Review__c> newReviews = new List<Guest_Review__c>();
for (Guest_Review__c review : reviews) {
review.Experience__c = experience.Id;
review.Contact__c = contacts[0].Id;
newReviews.add(review);
}
insert newReviews;

Check warning on line 43 in cc-base-app/main/setup/classes/DataTreeImporter.cls

View workflow job for this annotation

GitHub Actions / scratch-org-test

Validate CRUD permission before SOQL/DML operation

The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. Since Apex runs by default in system mode not having proper permissions checks results in escalation of privilege and may produce runtime errors. This check forces you to handle such scenarios. Since Winter '23 (API Version 56) you can enforce user mode for database operations by using `WITH USER_MODE` in SOQL. This makes Apex to respect Field-level security (FLS) and object permissions of the running user. When using user mode, no violation is reported by this rule. By default, the rule allows access checks can be performed using system Apex provisions such as `DescribeSObjectResult.isAccessible/Createable/etc.`, the SOQL `WITH SECURITY_ENFORCED` clause, or using the open source [Force.com ESAPI](https://github.com/forcedotcom/force-dot-com-esapi) class library. Because it is common to use authorization facades to assist with this task, the rule also allows configuration of regular expression-based patterns for the methods used to authorize each type of CRUD operation. These pattern are configured via the following properties: * `createAuthMethodPattern`/`createAuthMethodTypeParamIndex` - a pattern for the method used for create authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for create. * `readAuthMethodPattern`/`readAuthMethodTypeParamIndex` - a pattern for the method used for read authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for read. * `updateAuthMethodPattern`/`updateAuthMethodTypeParamIndex` - a pattern for the method used for update authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for update. * `deleteAuthMethodPattern`/`deleteAuthMethodTypeParamIndex` - a pattern for the method used for delete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for delete. * `undeleteAuthMethodPattern`/`undeleteAuthMethodTypeParamIndex` - a pattern for the method used for undelete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for undelete. * `mergeAuthMethodPattern`/`mergeAuthMethodTypeParamIndex` - a pattern for the method used for merge authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for merge. The following example shows how the rule can be configured for the [sirono-common](https://github.com/SCWells72/sirono-common) [`AuthorizationUtil`](https://github.com/SCWells72/sirono-common#authorization-utilities) class: ```xml <rule ref="category/apex/security.xml/ApexCRUDViolation" message="Validate CRUD permission before SOQL/DML operation"> <priority>3</priority> <properties> <property name="createAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Createable|Upsertable)"/> <property name="readAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Accessible"/> <property name="updateAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Updateable|Upsertable)"/> <property name="deleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Deletable"/> <property name="undeleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Undeletable"/> <property name="mergeAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Mergeable"/> </properties> </rule> ``` Note: This rule will produce false positives for VF getter methods. In VF getters the access permission check happens automatically and is not needed explicitly. However, the rule can't reliably determine whether a getter is a VF getter or not and reports a violation in any case. In such cases, the violation should be [suppressed](pmd_userdocs_suppressing_warnings.html). ApexCRUDViolation (Priority

Contact cont = [
SELECT Id
FROM Contact
WHERE LastName = 'Rodriguez'
];

Check warning on line 49 in cc-base-app/main/setup/classes/DataTreeImporter.cls

View workflow job for this annotation

GitHub Actions / scratch-org-test

Validate CRUD permission before SOQL/DML operation

The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. Since Apex runs by default in system mode not having proper permissions checks results in escalation of privilege and may produce runtime errors. This check forces you to handle such scenarios. Since Winter '23 (API Version 56) you can enforce user mode for database operations by using `WITH USER_MODE` in SOQL. This makes Apex to respect Field-level security (FLS) and object permissions of the running user. When using user mode, no violation is reported by this rule. By default, the rule allows access checks can be performed using system Apex provisions such as `DescribeSObjectResult.isAccessible/Createable/etc.`, the SOQL `WITH SECURITY_ENFORCED` clause, or using the open source [Force.com ESAPI](https://github.com/forcedotcom/force-dot-com-esapi) class library. Because it is common to use authorization facades to assist with this task, the rule also allows configuration of regular expression-based patterns for the methods used to authorize each type of CRUD operation. These pattern are configured via the following properties: * `createAuthMethodPattern`/`createAuthMethodTypeParamIndex` - a pattern for the method used for create authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for create. * `readAuthMethodPattern`/`readAuthMethodTypeParamIndex` - a pattern for the method used for read authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for read. * `updateAuthMethodPattern`/`updateAuthMethodTypeParamIndex` - a pattern for the method used for update authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for update. * `deleteAuthMethodPattern`/`deleteAuthMethodTypeParamIndex` - a pattern for the method used for delete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for delete. * `undeleteAuthMethodPattern`/`undeleteAuthMethodTypeParamIndex` - a pattern for the method used for undelete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for undelete. * `mergeAuthMethodPattern`/`mergeAuthMethodTypeParamIndex` - a pattern for the method used for merge authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for merge. The following example shows how the rule can be configured for the [sirono-common](https://github.com/SCWells72/sirono-common) [`AuthorizationUtil`](https://github.com/SCWells72/sirono-common#authorization-utilities) class: ```xml <rule ref="category/apex/security.xml/ApexCRUDViolation" message="Validate CRUD permission before SOQL/DML operation"> <priority>3</priority> <properties> <property name="createAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Createable|Upsertable)"/> <property name="readAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Accessible"/> <property name="updateAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Updateable|Upsertable)"/> <property name="deleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Deletable"/> <property name="undeleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Undeletable"/> <property name="mergeAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Mergeable"/> </properties> </rule> ``` Note: This rule will produce false positives for VF getter methods. In VF getters the access permission check happens automatically and is not needed explicitly. However, the rule can't reliably determine whether a getter is a VF getter or not and reports a violation in any case. In such cases, the violation should be [suppressed](pmd_userdocs_suppressing_warnings.html). ApexCRUDViolation (Priority
for (Case c : cases) {
c.ContactId = cont.Id;
}
insert cases;

Check warning on line 53 in cc-base-app/main/setup/classes/DataTreeImporter.cls

View workflow job for this annotation

GitHub Actions / scratch-org-test

Validate CRUD permission before SOQL/DML operation

The rule validates you are checking for access permissions before a SOQL/SOSL/DML operation. Since Apex runs by default in system mode not having proper permissions checks results in escalation of privilege and may produce runtime errors. This check forces you to handle such scenarios. Since Winter '23 (API Version 56) you can enforce user mode for database operations by using `WITH USER_MODE` in SOQL. This makes Apex to respect Field-level security (FLS) and object permissions of the running user. When using user mode, no violation is reported by this rule. By default, the rule allows access checks can be performed using system Apex provisions such as `DescribeSObjectResult.isAccessible/Createable/etc.`, the SOQL `WITH SECURITY_ENFORCED` clause, or using the open source [Force.com ESAPI](https://github.com/forcedotcom/force-dot-com-esapi) class library. Because it is common to use authorization facades to assist with this task, the rule also allows configuration of regular expression-based patterns for the methods used to authorize each type of CRUD operation. These pattern are configured via the following properties: * `createAuthMethodPattern`/`createAuthMethodTypeParamIndex` - a pattern for the method used for create authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for create. * `readAuthMethodPattern`/`readAuthMethodTypeParamIndex` - a pattern for the method used for read authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for read. * `updateAuthMethodPattern`/`updateAuthMethodTypeParamIndex` - a pattern for the method used for update authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for update. * `deleteAuthMethodPattern`/`deleteAuthMethodTypeParamIndex` - a pattern for the method used for delete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for delete. * `undeleteAuthMethodPattern`/`undeleteAuthMethodTypeParamIndex` - a pattern for the method used for undelete authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for undelete. * `mergeAuthMethodPattern`/`mergeAuthMethodTypeParamIndex` - a pattern for the method used for merge authorization and an optional 0-based index of the parameter passed to that method that denotes the `SObjectType` being authorized for merge. The following example shows how the rule can be configured for the [sirono-common](https://github.com/SCWells72/sirono-common) [`AuthorizationUtil`](https://github.com/SCWells72/sirono-common#authorization-utilities) class: ```xml <rule ref="category/apex/security.xml/ApexCRUDViolation" message="Validate CRUD permission before SOQL/DML operation"> <priority>3</priority> <properties> <property name="createAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Createable|Upsertable)"/> <property name="readAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Accessible"/> <property name="updateAuthMethodPattern" value="AuthorizationUtil\.(is|assert)(Updateable|Upsertable)"/> <property name="deleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Deletable"/> <property name="undeleteAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Undeletable"/> <property name="mergeAuthMethodPattern" value="AuthorizationUtil\.(is|assert)Mergeable"/> </properties> </rule> ``` Note: This rule will produce false positives for VF getter methods. In VF getters the access permission check happens automatically and is not needed explicitly. However, the rule can't reliably determine whether a getter is a VF getter or not and reports a violation in any case. In such cases, the violation should be [suppressed](pmd_userdocs_suppressing_warnings.html). ApexCRUDViolation (Priority

System.debug('Data import completed successfully!');
} catch (Exception e) {
System.debug('Error during data import: ' + e.getMessage());
}
}

private static List<sObject> fetchJsonFromGitHub(String url) {
HttpRequest req = new HttpRequest();
req.setEndpoint(url);
req.setMethod('GET');

Http http = new Http();
HttpResponse res = http.send(req);

if (res.getStatusCode() == 200) {
SObjectTree treeData = (SObjectTree) JSON.deserialize(
res.getBody(),
SObjectTree.class
);

// Parse JSON data into a list of ObjectData
List<sObject> records = treeData.records;
return records;
} else {
throw new CalloutException(
'Failed to fetch JSON data. Status: ' + res.getStatus()
);
}
}
}
5 changes: 5 additions & 0 deletions cc-base-app/main/setup/classes/DataTreeImporter.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<status>Active</status>
</ApexClass>
1 change: 1 addition & 0 deletions cc-base-app/main/setup/classes/SampleDataGenerator.cls
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public with sharing class SampleDataGenerator {
@TestVisible
private static final Integer PAST_DAYS_COVERED = 1;

@AuraEnabled
public static Id generateData() {
// Remove current sessions and bookings
delete [SELECT Id FROM Booking__c];
Expand Down
144 changes: 72 additions & 72 deletions sfdx-project.json
Original file line number Diff line number Diff line change
@@ -1,74 +1,74 @@
{
"packageDirectories": [
{
"path": "cc-base-app",
"default": true,
"package": "Coral Cloud - Base",
"versionName": "v1.0",
"versionDescription": "Base package for the Coral Cloud sample app",
"versionNumber": "1.0.0.NEXT",
"definitionFile": "config/cc-base-project-scratch-def.json"
"packageDirectories": [
{
"path": "cc-base-app",
"default": true,
"package": "Coral Cloud - Base",
"versionName": "v1.0",
"versionDescription": "Base package for the Coral Cloud sample app",
"versionNumber": "1.0.0.NEXT",
"definitionFile": "config/cc-base-project-scratch-def.json"
},
{
"path": "cc-employee-app"
},
{
"path": "cc-service-app"
}
],
"name": "Coral Cloud Resorts",
"namespace": "",
"sfdcLoginUrl": "https://login.salesforce.com",
"sourceApiVersion": "62.0",
"packageAliases": {
"Coral Cloud - Base": "0HoWx00000000mPKAQ",
"Coral Cloud - [email protected]": "04tWx0000001REHIA2"
},
{
"path": "cc-employee-app"
},
{
"path": "cc-service-app"
}
],
"name": "Coral Cloud Resorts",
"namespace": "",
"sfdcLoginUrl": "https://login.salesforce.com",
"sourceApiVersion": "62.0",
"packageAliases": {
"Coral Cloud - Base": "0HoWx00000000mPKAQ",
"Coral Cloud - [email protected]": "04tWx0000001REHIA2"
},
"replacements": [
{
"filename": "cc-service-app/main/default/digitalExperiences/site/coral_cloud1/sfdc_cms__view/home/content.json",
"stringToReplace": "%%SF_CC_PLACEHOLDER_DOMAIN%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_DOMAIN"
},
{
"filename": "cc-service-app/main/default/bots/Coral_Cloud_Agent/Coral_Cloud_Agent.bot-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_USERNAME%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_USERNAME"
},
{
"filename": "cc-service-app/main/setup/classes/SetupServiceAgentUser.cls",
"stringToReplace": "%%SF_CC_PLACEHOLDER_USERNAME%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_USERNAME"
},
{
"glob": "cc-service-app/**/networks/*.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_USERNAME%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_USERNAME"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Agent.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_AGENT_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_AGENT_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Agent.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Agent.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_QUEUE_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_QUEUE_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Queue.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Queue.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_QUEUE_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_QUEUE_ID"
}
]
}
"replacements": [
{
"filename": "cc-service-app/main/default/digitalExperiences/site/coral_cloud1/sfdc_cms__view/home/content.json",
"stringToReplace": "%%SF_CC_PLACEHOLDER_DOMAIN%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_DOMAIN"
},
{
"filename": "cc-service-app/main/default/bots/Coral_Cloud_Agent/Coral_Cloud_Agent.bot-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_USERNAME%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_USERNAME"
},
{
"filename": "cc-service-app/main/setup/classes/SetupServiceAgentUser.cls",
"stringToReplace": "%%SF_CC_PLACEHOLDER_USERNAME%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_USERNAME"
},
{
"glob": "cc-service-app/**/networks/*.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_USERNAME%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_USERNAME"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Agent.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_AGENT_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_AGENT_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Agent.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Agent.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_QUEUE_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_QUEUE_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Queue.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_CHANNEL_ID"
},
{
"filename": "cc-service-app/main/default/flows/Route_to_Queue.flow-meta.xml",
"stringToReplace": "%%SF_CC_PLACEHOLDER_FLOW_QUEUE_ID%%",
"replaceWithEnv": "SF_CC_PLACEHOLDER_FLOW_QUEUE_ID"
}
]
}

0 comments on commit ee63f3b

Please sign in to comment.