@acorex/platform 20.8.22 → 20.8.24

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.
@@ -3,7 +3,7 @@ import { InjectionToken, inject, Injectable, Injector, makeEnvironmentProviders,
3
3
  import { kebabCase, merge, sortBy, cloneDeep, get, omit } from 'lodash-es';
4
4
  import { Router, ROUTES, RedirectCommand, RouterModule } from '@angular/router';
5
5
  import { AXPSessionService, AXPSessionStatus, AXPAuthGuard } from '@acorex/platform/auth';
6
- import { Subject, distinctUntilChanged, merge as merge$1, first, switchMap, from } from 'rxjs';
6
+ import { Subject, distinctUntilChanged, merge as merge$1, first, switchMap, from, map } from 'rxjs';
7
7
  import { AXPPlatformScope, AXPBroadcastEventService, objectKeyValueTransforms, AXPSystemActionType, AXPModuleManifestModule, AXPAppStartUpProvider, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXPHookService, AXPDataGenerator, AXPModuleManifestRegistry } from '@acorex/platform/core';
8
8
  import { AXTranslationService } from '@acorex/core/translation';
9
9
  import { AXPWidgetsCatalog } from '@acorex/platform/layout/widget-core';
@@ -1042,12 +1042,20 @@ class AXPHomePageService {
1042
1042
  // TODO: check this for custom menu like :app/terms
1043
1043
  router.resetConfig(merged);
1044
1044
  }
1045
+ /**
1046
+ * Resolves the current user's home page as a router URL tree.
1047
+ */
1048
+ resolveHomeUrlTree() {
1049
+ const router = this.injector.get(Router);
1050
+ const current = this.getCurrent();
1051
+ const path = current.path.startsWith('/') ? current.path : `/${current.path}`;
1052
+ return router.parseUrl(path);
1053
+ }
1045
1054
  async navigateTo() {
1046
1055
  // wait for the router to be initialized
1047
1056
  setTimeout(() => {
1048
1057
  const router = this.injector.get(Router);
1049
- const current = this.getCurrent();
1050
- router.navigate([current.path], { onSameUrlNavigation: 'reload' });
1058
+ router.navigateByUrl(this.resolveHomeUrlTree(), { onSameUrlNavigation: 'reload' });
1051
1059
  }, 100);
1052
1060
  }
1053
1061
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPHomePageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -1314,6 +1322,15 @@ function axpRedirectToNotFound(router = inject(Router)) {
1314
1322
  return new RedirectCommand(router.parseUrl(AXP_NOT_FOUND_ROUTE));
1315
1323
  }
1316
1324
 
1325
+ /** Canonical route path for the platform 401 page. */
1326
+ const AXP_UNAUTHORIZED_ROUTE = '/error/401';
1327
+ /**
1328
+ * Creates an Angular redirect command to the platform 401 page.
1329
+ */
1330
+ function axpRedirectToUnauthorized(router = inject(Router)) {
1331
+ return new RedirectCommand(router.parseUrl(AXP_UNAUTHORIZED_ROUTE));
1332
+ }
1333
+
1317
1334
  const AXP_TOKEN_DEFINITION_PROVIDER = new InjectionToken('AXP_TOKEN_DEFINITION_PROVIDER', {
1318
1335
  factory: () => [],
1319
1336
  });
@@ -2394,10 +2411,10 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
2394
2411
  function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = DEFAULT_TRAILING_SEGMENTS) {
2395
2412
  let bestMatch = null;
2396
2413
  let bestEffectiveLength = -1;
2397
- const visit = (menuItems) => {
2414
+ const visit = (menuItems, ancestors) => {
2398
2415
  for (const item of menuItems) {
2399
2416
  if (item.children?.length) {
2400
- visit(item.children);
2417
+ visit(item.children, [...ancestors, item]);
2401
2418
  }
2402
2419
  if (!item.path) {
2403
2420
  continue;
@@ -2416,11 +2433,11 @@ function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = D
2416
2433
  }
2417
2434
  if (effectiveMenuLength > bestEffectiveLength) {
2418
2435
  bestEffectiveLength = effectiveMenuLength;
2419
- bestMatch = { item, isPartialMatch: matchResult.isPartial };
2436
+ bestMatch = { item, ancestors, isPartialMatch: matchResult.isPartial };
2420
2437
  }
2421
2438
  }
2422
2439
  };
2423
- visit(items);
2440
+ visit(items, []);
2424
2441
  return bestMatch;
2425
2442
  }
2426
2443
 
@@ -2530,6 +2547,18 @@ class AXPMenuVisibilityService {
2530
2547
  constructor() {
2531
2548
  this.sessionService = inject(AXPSessionService);
2532
2549
  }
2550
+ /**
2551
+ * Checks visibility for a menu branch, including ancestor policies.
2552
+ * Parent module features and permissions must pass before child routes are accessible.
2553
+ */
2554
+ isMenuBranchVisible(item, ancestors = []) {
2555
+ for (const menuItem of [...ancestors, item]) {
2556
+ if (!this.isItemVisible(menuItem)) {
2557
+ return false;
2558
+ }
2559
+ }
2560
+ return true;
2561
+ }
2533
2562
  /**
2534
2563
  * Checks if a menu item should be visible based on permissions and features.
2535
2564
  */
@@ -2622,19 +2651,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
2622
2651
  }] });
