@acorex/platform 21.0.0-next.2 → 21.0.0-next.5

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 (72) hide show
  1. package/auth/index.d.ts +97 -238
  2. package/common/index.d.ts +783 -213
  3. package/core/index.d.ts +311 -442
  4. package/fesm2022/acorex-platform-auth.mjs +156 -200
  5. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  6. package/fesm2022/acorex-platform-common.mjs +1038 -127
  7. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  8. package/fesm2022/acorex-platform-core.mjs +602 -413
  9. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  10. package/fesm2022/acorex-platform-domain.mjs +54 -11
  11. package/fesm2022/acorex-platform-domain.mjs.map +1 -1
  12. package/fesm2022/acorex-platform-layout-builder.mjs +412 -270
  13. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  14. package/fesm2022/acorex-platform-layout-components.mjs +2100 -3141
  15. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  16. package/fesm2022/acorex-platform-layout-designer.mjs +7 -7
  17. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  18. package/fesm2022/acorex-platform-layout-entity.mjs +730 -652
  19. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  20. package/fesm2022/acorex-platform-layout-views.mjs +4 -4
  21. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  22. package/fesm2022/acorex-platform-layout-widget-core.mjs +249 -205
  23. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  24. package/fesm2022/{acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs → acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs} +2 -2
  25. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +1 -0
  26. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-m8rHZP8L.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs} +2 -2
  27. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +1 -0
  28. package/fesm2022/acorex-platform-layout-widgets.mjs +3066 -1040
  29. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  30. package/fesm2022/{acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs → acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs} +26 -5
  31. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +1 -0
  32. package/fesm2022/{acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs → acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs} +4 -5
  33. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-DyDa_hyd.mjs.map +1 -0
  34. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +101 -0
  35. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +1 -0
  36. package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.mjs → acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs} +3 -3
  37. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +1 -0
  38. package/fesm2022/acorex-platform-themes-default.mjs +166 -30
  39. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  40. package/fesm2022/acorex-platform-themes-shared.mjs +27 -27
  41. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  42. package/fesm2022/acorex-platform-workflow.mjs +474 -1527
  43. package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
  44. package/layout/builder/index.d.ts +4 -1
  45. package/layout/components/index.d.ts +405 -327
  46. package/layout/designer/index.d.ts +3 -3
  47. package/layout/entity/index.d.ts +154 -108
  48. package/layout/widget-core/index.d.ts +39 -52
  49. package/layout/widgets/index.d.ts +368 -54
  50. package/package.json +9 -9
  51. package/themes/default/index.d.ts +15 -2
  52. package/themes/shared/index.d.ts +10 -10
  53. package/workflow/index.d.ts +182 -817
  54. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs +0 -50
  55. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-edit.component-fhhZOWul.mjs.map +0 -1
  56. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs +0 -42
  57. package/fesm2022/acorex-platform-layout-widgets-extra-properties-schema-widget-view.component-C3Qbs0fz.mjs.map +0 -1
  58. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs +0 -55
  59. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-edit.component-CngQBUlN.mjs.map +0 -1
  60. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs +0 -50
  61. package/fesm2022/acorex-platform-layout-widgets-extra-properties-values-widget-view.component-DSNo9e4W.mjs.map +0 -1
  62. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs +0 -48
  63. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-edit.component-CL0CwEHX.mjs.map +0 -1
  64. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs +0 -42
  65. package/fesm2022/acorex-platform-layout-widgets-extra-properties-widget-view.component-B6Fi0xTw.mjs.map +0 -1
  66. package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-D0y-9nE5.mjs.map +0 -1
  67. package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-m8rHZP8L.mjs.map +0 -1
  68. package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-mARj77Mr.mjs.map +0 -1
  69. package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-Cym8pq0v.mjs.map +0 -1
  70. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs +0 -101
  71. package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-BTA6h7Xd.mjs.map +0 -1
  72. package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-B_P0a5KW.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, 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';
2
+ import { InjectionToken, Injector, Injectable, signal, inject, Input, Directive, provideAppInitializer, Optional, Inject, NgModule } from '@angular/core';
3
+ import { AXPBroadcastEventService, AXP_SESSION_SERVICE } from '@acorex/platform/core';
5
4
  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,25 +11,29 @@ const AXP_APPLICATION_LOADER = new InjectionToken('AXP_APPLICATION_LOADER', {
11
11
  },
12
12
  });
