@acorex/platform 20.8.19 → 20.8.22

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/common/index.d.ts CHANGED
@@ -8,8 +8,8 @@ import { AXPValueTransformerFunctions, AXPOptionsData, AXPExpression, AXPFilterD
8
8
  import { AXPWidgetTypesMap, AXPMetaDataDefinition, AXPWidgetNode } from '@acorex/platform/layout/widget-core';
9
9
  import * as i3 from '@acorex/core/date-time';
10
10
  import { AXCalendarService } from '@acorex/core/date-time';
11
- import * as i6 from '@angular/router';
12
- import { Route, Routes } from '@angular/router';
11
+ import * as _angular_router from '@angular/router';
12
+ import { Route, Routes, Router, RedirectCommand, ActivatedRouteSnapshot, CanActivateFn } from '@angular/router';
13
13
  import * as i1 from '@acorex/platform/workflow';
14
14
  import { AXPWorkflowAction, AXPWorkflowContext, AXPWorkflow } from '@acorex/platform/workflow';
15
15
  import * as i4 from '@acorex/components/toast';
@@ -559,6 +559,32 @@ declare class AXPGlobalErrorHandler extends ErrorHandler {
559
559
  static ɵprov: i0.ɵɵInjectableDeclaration<AXPGlobalErrorHandler>;
560
560
  }
561
561
 
562
+ /** Thrown when a requested platform resource cannot be resolved. */
563
+ declare class AXPNotFoundError extends Error {
564
+ constructor(message?: string);
565
+ }
566
+
567
+ /** Canonical route path for the platform 404 page. */
568
+ declare const AXP_NOT_FOUND_ROUTE = "/error/404";
569
+ /**
570
+ * Catch-all route that redirects unknown URLs to the platform 404 page.
571
+ * Register this as the **last** route source in the application (after all app and module routes).
572
+ */
573
+ declare const AXP_NOT_FOUND_CATCH_ALL_ROUTE: Route;
574
+ /**
575
+ * Registers the platform catch-all 404 route.
576
+ * Must be the last `ROUTES` provider in `app.config` so custom app routes are matched first.
577
+ */
578
+ declare function AXPNotFoundCatchAllRoute(): EnvironmentProviders;
579
+ /**
580
+ * Returns true when an entity byKey query did not resolve a record.
581
+ */
582
+ declare function axpIsEntityRecordNotFound(data: unknown): boolean;
583
+ /**
584
+ * Creates an Angular redirect command to the platform 404 page.
585
+ */
586
+ declare function axpRedirectToNotFound(router?: Router): RedirectCommand;
587
+
562
588
  interface AXPCommonModuleConfigs {
563
589
  errorHandlers: (new () => AXPErrorHandler)[];
564
590
  }
@@ -570,7 +596,7 @@ declare class AXPCommonModule {
570
596
  */
571
597
  constructor(instances: any[]);
572
598
  static ɵfac: i0.ɵɵFactoryDeclaration<AXPCommonModule, never>;
573
- static ɵmod: i0.ɵɵNgModuleDeclaration<AXPCommonModule, never, [typeof i1.AXPWorkflowModule, typeof i2.AXPopupModule, typeof i3.AXDateTimeModule, typeof i4.AXToastModule, typeof i5.AXPModuleManifestModule], [typeof i6.RouterModule]>;
599
+ static ɵmod: i0.ɵɵNgModuleDeclaration<AXPCommonModule, never, [typeof i1.AXPWorkflowModule, typeof i2.AXPopupModule, typeof i3.AXDateTimeModule, typeof i4.AXToastModule, typeof i5.AXPModuleManifestModule], [typeof _angular_router.RouterModule]>;
574
600
  static ɵinj: i0.ɵɵInjectorDeclaration<AXPCommonModule>;
575
601
  }
576
602
 
@@ -1573,6 +1599,56 @@ declare class AXPMenuVisibilityService {
1573
1599
  static ɵprov: i0.ɵɵInjectableDeclaration<AXPMenuVisibilityService>;
1574
1600
  }
1575
1601
 
1602
+ interface AXPMenuRouteMatchResult {
1603
+ item: AXPMenuItem;
1604
+ isPartialMatch: boolean;
1605
+ }
1606
+ /**
1607
+ * Compares a menu item path with the current browser path.
1608
+ * Mirrors the matching rules used when selecting the active menu item.
1609
+ */
1610
+ declare function axpMenuPathsMatch(itemPath: string, currentPath: string, trailingSegmentsToIgnore?: string[]): {
1611
+ isMatch: boolean;
1612
+ isPartial: boolean;
1613
+ };
1614
+ /**
1615
+ * Finds the most specific menu item that matches the given route path.
1616
+ */
1617
+ declare function axpFindMenuItemByRoute(items: AXPMenuItem[], currentPath: string, trailingSegmentsToIgnore?: string[]): AXPMenuRouteMatchResult | null;
1618
+
1619
+ /**
1620
+ * Resolves route access using the same permission and feature policies defined on menu items.
1621
+ */
1622
+ declare class AXPMenuRoutePermissionService {
1623
+ private readonly menuProvider;
1624
+ private readonly menuVisibility;
1625
+ private readonly sessionService;
1626
+ private readonly toastService;
1627
+ private readonly translationService;
1628
+ /**
1629
+ * Checks whether navigation to the target URL is allowed for the current user.
1630
+ */
1631
+ canAccess(route: ActivatedRouteSnapshot, url: string): Promise<boolean>;
1632
+ private shouldSkip;
1633
+ private hasRouteFlag;
1634
+ private hasExplicitRouteAccess;
1635
+ private getInheritedRouteData;
1636
+ private normalizeKeys;
1637
+ private normalizeUrl;
1638
+ private showAccessDeniedToast;
1639
+ static ɵfac: i0.ɵɵFactoryDeclaration<AXPMenuRoutePermissionService, never>;
1640
+ static ɵprov: i0.ɵɵInjectableDeclaration<AXPMenuRoutePermissionService>;
1641
+ }
1642
+
1643
+ /**
1644
+ * Blocks navigation when the target route matches a menu item the current user cannot access.
1645
+ * Uses the same permission and feature policies applied to menu visibility.
1646
+ */
1647
+ declare const AXPMenuPermissionGuard: CanActivateFn;
1648
+
1649
+ /** Standard guards for authenticated routes with menu-based permission enforcement. */
1650
+ declare const AXP_PROTECTED_ROUTE_GUARDS: readonly [_angular_router.CanActivateFn, _angular_router.CanActivateFn];
1651
+
1576
1652
  interface AXPSearchDefinitionDisplayFormat {
1577
1653
  title?: string;
1578
1654
  description?: string;
@@ -2734,5 +2810,5 @@ declare class AXMWorkflowErrorHandler implements AXPErrorHandler {
2734
2810
  static ɵprov: i0.ɵɵInjectableDeclaration<AXMWorkflowErrorHandler>;
2735
2811
  }
2736
2812
 
2737
- 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, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateWorkflow, 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_PLATFORM_CONFIG_TOKEN, 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, configPlatform, createAllQueryView, createMenuContext, createMenuMiddleware, createQueryView, findManualPresetIdByOperation, getEntityInfo, getStatusInfo, getSystemStatus, provideDynamicHomePage, provideMenuMiddleware, resolveDateFilterPresets, resolveStatusLook, systemStatusToDefinition };
2738
- export type { AXCFileUploaderAction, AXCFileUploaderActionsPayload, AXCFileUploaderCapabilities, AXEntityPropertyWidget, AXPAggregate, AXPAppVersion, AXPAppVersionProvider, AXPApplication, AXPCategoryEntity, AXPColumnAlign, AXPColumnContentAlign, AXPCommandActionCallback, AXPCommandActionDisplay, AXPCommandActionLook, AXPCommandActionPriority, AXPCommandActionType, AXPCommonModuleConfigs, AXPCurrency, AXPDateTimeFilterPreset, AXPDateTimeFilterPresetKind, AXPDateTimeFilterValue, AXPDomToImageOptions, AXPEntity, AXPEntityAction, AXPEntityCommand, AXPEntityDetailListView, AXPEntityMasterCreateLayoutView, AXPEntityMasterLayoutView, AXPEntityMasterListView, AXPEntityMasterSingleLayoutView, AXPEntityMasterUpdateLayoutView, AXPEntityProperty, AXPEntityPropertyCreateView, AXPEntityPropertyGroup, AXPEntityPropertyLayoutConfig, AXPEntityPropertyUpdateView, AXPEntityPropertyView, AXPEntityQuery, AXPEntitySectionView, AXPEntityTableColumn, AXPEntityVersionHistory, AXPErrorHandler, AXPFileActionProvider, AXPFileActionProviderToken, AXPFileExtension, AXPFileManyStorageInfo, AXPFileStorageCreateRequest, AXPFileStorageFindRequest, AXPFileStorageInfo, AXPFileStorageUpdateRequest, AXPFileType, AXPFileTypeInfoProvider, AXPFilterOperator, AXPGeoLocation, AXPGroupSearchResult, AXPHomePageDefinition, AXPLanguage, AXPLocaleProfile, AXPLockGetInfoRequest, AXPLockInfo, AXPLockRequest, AXPLockType, AXPMenuFinderResult, AXPMenuInsertion, AXPMenuItem, AXPMenuItemCommand, AXPMenuItemFinder, AXPMenuItemWithParent, AXPMenuMiddleware, AXPMenuMiddlewareContext, AXPMenuMiddlewareProvider, AXPMenuProvider, AXPMenuProviderContext, AXPMenuType, AXPModule, AXPPlatformConfigs, AXPQueryFilter, AXPQuerySort, AXPQueryView, AXPRelatedEntity, AXPRelationship, AXPRootConfigs, AXPSearchAction, AXPSearchDefinition, AXPSearchDefinitionDisplayFormat, AXPSearchDefinitionProvider, AXPSearchDisplayGroupResult, AXPSearchDisplayResult, AXPSearchDisplayResultForSave, AXPSearchParentResult, AXPSearchProvider, AXPSearchResult, AXPSettingChangedEvent, AXPSettingDefaultValuesProvider, AXPSettingDefinition, AXPSettingDefinitionGroup, AXPSettingDefinitionProvider, AXPSettingDefinitionSection, AXPSettingValue, AXPSettingValueProvider, AXPSettingsServiceInterface, AXPStatusDefinition, AXPStatusTransition, AXPTimeZone, AXPTokenDefinition, AXPTokenDefinitionProvider, AXPTokenDefinitionProviderToken, AXPUnLockRequest, AXPVersionChange, AXPVersionEntry, AXPVersionStream, CanonicalChange, CanonicalChangeOp, VersionedFileInfo };
2813
+ 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 };
2814
+ export type { AXCFileUploaderAction, AXCFileUploaderActionsPayload, AXCFileUploaderCapabilities, AXEntityPropertyWidget, AXPAggregate, AXPAppVersion, AXPAppVersionProvider, AXPApplication, AXPCategoryEntity, AXPColumnAlign, AXPColumnContentAlign, AXPCommandActionCallback, AXPCommandActionDisplay, AXPCommandActionLook, AXPCommandActionPriority, AXPCommandActionType, AXPCommonModuleConfigs, AXPCurrency, AXPDateTimeFilterPreset, AXPDateTimeFilterPresetKind, AXPDateTimeFilterValue, AXPDomToImageOptions, AXPEntity, AXPEntityAction, AXPEntityCommand, AXPEntityDetailListView, AXPEntityMasterCreateLayoutView, AXPEntityMasterLayoutView, AXPEntityMasterListView, AXPEntityMasterSingleLayoutView, AXPEntityMasterUpdateLayoutView, AXPEntityProperty, AXPEntityPropertyCreateView, AXPEntityPropertyGroup, AXPEntityPropertyLayoutConfig, AXPEntityPropertyUpdateView, AXPEntityPropertyView, AXPEntityQuery, AXPEntitySectionView, AXPEntityTableColumn, AXPEntityVersionHistory, AXPErrorHandler, AXPFileActionProvider, AXPFileActionProviderToken, AXPFileExtension, AXPFileManyStorageInfo, AXPFileStorageCreateRequest, AXPFileStorageFindRequest, AXPFileStorageInfo, AXPFileStorageUpdateRequest, AXPFileType, AXPFileTypeInfoProvider, AXPFilterOperator, AXPGeoLocation, AXPGroupSearchResult, AXPHomePageDefinition, AXPLanguage, AXPLocaleProfile, AXPLockGetInfoRequest, AXPLockInfo, AXPLockRequest, AXPLockType, AXPMenuFinderResult, AXPMenuInsertion, AXPMenuItem, AXPMenuItemCommand, AXPMenuItemFinder, AXPMenuItemWithParent, AXPMenuMiddleware, AXPMenuMiddlewareContext, AXPMenuMiddlewareProvider, AXPMenuProvider, AXPMenuProviderContext, AXPMenuRouteMatchResult, AXPMenuType, AXPModule, AXPPlatformConfigs, AXPQueryFilter, AXPQuerySort, AXPQueryView, AXPRelatedEntity, AXPRelationship, AXPRootConfigs, AXPSearchAction, AXPSearchDefinition, AXPSearchDefinitionDisplayFormat, AXPSearchDefinitionProvider, AXPSearchDisplayGroupResult, AXPSearchDisplayResult, AXPSearchDisplayResultForSave, AXPSearchParentResult, AXPSearchProvider, AXPSearchResult, AXPSettingChangedEvent, AXPSettingDefaultValuesProvider, AXPSettingDefinition, AXPSettingDefinitionGroup, AXPSettingDefinitionProvider, AXPSettingDefinitionSection, AXPSettingValue, AXPSettingValueProvider, AXPSettingsServiceInterface, AXPStatusDefinition, AXPStatusTransition, AXPTimeZone, AXPTokenDefinition, AXPTokenDefinitionProvider, AXPTokenDefinitionProviderToken, AXPUnLockRequest, AXPVersionChange, AXPVersionEntry, AXPVersionStream, CanonicalChange, CanonicalChangeOp, VersionedFileInfo };
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, Injectable, Injector, makeEnvironmentProviders, NgModule, ErrorHandler, EventEmitter, Input, Output, Directive, Component, ViewEncapsulation, Inject, runInInjectionContext, signal, model, linkedSignal, afterNextRender } from '@angular/core';
3
3
  import { kebabCase, merge, sortBy, cloneDeep, get, omit } from 'lodash-es';
