@acorex-platform/framework-client 0.0.10 → 0.0.14

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 (119) hide show
  1. package/fesm2022/acorex-platform-framework-client-auth.mjs +285 -50
  2. package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs → acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs} +55 -36
  4. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs +29 -0
  6. package/fesm2022/acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-framework-client-common.mjs +1576 -408
  8. package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-framework-client-core.mjs +561 -25
  10. package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +154 -42
  12. package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
  13. package/fesm2022/{acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CWVU3wXL.mjs → acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs} +7 -7
  14. package/fesm2022/acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs +77 -0
  16. package/fesm2022/acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-framework-client-layout-components.mjs +2378 -1274
  18. package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-framework-client-layout-designer.mjs +92 -84
  20. package/fesm2022/acorex-platform-framework-client-layout-designer.mjs.map +1 -1
  21. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-CxBxxpmA.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs} +3 -3
  22. package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-CxBxxpmA.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs.map} +1 -1
  23. package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-l0JAHKIH.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs} +6 -6
  24. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs +256 -0
  26. package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +17599 -17114
  28. package/fesm2022/acorex-platform-framework-client-layout-entity.mjs.map +1 -1
  29. package/fesm2022/acorex-platform-framework-client-layout-views.mjs +120 -70
  30. package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
  31. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +302 -263
  32. package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
  33. package/fesm2022/{acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CpkWwygb.mjs → acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs} +2 -2
  34. package/fesm2022/acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs.map +1 -0
  35. package/fesm2022/{acorex-platform-framework-client-layout-widgets-image-preview.popup-C_EPAvCU.mjs → acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs} +3 -3
  36. package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs.map +1 -0
  37. package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-CmtTq2Mt.mjs → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs} +5 -5
  38. package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-CmtTq2Mt.mjs.map → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs.map} +1 -1
  39. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DSx0E3NV.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs} +3 -3
  40. package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DSx0E3NV.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs.map} +1 -1
  41. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-DdfcGV1C.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs} +10 -10
  42. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs.map +1 -0
  43. package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-CntopmDS.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs} +5 -5
  44. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs.map +1 -0
  45. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs +61 -0
  46. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs.map +1 -0
  47. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +2218 -1504
  48. package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs.map +1 -1
  49. package/fesm2022/acorex-platform-framework-client-realtime.mjs +227 -0
  50. package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -0
  51. package/fesm2022/acorex-platform-framework-client-runtime.mjs +201 -13
  52. package/fesm2022/acorex-platform-framework-client-runtime.mjs.map +1 -1
  53. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs +158 -0
  54. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs +119 -0
  56. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs.map +1 -0
  57. package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-single-view.component-D1a7UI71.mjs → acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs} +5 -6
  58. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs.map +1 -0
  59. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs +48 -0
  60. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs.map +1 -0
  61. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs +42 -0
  62. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs.map +1 -0
  63. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs +19 -0
  64. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-framework-client-themes-default.mjs +123 -96
  66. package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
  67. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CXSGiTCK.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs} +3 -3
  68. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs.map +1 -0
  69. package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BY5clQ1J.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs} +3 -3
  70. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs.map +1 -0
  71. package/fesm2022/{acorex-platform-framework-client-themes-shared-settings.provider-DEL2YOTP.mjs → acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs} +11 -2
  72. package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs.map +1 -0
  73. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BXl8u4Yp.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs} +7 -7
  74. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs.map +1 -0
  75. package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-i2sOOkVj.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs} +7 -7
  76. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs.map +1 -0
  77. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +124 -112
  78. package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
  79. package/fesm2022/acorex-platform-framework-client-workflow.mjs +26 -483
  80. package/fesm2022/acorex-platform-framework-client-workflow.mjs.map +1 -1
  81. package/package.json +14 -9
  82. package/types/acorex-platform-framework-client-auth.d.ts +76 -5
  83. package/types/acorex-platform-framework-client-common.d.ts +499 -129
  84. package/types/acorex-platform-framework-client-core.d.ts +291 -10
  85. package/types/acorex-platform-framework-client-layout-builder.d.ts +81 -31
  86. package/types/acorex-platform-framework-client-layout-components.d.ts +295 -41
  87. package/types/acorex-platform-framework-client-layout-entity.d.ts +1895 -1743
  88. package/types/acorex-platform-framework-client-layout-views.d.ts +8 -18
  89. package/types/acorex-platform-framework-client-layout-widget-core.d.ts +20 -35
  90. package/types/acorex-platform-framework-client-layout-widgets.d.ts +167 -33
  91. package/types/acorex-platform-framework-client-realtime.d.ts +100 -0
  92. package/types/acorex-platform-framework-client-runtime.d.ts +60 -2
  93. package/types/acorex-platform-framework-client-themes-default.d.ts +4 -48
  94. package/types/acorex-platform-framework-client-workflow.d.ts +16 -127
  95. package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs.map +0 -1
  96. package/fesm2022/acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CWVU3wXL.mjs.map +0 -1
  97. package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-l0JAHKIH.mjs.map +0 -1
  98. package/fesm2022/acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CpkWwygb.mjs.map +0 -1
  99. package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +0 -1
  100. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-DdfcGV1C.mjs.map +0 -1
  101. package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-CntopmDS.mjs.map +0 -1
  102. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-B5kSWxGk.mjs +0 -34
  103. package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-B5kSWxGk.mjs.map +0 -1
  104. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DnTHwsDJ.mjs +0 -160
  105. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DnTHwsDJ.mjs.map +0 -1
  106. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BpR9g6QS.mjs +0 -121
  107. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BpR9g6QS.mjs.map +0 -1
  108. package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-D1a7UI71.mjs.map +0 -1
  109. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-D--_MIar.mjs +0 -48
  110. package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-D--_MIar.mjs.map +0 -1
  111. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-Byyqk8pH.mjs +0 -42
  112. package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-Byyqk8pH.mjs.map +0 -1
  113. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DR6G8gPC.mjs +0 -19
  114. package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DR6G8gPC.mjs.map +0 -1
  115. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CXSGiTCK.mjs.map +0 -1
  116. package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BY5clQ1J.mjs.map +0 -1
  117. package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-DEL2YOTP.mjs.map +0 -1
  118. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BXl8u4Yp.mjs.map +0 -1
  119. package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-i2sOOkVj.mjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, Injector, Injectable, signal, inject, Input, Directive, provideAppInitializer, Optional, Inject, NgModule, input, output, Component } from '@angular/core';