13
13
  class AXPApplicationDefaultLoader {
14
- getList(context) {
15
- return of([
14
+ async getList(context) {
15
+ return [
16
16
  {
17
17
  id: '1',
18
18
  name: 'default-app',
19
19
  title: 'Default Application',
20
20
  version: '1.0.0',
21
- editionName: 'Standard',
22
- features: [],
21
+ edition: {
22
+ id: 'default-edition-1',
23
+ title: 'Standard',
24
+ },
23
25
  },
24
26
  {
25
27
  id: '2',
26
28
  name: 'default-app',
27
29
  title: 'Default Application',
28
30
  version: '1.0.0',
29
- editionName: 'Standard',
30
- features: [],
31
+ edition: {
32
+ id: 'default-edition-2',
33
+ title: 'Standard',
34
+ },
31
35
  },
32
- ]);
36
+ ];
33
37
  }
34
38
  }
35
39
 
@@ -40,14 +44,14 @@ const AXP_TENANT_LOADER = new InjectionToken('AXP_TENANT_LOADER', {
40
44
  },
41
45
  });
42
46
  class AXPTenantDefaultLoader {
43
- getList(context) {
44
- return of([
47
+ async getList(context) {
48
+ return [
45
49
  {
46
50
  id: '1',
47
51
  name: 'default-tenant',
48
52
  title: 'Default Tenant',
49
53
  },
50
- ]);
54
+ ];
51
55
  }
52
56
  }
53
57
 
@@ -85,8 +89,8 @@ const AXP_FEATURE_LOADER = new InjectionToken('AXP_FEATURE_LOADER', {
85
89
  },
86
90
  });
87
91
  class AXPFeatureDefaultLoader {
88
- getList(context) {
89
- return of([]);
92
+ async getList(context) {
93
+ return [];
90
94
  }
91
95
  }
92
96
 
@@ -173,6 +177,13 @@ const AXPFeatureGuard = (route, state) => {
173
177
  }));
174
178
  };
