@acorex-platform/module-security-management-client 0.0.15 → 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 (16) 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 +158 -1677
  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-CoQgWdya.mjs +81 -0
  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 -1704
  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 +208 -33
  15. package/types/acorex-platform-module-security-management-client.d.ts +139 -35
  16. package/fesm2022/acorex-platform-module-security-management-client-terminate-session.command-CKq-4Z4O.mjs.map +0 -1
@@ -1,10 +1,7 @@
1
- import { AXPEntity, AXPEntityModel } from '@acorex-platform/framework-shared/entity';
2
- import { AXPExpression } from '@acorex-platform/framework-shared/core';
1
+ import { AXPContextDefinition, AXPExpression } from '@acorex-platform/framework-shared/core';
2
+ import { AXPEntityModel } from '@acorex-platform/framework-shared/entity';
3
3
 
4
- /** Security Management datasource registry names. */
5
- declare const AXMSecurityManagementDataSourceKeys: {
6
- readonly Users: "users";
7
- };
4
+ declare const AXM_SECURITY_CONTEXT_DEFINITIONS: AXPContextDefinition[];
8
5
 
9
6
  /**
10
7
  * Security Management Module Feature Keys.
@@ -16,6 +13,8 @@ declare const AXPSecurityManagementFeatureKeys: {
16
13
  readonly MaxTotalUsers: "SecurityManagement:Feature:MaxTotalUsers";
17
14
  readonly ManageSessions: "SecurityManagement:Feature:ManageSessions";
18
15
  readonly ManagePolicies: "SecurityManagement:Feature:ManagePolicies";
16
+ /** Platform Console only — Identity Provider management menu + CRUD. */
17
+ readonly ManageIdentityProviders: "SecurityManagement:Feature:ManageIdentityProviders";
19
18
  };
20
19
 