3
+ import { map, BehaviorSubject, shareReplay, defaultIfEmpty, switchMap, filter, from, combineLatest, first } from 'rxjs';
3
4
  import { AXPBroadcastEventService, AXP_SESSION_SERVICE } from '@acorex-platform/framework-client/core';
4
5
  import { isEmpty } from 'lodash-es';
5
- import { map, BehaviorSubject, shareReplay, defaultIfEmpty, switchMap, filter, from, first } from 'rxjs';
6
6
  import { AXPWidgetsCatalog } from '@acorex-platform/framework-shared/core';
7
7
  import { AXDataSource } from '@acorex/cdk/common';
8
8
 
@@ -244,6 +244,9 @@ class AXPPermissionDefaultLoader {
244
244
  */
245
245
  const AXP_PERMISSION_CHECKER = new InjectionToken('AXP_PERMISSION_CHECKER');
246
246
 
247
+ const AXP_ACCESS_POLICY_CACHE_PORT = new InjectionToken('AXP_ACCESS_POLICY_CACHE_PORT');
248
+ //#endregion
249
+
247
250
  class AXPSessionService {
248
251
  constructor() {
249
252
  this.eventService = inject(AXPBroadcastEventService);
@@ -255,6 +258,7 @@ class AXPSessionService {
255
258
  this.applicationLoader = inject(AXP_APPLICATION_LOADER);
256
259
  this.permissionChecker = inject(AXP_PERMISSION_CHECKER, { optional: true });
257
260
  this.featureChecker = inject(AXP_FEATURE_CHECKER, { optional: true });
261
+ this.accessPolicyCache = inject(AXP_ACCESS_POLICY_CACHE_PORT, { optional: true });
258
262
  this.status = new BehaviorSubject(AXPSessionStatus.Unauthenticated);
259
263
  this.status$ = this.status.asObservable().pipe(shareReplay(1));
260
264
  // Add loading state to prevent premature redirects
@@ -294,27 +298,18 @@ class AXPSessionService {
294
298
  }
295
299
  static { this.SESSION_KEY = 'AXP_SESSION'; }
296
300
  get user() {
297
- const session = this.getSessionData();
298
- if (session?.user && !this.currentUserSubject.value) {
299
- this.currentUserSubject.next(session.user);
300
- }
301
+ this.syncContextSubjectsFromStorage();
301
302
  return this.currentUserSubject.value;
302
303
  }
303
304
  get tenant() {
304
- const session = this.getSessionData();
305
- if (session?.tenant && !this.currentTenantSubject.value) {
306
- this.currentTenantSubject.next(session.tenant);
307
- }
305
+ this.syncContextSubjectsFromStorage();
308
306
  return this.currentTenantSubject.value;
309
307
  }
310
308
  get tenants$() {
311
309
  return from(this.tenantLoader.getList(this.getContext()));
312
310
  }
313
311
  get application() {
314
- const session = this.getSessionData();
315
- if (session?.application && !this.currentApplicationSubject.value) {
316
- this.currentApplicationSubject.next(session.application);
317
- }
312
+ this.syncContextSubjectsFromStorage();
318
313
  return this.currentApplicationSubject.value;
319
314
  }
320
315
  get applications$() {
@@ -343,7 +338,7 @@ class AXPSessionService {
343
338
  this.status.next(AXPSessionStatus.Authenticated);
344
339
  await this.loadPermissions();
345
340
  await this.loadFeatures();
346
- await this.signInComplete();
341
+ await this.syncSessionAuthorization();
347
342
  }
348
343
  }
349
344
  else {
@@ -371,22 +366,7 @@ class AXPSessionService {
371
366
  if (!result)
372
367
  return;
373
368
  if (result?.succeed) {
374
- this.permissionsSubject.next([]);
375
- this.featuresSubject.next([]);
376
- this.currentUserSubject.next(result.data.user);
377
- this.setSession({
378
- accessToken: result.data.accessToken,
379
- refreshToken: result.data.refreshToken,
380
- strategy: credentials.strategy,
381
- user: result.data.user,
382
- application: result.data?.application,
383
- tenant: result.data?.tenant,
384
- expiresIn: result.data?.expiresIn,
385
- idToken: result.data?.idToken ?? null,
386
- locked: false,
387
- });
388
- await this.loadPermissions();
389
- await this.loadFeatures();
369
+ await this.applySignInResult(credentials.strategy, result);
390
370
  }
391
371
  else {
392
372
  this.status.next(AXPSessionStatus.Unauthenticated);
@@ -403,6 +383,47 @@ class AXPSessionService {
403
383
  console.log('Signin process completed');
404
384
  }
405
385
  }
386
+ async register(credentials) {
387
+ this.isLoading.next(true);
388
+ try {
389
+ const strategy = this.authStrategyRegistry.get(credentials.strategy);
390
+ if (!strategy || typeof strategy.register !== 'function') {
391
+ throw new Error(`Registration is not supported for strategy '${credentials.strategy}'`);
392
+ }
393
+ const result = await strategy.register(credentials);
394
+ if (!result?.succeed) {
395
+ this.status.next(AXPSessionStatus.Unauthenticated);
396
+ throw new Error('Registration failed');
397
+ }
398
+ await this.applySignInResult(credentials.strategy, result);
399
+ }
400
+ catch (error) {
401
+ console.error('Register error:', error);
402
+ this.status.next(AXPSessionStatus.Unauthenticated);
403
+ throw error;
404
+ }
405
+ finally {
406
+ this.isLoading.next(false);
407
+ }
408
+ }
409
+ async applySignInResult(strategy, result) {
410
+ this.clearSession();
411
+ this.currentUserSubject.next(result.data.user);
412
+ this.setSession({
413
+ accessToken: result.data.accessToken,
414
+ refreshToken: result.data.refreshToken,
415
+ strategy,
416
+ user: result.data.user,
417
+ tenant: result.data?.tenant ?? null,
418
+ application: result.data?.application ?? null,
419
+ expiresIn: result.data?.expiresIn,
420
+ idToken: result.data?.idToken ?? null,
421
+ locked: false,
422
+ });
423
+ await this.loadPermissions();
424
+ await this.loadFeatures();
425
+ await this.syncSessionAuthorization();
426
+ }
406
427
  async updateToken(params) {
407
428
  this.isLoading.next(true);
408
429
  try {
@@ -416,22 +437,29 @@ class AXPSessionService {
416
437
  }
417
438
  const result = await strategy.updateToken(params);
418
439
  if (result?.succeed) {
440
+ if (params?.['code']) {
441
+ this.clearSession();
442
+ }
443
+ else {
444
+ this.permissionsSubject.next([]);
445
+ this.featuresSubject.next([]);
446
+ this.invalidateAccessPolicyCache();
447
+ }
419
448
  this.currentUserSubject.next(result.data.user);
420
449
  this.setSession({
421
450
  accessToken: result.data.accessToken,
422
451
  refreshToken: result.data.refreshToken,
423
452
  strategy: strategyName,
424
453
  user: result.data.user,
425
- application: result.data?.application,
426
- tenant: result.data?.tenant,
454
+ tenant: result.data?.tenant ?? null,
455
+ application: result.data?.application ?? null,
427
456
  expiresIn: result.data?.expiresIn,
428
457
  idToken: result.data?.idToken ?? null,
458
+ locked: false,
429
459
  });
430
- this.status.next(AXPSessionStatus.Authenticated);
431
- // If we have both tenant and application, complete the sign-in
432
- if (this.application && this.tenant) {
433
- await this.restoreSession();
434
- }
460
+ await this.loadPermissions();
461
+ await this.loadFeatures();
462
+ await this.syncSessionAuthorization();
435
463
  }
436
464
  else {
437
465
  this.status.next(AXPSessionStatus.Unauthenticated);
@@ -538,6 +566,25 @@ class AXPSessionService {
538
566
  // Set status to Authorized
539
567
  this.status.next(AXPSessionStatus.Authorized);
540
568
  }
569
+ /** Tenant + application must be bound before menu, permissions, and features are fully valid. */
570
+ hasCompleteSessionContext() {
571
+ return !!(this.tenant?.id && this.application?.id);
572
+ }
573
+ /**
574
+ * Keeps session status aligned with context: Authenticated after sign-in / tenant pick,
575
+ * Authorized only once tenant and application are selected and loaders have finished.
576
+ */
577
+ async syncSessionAuthorization() {
578
+ if (!this.user) {
579
+ this.status.next(AXPSessionStatus.Unauthenticated);
580
+ return;
581
+ }
582
+ if (this.hasCompleteSessionContext()) {
583
+ await this.signInComplete();
584
+ return;
585
+ }
586
+ this.status.next(AXPSessionStatus.Authenticated);
587
+ }
541
588
  setSession(tokens) {
542
589
  const existing = this.getSessionData() ?? {};
543
590
  const sessionData = {
@@ -548,11 +595,11 @@ class AXPSessionService {
548
595
  if (tokens.user) {
549
596
  this.currentUserSubject.next(tokens.user);
550
597
  }
551
- if (tokens.tenant) {
552
- this.currentTenantSubject.next(tokens.tenant);
598
+ if ('tenant' in tokens) {
599
+ this.currentTenantSubject.next(tokens.tenant ?? null);
553
600
  }
554
- if (tokens.application) {
555
- this.currentApplicationSubject.next(tokens.application);
601
+ if ('application' in tokens) {
602
+ this.currentApplicationSubject.next(tokens.application ?? null);
556
603
  }
557
604
  localStorage.setItem(AXPSessionService.SESSION_KEY, JSON.stringify(sessionData));
558
605
  }
@@ -590,18 +637,33 @@ class AXPSessionService {
590
637
  }
591
638
  }
592
639
  clearSession() {
593
- //
640
+ this.invalidateAccessPolicyCache();
594
641
  this.currentUserSubject.next(null);
595
- //
596
642
  this.currentTenantSubject.next(null);
597
- //
598
643
  this.currentApplicationSubject.next(null);
599
- //
600
644
  this.permissionsSubject.next([]);
601
- //
602
645
  this.featuresSubject.next([]);
603
- //
604
646
  localStorage.removeItem(AXPSessionService.SESSION_KEY);
647
+ this.status.next(AXPSessionStatus.Unauthenticated);
648
+ }
649
+ /** Keeps in-memory subjects aligned with persisted session (e.g. after user switch). */
650
+ syncContextSubjectsFromStorage() {
651
+ const session = this.getSessionData();
652
+ if (!session) {
653
+ return;
654
+ }
655
+ const sessionUser = session.user ?? null;
656
+ if (sessionUser?.id !== this.currentUserSubject.value?.id) {
657
+ this.currentUserSubject.next(sessionUser);
658
+ }
659
+ const sessionTenant = session.tenant ?? null;
660
+ if (sessionTenant?.id !== this.currentTenantSubject.value?.id) {
661
+ this.currentTenantSubject.next(sessionTenant);
662
+ }
663
+ const sessionApplication = session.application ?? null;
664
+ if (sessionApplication?.id !== this.currentApplicationSubject.value?.id) {
665
+ this.currentApplicationSubject.next(sessionApplication);
666
+ }
605
667
  }
606
668
  authorize(...keys) {
607
669
  // Calculate base result
@@ -660,6 +722,9 @@ class AXPSessionService {
660
722
  application: this.application,
661
723
  });
662
724
  }
725
+ invalidateAccessPolicyCache() {
726
+ this.accessPolicyCache?.invalidate();
727
+ }
663
728
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
664
729
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSessionService, providedIn: 'root' }); }
665
730
  }
@@ -685,8 +750,10 @@ class AXPPermissionDirective {
685
750
  this.hasView.set(true);
686
751
  return;
687
752
  }
688
- this.subscription = this.sessionService.isAuthorized$
689
- .subscribe((isAuthorized) => {
753
+ this.subscription = combineLatest([
754
+ this.sessionService.isAuthorized$,
755
+ this.sessionService.permissions$,
756
+ ]).subscribe(([isAuthorized]) => {
690
757
  if (isAuthorized && this.sessionService.authorize(...keys)) {
691
758
  if (!this.hasView()) {
692
759
  this.viewContainer.createEmbeddedView(this.templateRef);
@@ -1215,6 +1282,174 @@ class TimeUtil {
1215
1282
  }
1216
1283
  //#endregion
1217
1284
 
1285
+ function platformOAuthSessionUpdateParams(params) {
1286
+ const tenant = params['tenant'];
1287
+ const application = params['application'];
1288
+ return {
1289
+ tenant,
1290
+ application,
1291
+ tenantId: params['tenantId'] ?? tenant?.id,
1292
+ applicationId: params['applicationId'] ?? application?.id,
1293
+ };
1294
+ }
1295
+ function shouldPlatformOAuthBindSession(accessToken, params) {
1296
+ if (!accessToken) {
1297
+ return false;
1298
+ }
1299
+ const { tenant, application, tenantId, applicationId } = platformOAuthSessionUpdateParams(params);
1300
+ return Boolean(tenantId || applicationId || tenant || application);
1301
+ }
1302
+ async function postPlatformOAuthSessionUpdate(baseUrl, accessToken, params) {
1303
+ const { tenant, application, tenantId, applicationId } = platformOAuthSessionUpdateParams(params);
1304
+ const response = await fetch(`${baseUrl.replace(/\/$/, '')}/v1/auth/session`, {
1305
+ method: 'POST',
1306
+ headers: {
1307
+ 'Content-Type': 'application/json',
1308
+ Authorization: `Bearer ${accessToken}`,
1309
+ },
1310
+ credentials: 'include',
1311
+ body: JSON.stringify({
1312
+ tenantId,
1313
+ applicationId,
1314
+ tenant,
1315
+ application,
1316
+ }),
1317
+ });
1318
+ if (!response.ok) {
1319
+ const detail = await response.text().catch(() => '');
1320
+ throw new Error(`Session update failed: ${response.status} ${response.statusText}${detail ? ` — ${detail}` : ''}`);
1321
+ }
1322
+ const result = (await response.json());
1323
+ return toPlatformOAuthSignInResult(result, {
1324
+ user: params['user'] ?? null,
1325
+ tenant: tenant ?? null,
1326
+ application: application ?? null,
1327
+ });
1328
+ }
1329
+ function toPlatformOAuthSignInResult(result, context) {
1330
+ const tenant = mergeTenant(mapPlatformTenant(result.tenant), context?.tenant ?? null);
1331
+ const application = mergeApplication(mapPlatformApplication(result.application), context?.application ?? null);
1332
+ return {
1333
+ succeed: true,
1334
+ data: {
1335
+ accessToken: result.accessToken,
1336
+ refreshToken: result.refreshToken,
1337
+ idToken: result.id_token ?? null,
1338
+ expiresIn: parsePlatformExpiresIn(result.expiresIn),
1339
+ user: result.user,
1340
+ tenant,
1341
+ application,
1342
+ },
1343
+ };
1344
+ }
1345
+ function mapPlatformTenant(value) {
1346
+ if (!value?.id) {
1347
+ return null;
1348
+ }
1349
+ return {
1350
+ id: value.id,
1351
+ name: value.name ?? value.id,
1352
+ title: value.title ?? value.name ?? value.id,
1353
+ };
1354
+ }
1355
+ function mapPlatformApplication(value) {
1356
+ if (!value?.id) {
1357
+ return null;
1358
+ }
1359
+ return {
1360
+ id: value.id,
1361
+ name: value.name ?? value.id,
1362
+ title: value.title ?? value.name ?? value.id,
1363
+ };
1364
+ }
1365
+ function mergeTenant(mapped, contextTenant) {
1366
+ if (!mapped && !contextTenant) {
1367
+ return null;
1368
+ }
1369
+ if (!mapped) {
1370
+ return contextTenant;
1371
+ }
1372
+ if (!contextTenant) {
1373
+ return mapped;
1374
+ }
1375
+ return {
1376
+ ...contextTenant,
1377
+ ...mapped,
1378
+ title: mapped.title && mapped.title !== mapped.id ? mapped.title : contextTenant.title || mapped.title,
1379
+ name: mapped.name && mapped.name !== mapped.id ? mapped.name : contextTenant.name || mapped.name,
1380
+ };
1381
+ }
1382
+ function mergeApplication(mapped, contextApplication) {
1383
+ if (!mapped && !contextApplication) {
1384
+ return null;
1385
+ }
1386
+ if (!mapped) {
1387
+ return contextApplication;
1388
+ }
1389
+ if (!contextApplication) {
1390
+ return mapped;
1391
+ }
1392
+ return {
1393
+ ...contextApplication,
1394
+ ...mapped,
1395
+ title: mapped.title && mapped.title !== mapped.id ? mapped.title : contextApplication.title || mapped.title,
1396
+ name: mapped.name && mapped.name !== mapped.id ? mapped.name : contextApplication.name || mapped.name,
1397
+ };
1398
+ }
1399
+ function parsePlatformExpiresIn(expiresIn) {
1400
+ if (!expiresIn) {
1401
+ return TimeUtil.calculateExpireInDate(0);
1402
+ }
1403
+ const asDate = new Date(expiresIn);
1404
+ if (!Number.isNaN(asDate.getTime())) {
1405
+ return asDate.toISOString();
1406
+ }
1407
+ return TimeUtil.calculateExpireInDate(Number(expiresIn) || 0);
1408
+ }
1409
+ //#endregion
1410
+
1411
+ const AXP_USER_AVATAR_CACHE_PORT = new InjectionToken('AXP_USER_AVATAR_CACHE_PORT');
1412
+
1413
+ //#region ---- User profile identity service ----
1414
+ /** Keeps session and avatar cache aligned after self-service profile identity updates. */
1415
+ class AXPUserProfileIdentityService {
1416
+ constructor() {
1417
+ //#region ---- Services & Dependencies ----
1418
+ this.sessionService = inject(AXPSessionService);
1419
+ this.avatarCachePort = inject(AXP_USER_AVATAR_CACHE_PORT, { optional: true });
1420
+ }
1421
+ //#endregion
1422
+ //#region ---- Public API ----
1423
+ async applySessionPatch(patch) {
1424
+ const session = this.sessionService.getSessionData();
1425
+ const userId = session?.user?.id;
1426
+ if (!session?.user || !userId) {
1427
+ return;
1428
+ }
1429
+ this.sessionService.setSession({
1430
+ ...session,
1431
+ user: {
1432
+ ...session.user,
1433
+ ...patch,
1434
+ },
1435
+ });
1436
+ await this.refreshAvatar(userId);
1437
+ }
1438
+ async refreshAvatar(userId) {
1439
+ const id = userId ?? this.sessionService.user?.id;
1440
+ if (!id) {
1441
+ return;
1442
+ }
1443
+ await this.avatarCachePort?.refreshUserInfo(id);
1444
+ }
1445
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPUserProfileIdentityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1446
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPUserProfileIdentityService, providedIn: 'root' }); }
1447
+ }
1448
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPUserProfileIdentityService, decorators: [{
1449
+ type: Injectable,
1450
+ args: [{ providedIn: 'root' }]
1451
+ }] });
1452
+
1218
1453
  //#region ---- Challenge Data Types ----
1219
1454
  //#endregion
1220
1455
 
@@ -1379,5 +1614,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1379
1614
  * Generated bundle index. Do not edit.
1380
1615
  */
1381
1616
 
1382
- export { AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureGuard, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDefinitionsDataSourceDefinition, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPPlatformAuthDataSourceKeys, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPUnauthorizedError, AXP_APPLICATION_LOADER, AXP_FEATURE_CHECKER, AXP_FEATURE_LOADER, AXP_LOGIN_CHALLENGE_PROVIDER, AXP_PERMISSION_CHECKER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, JwtUtil, PkceUtil, TimeUtil, initializeAppState };
1617
+ export { AXPAuthGuard, AXPAuthModule, AXPAuthStrategy, AXPAuthStrategyRegistryService, AXPFeatureDirective, AXPFeatureGuard, AXPLoginChallengeComponentBase, AXPLoginChallengeProvider, AXPPermissionDefinitionBuilder, AXPPermissionDefinitionGroupBuilder, AXPPermissionDefinitionProviderContext, AXPPermissionDefinitionService, AXPPermissionDefinitionsDataSourceDefinition, AXPPermissionDirective, AXPPermissionEvaluatorScopeProvider, AXPPermissionGuard, AXPPlatformAuthDataSourceKeys, AXPSessionContext, AXPSessionService, AXPSessionStatus, AXPUnauthenticatedError, AXPUnauthorizedError, AXPUserProfileIdentityService, AXP_ACCESS_POLICY_CACHE_PORT, AXP_APPLICATION_LOADER, AXP_FEATURE_CHECKER, AXP_FEATURE_LOADER, AXP_LOGIN_CHALLENGE_PROVIDER, AXP_PERMISSION_CHECKER, AXP_PERMISSION_DEFINITION_PROVIDER, AXP_PERMISSION_LOADER, AXP_TENANT_LOADER, AXP_USER_AVATAR_CACHE_PORT, JwtUtil, PkceUtil, TimeUtil, initializeAppState, platformOAuthSessionUpdateParams, postPlatformOAuthSessionUpdate, shouldPlatformOAuthBindSession, toPlatformOAuthSignInResult };
1383
1618
  //# sourceMappingURL=acorex-platform-framework-client-auth.mjs.map