File

src/app/core/permissions/ability/entity-ability.ts

Description

An extension of the Ability class which can check permissions on Entities. Inject this class in your component to check for permissions.

e.g.

Example :
export class ExampleComponent {
  constructor(private ability: EntityAbility) {
    this.ability.can("update", new Child());
  }
}

Entities are transformed to the database format and permissions are evaluated based on the configuration found in the database.

Extends

Ability

Index

Methods

Constructor

constructor(entitySchemaService: EntitySchemaService)
Parameters :
Name Type Optional
entitySchemaService EntitySchemaService No

Methods

can
can(action: EntityActionPermission, entity: EntitySubject, field?: string, enforceConditions?: boolean)
Parameters :
Name Type Optional
action EntityActionPermission No
entity EntitySubject No
field string Yes
enforceConditions boolean Yes
Returns : boolean
cannot
cannot(action: EntityActionPermission, entity: EntitySubject, field?: string)
Parameters :
Name Type Optional
action EntityActionPermission No
entity EntitySubject No
field string Yes
Returns : boolean
import { Injectable } from "@angular/core";
import { EntityActionPermission, EntitySubject } from "../permission-types";
import { Ability, subject } from "@casl/ability";
import { EntitySchemaService } from "../../entity/schema/entity-schema.service";
import { Entity } from "../../entity/model/entity";

/**
 * An extension of the Ability class which can check permissions on Entities.
 * Inject this class in your component to check for permissions.
 *
 * e.g.
 * ```
 * export class ExampleComponent {
 *   constructor(private ability: EntityAbility) {
 *     this.ability.can("update", new Child());
 *   }
 * }
 * ```
 * Entities are transformed to the database format and permissions are evaluated based on the configuration found in the database.
 */
@Injectable()
export class EntityAbility extends Ability<
  [EntityActionPermission, string | any]
> {
  constructor(private entitySchemaService: EntitySchemaService) {
    super([]);
  }

  override can(
    action: EntityActionPermission,
    entity: EntitySubject,
    field?: string,
    enforceConditions?: boolean,
  ): boolean {
    if (action === "create" && !enforceConditions) {
      const rules = this.rules.map((r) => {
        const simplifiedRule = { ...r };
        delete simplifiedRule.conditions;
        return simplifiedRule;
      });
      const abilityWithoutConditions = new Ability(rules);
      return abilityWithoutConditions.can(
        action,
        this.getSubject(entity),
        field,
      );
    }
    return super.can(action, this.getSubject(entity), field);
  }

  override cannot(
    action: EntityActionPermission,
    entity: EntitySubject,
    field?: string,
  ): boolean {
    return super.cannot(action, this.getSubject(entity), field);
  }

  private getSubject(entity: EntitySubject): any {
    if (
      !entity ||
      typeof entity === "string" ||
      entity["__caslSubjectType__"]
    ) {
      // This happens in case the subject has already been processed
      return entity;
    } else if (entity instanceof Entity) {
      return subject(
        entity.getType(),
        this.entitySchemaService.transformEntityToDatabaseFormat(entity),
      );
    } else if (entity.ENTITY_TYPE) {
      return entity.ENTITY_TYPE;
    } else {
      throw new Error(`${JSON.stringify(entity)} is not a valid subject`);
    }
  }
}

results matching ""

    No results matching ""