21
20
  declare const AXPSecurityManagementMenuKeys: {
@@ -24,38 +23,74 @@ declare const AXPSecurityManagementMenuKeys: {
24
23
  readonly Roles: "SecurityManagement:Menu:Roles";
25
24
  readonly DeviceSessions: "SecurityManagement:Menu:DeviceSessions";
26
25
  readonly Policy: "SecurityManagement:Menu:Policy";
26
+ readonly IdentityProviders: "SecurityManagement:Menu:IdentityProviders";
27
27
  readonly MyProfile: "SecurityManagement:Menu:MyProfile";
28
28
  };
29
29
 
30
+ /**
31
+ * Administration capabilities used by this module.
32
+ * Domain capability keys for this module. Root groups live in `AXPCommonPermissionGroupKeys` (common contracts).
33
+ */
34
+ declare const AXPAdministrationPermissionKeys: {
35
+ readonly Access: "Administration:Permission:Access";
36
+ /** Create and maintain users, roles, role assignments, and related security-access reports. */
37
+ readonly MaintainUsersAndRoles: "Administration:Permission:MaintainUsersAndRoles";
38
+ readonly ManageSessions: "Administration:Permission:ManageSessions";
39
+ readonly MaintainPolicies: "Administration:Permission:MaintainPolicies";
40
+ readonly ViewIntegrations: "Administration:Permission:ViewIntegrations";
41
+ readonly MaintainConnections: "Administration:Permission:MaintainConnections";
42
+ readonly ManageIntegrationActions: "Administration:Permission:ManageIntegrationActions";
43
+ readonly MaintainWorkflows: "Administration:Permission:MaintainWorkflows";
44
+ readonly ManageWorkflowActions: "Administration:Permission:ManageWorkflowActions";
45
+ readonly ViewRules: "Administration:Permission:ViewRules";
46
+ readonly MaintainRules: "Administration:Permission:MaintainRules";
47
+ readonly ManageRuleActions: "Administration:Permission:ManageRuleActions";
48
+ readonly MaintainAi: "Administration:Permission:MaintainAi";
49
+ readonly UseAiAssist: "Administration:Permission:UseAiAssist";
50
+ readonly MaintainDashboards: "Administration:Permission:MaintainDashboards";
51
+ readonly ViewJobs: "Administration:Permission:ViewJobs";
52
+ readonly ManageJobActions: "Administration:Permission:ManageJobActions";
53
+ readonly ViewObservability: "Administration:Permission:ViewObservability";
54
+ readonly MaintainObservability: "Administration:Permission:MaintainObservability";
55
+ };
56
+ /**
57
+ * @deprecated Prefer {@link AXPAdministrationPermissionKeys}.
58
+ * Legacy nested shape kept so existing imports compile during migration.
59
+ */
30
60
  declare const AXPSecurityManagementPermissionKeys: {
31
61
  readonly User: {
32
- readonly Management: "SecurityManagement:Permission:User.Management";
33
- readonly View: "SecurityManagement:Permission:User.View";
34
- readonly Edit: "SecurityManagement:Permission:User.Edit";
35
- readonly Delete: "SecurityManagement:Permission:User.Delete";
36
- readonly Create: "SecurityManagement:Permission:User.Create";
62
+ readonly Management: "Administration:Permission:MaintainUsersAndRoles";
63
+ readonly View: "Administration:Permission:MaintainUsersAndRoles";
64
+ readonly Edit: "Administration:Permission:MaintainUsersAndRoles";
65
+ readonly Delete: "Administration:Permission:MaintainUsersAndRoles";
66
+ readonly Create: "Administration:Permission:MaintainUsersAndRoles";
37
67
  };
38
68
  readonly Role: {
39
- readonly Management: "SecurityManagement:Permission:Role.Management";
40
- readonly View: "SecurityManagement:Permission:Role.View";
41
- readonly Edit: "SecurityManagement:Permission:Role.Edit";
42
- readonly Delete: "SecurityManagement:Permission:Role.Delete";
43
- readonly Create: "SecurityManagement:Permission:Role.Create";
69
+ readonly Management: "Administration:Permission:MaintainUsersAndRoles";
70
+ readonly View: "Administration:Permission:MaintainUsersAndRoles";
71
+ readonly Edit: "Administration:Permission:MaintainUsersAndRoles";
72
+ readonly Delete: "Administration:Permission:MaintainUsersAndRoles";
73
+ readonly Create: "Administration:Permission:MaintainUsersAndRoles";
44
74
  };
45
75
  readonly DeviceSession: {
46
- readonly Management: "SecurityManagement:Permission:DeviceSession.Management";
47
- readonly View: "SecurityManagement:Permission:DeviceSession.View";
48
- readonly Terminate: "SecurityManagement:Permission:DeviceSession.Terminate";
76
+ readonly Management: "Administration:Permission:ManageSessions";
77
+ readonly View: "Administration:Permission:ManageSessions";
78
+ readonly Terminate: "Administration:Permission:ManageSessions";
49
79
  };
50
80
  readonly Policy: {
51
- readonly Management: "SecurityManagement:Permission:Policy.Management";
52
- readonly View: "SecurityManagement:Permission:Policy.View";
53
- readonly Edit: "SecurityManagement:Permission:Policy.Edit";
54
- readonly Delete: "SecurityManagement:Permission:Policy.Delete";
55
- readonly Create: "SecurityManagement:Permission:Policy.Create";
81
+ readonly Management: "Administration:Permission:MaintainPolicies";
82
+ readonly View: "Administration:Permission:MaintainPolicies";
83
+ readonly Edit: "Administration:Permission:MaintainPolicies";
84
+ readonly Delete: "Administration:Permission:MaintainPolicies";
85
+ readonly Create: "Administration:Permission:MaintainPolicies";
56
86
  };
57
87
  };
58
88
 
89
+ /** Component key for the Role permissions page tab. Register via AXP_PAGE_COMPONENT_PROVIDER. */
90
+ declare const ROLE_PERMISSIONS_PAGE_COMPONENT_KEY = "role-permissions-page";
91
+
92
+ declare const USER_ROLES_PAGE_COMPONENT_KEY = "user-roles-page";
93
+
59
94
  declare const RootConfig: {
60
95
  readonly config: {
61
96
  i18n: string;
@@ -92,12 +127,39 @@ declare const RootConfig: {
92
127
  readonly titlePlural: `@${string}:roles.entities.role.plural`;
93
128
  readonly icon: "fa-light fa-user-tag";
94
129
  };
130
+ readonly rolePermission: {
131
+ readonly name: "RolePermission";
132
+ readonly title: `@${string}:role-permissions.entities.role-permission.title`;
133
+ readonly titlePlural: `@${string}:role-permissions.entities.role-permission.plural`;
134
+ readonly icon: "fa-light fa-key";
135
+ };
136
+ readonly userRole: {
137
+ readonly name: "UserRole";
138
+ readonly title: `@${string}:user-roles.entities.user-role.title`;
139
+ readonly titlePlural: `@${string}:user-roles.entities.user-role.plural`;
140
+ readonly icon: "fa-light fa-user-tag";
141
+ };
95
142
  readonly profile: {
96
143
  readonly name: "Profile";
97
144
  readonly title: `@${string}:profile.entities.profile.title`;
98
145
  readonly titlePlural: `@${string}:profile.entities.profile.plural`;
99
146
  readonly icon: "fa-light fa-user";
100
147
  };
148
+ readonly identityProvider: {
149
+ readonly name: "IdentityProvider";
150
+ readonly title: `@${string}:identity-providers.entities.identity-provider.title`;
151
+ readonly titlePlural: `@${string}:identity-providers.entities.identity-provider.plural`;
152
+ readonly icon: "fa-light fa-id-badge";
153
+ };
154
+ };
155
+ readonly queries: {
156
+ readonly reports: {
157
+ readonly getUserEffectiveRolesHistory: "SecurityManagement:Reports:GetUserEffectiveRolesHistory";
158
+ readonly getUserEffectivePermissionsHistory: "SecurityManagement:Reports:GetUserEffectivePermissionsHistory";
159
+ readonly getRoleHoldersHistory: "SecurityManagement:Reports:GetRoleHoldersHistory";
160
+ readonly getPermissionHoldersHistory: "SecurityManagement:Reports:GetPermissionHoldersHistory";
161
+ readonly getUserPasswordChangeHistory: "SecurityManagement:Reports:GetUserPasswordChangeHistory";
162
+ };
101
163
  };
102
164
  };
103
165
 
@@ -130,7 +192,58 @@ declare enum AXMUserEffectiveState {
130
192
  CredentialExpired = "credential-expired"
131
193
  }
132
194
 
133
- declare function deviceSessionsFactory(): Promise<AXPEntity | null>;
195
+ /**
196
+ * Derives the unified operational state from account lifecycle and sign-in gate.
197
+ * Used for persisted `effectiveState` on SecurityManagement.User.
198
+ */
199
+ declare function resolveAXMUserEffectiveState(input: {
200
+ accountState: string | undefined;
201
+ accessState: AXMUserAccessState | string | undefined;
202
+ }): AXMUserEffectiveState;
203
+
204
+ /**
205
+ * One-time password-reset token state stored as JSON on SecurityManagement.User.
206
+ * The raw token is never persisted — only a SHA-256 hash.
207
+ */
208
+ interface AXMUserPasswordResetInfo {
209
+ tokenHash: string;
210
+ expiresAt: string;
211
+ sentAt: string;
212
+ }
213
+
214
+ declare const AXMSecurityManagementServerCommands: {
215
+ readonly SendPasswordResetEmail: "SecurityManagement:Server:SendPasswordResetEmail";
216
+ readonly CompletePasswordReset: "SecurityManagement:Server:CompletePasswordReset";
217
+ readonly ChangeOwnPassword: "SecurityManagement:Server:ChangeOwnPassword";
218
+ };
219
+ /** Stable codes for self-service password change (client maps to i18n). */
220
+ declare const AXM_CHANGE_OWN_PASSWORD_ERROR_CODES: {
221
+ readonly NotSignedIn: "CHANGE_OWN_PASSWORD_NOT_SIGNED_IN";
222
+ readonly IncorrectCurrent: "CHANGE_OWN_PASSWORD_INCORRECT_CURRENT";
223
+ readonly SameAsCurrent: "CHANGE_OWN_PASSWORD_SAME_AS_CURRENT";
224
+ readonly InvalidInput: "CHANGE_OWN_PASSWORD_INVALID_INPUT";
225
+ };
226
+ /** Client/UI action key (confirm dialog → server send). */
227
+ declare const AXM_USER_SEND_PASSWORD_RESET_COMMAND = "SecurityManagement:User:SendPasswordResetEmail";
228
+ interface AXMSendPasswordResetEmailInput {
229
+ /** Admin path: target user id. */
230
+ userId?: string;
231
+ /** Forgot path: email or username. */
232
+ login?: string;
233
+ /** Optional absolute web origin for reset link (defaults to env / localhost). */
234
+ webOrigin?: string;
235
+ }
236
+ interface AXMCompletePasswordResetInput {
237
+ token: string;
238
+ newPassword: string;
239
+ }
240
+ interface AXMChangeOwnPasswordInput {
241
+ currentPassword: string;
242
+ newPassword: string;
243
+ }
244
+ interface AXMChangeOwnPasswordResult {
245
+ passwordChangedAt: string;
246
+ }
134
247
 
135
248
  declare enum AXMSessionStatusTypes {
136
249
  revoked = "revoked",
@@ -164,9 +277,37 @@ interface AXMSecurityManagementDeviceSessionsEntityModel extends AXPEntityModel<
164
277
  browser: string;
165
278
  location: string;
166
279
  lastLoginDate: Date;
280
+ /** When the session was revoked / logged out (null while still active). */
281
+ loggedOutAt?: Date | string | null;
167
282
  }
168
283
 
169
- declare function policyFactory(): Promise<AXPEntity | null>;
284
+ /**
285
+ * Platform login IdP row (SecurityManagement.IdentityProvider).
286
+ * Active/inactive uses the disable plugin field `isDisabled`.
287
+ * Broker routing uses `key` as OAuth `acr_values`.
288
+ */
289
+ interface AXMIdentityProviderEntityModel {
290
+ id: string;
291
+ /** Stable key used by ListProviders and `/connect` (`google`, `okta-hr`, …). */
292
+ key: string;
293
+ title: string;
294
+ icon?: string | null;
295
+ /** External IdP authorize URL (e.g. Google accounts endpoint). */
296
+ authorizationUrl?: string | null;
297
+ /** External IdP token URL. */
298
+ tokenUrl?: string | null;
299
+ /** Optional userinfo URL when id_token is absent. */
300
+ userInfoUrl?: string | null;
301
+ /** Space-separated scopes requested from the external IdP. */
302
+ scopes?: string | null;
303
+ issuerUrl?: string | null;
304
+ clientId?: string | null;
305
+ /** Platform broker client secret (admin / seed). */
306
+ clientSecret?: string | null;
307
+ /** From disable plugin — `true` means not offered on login. */
308
+ isDisabled?: boolean;
309
+ priority: number;
310
+ }
170
311
 
171
312
  interface AXMSecurityManagementPolicyEntityModel extends AXPEntityModel<string> {
172
313
  name: string;
@@ -190,39 +331,73 @@ interface AXMPolicyEffectRule {
190
331
  target: string;
191
332
  }
192
333
 
193
- declare function profileFactory(): Promise<AXPEntity | null>;
194
-
195
334
  interface AXMSecurityManagementProfileEntityModel extends AXPEntityModel<string> {
196
335
  name: string;
197
336
  title: string;
198
337
  }
199
338
 
200
- declare function rolesFactory(): Promise<AXPEntity | null>;
339
+ /**
340
+ * Scoped permission grants for a Role.
341
+ * Role rows are identity-only; all capability keys live here.
342
+ */
343
+ interface AXMSecurityManagementRolePermissionEntityModel extends AXPEntityModel<string> {
344
+ /** Target {@link SecurityManagement.Role} id. */
345
+ roleId: string;
346
+ /** Capability keys granted for this scope. */
347
+ permissions: string[];
348
+ }
201
349
 
350
+ /**
351
+ * Role identity only. Capability grants live on
352
+ * {@link AXMSecurityManagementRolePermissionEntityModel}.
353
+ */
202
354
  interface AXMSecurityManagementRolesEntityModel extends AXPEntityModel<string> {
203
355
  name: string;
204
356
  title: string;
205
357
  description?: string;
206
- permissions?: string[];
207
358
  }
208
359
 
209
- declare function usersFactory(): Promise<AXPEntity | null>;
360
+ /**
361
+ * Scoped role assignments for a User.
362
+ * User rows are identity-only for roles; all role memberships live here.
363
+ */
364
+ interface AXMSecurityManagementUserRoleEntityModel extends AXPEntityModel<string> {
365
+ /** Target {@link SecurityManagement.User} id. */
366
+ userId: string;
367
+ /** Role ids granted for this scope. */
368
+ roleIds: string[];
369
+ }
210
370
 
211
371
  interface AXMSecurityManagementUsersEntityModel extends AXPEntityModel<string> {
212
372
  id: string;
213
373
  username: string;
214
374
  displayName: string;
375
+ /** Globally unique login email (required for password-reset email). */
376
+ email?: string;
215
377
  password: string;
216
378
  /** Profile photo file storage id or external URL. */
217
379
  avatar?: string | null;
218
380
  pinCode?: string;
381
+ /** ISO timestamp of last successful security PIN change. */
382
+ pinChangedAt?: string | null;
383
+ /**
384
+ * Directory-owning tenant for soft profile admin (display name, avatar, email).
385
+ * Initialized from the creating/inviting tenant; not the same as membership scope.
386
+ */
387
+ homeTenantId?: string;
219
388
  /** Account lifecycle: `security-management.account-state.user`. */
220
389
  accountState?: string;
221
390
  /** Derived operational state: `security-management.effective-state.user` (persisted snapshot in demo/mock). */
222
391
  effectiveState?: AXMUserEffectiveState | string;
223
392
  /** Sign-in gate (read-only in UI); lockout and credential expiry map here, not to `accountState`. */
224
393
  accessState?: AXMUserAccessState;
394
+ /** ISO timestamp of last successful password change. */
395
+ passwordChangedAt?: string | null;
396
+ /** ISO timestamp of last successful sign-in. */
397
+ lastSignInAt?: string | null;
398
+ /** Active password-reset challenge (hidden from UI). */
399
+ passwordReset?: AXMUserPasswordResetInfo | null;
225
400
  }
226
401
 
227
- export { AXMSecurityManagementDataSourceKeys, AXMSessionStatusTypes, AXMUserAccessState, AXMUserEffectiveState, AXM_USER_ACCESS_STATE_DEFINITION_KEY, AXM_USER_EFFECTIVE_STATE_DEFINITION_KEY, AXPSecurityManagementFeatureKeys, AXPSecurityManagementMenuKeys, AXPSecurityManagementPermissionKeys, RootConfig, deviceSessionsFactory, policyFactory, profileFactory, rolesFactory, usersFactory };
228
- export type { AXMPolicyEffect, AXMPolicyEffectRule, AXMPolicyScope, AXMSecurityManagementDeviceSessionsEntityModel, AXMSecurityManagementPolicyEntityModel, AXMSecurityManagementProfileEntityModel, AXMSecurityManagementRolesEntityModel, AXMSecurityManagementUsersEntityModel };
402
+ export { AXMSecurityManagementServerCommands, AXMSessionStatusTypes, AXMUserAccessState, AXMUserEffectiveState, AXM_CHANGE_OWN_PASSWORD_ERROR_CODES, AXM_SECURITY_CONTEXT_DEFINITIONS, AXM_USER_ACCESS_STATE_DEFINITION_KEY, AXM_USER_EFFECTIVE_STATE_DEFINITION_KEY, AXM_USER_SEND_PASSWORD_RESET_COMMAND, AXPAdministrationPermissionKeys, AXPSecurityManagementFeatureKeys, AXPSecurityManagementMenuKeys, AXPSecurityManagementPermissionKeys, ROLE_PERMISSIONS_PAGE_COMPONENT_KEY, RootConfig, USER_ROLES_PAGE_COMPONENT_KEY, resolveAXMUserEffectiveState };
403
+ export type { AXMChangeOwnPasswordInput, AXMChangeOwnPasswordResult, AXMCompletePasswordResetInput, AXMIdentityProviderEntityModel, AXMPolicyEffect, AXMPolicyEffectRule, AXMPolicyScope, AXMSecurityManagementDeviceSessionsEntityModel, AXMSecurityManagementPolicyEntityModel, AXMSecurityManagementProfileEntityModel, AXMSecurityManagementRolePermissionEntityModel, AXMSecurityManagementRolesEntityModel, AXMSecurityManagementUserRoleEntityModel, AXMSecurityManagementUsersEntityModel, AXMSendPasswordResetEmailInput, AXMUserPasswordResetInfo };
@@ -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-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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"}