Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions sfdx-project.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
"default": false,
"package": "custom-metadata-dao",
"versionDescription": "Custom Metadata Data Access Object class used to get access to Custom Metadata objects, and at the same time make it easier to test the various paths the code can take based on the values in the Custom Metadata."
},
{
"versionNumber": "0.1.0.NEXT",
"path": "src/platform-utility/custom-permission-helper",
"default": false,
"package": "custom-permission-helper",
"versionDescription": "Custom Permission Helper class used to get access to Custom Permissions, and at the same time make it easier to test the various paths the code can take based on the values in the Custom Permissions."
}
],
"packageAliases": {
Expand Down
69 changes: 69 additions & 0 deletions src/platform-utility/custom-permission-helper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# custom-permission-helper

Denne pakken inneholder en hjelpeklasse for å håndtere custom permissions.

Salesforce har fra før metoden `FeatureManagement.checkPermission` som kan sjekke dette, men den er begrenset til å kun kjøre for running user og kan heller ikke mockes/stubbes. Denne har også muligheten til å verifisere om en custom setting eksisterer (eller om du skriver inn feil navn).

Hjelpeklassen her er tiltenkt å brukes når:

- Sjekke flere custom permissions.
- Sjekke custom permissions i en test kontekts
- Sjelle custom permissions for andre enn kjørende bruker.

## Hvordan ta i bruk

I utgangspunktet så er det bare å kalle på klassen og starte å bruke public metodene. En ting å være klar over er at man må kalle på `setCustomPermissionsMaps()` dersom man skal benytte seg av en del av metodene. Om ikke vil det kastes en exception.

### Eksempler

#### Sjekke en custom permissison

```java
// Check if running user has the custom permission
new CustomPermissionHelper().hasCustomPermission('MyPermission');
```

#### Sjekke en custom permissison for en annen bruker

```java
new CustomPermissionHelper()
.setCustomPermissionMaps() // Load all custom permissions
.validateCustomPermission('MyPermission') // Validate that the custom permission exists
.hasCustomPermission(userId, 'MyPermission'); // Check if the user has the custom permission
```

#### Få liste over _mine_ custom permissions

```java
CustomPermissionHelper().setCustomPermissionMaps().;
```

### Bruke stub klassen i testing

Stub klassen implementerer `System.StubProvider` og kan brukes til å mocke responsen fra `CustomPermissionHelper`.

I stub klassen kan man på forhånd sette verdiene sånn at man enkelt kan kjøre testene.

Resultatene legges inn i en liste, noe som muliggjør at man kan lage en mock som returnerer ulike verdier iløpet av en kjøring.

```java
CustomPermissionHelperStub stub = new CustomPermissionHelperStub();
stub.addHasCustomPermission(true);
CustomPermissionHelper customPermissionHelper = stub.getMock();

System.Assert.isTrue(customPermissionHelper.hasCustomPermission('MyPermission'));
```

Alternativt hvor man ønsker flere ulike responser etter hverandre:

```java
CustomPermissionHelper customPermissionHelper = new CustomPermissionHelperStub()
.addHasCustomPermission(true)
.addHasCustomPermission(false)
.addHasCustomPermission(true)
.getMock();

System.Assert.isTrue(customPermissionHelper.hasCustomPermission('MyPermission'));
System.Assert.isFalse(customPermissionHelper.hasCustomPermission('MyPermission'));
System.Assert.isTrue(customPermissionHelper.hasCustomPermission('MyPermission'));
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/**
* @description Helper class for checking custom permissions.
* The easiest way to check if the running user has permsissions is to use the `FeatureManagement.checkPermission` method.
* This class is intended to be used when you need to check:
* - Multiple custom permissions.
* - Custom permissions in a test context.
* - Custom permissions for a different user than the running user.
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @group Custom Permission Helper
* @example
* Eksempel på bruk:
* ```
* Set<String> myCustomPermissionsSet = new CustomPermissionHelper().setCustomPermissionMaps().getAssignedCustomPermissions();
* ```
*/
public inherited sharing class CustomPermissionHelper {
@TestVisible
private Map<Id, Set<String>> usersCustomPermissionsMap;
@TestVisible
private Map<Id, CustomPermission> customPermissionMapById;
@TestVisible
private Map<String, CustomPermission> customPermissionMapByDeveloperName;

/**
* @description Load all custom permissions into maps.
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @return `CustomPermissionHelper` instance
*/
public CustomPermissionHelper setCustomPermissionMaps() {
return this.setCustomPermissionMaps(
[SELECT Id, DeveloperName FROM CustomPermission LIMIT 1000]
);
}

/**
* @description Load all custom permissions into maps.
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @param customPermissions List of custom permissions to load into the maps
* @return `CustomPermissionHelper` instance
*/
public CustomPermissionHelper setCustomPermissionMaps(
List<CustomPermission> customPermissions
) {
customPermissionMapById = new Map<Id, CustomPermission>();
customPermissionMapByDeveloperName = new Map<String, CustomPermission>();
for (CustomPermission customPermission : customPermissions) {
customPermissionMapById.put(customPermission.Id, customPermission);
customPermissionMapByDeveloperName.put(
customPermission.DeveloperName,
customPermission
);
}
return this;
}

/**
* @description Validate that the custom permission exists. If not, throw an exception.
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @param customPermissionDeveloperName Developer name of the custom permission to validate
* @return self for chaining
* @exception Throws `CustomPermissionHelperException` if custom permission with developer name is not found
*/
public CustomPermissionHelper validateCustomPermission(
String customPermissionDeveloperName
) {
if (
!customPermissionMapByDeveloperName.containsKey(
customPermissionDeveloperName
)
) {
throw new CustomPermissionHelperException(
'Custom Permission with Developer Name ' +
customPermissionDeveloperName +
' not found'
);
}
return this;
}

/**
* @description Get the running users assigned custom permissions
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @return `Set<String>` containing the developer name of the assigned custom permissions
*/
public Set<String> getAssignedCustomPermissions() {
return getAssignedCustomPermissions(UserInfo.getUserId());
}

/**
* @description get the assigned custom permissions for a user
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @param userId of the user to get the assigned custom permissions for
* @return `Set<String>` containing the developer name of the assigned custom permissions
*/
public Set<String> getAssignedCustomPermissions(Id userId) {
if (!this.usersCustomPermissionsMap.containsKey(userId)) {
setAssignedCustomPermissionsByUser(
userId,
this.getSetupEntityAccesses(userId)
);
}
return this.usersCustomPermissionsMap.get(userId);
}

/**
* @description Check if the running user has a custom permission
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @param customPermissionDeveloperName Developer name of the custom permission to check
* @return `Boolean` indicating if the running user has the custom permission
*/
public Boolean hasCustomPermission(String customPermissionDeveloperName) {
return FeatureManagement.checkPermission(customPermissionDeveloperName);
}

/**
* @description Check if a user has a custom permission
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @param userId of the user to check the custom permission for
* @param customPermissionDeveloperName Developer name of the custom permission to check
* @return `Boolean` indicating if the user has the custom permission
*/
public Boolean hasCustomPermission(
Id userId,
String customPermissionDeveloperName
) {
return getAssignedCustomPermissions(userId)
.contains(customPermissionDeveloperName);
}

/**
* @description Load the assigned custom permissions for users
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @param userId of the user to load the assigned custom permissions for
* @param setupEntityAccessesList List of SetupEntityAccess objects for the users
* @return `CustomPermissionHelper` instance
*/
@TestVisible
private CustomPermissionHelper setAssignedCustomPermissionsByUser(
Id userId,
List<SetupEntityAccess> setupEntityAccessesList
) {
if (usersCustomPermissionsMap == null) {
usersCustomPermissionsMap = new Map<Id, Set<String>>();
}

usersCustomPermissionsMap.put(userId, new Set<String>());
for (SetupEntityAccess setupEntityAccess : setupEntityAccessesList) {
if (
customPermissionMapById == null ||
!customPermissionMapById.containsKey(
setupEntityAccess.SetupEntityId
)
) {
throw new CustomPermissionHelperException(
'Could not map Custom Permissions to user. Custom Permission with Id ' +
setupEntityAccess.SetupEntityId +
' not found. Try calling setCustomPermissionMaps() first.'
);
}
usersCustomPermissionsMap.get(userId)
.add(
customPermissionMapById.get(setupEntityAccess.SetupEntityId)
.DeveloperName
);
}
return this;
}

/**
* @description Get the SetupEntityAccess objects for the provided user
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
* @param userId of the user to get the SetupEntityAccess objects for
* @return `List<SetupEntityAccess>` containing the SetupEntityAccess objects for the provided users
*/
@TestVisible
private List<SetupEntityAccess> getSetupEntityAccesses(Id userId) {
return [
SELECT SetupEntityId
FROM SetupEntityAccess
WHERE
SetupEntityId IN :customPermissionMapById.keySet()
AND ParentId IN (
SELECT PermissionSetId
FROM PermissionSetAssignment
WHERE AssigneeId = :userId
)
WITH SECURITY_ENFORCED
];
}
}
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>63.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @description Exception related to the package custom permission helper.
*
* @author Tor Håkon Sigurdsen
* @since 0.1.0, March 2025
*/
public inherited sharing class CustomPermissionHelperException extends Exception {
// Added in order to avoid no test coverage even if the exception class is used.
// This is probably a bug in the Salesforce platform.
private Boolean isCustomPermissionHelperException = true;
}
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>63.0</apiVersion>
<status>Active</status>
</ApexClass>
Loading