File

src/app/core/entity/entity-actions/entity-delete.service.ts

Description

Safely delete an entity including handling references with related entities. This service is usually used in combination with the EntityActionsService, which provides user confirmation processes around this.

Extends

CascadingEntityAction

Index

Methods

Constructor

constructor(entityMapper: EntityMapperService, schemaService: EntitySchemaService, entityRelationsService: EntityRelationsService, userAdminService: UserAdminService, confirmationDialog: ConfirmationDialogService)
Parameters :
Name Type Optional
entityMapper EntityMapperService No
schemaService EntitySchemaService No
entityRelationsService EntityRelationsService No
userAdminService UserAdminService No
confirmationDialog ConfirmationDialogService No

Methods

Async deleteEntity
deleteEntity(entity: Entity, showKeycloakWarning)

The actual delete action without user interactions.

Returns an array of all affected entities (including the given entity) in their state before the action to support an undo action.

Parameters :
Name Type Optional Default value Description
entity Entity No
showKeycloakWarning No false

if keycloak deleteUser request fails, a popup warning is shown to the user

Protected Async cascadeActionToRelatedEntities
cascadeActionToRelatedEntities(entity: Entity, compositeAction: (relatedEntity: Entity,refField: string,entity: Entity) => void, aggregateAction: (relatedEntity: Entity,refField: string,entity: Entity) => void)
Inherited from CascadingEntityAction

Recursively call the given actions on all related entities that contain a reference to the given entity.

Returns an array of all affected related entities (excluding the given entity) in their state before the action to support an undo action.

Parameters :
Name Type Optional Description
entity Entity No
compositeAction function No

The method to be called on relationships with entityReferenceRole "composite"

aggregateAction function No

The method to be called on relationships with entityReferenceRole "aggregate" (this is also the default for any relationship)

import { Injectable } from "@angular/core";
import { EntityMapperService } from "../entity-mapper/entity-mapper.service";
import { Entity } from "../model/entity";
import { EntitySchemaService } from "../schema/entity-schema.service";
import {
  CascadingActionResult,
  CascadingEntityAction,
} from "./cascading-entity-action";
import { OkButton } from "../../common-components/confirmation-dialog/confirmation-dialog/confirmation-dialog.component";
import { ConfirmationDialogService } from "../../common-components/confirmation-dialog/confirmation-dialog.service";
import { EntityRelationsService } from "../entity-mapper/entity-relations.service";
import { UserAdminService } from "../../user/user-admin-service/user-admin.service";

/**
 * Safely delete an entity including handling references with related entities.
 * This service is usually used in combination with the `EntityActionsService`, which provides user confirmation processes around this.
 */
@Injectable({
  providedIn: "root",
})
export class EntityDeleteService extends CascadingEntityAction {
  constructor(
    protected override entityMapper: EntityMapperService,
    protected override schemaService: EntitySchemaService,
    protected override entityRelationsService: EntityRelationsService,
    private userAdminService: UserAdminService,
    private confirmationDialog: ConfirmationDialogService,
  ) {
    super(entityMapper, schemaService, entityRelationsService);
  }

  /**
   * The actual delete action without user interactions.
   *
   * Returns an array of all affected entities (including the given entity) in their state before the action
   * to support an undo action.
   *
   * @param entity
   * @param showKeycloakWarning if keycloak deleteUser request fails, a popup warning is shown to the user
   * @private
   */
  async deleteEntity(
    entity: Entity,
    showKeycloakWarning = false,
  ): Promise<CascadingActionResult> {
    if (entity.getConstructor()?.enableUserAccounts) {
      this.userAdminService.deleteUser(entity.getId()).subscribe({
        next: () => {},
        error: () => {
          if (showKeycloakWarning) {
            this.confirmationDialog.getConfirmation(
              $localize`:delete account in keycloak related error title:Keycloak User could not be deleted`,
              $localize`:delete account in keycloak related error dialog:User Account could not be deleted in Keycloak. Please delete user manually in Keycloak.`,
              OkButton,
            );
          }
        },
      });
    }

    const cascadeResult = await this.cascadeActionToRelatedEntities(
      entity,
      (e) => this.deleteEntity(e),
      (e, refField, entity) =>
        this.removeReferenceFromEntity(e, refField, entity),
    );

    const originalEntity = entity.copy();
    await this.entityMapper.remove(entity);

    return new CascadingActionResult([originalEntity]).mergeResults(
      cascadeResult,
    );
  }

  /**
   * Change and save the entity, removing referenced ids of the given referenced entity.
   *
   * Returns an array of the affected entities (which here is only the given entity) in the state before the action
   * to support an undo action.
   *
   * @param relatedEntityWithReference
   * @param refField
   * @param referencedEntity
   * @private
   */
  private async removeReferenceFromEntity(
    relatedEntityWithReference: Entity,
    refField: string,
    referencedEntity: Entity,
  ): Promise<CascadingActionResult> {
    const originalEntity = relatedEntityWithReference.copy();

    if (Array.isArray(relatedEntityWithReference[refField])) {
      relatedEntityWithReference[refField] = relatedEntityWithReference[
        refField
      ].filter((id) => id !== referencedEntity.getId());
    } else {
      delete relatedEntityWithReference[refField];
    }

    await this.entityMapper.save(relatedEntityWithReference);

    return new CascadingActionResult(
      [originalEntity],
      relatedEntityWithReference.getConstructor().hasPII
        ? [relatedEntityWithReference]
        : [],
    );
  }
}

results matching ""

    No results matching ""