2623
2652
 
2624
2653
  const SKIP_ROUTE_PREFIXES = ['/auth', '/error'];
2625
- const SKIP_ROUTE_PATHS = new Set(['/404', '/401']);
2626
- //#region ---- Menu Route Permission Service ----
2654
+ const SKIP_ROUTE_PATHS = new Set(['/404', '/401', '/error/404', '/error/401']);
2655
+ //#region ---- Menu Route Access Service ----
2627
2656
  /**
2628
- * Resolves route access using the same permission and feature policies defined on menu items.
2657
+ * Resolves route access using menu policy, route metadata, permissions, and features.
2629
2658
  */
2630
- class AXPMenuRoutePermissionService {
2659
+ class AXPMenuRouteAccessService {
2631
2660
  constructor() {
2632
2661
  //#region ---- Services & Dependencies ----
2633
2662
  this.menuProvider = inject(AXPMenuProviderService);
2634
2663
  this.menuVisibility = inject(AXPMenuVisibilityService);
2635
2664
  this.sessionService = inject(AXPSessionService);
2636
- this.toastService = inject(AXToastService);
2637
- this.translationService = inject(AXTranslationService);
2638
2665
  }
2639
2666
  //#endregion
2640
2667
  //#region ---- Public Methods ----
@@ -2646,7 +2673,6 @@ class AXPMenuRoutePermissionService {
2646
2673
  return true;
2647
2674
  }
2648
2675
  if (!this.hasExplicitRouteAccess(route)) {
2649
- await this.showAccessDeniedToast();
2650
2676
  return false;
2651
2677
  }
2652
2678
  const menuItems = await this.menuProvider.items();
@@ -2654,16 +2680,15 @@ class AXPMenuRoutePermissionService {
2654
2680
  if (!menuMatch) {
2655
2681
  return true;
2656
2682
  }
2657
- if (this.menuVisibility.isItemVisible(menuMatch.item)) {
2683
+ if (this.menuVisibility.isMenuBranchVisible(menuMatch.item, menuMatch.ancestors)) {
2658
2684
  return true;
2659
2685
  }
2660
- await this.showAccessDeniedToast();
2661
2686
  return false;
2662
2687
  }
2663
2688
  //#endregion
2664
2689
  //#region ---- Utility Methods ----
2665
2690
  shouldSkip(route, url) {
2666
- if (this.hasRouteFlag(route, 'skipMenuPermissionGuard')) {
2691
+ if (this.hasRouteFlag(route, 'skipMenuRouteGuard')) {
2667
2692
  return true;
2668
2693
  }
2669
2694
  const normalizedUrl = this.normalizeUrl(url);
@@ -2716,41 +2741,35 @@ class AXPMenuRoutePermissionService {
2716
2741
  const path = url.split('?')[0]?.split('#')[0] ?? url;
2717
2742
  return path.startsWith('/') ? path : `/${path}`;
2718
2743
  }
2719
- async showAccessDeniedToast() {
2720
- const title = await this.translationService.translateAsync('@general:messages.network.forbidden.title');
2721
- const description = await this.translationService.translateAsync('@general:messages.network.forbidden.description');
2722
- this.toastService.show({
2723
- color: 'danger',
2724
- title,
2725
- content: description,
2726
- timeOut: 5000,
2727
- });
2728
- }
2729
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPMenuRoutePermissionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2730
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPMenuRoutePermissionService, providedIn: 'root' }); }
2744
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPMenuRouteAccessService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2745
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPMenuRouteAccessService, providedIn: 'root' }); }
2731
2746
  }