4
- import { Router, ROUTES, RouterModule } from '@angular/router';
5
- import { AXPSessionService, AXPSessionStatus } from '@acorex/platform/auth';
6
- import { Subject, distinctUntilChanged, merge as merge$1 } from 'rxjs';
4
+ import { Router, ROUTES, RedirectCommand, RouterModule } from '@angular/router';
5
+ import { AXPSessionService, AXPSessionStatus, AXPAuthGuard } from '@acorex/platform/auth';
6
+ import { Subject, distinctUntilChanged, merge as merge$1, first, switchMap, from } 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';
@@ -1270,6 +1270,50 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
1270
1270
  args: [{ providedIn: 'root' }]
1271
1271
  }], ctorParameters: () => [{ type: i0.Injector }, { type: AXPErrorHandlerRegistryService }] });
1272
1272
 
1273
+ /** Thrown when a requested platform resource cannot be resolved. */
1274
+ class AXPNotFoundError extends Error {
1275
+ constructor(message = 'Resource not found') {
1276
+ super(message);
1277
+ this.name = 'AXPNotFoundError';
1278
+ }
1279
+ }
1280
+
1281
+ /** Canonical route path for the platform 404 page. */
1282
+ const AXP_NOT_FOUND_ROUTE = '/error/404';
1283
+ /**
1284
+ * Catch-all route that redirects unknown URLs to the platform 404 page.
1285
+ * Register this as the **last** route source in the application (after all app and module routes).
1286
+ */
1287
+ const AXP_NOT_FOUND_CATCH_ALL_ROUTE = {
1288
+ path: '**',
1289
+ redirectTo: AXP_NOT_FOUND_ROUTE,
1290
+ };
1291
+ /**
1292
+ * Registers the platform catch-all 404 route.
1293
+ * Must be the last `ROUTES` provider in `app.config` so custom app routes are matched first.
1294
+ */
1295
+ function AXPNotFoundCatchAllRoute() {
1296
+ return makeEnvironmentProviders([
1297
+ {
1298
+ provide: ROUTES,
1299
+ multi: true,
1300
+ useValue: [AXP_NOT_FOUND_CATCH_ALL_ROUTE],
1301
+ },
1302
+ ]);
1303
+ }
1304
+ /**
1305
+ * Returns true when an entity byKey query did not resolve a record.
1306
+ */
1307
+ function axpIsEntityRecordNotFound(data) {
1308
+ return data == null;
1309
+ }
1310
+ /**
1311
+ * Creates an Angular redirect command to the platform 404 page.
1312
+ */
1313
+ function axpRedirectToNotFound(router = inject(Router)) {
1314
+ return new RedirectCommand(router.parseUrl(AXP_NOT_FOUND_ROUTE));
1315
+ }
1316
+
1273
1317
  const AXP_TOKEN_DEFINITION_PROVIDER = new InjectionToken('AXP_TOKEN_DEFINITION_PROVIDER', {
1274
1318
  factory: () => [],
1275
1319
  });
