@acorex-platform/module-security-management-client 0.0.18 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (17) hide show
  1. package/fesm2022/acorex-platform-module-security-management-client-acorex-platform-module-security-management-client-jSDkyMMZ.mjs +2088 -0
  2. package/fesm2022/acorex-platform-module-security-management-client-acorex-platform-module-security-management-client-jSDkyMMZ.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-module-security-management-client-contracts.mjs +108 -1576
  4. package/fesm2022/acorex-platform-module-security-management-client-contracts.mjs.map +1 -1
  5. package/fesm2022/acorex-platform-module-security-management-client-index-DOHWBEzM.mjs +462 -0
  6. package/fesm2022/acorex-platform-module-security-management-client-index-DOHWBEzM.mjs.map +1 -0
  7. package/fesm2022/{acorex-platform-module-security-management-client-send-password-reset-email.command-DzfUvFk2.mjs → acorex-platform-module-security-management-client-send-password-reset-email.command-CoQgWdya.mjs} +9 -9
  8. package/fesm2022/acorex-platform-module-security-management-client-send-password-reset-email.command-CoQgWdya.mjs.map +1 -0
  9. package/fesm2022/{acorex-platform-module-security-management-client-terminate-session.command-CKq-4Z4O.mjs → acorex-platform-module-security-management-client-terminate-session.command-dsU7scOK.mjs} +19 -12
  10. package/fesm2022/acorex-platform-module-security-management-client-terminate-session.command-dsU7scOK.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-security-management-client.mjs +1 -1712
  12. package/fesm2022/acorex-platform-module-security-management-client.mjs.map +1 -1
  13. package/package.json +1 -1
  14. package/types/acorex-platform-module-security-management-client-contracts.d.ts +163 -34
  15. package/types/acorex-platform-module-security-management-client.d.ts +139 -35
  16. package/fesm2022/acorex-platform-module-security-management-client-send-password-reset-email.command-DzfUvFk2.mjs.map +0 -1
  17. package/fesm2022/acorex-platform-module-security-management-client-terminate-session.command-CKq-4Z4O.mjs.map +0 -1
@@ -4,8 +4,10 @@ import { AXPValueWidgetComponent, AXPColumnWidgetComponent } from '@acorex-platf
4
4
  import { AXBasePageComponent } from '@acorex/components/page';
5
5
  import { AXPPermissionGroupDefinition, AXPPermissionDefinition } from '@acorex-platform/framework-client/auth';
6
6
  import { AXValueChangedEvent } from '@acorex/cdk/common';
