For each element of the user interface which is shown/hidden or enabled/disabled in the front-end based on an access control policy, a separate call is defined. These calls are subsequently bundled by the PermissionService, which is exported from @valtimo/access-control.
Defining permissions
For a part of your user interface, for example a page, it is best to define all the permissions it needs to request in one file. In this file, define each permission to be requested separately, conforming to the interface PermissionRequest:
sample.permissions.ts
import {PermissionRequest} from'@valtimo/access-control';// Enums are defined for use in the below permissions. This is to avoid duplication, and is optional.enumPERMISSION_ACTION { assign ='ASSIGN', claim ='CLAIM',}enumDOSSIER_DETAIL_PERMISSION_RESOURCE { domain ='com.ritense.document.domain.impl.JsonSchemaDocument',}constCAN_CLAIM_CASE_PERMISSION:PermissionRequest= { action:PERMISSION_ACTION.claim, resource:DOSSIER_DETAIL_PERMISSION_RESOURCE.domain,};constCAN_ASSIGN_CASE_PERMISSION:PermissionRequest= { action:PERMISSION_ACTION.assign, resource:DOSSIER_DETAIL_PERMISSION_RESOURCE.domain,};export {CAN_CLAIM_CASE_PERMISSION, CAN_ASSIGN_CASE_PERMISSION}
Using permissions
Permissions defined in the above example, are imported into your component code and transferred to the PermissionService, which returns an Observable emitting a boolean value for the respective permission:
sample.component.ts
...// import PermissionServiceimport {PermissionService} from'@valtimo/access-control';...// import previously defined permissionsimport { CAN_CLAIM_CASE_PERMISSION, CAN_ASSIGN_CASE_PERMISSION,} from'../permissions';...@Component({ selector:'sample-component', templateUrl:'./sample-component.component.html', styleUrls: ['./sample-component.component.css'],})exportclassSampleComponent {// the permission to claim a case is defined directly as a component propertypublicreadonly canClaimCase$:Observable<boolean> =this.permissionService.requestPermission(CAN_CLAIM_CASE_PERMISSION)// route paramaters are used to add dynamic context to the 'can assign case permission'publicreadonly canAssign$:Observable<boolean> =this.route.paramMap.pipe(switchMap((params:ParamMap) =>this.permissionService.requestPermission(// the defined permission itselfCAN_ASSIGN_CASE_PERMISSION,// context object as a second paramter { resource:DOSSIER_DETAIL_PERMISSION_RESOURCE.domain, identifier:params.get('documentId') ??'', }) ) );constructor( ...// inject PermissionServiceprivatereadonly permissionService:PermissionService ) { }}
With each permission defined as an Observable emitting a boolean value, with its own component property, they may now be used in the template code of your component. To do this efficiently, it is recommended to use async pipes:
sample.component.html
<div class="container">
<!-- The claim button is shown when a case can be claimed-->
<button *ngIf="canClaimCase$ | async" (click)="claim()">
Claim case
</button>
<!-- The assign button is enabled when a case can be assigned-->
<button [disabled]="(canAssign$ | async) === false" (click)="assign()">
Assign case
</button>
</div>