175
179
 
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
+
176
187
  const AXP_PERMISSION_LOADER = new InjectionToken('AXP_PERMISSION_LOADER', {
177
188
  providedIn: 'root',
178
189
  factory: () => {
@@ -180,11 +191,18 @@ const AXP_PERMISSION_LOADER = new InjectionToken('AXP_PERMISSION_LOADER', {
180
191
  }
181
192
  });
182
193
  class AXPPermissionDefaultLoader {
183
- getList(context) {
184
- return of([]);
194
+ async getList(context) {
195
+ return [];
185
196
  }
186
197
  }
187
198
 
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
+
188
206
  class AXPSessionContext {
189
207
  get user() {
190
208
  return this._user;
@@ -218,10 +236,13 @@ class AXPSessionService {
218
236
  constructor() {
219
237
  this.eventService = inject(AXPBroadcastEventService);
220
238
  this.authStrategyRegistry = inject(AXPAuthStrategyRegistryService);
239
+ this.injector = inject(Injector);
221
240
  this.permissionLoader = inject(AXP_PERMISSION_LOADER);
222
241
  this.featureLoader = inject(AXP_FEATURE_LOADER);
223
242
  this.tenantLoader = inject(AXP_TENANT_LOADER);
224
243
  this.applicationLoader = inject(AXP_APPLICATION_LOADER);
244
+ this.permissionChecker = inject(AXP_PERMISSION_CHECKER, { optional: true });
245
+ this.featureChecker = inject(AXP_FEATURE_CHECKER, { optional: true });
225
246
  this.status = new BehaviorSubject(AXPSessionStatus.Unauthenticated);
226
247
  this.status$ = this.status.asObservable().pipe(shareReplay(1));
227
248
  // Add loading state to prevent premature redirects
@@ -244,8 +265,10 @@ class AXPSessionService {
244
265
  // Add a new observable that considers loading state
245
266
  this.isAuthenticatedWithLoading$ = this.isLoading$.pipe(switchMap((loading) => {
246
267
  if (loading) {
268
+ // Wait for loading to complete, then return authentication status
247
269
  return this.isLoading$.pipe(filter((isLoading) => !isLoading), switchMap(() => this.isAuthenticated$));
248
270
  }
271
+ // If not loading, return current authentication status
249
272
  return this.isAuthenticated$;
250
273
  }), shareReplay(1));
251
274
  this.isAuthorized$ = this.status$.pipe(map((status) => status === AXPSessionStatus.Authorized), shareReplay(1));
@@ -266,7 +289,7 @@ class AXPSessionService {
266
289
  return this.currentTenantSubject.value;
267
290
  }
268
291
  get tenants$() {
269
- return this.tenantLoader.getList(this.getContext());
292
+ return from(this.tenantLoader.getList(this.getContext()));
270
293
  }
271
294
  get application() {
272
295
  const session = this.getSessionData();
@@ -276,7 +299,7 @@ class AXPSessionService {
276
299
  return this.currentApplicationSubject.value;
277
300
  }
278
301
  get applications$() {
279
- return this.applicationLoader.getList(this.getContext());
302
+ return from(this.applicationLoader.getList(this.getContext()));
280
303
  }
281
304
  get permissions() {
282
305
  return this.permissionsSubject.value ?? [];
@@ -291,6 +314,13 @@ class AXPSessionService {
291
314
  if (sessionData) {
292
315
  if (sessionData.user) {
293
316
  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
+ }
294
324
  this.status.next(AXPSessionStatus.Authenticated);
295
325
  await this.loadPermissions();
296
326
  await this.loadFeatures();
@@ -457,7 +487,7 @@ class AXPSessionService {
457
487
  }
458
488
  async loadPermissions() {
459
489
  try {
460
- const permissions = await firstValueFrom(this.permissionLoader.getList(this.getContext()));
490
+ const permissions = await this.permissionLoader.getList(this.getContext());
461
491
  this.permissionsSubject.next(permissions ?? []);
462
492
  }
463
493
  catch (error) {
@@ -467,7 +497,7 @@ class AXPSessionService {
467
497
  }
468
498
  async loadFeatures() {
469
499
  try {
470
- const features = await firstValueFrom(this.featureLoader.getList(this.getContext()));
500
+ const features = await this.featureLoader.getList(this.getContext());
471
501
  this.featuresSubject.next(features ?? []);
472
502
  }
473
503
  catch (error) {
@@ -547,26 +577,55 @@ class AXPSessionService {
547
577
  localStorage.removeItem(AXPSessionService.SESSION_KEY);
548
578
  }
549
579
  authorize(...keys) {
550
- return keys.every((k) => isEmpty(k) || this.permissions.indexOf(k) > -1 || this.user?.name == 'root');
580
+ // Calculate base result
581
+ const baseResult = keys.every((k) => {
582
+ if (isEmpty(k))
583
+ return true;
584
+ // Check if user has the permission
585
+ const hasPermission = this.permissions.indexOf(k) > -1;
586
+ if (!hasPermission)
587
+ return false;
588
+ // Check if permission has required features (if permission definition service is available)
589
+ // Note: This is a lightweight check. Full feature validation happens in permission definition service.
590
+ return true;
591
+ });
592
+ // If permission checker is provided, use it to potentially override the result
593
+ if (this.permissionChecker) {
594
+ const context = this.getContext();
595
+ return this.permissionChecker.check(keys, context, baseResult);
596
+ }
597
+ return baseResult;
551
598
  }
552
599
  isFeatureEnabled(...keys) {
553
- return keys.every((k) => isEmpty(k) || this.features.some((c) => c.name == k && c.value == true));
600
+ // Calculate base result
601
+ const baseResult = keys.every((k) => isEmpty(k) || this.features.some((c) => c.name == k && c.value == true));
602
+ // If feature checker is provided, use it to potentially override the result
603
+ if (this.featureChecker) {
604
+ const context = this.getContext();
605
+ return this.featureChecker.check(keys, context, baseResult);
606
+ }
607
+ return baseResult;
608
+ }
609
+ /**
610
+ * Checks if a module is enabled for the current tenant/application.
611
+ * Module names are stored as features with value: true when enabled.
612
+ * Module names can be provided in PascalCase (e.g., 'SecurityManagement') or kebab-case (e.g., 'security-management').
613
+ */
614
+ isModuleEnabled(moduleName) {
615
+ if (!moduleName) {
616
+ return false;
617
+ }
618
+ // Normalize module name: convert kebab-case to PascalCase if needed
619
+ const normalizedModuleName = moduleName.includes('-')
620
+ ? moduleName.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('')
621
+ : moduleName;
622
+ // Module names are stored as features with value: true when enabled
623
+ return this.features.some(f => f.name === normalizedModuleName && f.value === true);
554
624
  }
555
625
  getToken() {
556
626
  const sessionData = this.getSessionData();
557
627
  return sessionData?.accessToken;
558
628
  }
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
- }
570
629
  getContext() {
571
630
  return new AXPSessionContext({
572
631
  user: this.user,
@@ -687,12 +746,13 @@ class AXPPermissionDefinitionGroupBuilder {
687
746
  this.context = context;
688
747
  this._group = group;
689
748
  }
690
- addPermission(name, title, description) {
749
+ addPermission(name, title, description, requiredFeatures) {
691
750
  const permission = {
692
751
  name,
693
752
  title,
694
753
  description,
695
- children: []
754
+ children: [],
755
+ requiredFeatures
696
756
  };
697
757
  this._group.permissions.push(permission);
698
758
  return new AXPPermissionDefinitionBuilder(this, permission);
@@ -712,16 +772,25 @@ class AXPPermissionDefinitionBuilder {
712
772
  this.groupBuilder = groupBuilder;
713
773
  this.permission = permission;
714
774
  }
715
- addChild(name, title, description) {
775
+ addChild(name, title, description, requiredFeatures) {
716
776
  const permission = {
717
777
  name,
718
778
  title,
719
779
  description,
720
- children: []
780
+ children: [],
781
+ requiredFeatures
721
782
  };
722
783
  this.permission.children.push(permission);
723
784
  return this;
724
785
  }
786
+ /**
787
+ * Set required features for this permission.
788
+ * @param features - Array of feature names (e.g., ['PlatformManagement.menu-customization'])
789
+ */
790
+ requireFeatures(...features) {
791
+ this.permission.requiredFeatures = features;
792
+ return this;
793
+ }
725
794
  endPermission() {
726
795
  return this.groupBuilder;
727
796
  }
@@ -736,6 +805,7 @@ const AXP_PERMISSION_DEFINITION_PROVIDER = new InjectionToken('AXP_PERMISSION_DE
736
805
  class AXPPermissionDefinitionService {
737
806
  constructor() {
738
807
  this.providers = inject(AXP_PERMISSION_DEFINITION_PROVIDER, { optional: true });
808
+ this.sessionService = inject(AXPSessionService);
739
809
  this.cache = null;
740
810
  }
741
811
  async load() {
@@ -743,6 +813,7 @@ class AXPPermissionDefinitionService {
743
813
  return;
744
814
  }
745
815
  const context = new AXPPermissionDefinitionProviderContext();
816
+ // Load providers from DI tokens
746
817
  if (Array.isArray(this.providers)) {
747
818
  for (const provider of this.providers) {
748
819
  if (provider instanceof Promise) {
@@ -756,7 +827,44 @@ class AXPPermissionDefinitionService {
756
827
  }
757
828
  }
758
829
  }
759
- this.cache = context.getGroupDefinitions();
830
+ // Filter permissions based on required features
831
+ const allGroups = context.getGroupDefinitions();
832
+ this.cache = this.filterByFeatures(allGroups);
833
+ }
834
+ /**
835
+ * Filter permissions based on required features.
836
+ * Removes permissions that have required features that are not enabled.
837
+ */
838
+ filterByFeatures(groups) {
839
+ return groups.map(group => ({
840
+ ...group,
841
+ permissions: this.filterPermissions(group.permissions)
842
+ })).filter(group => group.permissions.length > 0);
843
+ }
844
+ /**
845
+ * Recursively filter permissions and their children based on required features.
846
+ */
847
+ filterPermissions(permissions) {
848
+ return permissions
849
+ .filter(permission => {
850
+ // Check if required features are enabled
851
+ if (permission.requiredFeatures && permission.requiredFeatures.length > 0) {
852
+ const allFeaturesEnabled = permission.requiredFeatures.every(featureName => this.sessionService.isFeatureEnabled(featureName));
853
+ if (!allFeaturesEnabled) {
854
+ return false; // Filter out this permission
855
+ }
856
+ }
857
+ return true;
858
+ })
859
+ .map(permission => ({
860
+ ...permission,
861
+ children: this.filterPermissions(permission.children)
862
+ }))
863
+ .filter(permission => {
864
+ // Remove permissions that have no children if they were only containers
865
+ // (This is optional - you might want to keep parent permissions even without children)
866
+ return true;
867
+ });
760
868
  }
761
869
  async reload() {
762
870
  this.cache = null;
@@ -882,6 +990,10 @@ class AXPAuthModule {
882
990
  const initializerFn = initializeAppState(inject(AXPSessionService));
883
991
  return initializerFn();
884
992
  }),
993
+ {
994
+ provide: AXP_SESSION_SERVICE,
995
+ useExisting: AXPSessionService,
996
+ },
885
997
  ] }); }
886
998
  }
887
999
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPAuthModule, decorators: [{
@@ -895,6 +1007,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
895
1007
  const initializerFn = initializeAppState(inject(AXPSessionService));
896
1008
  return initializerFn();
897
1009
  }),
1010
+ {
1011
+ provide: AXP_SESSION_SERVICE,
1012
+ useExisting: AXPSessionService,
1013
+ },
898
1014
  ],
899
1015
  }]
900
1016
  }], ctorParameters: () => [{ type: undefined, decorators: [{
@@ -984,169 +1100,9 @@ class TimeUtil {
984
1100
  }
985
1101
  //#endregion
986
1102
 
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
-
1147
1103
  /**
1148
1104
  * Generated bundle index. Do not edit.
1149
1105
  */
1150
1106
 
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 };
1107
+ export { AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureGuard, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPUnauthorizedError, AXP_APPLICATION_LOADER, AXP_FEATURE_CHECKER, AXP_FEATURE_LOADER, AXP_PERMISSION_CHECKER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, JwtUtil, PkceUtil, TimeUtil, initializeAppState };
1152
1108
  //# sourceMappingURL=acorex-platform-auth.mjs.map