2732
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPMenuRoutePermissionService, decorators: [{
2747
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPMenuRouteAccessService, decorators: [{
2733
2748
  type: Injectable,
2734
2749
  args: [{ providedIn: 'root' }]
2735
2750
  }] });
2736
2751
 
2737
2752
  /**
2738
- * Blocks navigation when the target route matches a menu item the current user cannot access.
2739
- * Uses the same permission and feature policies applied to menu visibility.
2753
+
2754
+ * Blocks navigation when the target route is not accessible for the current user.
2755
+
2756
+ * Evaluates menu policy, permissions, and features.
2757
+
2740
2758
  */
2741
- const AXPMenuPermissionGuard = (route, state) => {
2759
+ const AXPMenuRouteGuard = (route, state) => {
2742
2760
  const sessionService = inject(AXPSessionService);
2743
- const menuRoutePermissionService = inject(AXPMenuRoutePermissionService);
2744
- return sessionService.isAuthorized$.pipe(first(), switchMap((isAuthorized) => {
2745
- if (!isAuthorized) {
2746
- return from(Promise.resolve(true));
2761
+ const menuRouteAccessService = inject(AXPMenuRouteAccessService);
2762
+ const router = inject(Router);
2763
+ return sessionService.isAuthorizedWithLoading$.pipe(first(), switchMap(() => from(menuRouteAccessService.canAccess(route, state.url))), map((isAllowed) => {
2764
+ if (isAllowed) {
2765
+ return true;
2747
2766
  }
2748
- return from(menuRoutePermissionService.canAccess(route, state.url));
2767
+ return router.parseUrl(AXP_UNAUTHORIZED_ROUTE);
2749
2768
  }));
2750
2769
  };
2751
2770
 
2752
- /** Standard guards for authenticated routes with menu-based permission enforcement. */
2753
- const AXP_PROTECTED_ROUTE_GUARDS = [AXPAuthGuard, AXPMenuPermissionGuard];
2771
+ /** Standard guards for authenticated routes with menu-based access enforcement. */
2772
+ const AXP_PROTECTED_ROUTE_GUARDS = [AXPAuthGuard, AXPMenuRouteGuard];
2754
2773
 
2755
2774
  class AXPMenuSearchDefinitionProvider {
2756
2775
  async provide(context) {
@@ -4196,16 +4215,23 @@ function systemStatusToDefinition(statusType, overrides) {
4196
4215
 
4197
4216
  class AXPClipBoardService {
4198
4217
  constructor() {
4218
+ //#region ---- Services & Dependencies ----
4199
4219
  this.toast = inject(AXToastService);
4220
+ this.translationService = inject(AXTranslationService);
4200
4221
  }
4201
- copy(title, value) {
4222
+ //#endregion
4223
+ //#region ---- Public Methods ----
4224
+ async copy(title, value) {
4202
4225
  const copyText = document.createElement('input');
4203
4226
  copyText.type = 'text';
4204
4227
  copyText.select();
4205
4228
  copyText.setSelectionRange(0, 99999); // For mobile devices
4206
4229
  copyText.remove();
4207
- navigator.clipboard.writeText(value);
4208
- this.toast.success(`${title} copied!`);
4230
+ await navigator.clipboard.writeText(value);
4231
+ const message = await this.translationService.translateAsync('@general:messages.clipboard.copied', {
4232
+ params: { title },
4233
+ });
4234
+ this.toast.success(message);
4209
4235
  }
4210
4236
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPClipBoardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4211
4237
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPClipBoardService, providedIn: 'root' }); }
@@ -4598,5 +4624,5 @@ class AXPVersioningService {
4598
4624
  * Generated bundle index. Do not edit.
4599
4625
  */
4600
4626
 
4601
- export { ALL_DEFAULT_OPERATORS, AXMWorkflowErrorHandler, AXPAppVersionService, AXPCleanNestedFilters, AXPClipBoardService, AXPCommonModule, AXPCommonSettings, AXPCustomOperatorService, AXPCustomOperatorServiceImpl, AXPDataProvider, AXPDebugService, AXPDialogConfirmAction, AXPEntityCommandScope, AXPEntityQueryType, AXPErrorHandlerRegistryService, AXPExportService, AXPFileActionsService, AXPFileStorageService, AXPFileStorageStatus, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPLockService, AXPMenuMiddlewareRegistry, AXPMenuPermissionGuard, AXPMenuProviderService, AXPMenuRoutePermissionService, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateWorkflow, AXPNotFoundCatchAllRoute, AXPNotFoundError, AXPPlatformDefaultConfigs, AXPRedirectEvent, AXPRefreshEvent, AXPRegionalSetting, AXPRelationshipCardinality, AXPRelationshipKind, AXPReloadAction, AXPReloadEvent, AXPSearchCommandProvider, AXPSearchDefinitionActionBuilder, AXPSearchDefinitionBuilder, AXPSearchDefinitionProviderContext, AXPSearchDefinitionProviderService, AXPSearchService, AXPSettingDefaultValuesAggregatorService, AXPSettingDefinitionGroupBuilder, AXPSettingDefinitionProviderContext, AXPSettingDefinitionProviderService, AXPSettingDefinitionSectionBuilder, AXPSettingsService, AXPStatusDefinitionProviderService, AXPStatusProvider, AXPStickyDirective, AXPSystemStatusType, AXPSystemStatuses, AXPToastAction, AXPTokenDefinitionService, AXPTokenEvaluatorScopeProvider, AXPVersioningService, AXPWorkflowNavigateAction, AXPWorkflowRouterNavigateAction, AXP_APP_VERSION_PROVIDER, AXP_FILE_ACTION_PROVIDER, AXP_FILE_TYPE_INFO_PROVIDER, AXP_HOME_PAGES, AXP_HOME_PAGE_DEFAULT_KEY, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_NOT_FOUND_CATCH_ALL_ROUTE, AXP_NOT_FOUND_ROUTE, AXP_PLATFORM_CONFIG_TOKEN, AXP_PROTECTED_ROUTE_GUARDS, AXP_ROOT_CONFIG_TOKEN, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTING_DEFAULT_VALUES_PROVIDERS, AXP_SETTING_DEFINITION_PROVIDER, AXP_SETTING_VALUE_PROVIDER, AXP_STATUS_PROVIDERS, AXP_TOKEN_DEFINITION_PROVIDER, AXVChangeType, BETWEEN_OPER, BOOLEAN_OPERATORS, CONTAINS_OPER, DATE_OPERATORS, DEFAULT_DATE_FILTER_PRESETS, ENDS_WITH_OPER, ENVIRONMENT, EQ_OPER, GTE_OPER, GT_OPER, IN_OPER, IS_EMPTY_OPER, IS_NOT_EMPTY_OPER, LTE_OPER, LT_OPER, NOT_CONTAINS_OPER, NOT_EQ_OPER, NUMBER_OPERATORS, STARTS_WITH_OPER, STRING_OPERATORS, UploadFromComputerActionProvider, applyDateFilterPreset, axpFindMenuItemByRoute, axpIsEntityRecordNotFound, axpMenuPathsMatch, axpRedirectToNotFound, configPlatform, createAllQueryView, createMenuContext, createMenuMiddleware, createQueryView, findManualPresetIdByOperation, getEntityInfo, getStatusInfo, getSystemStatus, provideDynamicHomePage, provideMenuMiddleware, resolveDateFilterPresets, resolveStatusLook, systemStatusToDefinition };
4627
+ export { ALL_DEFAULT_OPERATORS, AXMWorkflowErrorHandler, AXPAppVersionService, AXPCleanNestedFilters, AXPClipBoardService, AXPCommonModule, AXPCommonSettings, AXPCustomOperatorService, AXPCustomOperatorServiceImpl, AXPDataProvider, AXPDebugService, AXPDialogConfirmAction, AXPEntityCommandScope, AXPEntityQueryType, AXPErrorHandlerRegistryService, AXPExportService, AXPFileActionsService, AXPFileStorageService, AXPFileStorageStatus, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPLockService, AXPMenuMiddlewareRegistry, AXPMenuProviderService, AXPMenuRouteAccessService, AXPMenuRouteGuard, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateWorkflow, AXPNotFoundCatchAllRoute, AXPNotFoundError, AXPPlatformDefaultConfigs, AXPRedirectEvent, AXPRefreshEvent, AXPRegionalSetting, AXPRelationshipCardinality, AXPRelationshipKind, AXPReloadAction, AXPReloadEvent, AXPSearchCommandProvider, AXPSearchDefinitionActionBuilder, AXPSearchDefinitionBuilder, AXPSearchDefinitionProviderContext, AXPSearchDefinitionProviderService, AXPSearchService, AXPSettingDefaultValuesAggregatorService, AXPSettingDefinitionGroupBuilder, AXPSettingDefinitionProviderContext, AXPSettingDefinitionProviderService, AXPSettingDefinitionSectionBuilder, AXPSettingsService, AXPStatusDefinitionProviderService, AXPStatusProvider, AXPStickyDirective, AXPSystemStatusType, AXPSystemStatuses, AXPToastAction, AXPTokenDefinitionService, AXPTokenEvaluatorScopeProvider, AXPVersioningService, AXPWorkflowNavigateAction, AXPWorkflowRouterNavigateAction, AXP_APP_VERSION_PROVIDER, AXP_FILE_ACTION_PROVIDER, AXP_FILE_TYPE_INFO_PROVIDER, AXP_HOME_PAGES, AXP_HOME_PAGE_DEFAULT_KEY, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_NOT_FOUND_CATCH_ALL_ROUTE, AXP_NOT_FOUND_ROUTE, AXP_PLATFORM_CONFIG_TOKEN, AXP_PROTECTED_ROUTE_GUARDS, AXP_ROOT_CONFIG_TOKEN, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTING_DEFAULT_VALUES_PROVIDERS, AXP_SETTING_DEFINITION_PROVIDER, AXP_SETTING_VALUE_PROVIDER, AXP_STATUS_PROVIDERS, AXP_TOKEN_DEFINITION_PROVIDER, AXP_UNAUTHORIZED_ROUTE, AXVChangeType, BETWEEN_OPER, BOOLEAN_OPERATORS, CONTAINS_OPER, DATE_OPERATORS, DEFAULT_DATE_FILTER_PRESETS, ENDS_WITH_OPER, ENVIRONMENT, EQ_OPER, GTE_OPER, GT_OPER, IN_OPER, IS_EMPTY_OPER, IS_NOT_EMPTY_OPER, LTE_OPER, LT_OPER, NOT_CONTAINS_OPER, NOT_EQ_OPER, NUMBER_OPERATORS, STARTS_WITH_OPER, STRING_OPERATORS, UploadFromComputerActionProvider, applyDateFilterPreset, axpFindMenuItemByRoute, axpIsEntityRecordNotFound, axpMenuPathsMatch, axpRedirectToNotFound, axpRedirectToUnauthorized, configPlatform, createAllQueryView, createMenuContext, createMenuMiddleware, createQueryView, findManualPresetIdByOperation, getEntityInfo, getStatusInfo, getSystemStatus, provideDynamicHomePage, provideMenuMiddleware, resolveDateFilterPresets, resolveStatusLook, systemStatusToDefinition };
4602
4628
  //# sourceMappingURL=acorex-platform-common.mjs.map