@acorex/platform 21.0.0-next.1 → 21.0.0-next.2
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.
- package/auth/index.d.ts +238 -92
- package/common/index.d.ts +42 -606
- package/core/index.d.ts +432 -574
- package/fesm2022/acorex-platform-auth.mjs +200 -153
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/acorex-platform-common.mjs +112 -1009
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-core.mjs +416 -694
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-domain.mjs +11 -54
- package/fesm2022/acorex-platform-domain.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +272 -414
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components.mjs +3105 -2064
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +7 -7
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +648 -756
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +4 -4
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +174 -248
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs +50 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs +42 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs +55 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs +50 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs +48 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs +42 -0
- package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs → acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs} +2 -2
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-m8rHZP8L.mjs} +2 -2
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-m8rHZP8L.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets.mjs +974 -2994
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs → acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs} +5 -26
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs → acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs} +5 -4
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs +101 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs → acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.mjs} +3 -3
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +30 -166
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-shared.mjs +27 -27
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/layout/builder/index.d.ts +1 -4
- package/layout/components/index.d.ts +327 -405
- package/layout/designer/index.d.ts +3 -3
- package/layout/entity/index.d.ts +108 -163
- package/layout/widget-core/index.d.ts +49 -39
- package/layout/widgets/index.d.ts +54 -368
- package/package.json +5 -5
- package/themes/default/index.d.ts +2 -15
- package/themes/shared/index.d.ts +10 -10
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +0 -101
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, Injector, Injectable, signal, inject, Input, Directive, provideAppInitializer, Optional, Inject, NgModule } from '@angular/core';
|
|
3
|
-
import {
|
|
2
|
+
import { InjectionToken, Injector, Injectable, signal, inject, Input, Directive, provideAppInitializer, Optional, Inject, NgModule, input, output, Component } from '@angular/core';
|
|
3
|
+
import { of, map, BehaviorSubject, shareReplay, defaultIfEmpty, switchMap, filter, firstValueFrom, first } from 'rxjs';
|
|
4
|
+
import { AXPBroadcastEventService } from '@acorex/platform/core';
|
|
4
5
|
import { isEmpty } from 'lodash-es';
|
|
5
|
-
import { map, BehaviorSubject, shareReplay, defaultIfEmpty, switchMap, filter, from, first } from 'rxjs';
|
|
6
6
|
|
|
7
7
|
const AXP_APPLICATION_LOADER = new InjectionToken('AXP_APPLICATION_LOADER', {
|
|
8
8
|
providedIn: 'root',
|
|
@@ -11,29 +11,25 @@ const AXP_APPLICATION_LOADER = new InjectionToken('AXP_APPLICATION_LOADER', {
|
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
13
|
class AXPApplicationDefaultLoader {
|
|
14
|
-
|
|
15
|
-
return [
|
|
14
|
+
getList(context) {
|
|
15
|
+
return of([
|
|
16
16
|
{
|
|
17
17
|
id: '1',
|
|
18
18
|
name: 'default-app',
|
|
19
19
|
title: 'Default Application',
|
|
20
20
|
version: '1.0.0',
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
title: 'Standard',
|
|
24
|
-
},
|
|
21
|
+
editionName: 'Standard',
|
|
22
|
+
features: [],
|
|
25
23
|
},
|
|
26
24
|
{
|
|
27
25
|
id: '2',
|
|
28
26
|
name: 'default-app',
|
|
29
27
|
title: 'Default Application',
|
|
30
28
|
version: '1.0.0',
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
title: 'Standard',
|
|
34
|
-
},
|
|
29
|
+
editionName: 'Standard',
|
|
30
|
+
features: [],
|
|
35
31
|
},
|
|
36
|
-
];
|
|
32
|
+
]);
|
|
37
33
|
}
|
|
38
34
|
}
|
|
39
35
|
|
|
@@ -44,14 +40,14 @@ const AXP_TENANT_LOADER = new InjectionToken('AXP_TENANT_LOADER', {
|
|
|
44
40
|
},
|
|
45
41
|
});
|
|
46
42
|
class AXPTenantDefaultLoader {
|
|
47
|
-
|
|
48
|
-
return [
|
|
43
|
+
getList(context) {
|
|
44
|
+
return of([
|
|
49
45
|
{
|
|
50
46
|
id: '1',
|
|
51
47
|
name: 'default-tenant',
|
|
52
48
|
title: 'Default Tenant',
|
|
53
49
|
},
|
|
54
|
-
];
|
|
50
|
+
]);
|
|
55
51
|
}
|
|
56
52
|
}
|
|
57
53
|
|
|
@@ -89,8 +85,8 @@ const AXP_FEATURE_LOADER = new InjectionToken('AXP_FEATURE_LOADER', {
|
|
|
89
85
|
},
|
|
90
86
|
});
|
|
91
87
|
class AXPFeatureDefaultLoader {
|
|
92
|
-
|
|
93
|
-
return [];
|
|
88
|
+
getList(context) {
|
|
89
|
+
return of([]);
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
92
|
|
|
@@ -177,13 +173,6 @@ const AXPFeatureGuard = (route, state) => {
|
|
|
177
173
|
}));
|
|
178
174
|
};
|
|
179
175
|
|
|
180
|
-
/**
|
|
181
|
-
* Optional injection token for feature checker.
|
|
182
|
-
* If provided, the checker will be called to potentially override
|
|
183
|
-
* feature enablement results based on custom logic.
|
|
184
|
-
*/
|
|
185
|
-
const AXP_FEATURE_CHECKER = new InjectionToken('AXP_FEATURE_CHECKER');
|
|
186
|
-
|
|
187
176
|
const AXP_PERMISSION_LOADER = new InjectionToken('AXP_PERMISSION_LOADER', {
|
|
188
177
|
providedIn: 'root',
|
|
189
178
|
factory: () => {
|
|
@@ -191,18 +180,11 @@ const AXP_PERMISSION_LOADER = new InjectionToken('AXP_PERMISSION_LOADER', {
|
|
|
191
180
|
}
|
|
192
181
|
});
|
|
193
182
|
class AXPPermissionDefaultLoader {
|
|
194
|
-
|
|
195
|
-
return [];
|
|
183
|
+
getList(context) {
|
|
184
|
+
return of([]);
|
|
196
185
|
}
|
|
197
186
|
}
|
|
198
187
|
|
|
199
|
-
/**
|
|
200
|
-
* Optional injection token for permission checker.
|
|
201
|
-
* If provided, the checker will be called to potentially override
|
|
202
|
-
* authorization results based on custom logic.
|
|
203
|
-
*/
|
|
204
|
-
const AXP_PERMISSION_CHECKER = new InjectionToken('AXP_PERMISSION_CHECKER');
|
|
205
|
-
|
|
206
188
|
class AXPSessionContext {
|
|
207
189
|
get user() {
|
|
208
190
|
return this._user;
|
|
@@ -240,9 +222,6 @@ class AXPSessionService {
|
|
|
240
222
|
this.featureLoader = inject(AXP_FEATURE_LOADER);
|
|
241
223
|
this.tenantLoader = inject(AXP_TENANT_LOADER);
|
|
242
224
|
this.applicationLoader = inject(AXP_APPLICATION_LOADER);
|
|
243
|
-
this.moduleProviderLoader = inject(AXP_MODULE_PROVIDER_LOADER);
|
|
244
|
-
this.permissionChecker = inject(AXP_PERMISSION_CHECKER, { optional: true });
|
|
245
|
-
this.featureChecker = inject(AXP_FEATURE_CHECKER, { optional: true });
|
|
246
225
|
this.status = new BehaviorSubject(AXPSessionStatus.Unauthenticated);
|
|
247
226
|
this.status$ = this.status.asObservable().pipe(shareReplay(1));
|
|
248
227
|
// Add loading state to prevent premature redirects
|
|
@@ -265,10 +244,8 @@ class AXPSessionService {
|
|
|
265
244
|
// Add a new observable that considers loading state
|
|
266
245
|
this.isAuthenticatedWithLoading$ = this.isLoading$.pipe(switchMap((loading) => {
|
|
267
246
|
if (loading) {
|
|
268
|
-
// Wait for loading to complete, then return authentication status
|
|
269
247
|
return this.isLoading$.pipe(filter((isLoading) => !isLoading), switchMap(() => this.isAuthenticated$));
|
|
270
248
|
}
|
|
271
|
-
// If not loading, return current authentication status
|
|
272
249
|
return this.isAuthenticated$;
|
|
273
250
|
}), shareReplay(1));
|
|
274
251
|
this.isAuthorized$ = this.status$.pipe(map((status) => status === AXPSessionStatus.Authorized), shareReplay(1));
|
|
@@ -289,7 +266,7 @@ class AXPSessionService {
|
|
|
289
266
|
return this.currentTenantSubject.value;
|
|
290
267
|
}
|
|
291
268
|
get tenants$() {
|
|
292
|
-
return
|
|
269
|
+
return this.tenantLoader.getList(this.getContext());
|
|
293
270
|
}
|
|
294
271
|
get application() {
|
|
295
272
|
const session = this.getSessionData();
|
|
@@ -299,7 +276,7 @@ class AXPSessionService {
|
|
|
299
276
|
return this.currentApplicationSubject.value;
|
|
300
277
|
}
|
|
301
278
|
get applications$() {
|
|
302
|
-
return
|
|
279
|
+
return this.applicationLoader.getList(this.getContext());
|
|
303
280
|
}
|
|
304
281
|
get permissions() {
|
|
305
282
|
return this.permissionsSubject.value ?? [];
|
|
@@ -314,18 +291,7 @@ class AXPSessionService {
|
|
|
314
291
|
if (sessionData) {
|
|
315
292
|
if (sessionData.user) {
|
|
316
293
|
this.currentUserSubject.next(sessionData.user);
|
|
317
|
-
// Restore tenant and application from session data
|
|
318
|
-
if (sessionData.tenant) {
|
|
319
|
-
this.currentTenantSubject.next(sessionData.tenant);
|
|
320
|
-
}
|
|
321
|
-
if (sessionData.application) {
|
|
322
|
-
this.currentApplicationSubject.next(sessionData.application);
|
|
323
|
-
}
|
|
324
294
|
this.status.next(AXPSessionStatus.Authenticated);
|
|
325
|
-
// Load required modules first to ensure entities are available for loaders
|
|
326
|
-
// This is critical because loaders (like application.loader) need entities
|
|
327
|
-
// from required modules (ApplicationManagement, TenantManagement, SecurityManagement)
|
|
328
|
-
await this.moduleProviderLoader.loadRequiredModules();
|
|
329
295
|
await this.loadPermissions();
|
|
330
296
|
await this.loadFeatures();
|
|
331
297
|
await this.signInComplete();
|
|
@@ -443,9 +409,6 @@ class AXPSessionService {
|
|
|
443
409
|
}
|
|
444
410
|
//
|
|
445
411
|
const userId = this.user?.id;
|
|
446
|
-
// Clear module provider loader cache before clearing session
|
|
447
|
-
// This ensures modules and providers from previous user are not cached
|
|
448
|
-
await this.moduleProviderLoader.clear();
|
|
449
412
|
this.clearSession();
|
|
450
413
|
this.eventService.publish(AXPSessionStatus.SignedOut, { id: userId });
|
|
451
414
|
this.isLoading.next(false);
|
|
@@ -494,7 +457,7 @@ class AXPSessionService {
|
|
|
494
457
|
}
|
|
495
458
|
async loadPermissions() {
|
|
496
459
|
try {
|
|
497
|
-
const permissions = await this.permissionLoader.getList(this.getContext());
|
|
460
|
+
const permissions = await firstValueFrom(this.permissionLoader.getList(this.getContext()));
|
|
498
461
|
this.permissionsSubject.next(permissions ?? []);
|
|
499
462
|
}
|
|
500
463
|
catch (error) {
|
|
@@ -504,7 +467,7 @@ class AXPSessionService {
|
|
|
504
467
|
}
|
|
505
468
|
async loadFeatures() {
|
|
506
469
|
try {
|
|
507
|
-
const features = await this.featureLoader.getList(this.getContext());
|
|
470
|
+
const features = await firstValueFrom(this.featureLoader.getList(this.getContext()));
|
|
508
471
|
this.featuresSubject.next(features ?? []);
|
|
509
472
|
}
|
|
510
473
|
catch (error) {
|
|
@@ -584,39 +547,26 @@ class AXPSessionService {
|
|
|
584
547
|
localStorage.removeItem(AXPSessionService.SESSION_KEY);
|
|
585
548
|
}
|
|
586
549
|
authorize(...keys) {
|
|
587
|
-
|
|
588
|
-
const baseResult = keys.every((k) => {
|
|
589
|
-
if (isEmpty(k))
|
|
590
|
-
return true;
|
|
591
|
-
// Check if user has the permission
|
|
592
|
-
const hasPermission = this.permissions.indexOf(k) > -1;
|
|
593
|
-
if (!hasPermission)
|
|
594
|
-
return false;
|
|
595
|
-
// Check if permission has required features (if permission definition service is available)
|
|
596
|
-
// Note: This is a lightweight check. Full feature validation happens in permission definition service.
|
|
597
|
-
return true;
|
|
598
|
-
});
|
|
599
|
-
// If permission checker is provided, use it to potentially override the result
|
|
600
|
-
if (this.permissionChecker) {
|
|
601
|
-
const context = this.getContext();
|
|
602
|
-
return this.permissionChecker.check(keys, context, baseResult);
|
|
603
|
-
}
|
|
604
|
-
return baseResult;
|
|
550
|
+
return keys.every((k) => isEmpty(k) || this.permissions.indexOf(k) > -1 || this.user?.name == 'root');
|
|
605
551
|
}
|
|
606
552
|
isFeatureEnabled(...keys) {
|
|
607
|
-
|
|
608
|
-
const baseResult = keys.every((k) => isEmpty(k) || this.features.some((c) => c.name == k && c.value == true));
|
|
609
|
-
// If feature checker is provided, use it to potentially override the result
|
|
610
|
-
if (this.featureChecker) {
|
|
611
|
-
const context = this.getContext();
|
|
612
|
-
return this.featureChecker.check(keys, context, baseResult);
|
|
613
|
-
}
|
|
614
|
-
return baseResult;
|
|
553
|
+
return keys.every((k) => isEmpty(k) || this.features.some((c) => c.name == k && c.value == true));
|
|
615
554
|
}
|
|
616
555
|
getToken() {
|
|
617
556
|
const sessionData = this.getSessionData();
|
|
618
557
|
return sessionData?.accessToken;
|
|
619
558
|
}
|
|
559
|
+
checkTokenValidation() {
|
|
560
|
+
let sessionData = this.getSessionData();
|
|
561
|
+
if (sessionData && sessionData?.accessToken && sessionData.expiresIn) {
|
|
562
|
+
const expiresInDate = new Date(sessionData.expiresIn);
|
|
563
|
+
if (expiresInDate > new Date()) {
|
|
564
|
+
// Token is still valid
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
620
570
|
getContext() {
|
|
621
571
|
return new AXPSessionContext({
|
|
622
572
|
user: this.user,
|
|
@@ -737,13 +687,12 @@ class AXPPermissionDefinitionGroupBuilder {
|
|
|
737
687
|
this.context = context;
|
|
738
688
|
this._group = group;
|
|
739
689
|
}
|
|
740
|
-
addPermission(name, title, description
|
|
690
|
+
addPermission(name, title, description) {
|
|
741
691
|
const permission = {
|
|
742
692
|
name,
|
|
743
693
|
title,
|
|
744
694
|
description,
|
|
745
|
-
children: []
|
|
746
|
-
requiredFeatures
|
|
695
|
+
children: []
|
|
747
696
|
};
|
|
748
697
|
this._group.permissions.push(permission);
|
|
749
698
|
return new AXPPermissionDefinitionBuilder(this, permission);
|
|
@@ -763,25 +712,16 @@ class AXPPermissionDefinitionBuilder {
|
|
|
763
712
|
this.groupBuilder = groupBuilder;
|
|
764
713
|
this.permission = permission;
|
|
765
714
|
}
|
|
766
|
-
addChild(name, title, description
|
|
715
|
+
addChild(name, title, description) {
|
|
767
716
|
const permission = {
|
|
768
717
|
name,
|
|
769
718
|
title,
|
|
770
719
|
description,
|
|
771
|
-
children: []
|
|
772
|
-
requiredFeatures
|
|
720
|
+
children: []
|
|
773
721
|
};
|
|
774
722
|
this.permission.children.push(permission);
|
|
775
723
|
return this;
|
|
776
724
|
}
|
|
777
|
-
/**
|
|
778
|
-
* Set required features for this permission.
|
|
779
|
-
* @param features - Array of feature names (e.g., ['PlatformManagement.menu-customization'])
|
|
780
|
-
*/
|
|
781
|
-
requireFeatures(...features) {
|
|
782
|
-
this.permission.requiredFeatures = features;
|
|
783
|
-
return this;
|
|
784
|
-
}
|
|
785
725
|
endPermission() {
|
|
786
726
|
return this.groupBuilder;
|
|
787
727
|
}
|
|
@@ -796,8 +736,6 @@ const AXP_PERMISSION_DEFINITION_PROVIDER = new InjectionToken('AXP_PERMISSION_DE
|
|
|
796
736
|
class AXPPermissionDefinitionService {
|
|
797
737
|
constructor() {
|
|
798
738
|
this.providers = inject(AXP_PERMISSION_DEFINITION_PROVIDER, { optional: true });
|
|
799
|
-
this.providerRegistry = inject(AXPModuleProviderRegistry);
|
|
800
|
-
this.sessionService = inject(AXPSessionService);
|
|
801
739
|
this.cache = null;
|
|
802
740
|
}
|
|
803
741
|
async load() {
|
|
@@ -805,7 +743,6 @@ class AXPPermissionDefinitionService {
|
|
|
805
743
|
return;
|
|
806
744
|
}
|
|
807
745
|
const context = new AXPPermissionDefinitionProviderContext();
|
|
808
|
-
// Load providers from DI tokens (backward compatibility)
|
|
809
746
|
if (Array.isArray(this.providers)) {
|
|
810
747
|
for (const provider of this.providers) {
|
|
811
748
|
if (provider instanceof Promise) {
|
|
@@ -819,49 +756,7 @@ class AXPPermissionDefinitionService {
|
|
|
819
756
|
}
|
|
820
757
|
}
|
|
821
758
|
}
|
|
822
|
-
|
|
823
|
-
const registryProviders = this.providerRegistry.getPermissionProviders();
|
|
824
|
-
for (const provider of registryProviders) {
|
|
825
|
-
await provider.define(context);
|
|
826
|
-
}
|
|
827
|
-
// Filter permissions based on required features
|
|
828
|
-
const allGroups = context.getGroupDefinitions();
|
|
829
|
-
this.cache = this.filterByFeatures(allGroups);
|
|
830
|
-
}
|
|
831
|
-
/**
|
|
832
|
-
* Filter permissions based on required features.
|
|
833
|
-
* Removes permissions that have required features that are not enabled.
|
|
834
|
-
*/
|
|
835
|
-
filterByFeatures(groups) {
|
|
836
|
-
return groups.map(group => ({
|
|
837
|
-
...group,
|
|
838
|
-
permissions: this.filterPermissions(group.permissions)
|
|
839
|
-
})).filter(group => group.permissions.length > 0);
|
|
840
|
-
}
|
|
841
|
-
/**
|
|
842
|
-
* Recursively filter permissions and their children based on required features.
|
|
843
|
-
*/
|
|
844
|
-
filterPermissions(permissions) {
|
|
845
|
-
return permissions
|
|
846
|
-
.filter(permission => {
|
|
847
|
-
// Check if required features are enabled
|
|
848
|
-
if (permission.requiredFeatures && permission.requiredFeatures.length > 0) {
|
|
849
|
-
const allFeaturesEnabled = permission.requiredFeatures.every(featureName => this.sessionService.isFeatureEnabled(featureName));
|
|
850
|
-
if (!allFeaturesEnabled) {
|
|
851
|
-
return false; // Filter out this permission
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
return true;
|
|
855
|
-
})
|
|
856
|
-
.map(permission => ({
|
|
857
|
-
...permission,
|
|
858
|
-
children: this.filterPermissions(permission.children)
|
|
859
|
-
}))
|
|
860
|
-
.filter(permission => {
|
|
861
|
-
// Remove permissions that have no children if they were only containers
|
|
862
|
-
// (This is optional - you might want to keep parent permissions even without children)
|
|
863
|
-
return true;
|
|
864
|
-
});
|
|
759
|
+
this.cache = context.getGroupDefinitions();
|
|
865
760
|
}
|
|
866
761
|
async reload() {
|
|
867
762
|
this.cache = null;
|
|
@@ -987,10 +882,6 @@ class AXPAuthModule {
|
|
|
987
882
|
const initializerFn = initializeAppState(inject(AXPSessionService));
|
|
988
883
|
return initializerFn();
|
|
989
884
|
}),
|
|
990
|
-
{
|
|
991
|
-
provide: AXP_SESSION_SERVICE,
|
|
992
|
-
useExisting: AXPSessionService,
|
|
993
|
-
},
|
|
994
885
|
] }); }
|
|
995
886
|
}
|
|
996
887
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPAuthModule, decorators: [{
|
|
@@ -1004,10 +895,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
1004
895
|
const initializerFn = initializeAppState(inject(AXPSessionService));
|
|
1005
896
|
return initializerFn();
|
|
1006
897
|
}),
|
|
1007
|
-
{
|
|
1008
|
-
provide: AXP_SESSION_SERVICE,
|
|
1009
|
-
useExisting: AXPSessionService,
|
|
1010
|
-
},
|
|
1011
898
|
],
|
|
1012
899
|
}]
|
|
1013
900
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
@@ -1097,9 +984,169 @@ class TimeUtil {
|
|
|
1097
984
|
}
|
|
1098
985
|
//#endregion
|
|
1099
986
|
|
|
987
|
+
//#region ---- Challenge Data Types ----
|
|
988
|
+
//#endregion
|
|
989
|
+
|
|
990
|
+
//#region ---- Abstract Challenge Provider ----
|
|
991
|
+
/**
|
|
992
|
+
* Abstract base class for login challenge providers
|
|
993
|
+
*
|
|
994
|
+
* Implement this class to create custom challenge mechanisms like:
|
|
995
|
+
* - Image CAPTCHA
|
|
996
|
+
* - reCAPTCHA
|
|
997
|
+
* - SMS verification
|
|
998
|
+
* - Email verification
|
|
999
|
+
*
|
|
1000
|
+
* @example
|
|
1001
|
+
* ```typescript
|
|
1002
|
+
* @Injectable()
|
|
1003
|
+
* export class MyImageCaptchaProvider extends AXPLoginChallengeProvider {
|
|
1004
|
+
* readonly name = 'image-captcha';
|
|
1005
|
+
*
|
|
1006
|
+
* checkResponse(error: unknown): AXPChallengeCheckResult | null {
|
|
1007
|
+
* if (error instanceof HttpErrorResponse) {
|
|
1008
|
+
* if (error.error?.requiresCaptcha) {
|
|
1009
|
+
* return { required: true };
|
|
1010
|
+
* }
|
|
1011
|
+
* }
|
|
1012
|
+
* return null;
|
|
1013
|
+
* }
|
|
1014
|
+
*
|
|
1015
|
+
* async getChallenge(): Promise<AXPLoginChallengeData> {
|
|
1016
|
+
* const response = await this.http.get('/api/captcha').toPromise();
|
|
1017
|
+
* return {
|
|
1018
|
+
* id: response.id,
|
|
1019
|
+
* content: response.image,
|
|
1020
|
+
* contentType: 'image-base64'
|
|
1021
|
+
* };
|
|
1022
|
+
* }
|
|
1023
|
+
*
|
|
1024
|
+
* async refreshChallenge(): Promise<AXPLoginChallengeData> {
|
|
1025
|
+
* return this.getChallenge();
|
|
1026
|
+
* }
|
|
1027
|
+
*
|
|
1028
|
+
* getChallengeComponent(): Type<AXPLoginChallengeComponentBase> {
|
|
1029
|
+
* return MyCaptchaChallengeComponent;
|
|
1030
|
+
* }
|
|
1031
|
+
* }
|
|
1032
|
+
* ```
|
|
1033
|
+
*/
|
|
1034
|
+
class AXPLoginChallengeProvider {
|
|
1035
|
+
/**
|
|
1036
|
+
* Returns the component type for rendering the challenge UI
|
|
1037
|
+
*
|
|
1038
|
+
* Override this method to provide a custom challenge UI component.
|
|
1039
|
+
* If not overridden (returns null), the login component will use
|
|
1040
|
+
* a default built-in UI.
|
|
1041
|
+
*
|
|
1042
|
+
* @returns Component type extending AXPLoginChallengeComponentBase, or null for default UI
|
|
1043
|
+
*/
|
|
1044
|
+
getChallengeComponent() {
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
//#endregion
|
|
1049
|
+
|
|
1050
|
+
//#region ---- Injection Token ----
|
|
1051
|
+
/**
|
|
1052
|
+
* Injection token for the login challenge provider
|
|
1053
|
+
*
|
|
1054
|
+
* This token is optional - if not provided, no challenge mechanism will be used.
|
|
1055
|
+
*
|
|
1056
|
+
* @example
|
|
1057
|
+
* ```typescript
|
|
1058
|
+
* // In your app module or provider configuration:
|
|
1059
|
+
* providers: [
|
|
1060
|
+
* {
|
|
1061
|
+
* provide: AXP_LOGIN_CHALLENGE_PROVIDER,
|
|
1062
|
+
* useClass: MyImageCaptchaProvider
|
|
1063
|
+
* }
|
|
1064
|
+
* ]
|
|
1065
|
+
*
|
|
1066
|
+
* // In a component:
|
|
1067
|
+
* private challengeProvider = inject(AXP_LOGIN_CHALLENGE_PROVIDER, { optional: true });
|
|
1068
|
+
* ```
|
|
1069
|
+
*/
|
|
1070
|
+
const AXP_LOGIN_CHALLENGE_PROVIDER = new InjectionToken('AXP_LOGIN_CHALLENGE_PROVIDER');
|
|
1071
|
+
//#endregion
|
|
1072
|
+
|
|
1073
|
+
//#region ---- Base Challenge Component ----
|
|
1074
|
+
/**
|
|
1075
|
+
* Base class for login challenge UI components
|
|
1076
|
+
*
|
|
1077
|
+
* Providers can extend this class to create custom challenge UIs.
|
|
1078
|
+
* The login component will render this component and listen to its outputs.
|
|
1079
|
+
*
|
|
1080
|
+
* @example
|
|
1081
|
+
* ```typescript
|
|
1082
|
+
* @Component({
|
|
1083
|
+
* selector: 'my-captcha-challenge',
|
|
1084
|
+
* template: `
|
|
1085
|
+
* <div class="captcha-container">
|
|
1086
|
+
* <img [src]="'data:image/png;base64,' + challengeData().content" />
|
|
1087
|
+
* <input
|
|
1088
|
+
* type="text"
|
|
1089
|
+
* [value]="response()"
|
|
1090
|
+
* (input)="onResponseChange($event)"
|
|
1091
|
+
* />
|
|
1092
|
+
* <button (click)="onRefreshClick()">Refresh</button>
|
|
1093
|
+
* </div>
|
|
1094
|
+
* `
|
|
1095
|
+
* })
|
|
1096
|
+
* export class MyCaptchaChallengeComponent extends AXPLoginChallengeComponentBase {
|
|
1097
|
+
* response = signal('');
|
|
1098
|
+
*
|
|
1099
|
+
* onResponseChange(event: Event) {
|
|
1100
|
+
* const value = (event.target as HTMLInputElement).value;
|
|
1101
|
+
* this.response.set(value);
|
|
1102
|
+
* this.responseChange.emit(value);
|
|
1103
|
+
* }
|
|
1104
|
+
*
|
|
1105
|
+
* onRefreshClick() {
|
|
1106
|
+
* this.refreshRequest.emit();
|
|
1107
|
+
* }
|
|
1108
|
+
* }
|
|
1109
|
+
* ```
|
|
1110
|
+
*/
|
|
1111
|
+
class AXPLoginChallengeComponentBase {
|
|
1112
|
+
constructor() {
|
|
1113
|
+
//#region ---- Inputs ----
|
|
1114
|
+
/**
|
|
1115
|
+
* Challenge data to display
|
|
1116
|
+
* Contains the image/content and metadata from the server
|
|
1117
|
+
*/
|
|
1118
|
+
this.challengeData = input.required(...(ngDevMode ? [{ debugName: "challengeData" }] : []));
|
|
1119
|
+
/**
|
|
1120
|
+
* Whether the challenge is currently loading (e.g., refreshing)
|
|
1121
|
+
*/
|
|
1122
|
+
this.isLoading = input(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region ---- Outputs ----
|
|
1125
|
+
/**
|
|
1126
|
+
* Emits when the user enters or changes their response
|
|
1127
|
+
* The login component will capture this value and include it in credentials
|
|
1128
|
+
*/
|
|
1129
|
+
this.responseChange = output();
|
|
1130
|
+
/**
|
|
1131
|
+
* Emits when the user requests a new challenge (e.g., clicks refresh button)
|
|
1132
|
+
* The login component will call provider.refreshChallenge()
|
|
1133
|
+
*/
|
|
1134
|
+
this.refreshRequest = output();
|
|
1135
|
+
}
|
|
1136
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLoginChallengeComponentBase, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1137
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.12", type: AXPLoginChallengeComponentBase, isStandalone: true, selector: "ng-component", inputs: { challengeData: { classPropertyName: "challengeData", publicName: "challengeData", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { responseChange: "responseChange", refreshRequest: "refreshRequest" }, ngImport: i0, template: '', isInline: true }); }
|
|
1138
|
+
}
|
|
1139
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLoginChallengeComponentBase, decorators: [{
|
|
1140
|
+
type: Component,
|
|
1141
|
+
args: [{
|
|
1142
|
+
template: '',
|
|
1143
|
+
standalone: true,
|
|
1144
|
+
}]
|
|
1145
|
+
}], propDecorators: { challengeData: [{ type: i0.Input, args: [{ isSignal: true, alias: "challengeData", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: false }] }], responseChange: [{ type: i0.Output, args: ["responseChange"] }], refreshRequest: [{ type: i0.Output, args: ["refreshRequest"] }] } });
|
|
1146
|
+
|
|
1100
1147
|
/**
|
|
1101
1148
|
* Generated bundle index. Do not edit.
|
|
1102
1149
|
*/
|
|
1103
1150
|
|
|
1104
|
-
export { AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureGuard, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPUnauthorizedError, AXP_APPLICATION_LOADER,
|
|
1151
|
+
export { AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureGuard, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPUnauthorizedError, AXP_APPLICATION_LOADER, AXP_FEATURE_LOADER, AXP_LOGIN_CHALLENGE_PROVIDER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, JwtUtil, PkceUtil, TimeUtil, initializeAppState };
|
|
1105
1152
|
//# sourceMappingURL=acorex-platform-auth.mjs.map
|