7
- import { AXPCommand } from '@acorex-platform/framework-shared/runtime';
8
- import { AXPExecuteCommandResult } from '@acorex-platform/framework-shared/core';
7
+ import { AXPCommand, AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';
8
+ import { AXPActionMenuItem, AXPExecuteCommand } from '@acorex-platform/framework-shared/core';
9
+ import { AXPPageLayoutBaseComponent } from '@acorex-platform/framework-client/layout/views';
10
+ import { AXPPageComponentProvider, AXPPageComponentDefinition } from '@acorex-platform/framework-client/layout/components';
9
11
  import { AXPWidgetConfig } from '@acorex-platform/framework-shared/widget-core';
10
12
 
11
13
  /**
@@ -35,17 +37,21 @@ interface MappedPermission extends Omit<AXPPermissionDefinition, 'children'> {
35
37
  isSelected: boolean;
36
38
  children: MappedPermission[] | null;
37
39
  }
40
+ /** Right-panel section (optional nested group) or a flat unsectioned block. */
41
+ interface PermissionPanelSection {
42
+ name: string;
43
+ title: string | null;
44
+ items: MappedPermission[];
45
+ }
38
46
  interface PermissionSearchGroupResult {
39
47
  group: AXPPermissionGroupDefinition & {
40
48
  badge: string;
41
49
  };
42
- items: MappedPermission[];
50
+ sections: PermissionPanelSection[];
43
51
  }
44
52
  declare class AXPPermissionsEditorComponent extends AXBasePageComponent {
45
53
  /** Service for fetching permission groups and definitions */
46
54
  private permissionService;
47
- /** Session service for checking module access */
48
- private sessionService;
49
55
  /** Translation service for resolving permission labels during search */
50
56
  private translationService;
51
57
  /** Currently selected permission group */
@@ -60,6 +66,9 @@ declare class AXPPermissionsEditorComponent extends AXBasePageComponent {
60
66
  readOnly: _angular_core.InputSignal<boolean>;
61
67
  /** Whether popup footer actions (Cancel / Select) are shown */
62
68
  showActions: _angular_core.InputSignal<boolean>;
69
+ /** When true, fills the host (detail page) without the dialog max-height cap. */
70
+ fillHeight: _angular_core.InputSignal<boolean>;
71
+ protected readonly hostClass: _angular_core.Signal<"axm-permissions-editor axm-permissions-editor--fill-height flex h-full min-h-0 flex-col overflow-hidden" | "axm-permissions-editor axm-permissions-editor--dialog flex h-full max-h-[75vh] min-h-0 flex-col overflow-hidden p-4 gap-3">;
63
72
  /** List of selected permission names */
64
73
  protected selectedPermissions: _angular_core.WritableSignal<string[]>;
65
74
  /** Event emitted when permissions selection changes */
@@ -81,22 +90,29 @@ declare class AXPPermissionsEditorComponent extends AXBasePageComponent {
81
90
  protected getInitialPermissions(): string[];
82
91
  /**
83
92
  * Recursively maps permissions to include selection state and children.
93
+ * Sorted alphabetically by translated title.
84
94
  */
85
95
  private mapPermissions;
86
96
  /**
87
- * Computed: Returns mapped permissions for the selected group.
97
+ * Locale-aware label comparison using the resolved translation when available.
88
98
  */
89
- protected items: _angular_core.Signal<MappedPermission[]>;
99
+ private compareByTitle;
90
100
  /**
91
- * Computed: Returns groups with badge counts, sorted by title.
101
+ * Computed: Left-nav roots only (groups without a parent), sorted by title.
92
102
  */
93
103
  protected groupsWithBadge: _angular_core.Signal<{
94
104
  badge: string;
95
105
  name: string;
96
106
  title: string;
97
107
  description?: string;
108
+ parent?: string;
109
+ order?: number;
98
110
  permissions: AXPPermissionDefinition[];
99
111
  }[]>;
112
+ /**
113
+ * Computed: Right-panel sections for the selected root (or one flat block).
114
+ */
115
+ protected selectedSections: _angular_core.Signal<PermissionPanelSection[]>;
100
116
  /** Sidebar group placeholders for the loading skeleton */
101
117
  protected readonly groupSkeletonPlaceholders: _angular_core.Signal<string[]>;
102
118
  /** Permission group placeholders (parent + child rows) for the loading skeleton */
@@ -107,28 +123,33 @@ declare class AXPPermissionsEditorComponent extends AXBasePageComponent {
107
123
  protected readonly childSkeletonPlaceholders: (count: number) => number[];
108
124
  /** Whether the user is actively searching permissions */
109
125
  protected isSearchActive: _angular_core.Signal<boolean>;
110
- /** Grouped search results across all permission groups */
126
+ /** Grouped search results across all root permission groups */
111
127
  protected searchResultsGrouped: _angular_core.Signal<PermissionSearchGroupResult[]>;
112
128
  /** Whether the active search returned any permission groups */
113
129
  protected hasSearchResults: _angular_core.Signal<boolean>;
114
130
  /**
115
- * Extracts module name from a permission group name.
116
- * Handles multiple formats:
117
- * - Permission key format: 'SecurityManagement:Permission:SecurityManagement.Management' -> 'SecurityManagement'
118
- * - PascalCase: 'TenantManagement' -> 'TenantManagement'
119
- * - kebab-case: 'tenant-management' -> 'TenantManagement' (converts to PascalCase)
131
+ * Drops empty roots/sections after session feature filtering in
132
+ * {@link AXPPermissionDefinitionService}. Keeps a root only when it or a child
133
+ * section still has at least one permission.
120
134
  */
121
- private extractModuleNameFromGroupName;
135
+ private filterGroupsByEnabledModules;
136
+ /** Permission keys still visible after edition/feature filtering. */
137
+ private collectAvailablePermissionNames;
122
138
  /**
123
- * Filters permission groups to only include those from enabled modules.
139
+ * Child section groups under a root, sorted alphabetically by translated title.
124
140
  */
125
- private filterGroupsByEnabledModules;
141
+ private getChildSections;
142
+ /**
143
+ * Builds right-panel sections for a root. When `normalizedQuery` is set, keeps
144
+ * only matching permissions/sections (and sections whose title matches).
145
+ */
146
+ private buildPanelSections;
126
147
  /**
127
148
  * Recursively collects all permission names (parents and children) from an array.
128
149
  */
129
150
  private collectAllPermissionNames;
130
151
  /**
131
- * Returns the badge count for a group (all selected permissions, including parents).
152
+ * Returns the badge count for a root (own permissions + child section permissions).
132
153
  */
133
154
  private getBadge;
134
155
  /**
@@ -139,6 +160,10 @@ declare class AXPPermissionsEditorComponent extends AXBasePageComponent {
139
160
  * Checks if a permission is selected.
140
161
  */
141
162
  protected badgeToNumber(value: unknown): number;
163
+ /** Looks up a left-nav root group by tab key (group name). */
164
+ protected getGroupByKey(key: string | undefined): (AXPPermissionGroupDefinition & {
165
+ badge: string;
166
+ }) | undefined;
142
167
  /**
143
168
  * Returns true when searchable text contains the query.
144
169
  */
@@ -201,37 +226,116 @@ declare class AXPPermissionsEditorComponent extends AXBasePageComponent {
201
226
  */
202
227
  protected handleSelectClick(): void;
203
228
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXPPermissionsEditorComponent, never>;
204
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXPPermissionsEditorComponent, "axm-permissions-editor", never, { "initialPermissions": { "alias": "initialPermissions"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; }, { "permissionsChanged": "permissionsChanged"; "permissionsSelected": "permissionsSelected"; }, never, never, true, never>;
229
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXPPermissionsEditorComponent, "axm-permissions-editor", never, { "initialPermissions": { "alias": "initialPermissions"; "required": false; "isSignal": true; }; "readOnly": { "alias": "readOnly"; "required": false; "isSignal": true; }; "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "fillHeight": { "alias": "fillHeight"; "required": false; "isSignal": true; }; }, { "permissionsChanged": "permissionsChanged"; "permissionsSelected": "permissionsSelected"; }, never, never, true, never>;
205
230
  }
206
231
 
207
232
  interface AXMAssignPermissionsCommandInput {
208
- __context__?: {
209
- data?: Record<string, unknown>;
210
- entity?: string;
211
- entityInfo?: {
212
- name?: string;
213
- module?: string;
214
- title?: string;
215
- parentKey?: string;
216
- source?: string;
217
- };
218
- options?: unknown;
219
- };
233
+ data?: Record<string, unknown>;
220
234
  }
221
235
  declare class AXMAssignPermissionsCommand implements AXPCommand<AXMAssignPermissionsCommandInput, string[] | null> {
222
236
  private readonly popupService;
223
237
  private readonly translationService;
224
- private readonly entityRegistry;
225
238
  private readonly toastService;
226
239
  private readonly settingsService;
227
- private readonly workflowEventService;
228
- execute(input: AXMAssignPermissionsCommandInput): Promise<AXPExecuteCommandResult<string[] | null>>;
240
+ private readonly grantService;
241
+ execute(input: AXMAssignPermissionsCommandInput): AXPCommandExecuteResultPromise<string[] | null>;
229
242
  private resolveRoleTitle;
230
243
  private showSuccessToast;
231
244
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXMAssignPermissionsCommand, never>;
232
245
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<AXMAssignPermissionsCommand>;
233
246
  }
234
247
 
248
+ interface RolePermissionGrantRow {
249
+ id: string;
250
+ roleId: string;
251
+ permissions: string[];
252
+ scopeInfo?: {
253
+ kind?: string;
254
+ tenantId?: string;
255
+ applicationId?: string;
256
+ };
257
+ stateInfo?: {
258
+ isSystem?: boolean;
259
+ isImmutable?: boolean;
260
+ isHidden?: boolean;
261
+ };
262
+ }
263
+ interface SaveRolePermissionGrantOptions {
264
+ existing: RolePermissionGrantRow | null;
265
+ roleId: string;
266
+ permissions: string[];
267
+ tenantId: string;
268
+ applicationId: string | undefined;
269
+ }
270
+
271
+ /**
272
+ * Loads and persists scoped RolePermission grants for a role.
273
+ * Shared by the Assign Permissions dialog and the Role permissions detail page.
274
+ */
275
+ declare class AXMRolePermissionGrantService {
276
+ private readonly entityRegistry;
277
+ private readonly entityService;
278
+ private readonly sessionService;
279
+ private readonly entityEvents;
280
+ resolveSessionScope(): {
281
+ tenantId: string;
282
+ applicationId: string | undefined;
283
+ } | null;
284
+ private rolePermissionData;
285
+ findGrant(roleId: string, tenantId: string, applicationId: string | undefined): Promise<RolePermissionGrantRow | null>;
286
+ saveGrant(options: SaveRolePermissionGrantOptions): Promise<Record<string, unknown>>;
287
+ notifyGrantModified(saved: Record<string, unknown>): void;
288
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXMRolePermissionGrantService, never>;
289
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<AXMRolePermissionGrantService>;
290
+ }
291
+
292
+ /**
293
+ * Role detail/create wizard page that edits scoped RolePermission grants.
294
+ * Extends AXPPageLayoutBaseComponent for Save/Discard footer actions and dirty tracking.
295
+ */
296
+ declare class AXMRolePermissionsPageComponent extends AXPPageLayoutBaseComponent {
297
+ rootContext: _angular_core.InputSignal<Record<string, unknown> | undefined>;
298
+ /** Optional page config set by the page-component-renderer. */
299
+ pageConfig: _angular_core.InputSignal<Record<string, unknown> | undefined>;
300
+ private readonly grantService;
301
+ private readonly hostPageLayout;
302
+ private readonly loadedRoleId;
303
+ private readonly existingGrant;
304
+ private readonly baselinePermissions;
305
+ private readonly currentPermissions;
306
+ protected readonly isLoading: _angular_core.WritableSignal<boolean>;
307
+ /** Bumps when the editor should remount with a new initialPermissions snapshot (e.g. after discard). */
308
+ protected readonly editorResetToken: _angular_core.WritableSignal<number>;
309
+ protected readonly roleId: _angular_core.Signal<string | undefined>;
310
+ protected readonly editorPermissions: _angular_core.Signal<string[]>;
311
+ protected readonly isDirty: _angular_core.Signal<boolean>;
312
+ /** System RolePermission grants are seeded and not editable in product/platform UI. */
313
+ protected readonly isGrantReadonly: _angular_core.Signal<boolean>;
314
+ constructor();
315
+ hasUnsavedChanges(): boolean;
316
+ getPrimaryMenuItems(): Promise<AXPActionMenuItem[]>;
317
+ execute(command: AXPExecuteCommand): void | Promise<void>;
318
+ private handleSaveExecute;
319
+ protected onPermissionsChanged(permissions: string[]): void;
320
+ private handleDiscard;
321
+ /**
322
+ * Do not merge permissions into the Role create/update payload.
323
+ * Grants live on SecurityManagement.RolePermission only.
324
+ */
325
+ getWizardStepContext(): Record<string, unknown> | null;
326
+ private loadGrantForRole;
327
+ private arePermissionSetsEqual;
328
+ protected recompute(): void;
329
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXMRolePermissionsPageComponent, never>;
330
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AXMRolePermissionsPageComponent, "axm-role-permissions-page", never, { "rootContext": { "alias": "rootContext"; "required": false; "isSignal": true; }; "pageConfig": { "alias": "pageConfig"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
331
+ }
332
+
333
+ declare class AXMRolePermissionsPageComponentProvider implements AXPPageComponentProvider {
334
+ components(): Promise<AXPPageComponentDefinition[]>;
335
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AXMRolePermissionsPageComponentProvider, never>;
336
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<AXMRolePermissionsPageComponentProvider>;
337
+ }
338
+
235
339
  interface PermissionPath {
236
340
  group: AXPPermissionGroupDefinition;
237
341
  path: AXPPermissionDefinition[];
@@ -268,4 +372,4 @@ declare class AXPPermissionsWidgetColumnComponent extends AXPColumnWidgetCompone
268
372
 
269
373
  declare const AXPPermissionsWidget: AXPWidgetConfig;
270
374
 
271
- export { AXMAssignPermissionsCommand, AXMDeviceSessionsService, AXMPermissionsModule, AXMSecurityManagementModule, AXPPermissionsEditorComponent, AXPPermissionsWidget, AXPPermissionsWidgetColumnComponent, AXPPermissionsWidgetEditComponent, AXPPermissionsWidgetViewComponent };
375
+ export { AXMAssignPermissionsCommand, AXMDeviceSessionsService, AXMPermissionsModule, AXMRolePermissionGrantService, AXMRolePermissionsPageComponent, AXMRolePermissionsPageComponentProvider, AXMSecurityManagementModule, AXPPermissionsEditorComponent, AXPPermissionsWidget, AXPPermissionsWidgetColumnComponent, AXPPermissionsWidgetEditComponent, AXPPermissionsWidgetViewComponent };
@@ -1 +0,0 @@
1
- {"version":3,"file":"acorex-platform-module-security-management-client-send-password-reset-email.command-DzfUvFk2.mjs","sources":["../../../../libs/modules/security-management/client/src/lib/commands/send-password-reset-email.command.ts"],"sourcesContent":["import { AXDialogService } from '@acorex/components/dialog';\nimport { AXToastService } from '@acorex/components/toast';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXPCommandService } from '@acorex-platform/framework-client/runtime';\nimport { AXPExecuteCommandResult } from '@acorex-platform/framework-shared/core';\nimport { AXPCommand } from '@acorex-platform/framework-shared/runtime';\nimport {\n AXM_USER_SEND_PASSWORD_RESET_COMMAND,\n AXMSecurityManagementServerCommands,\n} from '@acorex-platform/module-security-management-client/contracts';\nimport { inject, Injectable } from '@angular/core';\n\n//#region ---- Types ----\n\nexport interface AXPSendPasswordResetEmailCommandInput {\n __context__?: {\n data?: { id?: string; email?: string; displayName?: string; username?: string };\n entity?: string;\n };\n userId?: string;\n}\n\n//#endregion\n\n//#region ---- Client command ----\n\n/**\n * Admin Action on User detail: confirm, then call server SendPasswordResetEmail.\n */\n@Injectable({ providedIn: 'root' })\nexport class AXPSendPasswordResetEmailCommand\n implements AXPCommand<AXPSendPasswordResetEmailCommandInput, AXPExecuteCommandResult>\n{\n private readonly dialogService = inject(AXDialogService);\n private readonly toastService = inject(AXToastService);\n private readonly translationService = inject(AXTranslationService);\n private readonly commandService = inject(AXPCommandService);\n\n async execute(input: AXPSendPasswordResetEmailCommandInput = {}): Promise<AXPExecuteCommandResult> {\n const userId = input.userId ?? input.__context__?.data?.id;\n if (!userId) {\n return { success: false, message: { text: 'User id is required.' } };\n }\n\n const who =\n input.__context__?.data?.displayName ||\n input.__context__?.data?.username ||\n input.__context__?.data?.email ||\n String(userId);\n\n const confirmTitle = await this.translationService\n .translateAsync('@security-management:users.entities.user.actions.send-password-reset.confirm-title')\n .catch(() => 'Send Password Reset Email');\n const confirmMessage = await this.translationService\n .translateAsync('@security-management:users.entities.user.actions.send-password-reset.confirm-message', {\n params: { user: who },\n })\n .catch(() => `Send a password reset email to ${who}?`);\n\n const confirmed = await this.dialogService.confirm(confirmTitle, confirmMessage, 'primary', 'horizontal');\n if (!confirmed.result) {\n return { success: false };\n }\n\n const webOrigin = typeof window !== 'undefined' ? window.location.origin : undefined;\n const result = await this.commandService.execute(AXMSecurityManagementServerCommands.SendPasswordResetEmail, {\n userId: String(userId),\n webOrigin,\n });\n\n if (result?.success) {\n const [toastTitle, toastContent] = await Promise.all([\n this.translationService\n .translateAsync(\n '@security-management:users.entities.user.actions.send-password-reset.success.title',\n )\n .catch(() => 'Email Sent'),\n this.translationService\n .translateAsync(\n '@security-management:users.entities.user.actions.send-password-reset.success.description',\n )\n .catch(() => 'Password reset email sent.'),\n ]);\n this.toastService.show({ color: 'success', title: toastTitle, content: toastContent, timeOut: 3000 });\n return { success: true };\n }\n\n const [toastTitle, fallbackContent] = await Promise.all([\n this.translationService\n .translateAsync(\n '@security-management:users.entities.user.actions.send-password-reset.error.title',\n )\n .catch(() => 'Send Failed'),\n this.translationService\n .translateAsync(\n '@security-management:users.entities.user.actions.send-password-reset.error.description',\n )\n .catch(() => 'Failed to send password reset email.'),\n ]);\n const toastContent =\n (typeof result?.message?.text === 'string' && result.message.text) || fallbackContent;\n this.toastService.show({ color: 'danger', title: toastTitle, content: toastContent, timeOut: 4000 });\n return { success: false, message: { text: toastContent } };\n }\n}\n\nexport { AXM_USER_SEND_PASSWORD_RESET_COMMAND };\n\n//#endregion\n"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"acorex-platform-module-security-management-client-terminate-session.command-CKq-4Z4O.mjs","sources":["../../../../libs/modules/security-management/client/src/lib/commands/terminate-session.command.ts"],"sourcesContent":["import { AXDialogService } from '@acorex/components/dialog';\nimport { AXLoadingDialogService } from '@acorex/components/loading-dialog';\nimport { AXToastService } from '@acorex/components/toast';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport {\n AXPCommonSettings,\n AXPRefreshEvent,\n AXPSettingsService,\n} from '@acorex-platform/framework-client/common';\nimport { AXPEntityDefinitionRegistryService, AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { AXPWorkflowEventService } from '@acorex-platform/framework-client/workflow';\nimport { AXPExecuteCommandResult } from '@acorex-platform/framework-shared/core';\nimport { AXPCommand } from '@acorex-platform/framework-shared/runtime';\nimport { RootConfig } from '@acorex-platform/module-security-management-client/contracts';\nimport { inject, Injectable } from '@angular/core';\n\n//#region ---- Types ----\n\nexport interface AXPTerminateSessionCommandContext {\n data: unknown;\n entity: string;\n entityInfo?: { parentKey?: string };\n options?: unknown;\n meta?: Record<string, unknown>;\n}\n\nexport interface AXPTerminateSessionCommandInput {\n __context__?: AXPTerminateSessionCommandContext;\n __metadata__?: unknown;\n}\n\n//#endregion\n\n//#region ---- Terminate session command ----\n\n/**\n * Terminates one or more device sessions (entity list / detail actions).\n * Replaces the former `terminate-entity` workflow (loading + terminate loop + success toast).\n */\n@Injectable({ providedIn: 'root' })\nexport class AXPTerminateSessionCommand implements AXPCommand<AXPTerminateSessionCommandInput, AXPExecuteCommandResult> {\n private readonly entityRegistry = inject(AXPEntityDefinitionRegistryService);\n private readonly entityService = inject(AXPEntityService);\n private readonly dialogService = inject(AXDialogService);\n private readonly loadingDialog = inject(AXLoadingDialogService);\n private readonly translationService = inject(AXTranslationService);\n private readonly toastService = inject(AXToastService);\n private readonly settingsService = inject(AXPSettingsService);\n private readonly workflowEventService = inject(AXPWorkflowEventService);\n private readonly deviceSessionsDataAccessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.deviceSessions.name)\n .data<string, { id: string }>();\n\n async execute(input: AXPTerminateSessionCommandInput = {}): Promise<AXPExecuteCommandResult> {\n const context = input.__context__;\n if (!context?.entity || context.data == null) {\n return { success: false };\n }\n\n const moduleEntity = context.entity;\n const [moduleName, entityName] = moduleEntity.split('.');\n const data = context.data as Record<string, unknown> | Record<string, unknown>[];\n const meta = { ...(context.meta ?? {}) };\n\n const ids = Array.isArray(data) ? data.map((item) => String(item['id'])) : [String(data['id'])];\n const entity = await this.entityRegistry.resolve(moduleName, entityName);\n\n if (entity.parentKey && !Array.isArray(data) && data[entity.parentKey]) {\n meta['refreshTargetId'] = data[entity.parentKey];\n }\n\n const dialog = this.loadingDialog.show({\n title: await this.translationService.translateAsync('workflow.terminating'),\n mode: 'determinate',\n status: 'Terminating...',\n progressValue: 0,\n text: `0/${ids.length}`,\n buttons: [\n {\n text: await this.translationService.translateAsync('cancel'),\n color: 'danger',\n onClick: () => {\n dialog.close();\n },\n },\n ],\n });\n\n let failedCounter = 0;\n for (const id of ids) {\n try {\n await this.deviceSessionsDataAccessor.update(id, { status: 'revoked' });\n } catch {\n failedCounter++;\n await this.dialogService.alert(\n await this.translationService.translateAsync('workflow.fail-delete-title'),\n await this.translationService.translateAsync('workflow.fail-delete-body', {\n params: { item: 1 },\n }),\n 'danger',\n );\n }\n }\n\n const success = failedCounter === 0;\n setTimeout(() => {\n dialog.close();\n this.workflowEventService.dispatch(AXPRefreshEvent({ entity: moduleEntity, meta }));\n }, 300);\n\n if (success) {\n await this.showSuccessToast();\n }\n\n return { success };\n }\n\n private async showSuccessToast(): Promise<void> {\n const showResult = await this.settingsService.get(AXPCommonSettings.EnableOperationToasts);\n if (!showResult) {\n return;\n }\n\n this.toastService.show({\n color: 'success',\n title: await this.translationService.translateAsync('workflow.session-terminated'),\n content: await this.translationService.translateAsync('workflow.session-terminated-body'),\n closeButton: true,\n timeOut: 3000,\n timeOutProgress: true,\n });\n }\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}