@@ -2291,6 +2335,95 @@ function createMenuMiddleware(config) {
2291
2335
  }
2292
2336
  //#endregion
2293
2337
 
2338
+ const DEFAULT_TRAILING_SEGMENTS = ['list', 'view', 'edit', 'create'];
2339
+ /**
2340
+ * Compares a menu item path with the current browser path.
2341
+ * Mirrors the matching rules used when selecting the active menu item.
2342
+ */
2343
+ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEFAULT_TRAILING_SEGMENTS) {
2344
+ const itemNoHash = itemPath.split('#')[0];
2345
+ const currentNoHash = currentPath.split('#')[0];
2346
+ const [itemBase, itemQueryString = ''] = itemNoHash.split('?');
2347
+ const [currentBase, currentQueryString = ''] = currentNoHash.split('?');
2348
+ const itemSegments = itemBase.split('/').filter((segment) => segment.length > 0);
2349
+ const pathSegments = currentBase.split('/').filter((segment) => segment.length > 0);
2350
+ const menuLength = itemSegments.length;
2351
+ const pathLength = pathSegments.length;
2352
+ let effectiveMenuLength = menuLength;
2353
+ if (menuLength > 0 && trailingSegmentsToIgnore.includes(itemSegments[menuLength - 1])) {
2354
+ effectiveMenuLength--;
2355
+ }
2356
+ if (pathLength < effectiveMenuLength) {
2357
+ return { isMatch: false, isPartial: false };
2358
+ }
2359
+ let isPrefix = true;
2360
+ for (let i = 0; i < effectiveMenuLength; i++) {
2361
+ if (itemSegments[i] !== pathSegments[i]) {
2362
+ isPrefix = false;
2363
+ break;
2364
+ }
2365
+ }
2366
+ if (!isPrefix) {
2367
+ return { isMatch: false, isPartial: false };
2368
+ }
2369
+ const isPartialMatch = effectiveMenuLength < pathLength;
2370
+ const isExactMatch = effectiveMenuLength === pathLength;
2371
+ const itemParams = new URLSearchParams(itemQueryString);
2372
+ const currentParams = new URLSearchParams(currentQueryString);
2373
+ let queryMatches = true;
2374
+ const itemParamPairs = [];
2375
+ itemParams.forEach((value, key) => {
2376
+ itemParamPairs.push([key, value]);
2377
+ });
2378
+ if (itemParamPairs.length > 0) {
2379
+ for (const [key, value] of itemParamPairs) {
2380
+ if (currentParams.get(key) !== value) {
2381
+ queryMatches = false;
2382
+ break;
2383
+ }
2384
+ }
2385
+ }
2386
+ return {
2387
+ isMatch: (isExactMatch || isPartialMatch) && queryMatches,
2388
+ isPartial: isPartialMatch && !isExactMatch,
2389
+ };
2390
+ }
2391
+ /**
2392
+ * Finds the most specific menu item that matches the given route path.
2393
+ */
2394
+ function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = DEFAULT_TRAILING_SEGMENTS) {
2395
+ let bestMatch = null;
2396
+ let bestEffectiveLength = -1;
2397
+ const visit = (menuItems) => {
2398
+ for (const item of menuItems) {
2399
+ if (item.children?.length) {
2400
+ visit(item.children);
2401
+ }
2402
+ if (!item.path) {
2403
+ continue;
2404
+ }
2405
+ const matchResult = axpMenuPathsMatch(item.path, currentPath, trailingSegmentsToIgnore);
2406
+ if (!matchResult.isMatch) {
2407
+ continue;
2408
+ }
2409
+ const itemNoHash = item.path.split('#')[0];
2410
+ const [itemBase] = itemNoHash.split('?');
2411
+ const itemSegments = itemBase.split('/').filter((segment) => segment.length > 0);
2412
+ let effectiveMenuLength = itemSegments.length;
2413
+ if (itemSegments.length > 0 &&
2414
+ trailingSegmentsToIgnore.includes(itemSegments[itemSegments.length - 1])) {
2415
+ effectiveMenuLength--;
2416
+ }
2417
+ if (effectiveMenuLength > bestEffectiveLength) {
2418
+ bestEffectiveLength = effectiveMenuLength;
2419
+ bestMatch = { item, isPartialMatch: matchResult.isPartial };
2420
+ }
2421
+ }
2422
+ };
2423
+ visit(items);
2424
+ return bestMatch;
2425
+ }
2426
+
2294
2427
  const AXPMenuService = signalStore({ providedIn: 'root' },
2295
2428
  // Initial State
2296
2429
  withState((router = inject(Router)) => {
@@ -2321,7 +2454,7 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
2321
2454
  }
2322
2455
  if (item.path) {
2323
2456
  // Check if the item path matches the current path (including query param subset if provided on item)
2324
- const matchResult = pathsMatch(item.path, currentRawPath, ['list', 'view', 'edit', 'create']);
2457
+ const matchResult = axpMenuPathsMatch(item.path, currentRawPath, ['list', 'view', 'edit', 'create']);
2325
2458
  if (matchResult.isMatch) {
2326
2459
  return { item, isPartialMatch: matchResult.isPartial };
2327
2460
  }
@@ -2329,60 +2462,6 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
2329
2462
  }
2330
2463
  return { item: null, isPartialMatch: false };
2331
2464
  };
2332
- const pathsMatch = (itemPath, currentPath, trailingSegmentsToIgnore = []) => {
2333
- // Split base and query/hash
2334
- const itemNoHash = itemPath.split('#')[0];
2335
- const currentNoHash = currentPath.split('#')[0];
2336
- const [itemBase, itemQueryString = ''] = itemNoHash.split('?');
2337
- const [currentBase, currentQueryString = ''] = currentNoHash.split('?');
2338
- const itemSegments = itemBase.split('/').filter((segment) => segment.length > 0);
2339
- const pathSegments = currentBase.split('/').filter((segment) => segment.length > 0);
2340
- const menuLength = itemSegments.length;
2341
- const pathLength = pathSegments.length;
2342
- // Identify the effective base length for the menuPath
2343
- let effectiveMenuLength = menuLength;
2344
- if (menuLength > 0 && trailingSegmentsToIgnore.includes(itemSegments[menuLength - 1])) {
2345
- effectiveMenuLength--; // Exclude trailing non-hierarchical segments
2346
- }
2347
- // Check if the menuPath (base segments) is a prefix of browserPath
2348
- let isPrefix = true;
2349
- if (pathLength < effectiveMenuLength) {
2350
- return { isMatch: false, isPartial: false };
2351
- }
2352
- for (let i = 0; i < effectiveMenuLength; i++) {
2353
- if (itemSegments[i] !== pathSegments[i]) {
2354
- isPrefix = false;
2355
- break;
2356
- }
2357
- }
2358
- if (!isPrefix) {
2359
- return { isMatch: false, isPartial: false };
2360
- }
2361
- // Partial match: menuPath base is a strict prefix of browserPath
2362
- const isPartialMatch = effectiveMenuLength < pathLength;
2363
- // Exact match: all segments match completely
2364
- const isExactMatch = effectiveMenuLength === pathLength;
2365
- // Query params subset match: if item defines any query params, require them to match
2366
- const itemParams = new URLSearchParams(itemQueryString);
2367
- const currentParams = new URLSearchParams(currentQueryString);
2368
- let queryMatches = true;
2369
- const itemParamPairs = [];
2370
- itemParams.forEach((value, key) => {
2371
- itemParamPairs.push([key, value]);
2372
- });
2373
- if (itemParamPairs.length > 0) {
2374
- for (const [k, v] of itemParamPairs) {
2375
- if (currentParams.get(k) !== v) {
2376
- queryMatches = false;
2377
- break;
2378
- }
2379
- }
2380
- }
2381
- return {
2382
- isMatch: (isExactMatch || isPartialMatch) && queryMatches,
2383
- isPartial: isPartialMatch && !isExactMatch,
2384
- };
2385
- };
2386
2465
  const items = store.items();
2387
2466
  const { item, isPartialMatch } = findItem(items);
2388
2467
  patchState(store, { selectedMenuItem: { item, isFullMatch: !isPartialMatch } });
@@ -2542,6 +2621,137 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImpo
2542
2621
  args: [{ providedIn: 'root' }]
2543
2622
  }] });
