@solcre-org/core-ui 2.16.2 → 2.16.3

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.
@@ -5965,11 +5965,30 @@ class GenericButtonComponent {
5965
5965
  return true;
5966
5966
  if (this.config().requiredPermission) {
5967
5967
  const perm = this.config().requiredPermission;
5968
- const hasPermission = this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
5968
+ const hasPermission = this.checkRequiredPermission(perm);
5969
5969
  return !hasPermission;
5970
5970
  }
5971
5971
  return false;
5972
5972
  });
5973
+ checkRequiredPermission(perm) {
5974
+ if (perm.custom_action && perm.action) {
5975
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
5976
+ }
5977
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
5978
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
5979
+ if (resources.length === 0 && actions.length === 0) {
5980
+ return true;
5981
+ }
5982
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
5983
+ for (const resource of resourcesToCheck) {
5984
+ for (const action of actions) {
5985
+ if (this.permissionService.hasPermission(resource, action)) {
5986
+ return true;
5987
+ }
5988
+ }
5989
+ }
5990
+ return false;
5991
+ }
5973
5992
  buttonClasses = computed(() => {
5974
5993
  const config = this.config();
5975
5994
  const classes = [];
@@ -10269,7 +10288,26 @@ class DropdownComponent {
10269
10288
  hasPermission(action) {
10270
10289
  if (!action.requiredPermission)
10271
10290
  return true;
10272
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action);
10291
+ return this.checkRequiredPermission(action.requiredPermission);
10292
+ }
10293
+ checkRequiredPermission(perm) {
10294
+ if (perm.custom_action && perm.action) {
10295
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
10296
+ }
10297
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
10298
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
10299
+ if (resources.length === 0 && actions.length === 0) {
10300
+ return true;
10301
+ }
10302
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
10303
+ for (const resource of resourcesToCheck) {
10304
+ for (const actionItem of actions) {
10305
+ if (this.permissionService.hasPermission(resource, actionItem)) {
10306
+ return true;
10307
+ }
10308
+ }
10309
+ }
10310
+ return false;
10273
10311
  }
10274
10312
  shouldShowAction(actionConfig) {
10275
10313
  const currentRow = this.row();
@@ -12492,7 +12530,7 @@ class FixedActionsMobileModalComponent {
12492
12530
  });
12493
12531
  shouldShowAction(action) {
12494
12532
  if (action.requiredPermission) {
12495
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
12533
+ const hasPermission = this.checkRequiredPermission(action.requiredPermission);
12496
12534
  if (!hasPermission)
12497
12535
  return false;
12498
12536
  }
@@ -12501,7 +12539,7 @@ class FixedActionsMobileModalComponent {
12501
12539
  return action.shouldShow(data.data);
12502
12540
  }
12503
12541
  if (action.customAction?.requiredPermission) {
12504
- const hasPermission = this.permissionService.hasPermission(action.customAction.requiredPermission.resource, action.customAction.requiredPermission.action, action.customAction.requiredPermission.custom_action);
12542
+ const hasPermission = this.checkRequiredPermission(action.customAction.requiredPermission);
12505
12543
  if (!hasPermission)
12506
12544
  return false;
12507
12545
  }
@@ -12509,7 +12547,7 @@ class FixedActionsMobileModalComponent {
12509
12547
  return action.customAction.shouldShow(data.data);
12510
12548
  }
12511
12549
  if (action.globalAction?.requiredPermission) {
12512
- const hasPermission = this.permissionService.hasPermission(action.globalAction.requiredPermission.resource, action.globalAction.requiredPermission.action, action.globalAction.requiredPermission.custom_action);
12550
+ const hasPermission = this.checkRequiredPermission(action.globalAction.requiredPermission);
12513
12551
  if (!hasPermission)
12514
12552
  return false;
12515
12553
  }
@@ -12557,6 +12595,25 @@ class FixedActionsMobileModalComponent {
12557
12595
  this.onClose();
12558
12596
  }
12559
12597
  }
12598
+ checkRequiredPermission(perm) {
12599
+ if (perm.custom_action && perm.action) {
12600
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
12601
+ }
12602
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
12603
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
12604
+ if (resources.length === 0 && actions.length === 0) {
12605
+ return true;
12606
+ }
12607
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
12608
+ for (const resource of resourcesToCheck) {
12609
+ for (const action of actions) {
12610
+ if (this.permissionService.hasPermission(resource, action)) {
12611
+ return true;
12612
+ }
12613
+ }
12614
+ }
12615
+ return false;
12616
+ }
12560
12617
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: FixedActionsMobileModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12561
12618
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: FixedActionsMobileModalComponent, isStandalone: true, selector: "core-fixed-actions-mobile-modal", ngImport: i0, template: "@if (isVisible()) {\n <div class=\"c-services-chat c-modal is-visible\">\n <div class=\"c-modal__overlay\" (click)=\"onOverlayClick($event)\"></div>\n <div class=\"c-modal__holder\">\n <div class=\"c-modal__header\">\n @if (modalData()?.title || modalData()?.subtitle) {\n <p class=\"c-modal__title\">\n {{ modalData()?.title }}\n @if (modalData()?.subtitle) {\n <br>\n <small>{{ modalData()?.subtitle }}</small>\n }\n </p>\n }\n <button \n type=\"button\" \n class=\"c-icon-btn c-modal__close\" \n aria-label=\"Cerrar\" \n title=\"Cerrar\"\n (click)=\"onClose()\">\n <span class=\"icon-cross-thin\"></span>\n </button>\n </div>\n <div class=\"c-modal__body\">\n <nav class=\"c-mobile-nav\">\n <ul>\n @for (action of visibleActions(); track $index) {\n <li class=\"c-mobile-nav__item\">\n <a \n class=\"c-mobile-nav__link\" \n [class.is-disabled]=\"isActionDisabled(action)\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n href=\"javascript:void(0)\"\n (click)=\"onActionClick(action)\">\n @if (getActionIcon(action)) {\n <span [ngClass]=\"getActionIcon(action) | coreIconCompat\"></span>\n }\n {{ getActionLabel(action) | translate }}\n </a>\n </li>\n }\n </ul>\n </nav>\n </div>\n </div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: IconCompatPipe, name: "coreIconCompat" }] });
12562
12619
  }
@@ -12834,8 +12891,7 @@ class GenericTableComponent {
12834
12891
  const modalActions = [];
12835
12892
  const createAction = this.actions().find(a => a.action === TableAction.CREATE);
12836
12893
  if (createAction && createAction.mobileConfig?.showInsideModal !== false && !this.getMobileShowInHeader(createAction) && !this.getMobileShowOutsideFixedActions(createAction)) {
12837
- if (!createAction.requiredPermission ||
12838
- this.permissionService.hasPermission(createAction.requiredPermission.resource, createAction.requiredPermission.action, createAction.requiredPermission.custom_action)) {
12894
+ if (!createAction.requiredPermission || this.checkRequiredPermission(createAction.requiredPermission)) {
12839
12895
  modalActions.push({
12840
12896
  icon: createAction.icon || this.getDefaultIconForAction(TableAction.CREATE),
12841
12897
  label: this.getActionLabel(TableAction.CREATE),
@@ -13643,7 +13699,7 @@ class GenericTableComponent {
13643
13699
  }
13644
13700
  shouldShowFixedAction(action) {
13645
13701
  if (action.requiredPermission) {
13646
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
13702
+ const hasPermission = this.checkRequiredPermission(action.requiredPermission);
13647
13703
  if (!hasPermission)
13648
13704
  return false;
13649
13705
  }
@@ -13652,7 +13708,7 @@ class GenericTableComponent {
13652
13708
  return action.shouldShow(selectedRow);
13653
13709
  }
13654
13710
  if (action.customAction?.requiredPermission) {
13655
- const hasPermission = this.permissionService.hasPermission(action.customAction.requiredPermission.resource, action.customAction.requiredPermission.action, action.customAction.requiredPermission.custom_action);
13711
+ const hasPermission = this.checkRequiredPermission(action.customAction.requiredPermission);
13656
13712
  if (!hasPermission)
13657
13713
  return false;
13658
13714
  }
@@ -13663,7 +13719,7 @@ class GenericTableComponent {
13663
13719
  }
13664
13720
  }
13665
13721
  if (action.globalAction?.requiredPermission) {
13666
- const hasPermission = this.permissionService.hasPermission(action.globalAction.requiredPermission.resource, action.globalAction.requiredPermission.action, action.globalAction.requiredPermission.custom_action);
13722
+ const hasPermission = this.checkRequiredPermission(action.globalAction.requiredPermission);
13667
13723
  if (!hasPermission)
13668
13724
  return false;
13669
13725
  }
@@ -13902,7 +13958,26 @@ class GenericTableComponent {
13902
13958
  hasPermission(action) {
13903
13959
  if (!action.requiredPermission)
13904
13960
  return true;
13905
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
13961
+ return this.checkRequiredPermission(action.requiredPermission);
13962
+ }
13963
+ checkRequiredPermission(perm) {
13964
+ if (perm.custom_action && perm.action) {
13965
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
13966
+ }
13967
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
13968
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
13969
+ if (resources.length === 0 && actions.length === 0) {
13970
+ return true;
13971
+ }
13972
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
13973
+ for (const resource of resourcesToCheck) {
13974
+ for (const action of actions) {
13975
+ if (this.permissionService.hasPermission(resource, action)) {
13976
+ return true;
13977
+ }
13978
+ }
13979
+ }
13980
+ return false;
13906
13981
  }
13907
13982
  showFiltersPopup() {
13908
13983
  this.isFilterModalOpen.set(true);
@@ -16204,7 +16279,7 @@ class HeaderComponent {
16204
16279
  hasPermission(action) {
16205
16280
  if (!action.requiredPermission)
16206
16281
  return true;
16207
- const hasPermission = this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
16282
+ const hasPermission = this.checkRequiredPermission(action.requiredPermission);
16208
16283
  if (!hasPermission)
16209
16284
  return false;
16210
16285
  const isMobile = this.mobileResolutionService.isMobile();
@@ -16234,7 +16309,7 @@ class HeaderComponent {
16234
16309
  hasCustomActionPermission(action) {
16235
16310
  if (!action.requiredPermission)
16236
16311
  return true;
16237
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
16312
+ return this.checkRequiredPermission(action.requiredPermission);
16238
16313
  }
16239
16314
  isCustomActionVisible(action) {
16240
16315
  if (action.visible === false)
@@ -16279,7 +16354,26 @@ class HeaderComponent {
16279
16354
  return false;
16280
16355
  if (!action.requiredPermission)
16281
16356
  return true;
16282
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
16357
+ return this.checkRequiredPermission(action.requiredPermission);
16358
+ }
16359
+ checkRequiredPermission(perm) {
16360
+ if (perm.custom_action && perm.action) {
16361
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
16362
+ }
16363
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
16364
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
16365
+ if (resources.length === 0 && actions.length === 0) {
16366
+ return true;
16367
+ }
16368
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
16369
+ for (const resource of resourcesToCheck) {
16370
+ for (const action of actions) {
16371
+ if (this.permissionService.hasPermission(resource, action)) {
16372
+ return true;
16373
+ }
16374
+ }
16375
+ }
16376
+ return false;
16283
16377
  }
16284
16378
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: HeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16285
16379
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: HeaderComponent, isStandalone: true, selector: "core-header", outputs: { filterRequested: "filterRequested", createRequested: "createRequested", globalActionTriggered: "globalActionTriggered" }, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "@if (headerService.getIsVisible()()) {\n @if(!headerService.getHeaderOutside()()) {\n <div class=\"c-header\">\n <div class=\"c-header__row\">\n\n <div class=\"c-header__group\">\n\n <h2 class=\"c-header__heading u-heading\">{{ getHeaderTitle() }}</h2>\n\n </div>\n\n <div class=\"c-header__group u-flex\">\n\n @for (element of headerService.getOrderedElements(); track element.type + '-' + (element.actionId || $index)) {\n @if (headerService.isElementVisible(element.type, element)) {\n \n @switch (element.type) {\n @case (HeaderElementType.GLOBAL_ACTIONS) {\n @for (globalAction of headerService.getGlobalActions()(); track globalAction.label || $index) {\n @if (hasPermission(globalAction)) {\n @if (globalAction.isSwitch && globalAction.switchOptions) {\n <core-generic-switch\n [options]=\"globalAction.switchOptions\"\n [selectedValue]=\"globalAction.switchSelectedValue\"\n [ariaLabel]=\"globalAction.switchAriaLabel || globalAction.label || 'Switch options'\"\n (valueChange)=\"onGlobalSwitchChange($event, globalAction)\">\n </core-generic-switch>\n } @else {\n <core-generic-button \n [config]=\"getGlobalActionButtonConfig(globalAction)\"\n (buttonClick)=\"onGlobalButtonClick($event, globalAction)\">\n </core-generic-button>\n }\n }\n }\n }\n \n @case (HeaderElementType.CUSTOM_ACTIONS) {\n @for (customAction of headerService.getCustomActions()(); track customAction.id) {\n @if (isCustomActionVisible(customAction)) {\n <core-generic-button \n [config]=\"getCustomActionButtonConfig(customAction)\"\n (buttonClick)=\"onCustomButtonClick($event, customAction)\">\n </core-generic-button>\n }\n }\n }\n \n @case (HeaderElementType.FILTER) {\n <core-generic-button \n [config]=\"getFilterButtonConfig()\"\n (buttonClick)=\"onFilterButtonClick()\">\n </core-generic-button>\n }\n \n @case (HeaderElementType.CREATE) {\n <core-generic-button \n [config]=\"getCreateButtonConfig()\"\n (buttonClick)=\"onCreateButtonClick()\">\n </core-generic-button>\n }\n\n @case (HeaderElementType.INDIVIDUAL_ACTION) {\n @if (getIndividualAction(element); as action) {\n @if (hasIndividualActionPermission(action)) {\n @if (isIndividualActionSwitch(action)) {\n <core-generic-switch\n [options]=\"action.switchOptions\"\n [selectedValue]=\"action.switchSelectedValue\"\n [ariaLabel]=\"action.switchAriaLabel || action.label || 'Switch options'\"\n (valueChange)=\"onGlobalSwitchChange($event, action)\">\n </core-generic-switch>\n } @else if (element.actionType === 'global') {\n <core-generic-button \n [config]=\"getGlobalActionButtonConfig(action)\"\n (buttonClick)=\"onGlobalButtonClick($event, action)\">\n </core-generic-button>\n } @else if (element.actionType === 'custom') {\n <core-generic-button \n [config]=\"getCustomActionButtonConfig(action)\"\n (buttonClick)=\"onCustomButtonClick($event, action)\">\n </core-generic-button>\n }\n }\n }\n }\n }\n \n }\n }\n\n </div>\n\n </div>\n\n <p class=\"c-header__text u-text\" *ngIf=\"getHeaderText()\">\n {{ getHeaderText() }}\n </p>\n\n @if (\n headerService.isElementVisible(HeaderElementType.CUSTOM_TEMPLATE) && \n headerService.getCustomTemplate()()\n ) {\n <ng-container [ngTemplateOutlet]=\"headerService.getCustomTemplate()()\"></ng-container>\n }\n </div>\n } @else {\n @if(\n headerService.isElementVisible(HeaderElementType.CUSTOM_TEMPLATE) && \n headerService.getCustomTemplate()()\n ) {\n <ng-container [ngTemplateOutlet]=\"headerService.getCustomTemplate()()\"></ng-container>\n }\n }\n}", styles: [":root{--header-bg: #ffffff;--header-text: #333;--header-shadow: rgba(0, 0, 0, .1);--logout-btn-color: #e74c3c;--logout-btn-hover: #c0392b;--theme-btn-color: #666;--theme-btn-hover: #007bff}.dark-mode{--header-bg: #1a1a1a;--header-text: #e0e0e0;--header-shadow: rgba(255, 255, 255, .1);--logout-btn-color: #ff6b6b;--logout-btn-hover: #ff8787;--theme-btn-color: #bbb;--theme-btn-hover: #4da8ff}.header{background-color:var(--header-bg);box-shadow:0 2px 4px var(--header-shadow);padding:15px 20px;display:flex;justify-content:space-between;align-items:center}.header .user-info{font-weight:500;color:var(--header-text)}.header .header-actions{display:flex;align-items:center;gap:15px}.header .theme-toggle-btn{background:none;border:none;color:var(--theme-btn-color);font-size:16px;cursor:pointer;display:flex;align-items:center}.header .theme-toggle-btn:hover{color:var(--theme-btn-hover)}.header .logout-btn{background:none;border:none;color:var(--logout-btn-color);font-size:16px;cursor:pointer;display:flex;align-items:center}.header .logout-btn i{margin-right:5px}.header .logout-btn:hover{color:var(--logout-btn-hover)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: GenericButtonComponent, selector: "core-generic-button", inputs: ["config", "data"], outputs: ["buttonClick"] }, { kind: "component", type: GenericSwitchComponent, selector: "core-generic-switch", inputs: ["options", "selectedValue", "ariaLabel"], outputs: ["valueChange"] }] });
@@ -16451,12 +16545,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
16451
16545
  // Este archivo es generado automáticamente por scripts/update-version.js
16452
16546
  // No edites manualmente este archivo
16453
16547
  const VERSION = {
16454
- full: '2.16.2',
16548
+ full: '2.16.3',
16455
16549
  major: 2,
16456
16550
  minor: 16,
16457
- patch: 2,
16458
- timestamp: '2025-12-04T13:41:32.467Z',
16459
- buildDate: '4/12/2025'
16551
+ patch: 3,
16552
+ timestamp: '2025-12-05T15:12:25.862Z',
16553
+ buildDate: '5/12/2025'
16460
16554
  };
16461
16555
 
16462
16556
  class MainNavComponent {
@@ -16598,7 +16692,27 @@ class MainNavComponent {
16598
16692
  return true;
16599
16693
  }
16600
16694
  try {
16601
- return this.permissionService.hasPermission(item.requiredPermission.resource, item.requiredPermission.action, item.requiredPermission.custom_action);
16695
+ const perm = item.requiredPermission;
16696
+ const matchMode = perm.match || 'any';
16697
+ const resources = perm.resources?.length
16698
+ ? perm.resources
16699
+ : [perm.resource];
16700
+ const actions = perm.actions?.length
16701
+ ? perm.actions
16702
+ : (perm.action ? [perm.action] : []);
16703
+ if (actions.length === 0) {
16704
+ return true;
16705
+ }
16706
+ const permissionChecks = [];
16707
+ for (const resource of resources) {
16708
+ for (const action of actions) {
16709
+ permissionChecks.push(this.permissionService.hasPermission(resource, action, perm.custom_action));
16710
+ }
16711
+ }
16712
+ if (matchMode === 'all') {
16713
+ return permissionChecks.every(result => result);
16714
+ }
16715
+ return permissionChecks.some(result => result);
16602
16716
  }
16603
16717
  catch (error) {
16604
16718
  return !this.isProduction();
@@ -17678,7 +17792,7 @@ class GenericFixedActionsComponent {
17678
17792
  })
17679
17793
  .filter(action => {
17680
17794
  if (action.requiredPermission) {
17681
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
17795
+ return this.checkRequiredPermission(action.requiredPermission);
17682
17796
  }
17683
17797
  return true;
17684
17798
  })
@@ -17700,7 +17814,7 @@ class GenericFixedActionsComponent {
17700
17814
  })
17701
17815
  .filter(action => {
17702
17816
  if (action.requiredPermission) {
17703
- return this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action, action.requiredPermission.custom_action);
17817
+ return this.checkRequiredPermission(action.requiredPermission);
17704
17818
  }
17705
17819
  return true;
17706
17820
  })
@@ -17734,7 +17848,7 @@ class GenericFixedActionsComponent {
17734
17848
  if (external && external.length > 0) {
17735
17849
  external.forEach(action => {
17736
17850
  if (action.requiredPermission) {
17737
- if (this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action)) {
17851
+ if (this.checkRequiredPermission(action.requiredPermission)) {
17738
17852
  actions.push(action);
17739
17853
  }
17740
17854
  }
@@ -17750,7 +17864,7 @@ class GenericFixedActionsComponent {
17750
17864
  : this.tableFixedActionsService.getActiveTableActions();
17751
17865
  tableActions.forEach(action => {
17752
17866
  if (action.requiredPermission) {
17753
- if (this.permissionService.hasPermission(action.requiredPermission.resource, action.requiredPermission.action)) {
17867
+ if (this.checkRequiredPermission(action.requiredPermission)) {
17754
17868
  actions.push(action);
17755
17869
  }
17756
17870
  }
@@ -17823,6 +17937,25 @@ class GenericFixedActionsComponent {
17823
17937
  actions: fixedActions
17824
17938
  });
17825
17939
  }
17940
+ checkRequiredPermission(perm) {
17941
+ if (perm.custom_action && perm.action) {
17942
+ return this.permissionService.hasPermission(perm.resource, perm.action, perm.custom_action);
17943
+ }
17944
+ const resources = perm.resources || (perm.resource ? [perm.resource] : []);
17945
+ const actions = perm.actions || (perm.action ? [perm.action] : []);
17946
+ if (resources.length === 0 && actions.length === 0) {
17947
+ return true;
17948
+ }
17949
+ const resourcesToCheck = resources.length > 0 ? resources : [undefined];
17950
+ for (const resource of resourcesToCheck) {
17951
+ for (const action of actions) {
17952
+ if (this.permissionService.hasPermission(resource, action)) {
17953
+ return true;
17954
+ }
17955
+ }
17956
+ }
17957
+ return false;
17958
+ }
17826
17959
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericFixedActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17827
17960
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericFixedActionsComponent, isStandalone: true, selector: "core-generic-fixed-actions", inputs: { externalActions: { classPropertyName: "externalActions", publicName: "externalActions", isSignal: true, isRequired: false, transformFunction: null }, tableId: { classPropertyName: "tableId", publicName: "tableId", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "c-fixed-actions c-fixed-actions--right" }, ngImport: i0, template: `
17828
17961
  @if (shouldShow() && visibleActions().length > 0) {
@@ -19989,25 +20122,136 @@ class AdAuthService {
19989
20122
  msalInstance = null;
19990
20123
  msalModule = null;
19991
20124
  initializationPromise = null;
20125
+ codeVerifier = null;
19992
20126
  authState = signal({
19993
20127
  isAuthenticated: false,
19994
20128
  user: null,
19995
20129
  isLoading: false,
19996
20130
  error: null
19997
20131
  });
20132
+ _authorizationCode = signal(null);
20133
+ authorizationCode = computed(() => this._authorizationCode());
19998
20134
  isAuthenticated = computed(() => this.authState().isAuthenticated);
19999
20135
  currentUser = computed(() => this.authState().user);
20000
20136
  isLoading = computed(() => this.authState().isLoading);
20001
20137
  error = computed(() => this.authState().error);
20002
20138
  constructor() {
20003
- // Only initialize if config is provided
20004
20139
  if (this.config) {
20005
- this.initializationPromise = this.initializeMsal();
20140
+ if (this.config.authorizationCodeOnly) {
20141
+ this.checkForAuthorizationCode();
20142
+ }
20143
+ else {
20144
+ this.initializationPromise = this.initializeMsal();
20145
+ }
20006
20146
  }
20007
20147
  }
20008
- /**
20009
- * Dynamically loads MSAL library only when needed
20010
- */
20148
+ checkForAuthorizationCode() {
20149
+ const urlParams = new URLSearchParams(window.location.search);
20150
+ const code = urlParams.get('code');
20151
+ const state = urlParams.get('state');
20152
+ const error = urlParams.get('error');
20153
+ const errorDescription = urlParams.get('error_description');
20154
+ if (error) {
20155
+ this.updateAuthState({
20156
+ error: { code: error, message: errorDescription },
20157
+ isLoading: false
20158
+ });
20159
+ this.cleanUrlParams();
20160
+ return;
20161
+ }
20162
+ if (code) {
20163
+ const storedCodeVerifier = sessionStorage.getItem('ad_auth_code_verifier');
20164
+ const storedState = sessionStorage.getItem('ad_auth_state');
20165
+ if (storedState && state !== storedState) {
20166
+ this.updateAuthState({
20167
+ error: { code: 'state_mismatch', message: 'State parameter mismatch' },
20168
+ isLoading: false
20169
+ });
20170
+ this.cleanUrlParams();
20171
+ return;
20172
+ }
20173
+ this._authorizationCode.set({
20174
+ code,
20175
+ state: state || undefined,
20176
+ codeVerifier: storedCodeVerifier || undefined
20177
+ });
20178
+ sessionStorage.removeItem('ad_auth_code_verifier');
20179
+ sessionStorage.removeItem('ad_auth_state');
20180
+ this.cleanUrlParams();
20181
+ }
20182
+ }
20183
+ cleanUrlParams() {
20184
+ const url = new URL(window.location.href);
20185
+ url.searchParams.delete('code');
20186
+ url.searchParams.delete('state');
20187
+ url.searchParams.delete('error');
20188
+ url.searchParams.delete('error_description');
20189
+ url.searchParams.delete('session_state');
20190
+ window.history.replaceState({}, document.title, url.pathname + url.hash);
20191
+ }
20192
+ async generatePKCE() {
20193
+ const array = new Uint8Array(32);
20194
+ crypto.getRandomValues(array);
20195
+ const codeVerifier = this.base64UrlEncode(array);
20196
+ const encoder = new TextEncoder();
20197
+ const data = encoder.encode(codeVerifier);
20198
+ const digest = await crypto.subtle.digest('SHA-256', data);
20199
+ const codeChallenge = this.base64UrlEncode(new Uint8Array(digest));
20200
+ return { codeVerifier, codeChallenge };
20201
+ }
20202
+ base64UrlEncode(buffer) {
20203
+ let binary = '';
20204
+ for (let i = 0; i < buffer.byteLength; i++) {
20205
+ binary += String.fromCharCode(buffer[i]);
20206
+ }
20207
+ return btoa(binary)
20208
+ .replace(/\+/g, '-')
20209
+ .replace(/\//g, '_')
20210
+ .replace(/=+$/, '');
20211
+ }
20212
+ generateState() {
20213
+ const array = new Uint8Array(16);
20214
+ crypto.getRandomValues(array);
20215
+ return this.base64UrlEncode(array);
20216
+ }
20217
+ async redirectToAzureLogin() {
20218
+ if (!this.config) {
20219
+ throw new Error('AD Auth configuration is not available');
20220
+ }
20221
+ this.updateAuthState({ isLoading: true, error: null });
20222
+ try {
20223
+ const { codeVerifier, codeChallenge } = await this.generatePKCE();
20224
+ const state = this.config.state || this.generateState();
20225
+ sessionStorage.setItem('ad_auth_code_verifier', codeVerifier);
20226
+ sessionStorage.setItem('ad_auth_state', state);
20227
+ this.codeVerifier = codeVerifier;
20228
+ const params = new URLSearchParams({
20229
+ client_id: this.config.clientId,
20230
+ response_type: 'code',
20231
+ redirect_uri: this.config.redirectUri,
20232
+ scope: (this.config.scopes || ['openid', 'profile', 'email']).join(' '),
20233
+ response_mode: 'query',
20234
+ state: state,
20235
+ code_challenge: codeChallenge,
20236
+ code_challenge_method: 'S256'
20237
+ });
20238
+ const authUrl = `${this.config.authority}/oauth2/v2.0/authorize?${params.toString()}`;
20239
+ window.location.href = authUrl;
20240
+ }
20241
+ catch (error) {
20242
+ this.updateAuthState({ isLoading: false, error });
20243
+ throw error;
20244
+ }
20245
+ }
20246
+ getAuthorizationCode() {
20247
+ return this._authorizationCode();
20248
+ }
20249
+ clearAuthorizationCode() {
20250
+ this._authorizationCode.set(null);
20251
+ }
20252
+ isAuthorizationCodeOnlyMode() {
20253
+ return this.config?.authorizationCodeOnly === true;
20254
+ }
20011
20255
  async loadMsalModule() {
20012
20256
  if (this.msalModule) {
20013
20257
  return this.msalModule;
@@ -20184,6 +20428,10 @@ class AdAuthService {
20184
20428
  }
20185
20429
  }
20186
20430
  async login() {
20431
+ if (this.config?.authorizationCodeOnly) {
20432
+ await this.redirectToAzureLogin();
20433
+ return null;
20434
+ }
20187
20435
  const interactionType = this.config?.interactionType || AdInteractionType.POPUP;
20188
20436
  if (interactionType === AdInteractionType.REDIRECT) {
20189
20437
  await this.loginWithRedirect();
@@ -20246,7 +20494,28 @@ class AdAuthService {
20246
20494
  throw error;
20247
20495
  }
20248
20496
  }
20497
+ async logoutFromAzure() {
20498
+ if (!this.config) {
20499
+ throw new Error('AD Auth configuration is not available');
20500
+ }
20501
+ this.updateAuthState({
20502
+ isAuthenticated: false,
20503
+ user: null,
20504
+ isLoading: false,
20505
+ error: null
20506
+ });
20507
+ this._authorizationCode.set(null);
20508
+ const params = new URLSearchParams({
20509
+ post_logout_redirect_uri: this.config.postLogoutRedirectUri || this.config.redirectUri
20510
+ });
20511
+ const logoutUrl = `${this.config.authority}/oauth2/v2.0/logout?${params.toString()}`;
20512
+ window.location.href = logoutUrl;
20513
+ }
20249
20514
  async logout() {
20515
+ if (this.config?.authorizationCodeOnly) {
20516
+ await this.logoutFromAzure();
20517
+ return;
20518
+ }
20250
20519
  const interactionType = this.config?.interactionType || AdInteractionType.POPUP;
20251
20520
  if (interactionType === AdInteractionType.REDIRECT) {
20252
20521
  await this.logoutWithRedirect();