2544
2623
 
2624
+ const SKIP_ROUTE_PREFIXES = ['/auth', '/error'];
2625
+ const SKIP_ROUTE_PATHS = new Set(['/404', '/401']);
2626
+ //#region ---- Menu Route Permission Service ----
2627
+ /**
2628
+ * Resolves route access using the same permission and feature policies defined on menu items.
2629
+ */
2630
+ class AXPMenuRoutePermissionService {
2631
+ constructor() {
2632
+ //#region ---- Services & Dependencies ----
2633
+ this.menuProvider = inject(AXPMenuProviderService);
2634
+ this.menuVisibility = inject(AXPMenuVisibilityService);
2635
+ this.sessionService = inject(AXPSessionService);
2636
+ this.toastService = inject(AXToastService);
2637
+ this.translationService = inject(AXTranslationService);
2638
+ }
2639
+ //#endregion
2640
+ //#region ---- Public Methods ----
2641
+ /**
2642
+ * Checks whether navigation to the target URL is allowed for the current user.
2643
+ */
2644
+ async canAccess(route, url) {
2645
+ if (this.shouldSkip(route, url)) {
2646
+ return true;
2647
+ }
2648
+ if (!this.hasExplicitRouteAccess(route)) {
2649
+ await this.showAccessDeniedToast();
2650
+ return false;
2651
+ }
2652
+ const menuItems = await this.menuProvider.items();
2653
+ const menuMatch = axpFindMenuItemByRoute(menuItems, url);
2654
+ if (!menuMatch) {
2655
+ return true;
2656
+ }
2657
+ if (this.menuVisibility.isItemVisible(menuMatch.item)) {
2658
+ return true;
2659
+ }
2660
+ await this.showAccessDeniedToast();
2661
+ return false;
2662
+ }
2663
+ //#endregion
2664
+ //#region ---- Utility Methods ----
2665
+ shouldSkip(route, url) {
2666
+ if (this.hasRouteFlag(route, 'skipMenuPermissionGuard')) {
2667
+ return true;
2668
+ }
2669
+ const normalizedUrl = this.normalizeUrl(url);
2670
+ if (SKIP_ROUTE_PATHS.has(normalizedUrl)) {
2671
+ return true;
2672
+ }
2673
+ return SKIP_ROUTE_PREFIXES.some((prefix) => normalizedUrl.startsWith(prefix));
2674
+ }
2675
+ hasRouteFlag(route, key) {
2676
+ let current = route;
2677
+ while (current) {
2678
+ if (current.data?.[key] === true) {
2679
+ return true;
2680
+ }
2681
+ current = current.parent;
2682
+ }
2683
+ return false;
2684
+ }
2685
+ hasExplicitRouteAccess(route) {
2686
+ const requiredPermission = this.getInheritedRouteData(route, 'requiredPermission');
2687
+ const requiredFeature = this.getInheritedRouteData(route, 'requiredFeature');
2688
+ const permissionKeys = this.normalizeKeys(requiredPermission);
2689
+ if (permissionKeys.length > 0 && !this.sessionService.authorize(...permissionKeys)) {
2690
+ return false;
2691
+ }
2692
+ const featureKeys = this.normalizeKeys(requiredFeature);
2693
+ if (featureKeys.length > 0 && !this.sessionService.isFeatureEnabled(...featureKeys)) {
2694
+ return false;
2695
+ }
2696
+ return true;
2697
+ }
2698
+ getInheritedRouteData(route, key) {
2699
+ let current = route;
2700
+ while (current) {
2701
+ const value = current.data?.[key];
2702
+ if (value != null) {
2703
+ return value;
2704
+ }
2705
+ current = current.parent;
2706
+ }
2707
+ return null;
2708
+ }
2709
+ normalizeKeys(keys) {
2710
+ if (!keys) {
2711
+ return [];
2712
+ }
2713
+ return Array.isArray(keys) ? keys : [keys];
2714
+ }
2715
+ normalizeUrl(url) {
2716
+ const path = url.split('?')[0]?.split('#')[0] ?? url;
2717
+ return path.startsWith('/') ? path : `/${path}`;
2718
+ }
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' }); }
2731
+ }
2732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: AXPMenuRoutePermissionService, decorators: [{
2733
+ type: Injectable,
2734
+ args: [{ providedIn: 'root' }]
2735
+ }] });
2736
+
2737
+ /**
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.
2740
+ */
2741
+ const AXPMenuPermissionGuard = (route, state) => {
2742
+ 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));
2747
+ }
2748
+ return from(menuRoutePermissionService.canAccess(route, state.url));
2749
+ }));
2750
+ };
2751
+
2752
+ /** Standard guards for authenticated routes with menu-based permission enforcement. */
2753
+ const AXP_PROTECTED_ROUTE_GUARDS = [AXPAuthGuard, AXPMenuPermissionGuard];
2754
+
2545
2755
  class AXPMenuSearchDefinitionProvider {
2546
2756
  async provide(context) {
2547
2757
  context.addDefinition('menu', 'Menu', 'menu', 'fa-thin fa-bars', 2, {
@@ -4388,5 +4598,5 @@ class AXPVersioningService {
4388
4598
  * Generated bundle index. Do not edit.
4389
4599
  */
4390
4600
 
4391
- 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, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateWorkflow, 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_PLATFORM_CONFIG_TOKEN, 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, configPlatform, createAllQueryView, createMenuContext, createMenuMiddleware, createQueryView, findManualPresetIdByOperation, getEntityInfo, getStatusInfo, getSystemStatus, provideDynamicHomePage, provideMenuMiddleware, resolveDateFilterPresets, resolveStatusLook, systemStatusToDefinition };
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 };
4392
4602
  //# sourceMappingURL=acorex-platform-common.mjs.map