RED-5482: wip permissions

This commit is contained in:
Dan Percic 2022-11-06 09:55:46 +02:00
parent 074881dae8
commit 5bf1122516
41 changed files with 210 additions and 139 deletions

View File

@ -1,31 +1,32 @@
import { Component, Inject, Renderer2, ViewContainerRef } from '@angular/core'; import { Component, Inject, Renderer2, ViewContainerRef } from '@angular/core';
import { RouterHistoryService } from '@services/router-history.service'; import { RouterHistoryService } from '@services/router-history.service';
import { UserService } from '@users/user.service';
import { REDDocumentViewer } from './modules/pdf-viewer/services/document-viewer.service'; import { REDDocumentViewer } from './modules/pdf-viewer/services/document-viewer.service';
import { DossiersChangesService } from '@services/dossiers/dossier-changes.service'; import { DossiersChangesService } from '@services/dossiers/dossier-changes.service';
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { UserPreferenceService } from '@users/user-preference.service'; import { UserPreferenceService } from '@users/user-preference.service';
import { IqserPermissionsService } from '@iqser/common-ui';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-root', selector: 'redaction-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
}) })
export class AppComponent { export class AppComponent {
// ViewContainerRef needs to be injected for the color picker to work
// RouterHistoryService needs to be injected for last dossiers screen to be updated on first app load
constructor( constructor(
/** ViewContainerRef needs to be injected for the color picker to work */
readonly viewContainerRef: ViewContainerRef, readonly viewContainerRef: ViewContainerRef,
/** RouterHistoryService needs to be injected for last dossiers screen to be updated on first app load */
private readonly _routerHistoryService: RouterHistoryService, private readonly _routerHistoryService: RouterHistoryService,
private readonly _userService: UserService,
private readonly _userPreferenceService: UserPreferenceService, private readonly _userPreferenceService: UserPreferenceService,
readonly documentViewer: REDDocumentViewer, readonly documentViewer: REDDocumentViewer,
private readonly _dossierChangesService: DossiersChangesService, private readonly _dossierChangesService: DossiersChangesService,
@Inject(DOCUMENT) private readonly _document: Document, @Inject(DOCUMENT) private readonly _document: Document,
private readonly _renderer: Renderer2, private readonly _renderer: Renderer2,
private readonly _permissionsService: IqserPermissionsService,
) { ) {
this._renderer.addClass(this._document.body, _userPreferenceService.getTheme()); this._renderer.addClass(this._document.body, _userPreferenceService.getTheme());
// TODO: Find a better place to initialize dossiers refresh // TODO: Find a better place to initialize dossiers refresh
if (_userService.currentUser?.isUser) { if (_permissionsService.has(ROLES.dossiers.read)) {
_dossierChangesService.initializeRefresh(); _dossierChangesService.initializeRefresh();
} }
} }

View File

@ -2,7 +2,7 @@
<div class="top-bar"> <div class="top-bar">
<ng-template #menuPlaceholder> <ng-template #menuPlaceholder>
<div *ngIf="!currentUser.isUser" class="menu-placeholder"></div> <div class="menu-placeholder"></div>
</ng-template> </ng-template>
<div *allow="roles.templates.read; else menuPlaceholder" class="flex-2 visible-lg breadcrumbs-container"> <div *allow="roles.templates.read; else menuPlaceholder" class="flex-2 visible-lg breadcrumbs-container">

View File

@ -52,6 +52,7 @@ import {
IqserHelpModeModule, IqserHelpModeModule,
IqserInputsModule, IqserInputsModule,
IqserListingModule, IqserListingModule,
IqserPermissionsModule,
IqserScrollbarModule, IqserScrollbarModule,
IqserSharedModule, IqserSharedModule,
IqserUploadFileModule, IqserUploadFileModule,
@ -127,6 +128,7 @@ const components = [
IqserEmptyStatesModule, IqserEmptyStatesModule,
IqserSharedModule, IqserSharedModule,
IqserHelpModeModule, IqserHelpModeModule,
IqserPermissionsModule,
], ],
}) })
export class AdminModule {} export class AdminModule {}

View File

@ -1,7 +1,7 @@
<iqser-page-header <iqser-page-header
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()" (closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[pageLabel]="'audit' | translate" [pageLabel]="'audit' | translate"
[showCloseButton]="currentUser.isUser" [showCloseButton]="permissionsService.has$(roles.dossiers.read) | async"
></iqser-page-header> ></iqser-page-header>
<iqser-table <iqser-table

View File

@ -1,15 +1,15 @@
import { Component, inject, OnDestroy, OnInit } from '@angular/core'; import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { applyIntervalConstraints } from '@utils/date-inputs-utils'; import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import { ListingComponent, listingProvidersFactory, LoadingService, TableColumnConfig } from '@iqser/common-ui'; import { IqserPermissionsService, ListingComponent, listingProvidersFactory, LoadingService, TableColumnConfig } from '@iqser/common-ui';
import { auditCategoriesTranslations } from '@translations/audit-categories-translations'; import { auditCategoriesTranslations } from '@translations/audit-categories-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { UserService } from '@users/user.service';
import { Audit, IAudit, IAuditResponse, IAuditSearchRequest } from '@red/domain'; import { Audit, IAudit, IAuditResponse, IAuditSearchRequest } from '@red/domain';
import { AuditService } from '../../services/audit.service'; import { AuditService } from '../../services/audit.service';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import { Dayjs } from 'dayjs'; import { Dayjs } from 'dayjs';
import { RouterHistoryService } from '@services/router-history.service'; import { RouterHistoryService } from '@services/router-history.service';
import { ROLES } from '@users/roles';
const PAGE_SIZE = 50; const PAGE_SIZE = 50;
@ -22,9 +22,11 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
readonly ALL_CATEGORIES = 'allCategories'; readonly ALL_CATEGORIES = 'allCategories';
readonly ALL_USERS = _('audit-screen.all-users'); readonly ALL_USERS = _('audit-screen.all-users');
readonly translations = auditCategoriesTranslations; readonly translations = auditCategoriesTranslations;
readonly currentUser = inject(UserService).currentUser;
readonly form: UntypedFormGroup = this._getForm(); readonly form: UntypedFormGroup = this._getForm();
readonly routerHistoryService = inject(RouterHistoryService); readonly routerHistoryService = inject(RouterHistoryService);
readonly permissionsService = inject(IqserPermissionsService);
readonly roles = ROLES;
categories: string[] = []; categories: string[] = [];
userIds: Set<string>; userIds: Set<string>;
logs: IAuditResponse; logs: IAuditResponse;

View File

@ -1,7 +1,7 @@
<iqser-page-header <iqser-page-header
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()" (closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[pageLabel]="'digital-signature' | translate" [pageLabel]="'digital-signature' | translate"
[showCloseButton]="currentUser.isUser" [showCloseButton]="permissionsService.has$(roles.dossiers.read) | async"
></iqser-page-header> ></iqser-page-header>
<div class="content-container"> <div class="content-container">
@ -11,8 +11,8 @@
*ngIf="!digitalSignature" *ngIf="!digitalSignature"
[buttonIcon]="null" [buttonIcon]="null"
[buttonLabel]="'digital-signature-screen.no-data.action' | translate" [buttonLabel]="'digital-signature-screen.no-data.action' | translate"
[text]="'digital-signature-screen.no-data.title' | translate"
[helpModeKey]="'digital_signature'" [helpModeKey]="'digital_signature'"
[text]="'digital-signature-screen.no-data.title' | translate"
icon="iqser:document" icon="iqser:document"
></iqser-empty-state> ></iqser-empty-state>

View File

@ -1,7 +1,6 @@
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; import { IconButtonTypes, IqserPermissionsService, LoadingService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { UserService } from '@users/user.service';
import { RouterHistoryService } from '@services/router-history.service'; import { RouterHistoryService } from '@services/router-history.service';
import { DigitalSignatureService } from '../../services/digital-signature.service'; import { DigitalSignatureService } from '../../services/digital-signature.service';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
@ -9,6 +8,7 @@ import { AdminDialogService } from '../../services/admin-dialog.service';
import { PkcsSignatureConfigurationComponent } from '../../dialogs/configure-digital-signature-dialog/form/pkcs-signature-configuration/pkcs-signature-configuration.component'; import { PkcsSignatureConfigurationComponent } from '../../dialogs/configure-digital-signature-dialog/form/pkcs-signature-configuration/pkcs-signature-configuration.component';
import { KmsSignatureConfigurationComponent } from '../../dialogs/configure-digital-signature-dialog/form/kms-signature-configuration/kms-signature-configuration.component'; import { KmsSignatureConfigurationComponent } from '../../dialogs/configure-digital-signature-dialog/form/kms-signature-configuration/kms-signature-configuration.component';
import { DigitalSignatureOptions, IKmsDigitalSignatureRequest, IPkcsDigitalSignatureRequest } from '@red/domain'; import { DigitalSignatureOptions, IKmsDigitalSignatureRequest, IPkcsDigitalSignatureRequest } from '@red/domain';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-digital-signature-screen', selector: 'redaction-digital-signature-screen',
@ -21,20 +21,38 @@ export class DigitalSignatureScreenComponent implements OnInit {
readonly certificateType = DigitalSignatureOptions; readonly certificateType = DigitalSignatureOptions;
readonly iconButtonTypes = IconButtonTypes; readonly iconButtonTypes = IconButtonTypes;
readonly currentUser = this._userService.currentUser; readonly roles = ROLES;
digitalSignature: IPkcsDigitalSignatureRequest | IKmsDigitalSignatureRequest; digitalSignature: IPkcsDigitalSignatureRequest | IKmsDigitalSignatureRequest;
constructor( constructor(
private readonly _toaster: Toaster, private readonly _toaster: Toaster,
private readonly _userService: UserService,
private readonly _loadingService: LoadingService, private readonly _loadingService: LoadingService,
private readonly _digitalSignatureService: DigitalSignatureService, private readonly _digitalSignatureService: DigitalSignatureService,
private readonly _dialogService: AdminDialogService, private readonly _dialogService: AdminDialogService,
private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _changeDetectorRef: ChangeDetectorRef,
readonly routerHistoryService: RouterHistoryService, readonly routerHistoryService: RouterHistoryService,
readonly permissionsService: IqserPermissionsService,
) {} ) {}
get disabled(): boolean {
//TODO remove second check when the update endpoint will be available for KMS signature
return this.activeComponent?.disabled || this.currentCertificateType === DigitalSignatureOptions.KMS;
}
get currentCertificateType() {
if (!this.digitalSignature) {
return;
}
return 'contactInfo' in this.digitalSignature ? DigitalSignatureOptions.PKCS : DigitalSignatureOptions.KMS;
}
get activeComponent() {
return this.currentCertificateType === DigitalSignatureOptions.PKCS
? this.pkcsSignatureConfigurationComponent
: this.kmsSignatureConfigurationComponent;
}
async ngOnInit(): Promise<void> { async ngOnInit(): Promise<void> {
await this.loadDigitalSignature(); await this.loadDigitalSignature();
} }
@ -51,11 +69,6 @@ export class DigitalSignatureScreenComponent implements OnInit {
} }
} }
get disabled(): boolean {
//TODO remove second check when the update endpoint will be available for KMS signature
return this.activeComponent?.disabled || this.currentCertificateType === DigitalSignatureOptions.KMS;
}
async saveDigitalSignature(): Promise<void> { async saveDigitalSignature(): Promise<void> {
try { try {
await this.activeComponent.save(); await this.activeComponent.save();
@ -66,19 +79,6 @@ export class DigitalSignatureScreenComponent implements OnInit {
} }
} }
get currentCertificateType() {
if (!this.digitalSignature) {
return;
}
return 'contactInfo' in this.digitalSignature ? DigitalSignatureOptions.PKCS : DigitalSignatureOptions.KMS;
}
get activeComponent() {
return this.currentCertificateType === DigitalSignatureOptions.PKCS
? this.pkcsSignatureConfigurationComponent
: this.kmsSignatureConfigurationComponent;
}
openConfigureCertificate(): void { openConfigureCertificate(): void {
const dialogRef = this._dialogService.openDialog('configureCertificate', null, null); const dialogRef = this._dialogService.openDialog('configureCertificate', null, null);
firstValueFrom(dialogRef.afterClosed()).then(async res => { firstValueFrom(dialogRef.afterClosed()).then(async res => {

View File

@ -53,10 +53,10 @@
<iqser-icon-button <iqser-icon-button
(action)="openAddEditStateDialog($event)" (action)="openAddEditStateDialog($event)"
*ngIf="permissionsService.canPerformDossierStatesActions()" *allow="roles.states.write"
[iqserHelpMode]="'create_new_dossier_state'"
[label]="'dossier-states-listing.add-new' | translate" [label]="'dossier-states-listing.add-new' | translate"
[type]="iconButtonTypes.primary" [type]="iconButtonTypes.primary"
[iqserHelpMode]="'create_new_dossier_state'"
icon="iqser:plus" icon="iqser:plus"
></iqser-icon-button> ></iqser-icon-button>
</div> </div>
@ -80,7 +80,7 @@
</div> </div>
<div class="cell"> <div class="cell">
<div *ngIf="permissionsService.canPerformDossierStatesActions()" class="action-buttons"> <div *allow="roles.states.write" class="action-buttons">
<div [iqserHelpMode]="'edit_delete_dossier_state'"> <div [iqserHelpMode]="'edit_delete_dossier_state'">
<iqser-circle-button <iqser-circle-button
(action)="openAddEditStateDialog($event, state)" (action)="openAddEditStateDialog($event, state)"

View File

@ -14,8 +14,8 @@ import { firstValueFrom, Observable } from 'rxjs';
import { AdminDialogService } from '../../services/admin-dialog.service'; import { AdminDialogService } from '../../services/admin-dialog.service';
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service'; import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
import { map, tap } from 'rxjs/operators'; import { map, tap } from 'rxjs/operators';
import { PermissionsService } from '@services/permissions.service';
import { DossierStatesService } from '@services/entity-services/dossier-states.service'; import { DossierStatesService } from '@services/entity-services/dossier-states.service';
import { ROLES } from '@users/roles';
@Component({ @Component({
templateUrl: './dossier-states-listing-screen.component.html', templateUrl: './dossier-states-listing-screen.component.html',
@ -26,6 +26,7 @@ import { DossierStatesService } from '@services/entity-services/dossier-states.s
export class DossierStatesListingScreenComponent extends ListingComponent<DossierState> implements OnInit, OnDestroy { export class DossierStatesListingScreenComponent extends ListingComponent<DossierState> implements OnInit, OnDestroy {
readonly iconButtonTypes = IconButtonTypes; readonly iconButtonTypes = IconButtonTypes;
readonly circleButtonTypes = CircleButtonTypes; readonly circleButtonTypes = CircleButtonTypes;
readonly roles = ROLES;
readonly tableHeaderLabel = _('dossier-states-listing.table-header.title'); readonly tableHeaderLabel = _('dossier-states-listing.table-header.title');
readonly tableColumnConfigs: TableColumnConfig<DossierState>[] = [ readonly tableColumnConfigs: TableColumnConfig<DossierState>[] = [
{ label: _('dossier-states-listing.table-col-names.name'), sortByKey: 'name', width: '3fr' }, { label: _('dossier-states-listing.table-col-names.name'), sortByKey: 'name', width: '3fr' },
@ -39,7 +40,6 @@ export class DossierStatesListingScreenComponent extends ListingComponent<Dossie
private readonly _dialogService: AdminDialogService, private readonly _dialogService: AdminDialogService,
private readonly _dossierStatesMapService: DossierStatesMapService, private readonly _dossierStatesMapService: DossierStatesMapService,
private readonly _dossierStatesService: DossierStatesService, private readonly _dossierStatesService: DossierStatesService,
readonly permissionsService: PermissionsService,
) { ) {
super(); super();
this.chartConfig$ = this._dossierStatesMapService.get$(this.#dossierTemplateId).pipe( this.chartConfig$ = this._dossierStatesMapService.get$(this.#dossierTemplateId).pipe(

View File

@ -2,7 +2,7 @@
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()" (closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[hideResetButton]="true" [hideResetButton]="true"
[pageLabel]="'dossier-templates.label' | translate" [pageLabel]="'dossier-templates.label' | translate"
[showCloseButton]="currentUser.isUser" [showCloseButton]="permissionsService.has$(roles.dossiers.read) | async"
></iqser-page-header> ></iqser-page-header>
<iqser-table <iqser-table
@ -19,7 +19,7 @@
<ng-template #bulkActions> <ng-template #bulkActions>
<iqser-circle-button <iqser-circle-button
(action)="openBulkDeleteTemplatesDialog($event)" (action)="openBulkDeleteTemplatesDialog($event)"
*ngIf="currentUser.isAdmin && (listingService.areSomeSelected$ | async)" *allow="roles.templates.write; if: listingService.areSomeSelected$ | async"
[icon]="'iqser:trash'" [icon]="'iqser:trash'"
[tooltip]="'dossier-templates-listing.bulk.delete' | translate" [tooltip]="'dossier-templates-listing.bulk.delete' | translate"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"
@ -35,7 +35,7 @@
<iqser-icon-button <iqser-icon-button
(action)="openAddDossierTemplateDialog()" (action)="openAddDossierTemplateDialog()"
*ngIf="currentUser.isAdmin && userPreferenceService.areDevFeaturesEnabled" *allow="roles.templates.write; if: userPreferenceService.areDevFeaturesEnabled"
[icon]="'iqser:plus'" [icon]="'iqser:plus'"
[label]="'dossier-templates-listing.add-new' | translate" [label]="'dossier-templates-listing.add-new' | translate"
[type]="iconButtonTypes.primary" [type]="iconButtonTypes.primary"

View File

@ -1,20 +1,21 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { ChangeDetectionStrategy, Component } from '@angular/core';
import { UserPreferenceService } from '@users/user-preference.service'; import { UserPreferenceService } from '@users/user-preference.service';
import { AdminDialogService } from '../../../services/admin-dialog.service'; import { AdminDialogService } from '../../../services/admin-dialog.service';
import { DossierTemplate } from '@red/domain'; import { DossierTemplate } from '@red/domain';
import { import {
CircleButtonTypes, CircleButtonTypes,
IconButtonTypes, IconButtonTypes,
IqserPermissionsService,
ListingComponent, ListingComponent,
listingProvidersFactory, listingProvidersFactory,
LoadingService, LoadingService,
TableColumnConfig, TableColumnConfig,
} from '@iqser/common-ui'; } from '@iqser/common-ui';
import { UserService } from '@users/user.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { RouterHistoryService } from '@services/router-history.service'; import { RouterHistoryService } from '@services/router-history.service';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import { ROLES } from '@users/roles';
@Component({ @Component({
templateUrl: './dossier-templates-listing-screen.component.html', templateUrl: './dossier-templates-listing-screen.component.html',
@ -28,7 +29,7 @@ import { firstValueFrom } from 'rxjs';
export class DossierTemplatesListingScreenComponent extends ListingComponent<DossierTemplate> { export class DossierTemplatesListingScreenComponent extends ListingComponent<DossierTemplate> {
readonly iconButtonTypes = IconButtonTypes; readonly iconButtonTypes = IconButtonTypes;
readonly circleButtonTypes = CircleButtonTypes; readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = inject(UserService).currentUser; readonly roles = ROLES;
readonly tableHeaderLabel = _('dossier-templates-listing.table-header.title'); readonly tableHeaderLabel = _('dossier-templates-listing.table-header.title');
readonly tableColumnConfigs: TableColumnConfig<DossierTemplate>[] = [ readonly tableColumnConfigs: TableColumnConfig<DossierTemplate>[] = [
{ label: _('dossier-templates-listing.table-col-names.name'), sortByKey: 'searchKey', width: '3fr' }, { label: _('dossier-templates-listing.table-col-names.name'), sortByKey: 'searchKey', width: '3fr' },
@ -45,6 +46,7 @@ export class DossierTemplatesListingScreenComponent extends ListingComponent<Dos
private readonly _dialogService: AdminDialogService, private readonly _dialogService: AdminDialogService,
readonly routerHistoryService: RouterHistoryService, readonly routerHistoryService: RouterHistoryService,
readonly userPreferenceService: UserPreferenceService, readonly userPreferenceService: UserPreferenceService,
readonly permissionsService: IqserPermissionsService,
private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _dossierTemplatesService: DossierTemplatesService,
) { ) {
super(); super();

View File

@ -5,7 +5,14 @@ import { SharedModule } from '@shared/shared.module';
import { TableItemComponent } from './table-item/table-item.component'; import { TableItemComponent } from './table-item/table-item.component';
import { DossierTemplatesListingScreenComponent } from './dossier-templates-listing-screen/dossier-templates-listing-screen.component'; import { DossierTemplatesListingScreenComponent } from './dossier-templates-listing-screen/dossier-templates-listing-screen.component';
import { SharedAdminModule } from '../../shared/shared-admin.module'; import { SharedAdminModule } from '../../shared/shared-admin.module';
import { IqserButtonsModule, IqserHelpModeModule, IqserInputsModule, IqserListingModule, IqserUsersModule } from '@iqser/common-ui'; import {
IqserButtonsModule,
IqserHelpModeModule,
IqserInputsModule,
IqserListingModule,
IqserPermissionsModule,
IqserUsersModule,
} from '@iqser/common-ui';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
const routes = [{ path: '', component: DossierTemplatesListingScreenComponent }]; const routes = [{ path: '', component: DossierTemplatesListingScreenComponent }];
@ -23,6 +30,7 @@ const routes = [{ path: '', component: DossierTemplatesListingScreenComponent }]
IqserButtonsModule, IqserButtonsModule,
IqserListingModule, IqserListingModule,
IqserHelpModeModule, IqserHelpModeModule,
IqserPermissionsModule,
], ],
}) })
export class DossierTemplatesListingModule {} export class DossierTemplatesListingModule {}

View File

@ -57,10 +57,10 @@
<div class="actions"> <div class="actions">
<iqser-icon-button <iqser-icon-button
(action)="openAddEntityDialog()" (action)="openAddEntityDialog()"
*ngIf="permissionsService.canEditEntities()" *allow="roles.dictionaryTypes.write"
[iqserHelpMode]="'create_new_entity'"
[label]="'entities-listing.add-new' | translate" [label]="'entities-listing.add-new' | translate"
[type]="iconButtonTypes.primary" [type]="iconButtonTypes.primary"
[iqserHelpMode]="'create_new_entity'"
icon="iqser:plus" icon="iqser:plus"
></iqser-icon-button> ></iqser-icon-button>
</div> </div>
@ -109,7 +109,7 @@
></iqser-circle-button> ></iqser-circle-button>
<iqser-circle-button <iqser-circle-button
*ngIf="permissionsService.canEditEntities()" *allow="roles.dictionaryTypes.write"
[routerLink]="dict.routerLink" [routerLink]="dict.routerLink"
[tooltip]="'entities-listing.action.edit' | translate" [tooltip]="'entities-listing.action.edit' | translate"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"

View File

@ -17,6 +17,7 @@ import { DossierTemplateStatsService } from '@services/entity-services/dossier-t
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
import { PermissionsService } from '@services/permissions.service'; import { PermissionsService } from '@services/permissions.service';
import { ROLES } from '@users/roles';
@Component({ @Component({
templateUrl: './entities-listing-screen.component.html', templateUrl: './entities-listing-screen.component.html',
@ -26,6 +27,7 @@ import { PermissionsService } from '@services/permissions.service';
export class EntitiesListingScreenComponent extends ListingComponent<Dictionary> { export class EntitiesListingScreenComponent extends ListingComponent<Dictionary> {
readonly iconButtonTypes = IconButtonTypes; readonly iconButtonTypes = IconButtonTypes;
readonly circleButtonTypes = CircleButtonTypes; readonly circleButtonTypes = CircleButtonTypes;
readonly roles = ROLES;
readonly tableHeaderLabel = _('entities-listing.table-header.title'); readonly tableHeaderLabel = _('entities-listing.table-header.title');
readonly tableColumnConfigs: TableColumnConfig<Dictionary>[] = [ readonly tableColumnConfigs: TableColumnConfig<Dictionary>[] = [
{ label: _('entities-listing.table-col-names.type'), sortByKey: 'searchKey', width: '2fr' }, { label: _('entities-listing.table-col-names.type'), sortByKey: 'searchKey', width: '2fr' },

View File

@ -8,7 +8,7 @@ import { EntityInfoComponent } from './screens/entity-info/entity-info.component
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor'; import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
import { SharedAdminModule } from '../../shared/shared-admin.module'; import { SharedAdminModule } from '../../shared/shared-admin.module';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { IqserHelpModeModule, IqserScrollbarModule } from '@iqser/common-ui'; import { IqserHelpModeModule, IqserPermissionsModule, IqserScrollbarModule } from '@iqser/common-ui';
const routes: Routes = [ const routes: Routes = [
{ path: '', redirectTo: 'info', pathMatch: 'full' }, { path: '', redirectTo: 'info', pathMatch: 'full' },
@ -45,6 +45,7 @@ const routes: Routes = [
TranslateModule, TranslateModule,
IqserScrollbarModule, IqserScrollbarModule,
IqserHelpModeModule, IqserHelpModeModule,
IqserPermissionsModule,
], ],
}) })
export class EntitiesModule {} export class EntitiesModule {}

View File

@ -17,7 +17,7 @@
></redaction-add-edit-entity> ></redaction-add-edit-entity>
</div> </div>
<div *ngIf="permissionsService.canEditEntities()" class="dialog-actions"> <div *allow="roles.dictionaryTypes.write" class="dialog-actions">
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button> <button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button>
{{ 'entity.info.actions.save' | translate }} {{ 'entity.info.actions.save' | translate }}
</button> </button>

View File

@ -7,6 +7,7 @@ import { PermissionsService } from '@services/permissions.service';
import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component'; import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component';
import { IqserEventTarget } from '@iqser/common-ui'; import { IqserEventTarget } from '@iqser/common-ui';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-entity-info', selector: 'redaction-entity-info',
@ -16,6 +17,7 @@ import { Observable } from 'rxjs';
}) })
export class EntityInfoComponent { export class EntityInfoComponent {
readonly currentUser = getCurrentUser(); readonly currentUser = getCurrentUser();
readonly roles = ROLES;
readonly entity$: Observable<Dictionary>; readonly entity$: Observable<Dictionary>;
readonly dossierTemplateId: string; readonly dossierTemplateId: string;
@ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent; @ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent;

View File

@ -4,7 +4,7 @@
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()" (closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[buttonConfigs]="buttonConfigs" [buttonConfigs]="buttonConfigs"
[pageLabel]="'license-information' | translate" [pageLabel]="'license-information' | translate"
[showCloseButton]="currentUser.isUser" [showCloseButton]="permissionsService.has$(roles.dossiers.read) | async"
></iqser-page-header> ></iqser-page-header>
<div class="content-inner"> <div class="content-inner">

View File

@ -1,20 +1,20 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ConfigService } from '@services/config.service'; import { ConfigService } from '@services/config.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { ButtonConfig, IconButtonTypes, LoadingService } from '@iqser/common-ui'; import { ButtonConfig, IconButtonTypes, IqserPermissionsService, LoadingService } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { UserService } from '@users/user.service';
import { RouterHistoryService } from '@services/router-history.service'; import { RouterHistoryService } from '@services/router-history.service';
import { LicenseService } from '@services/license.service'; import { LicenseService } from '@services/license.service';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { ROLES } from '@users/roles';
@Component({ @Component({
templateUrl: './license-screen.component.html', templateUrl: './license-screen.component.html',
styleUrls: ['./license-screen.component.scss'], styleUrls: ['./license-screen.component.scss'],
}) })
export class LicenseScreenComponent implements OnInit { export class LicenseScreenComponent implements OnInit {
readonly roles = ROLES;
readonly currentYear = new Date().getFullYear(); readonly currentYear = new Date().getFullYear();
readonly currentUser = this._userService.currentUser;
readonly buttonConfigs: readonly ButtonConfig[] = [ readonly buttonConfigs: readonly ButtonConfig[] = [
{ {
label: _('license-info-screen.email-report'), label: _('license-info-screen.email-report'),
@ -29,7 +29,7 @@ export class LicenseScreenComponent implements OnInit {
constructor( constructor(
readonly configService: ConfigService, readonly configService: ConfigService,
readonly licenseService: LicenseService, readonly licenseService: LicenseService,
private readonly _userService: UserService, readonly permissionsService: IqserPermissionsService,
private readonly _loadingService: LoadingService, private readonly _loadingService: LoadingService,
readonly routerHistoryService: RouterHistoryService, readonly routerHistoryService: RouterHistoryService,
private readonly _translateService: TranslateService, private readonly _translateService: TranslateService,

View File

@ -1,7 +1,7 @@
<iqser-page-header <iqser-page-header
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()" (closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[pageLabel]="'permissions-screen.label' | translate: { targetObject: this.targetObject }" [pageLabel]="'permissions-screen.label' | translate: { targetObject: this.targetObject }"
[showCloseButton]="currentUser.isUser" [showCloseButton]="permissionsService.has$(roles.dossiers.read) | async"
></iqser-page-header> ></iqser-page-header>
<iqser-table [itemSize]="80" [tableColumnConfigs]="tableColumnConfigs"></iqser-table> <iqser-table [itemSize]="80" [tableColumnConfigs]="tableColumnConfigs"></iqser-table>

View File

@ -1,5 +1,12 @@
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ListingComponent, listingProvidersFactory, LoadingService, SortingOrders, TableColumnConfig } from '@iqser/common-ui'; import {
IqserPermissionsService,
ListingComponent,
listingProvidersFactory,
LoadingService,
SortingOrders,
TableColumnConfig,
} from '@iqser/common-ui';
import { PermissionsMapping } from '@red/domain'; import { PermissionsMapping } from '@red/domain';
import { ConfigService } from '../config.service'; import { ConfigService } from '../config.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@ -11,8 +18,8 @@ import { firstValueFrom } from 'rxjs';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { permissionsTranslations } from '@translations/permissions-translations'; import { permissionsTranslations } from '@translations/permissions-translations';
import { UserService } from '@users/user.service';
import { RouterHistoryService } from '@services/router-history.service'; import { RouterHistoryService } from '@services/router-history.service';
import { ROLES } from '@users/roles';
@UntilDestroy() @UntilDestroy()
@Component({ @Component({
@ -22,7 +29,7 @@ import { RouterHistoryService } from '@services/router-history.service';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class PermissionsScreenComponent extends ListingComponent<PermissionsMapping> { export class PermissionsScreenComponent extends ListingComponent<PermissionsMapping> {
readonly currentUser = inject(UserService).currentUser; readonly roles = ROLES;
readonly translations = permissionsTranslations; readonly translations = permissionsTranslations;
readonly tableColumnConfigs: TableColumnConfig<PermissionsMapping>[]; readonly tableColumnConfigs: TableColumnConfig<PermissionsMapping>[];
readonly tableHeaderLabel = _('permissions-screen.table-header.title'); readonly tableHeaderLabel = _('permissions-screen.table-header.title');
@ -34,6 +41,7 @@ export class PermissionsScreenComponent extends ListingComponent<PermissionsMapp
configService: ConfigService, configService: ConfigService,
private readonly _loadingService: LoadingService, private readonly _loadingService: LoadingService,
readonly routerHistoryService: RouterHistoryService, readonly routerHistoryService: RouterHistoryService,
readonly permissionsService: IqserPermissionsService,
private readonly _permissionsMapService: PermissionsMapService, private readonly _permissionsMapService: PermissionsMapService,
private readonly _entityPermissionsService: EntityPermissionsService, private readonly _entityPermissionsService: EntityPermissionsService,
permissionsConfigurationMapService: PermissionsConfigurationMapService, permissionsConfigurationMapService: PermissionsConfigurationMapService,

View File

@ -6,7 +6,7 @@ import { TableItemComponent } from './components/table-item/table-item.component
import { SharedModule } from '@shared/shared.module'; import { SharedModule } from '@shared/shared.module';
import { ConfigService } from './services/config.service'; import { ConfigService } from './services/config.service';
import { SharedDossiersModule } from '../shared-dossiers/shared-dossiers.module'; import { SharedDossiersModule } from '../shared-dossiers/shared-dossiers.module';
import { IqserButtonsModule, IqserHelpModeModule, IqserListingModule, IqserUsersModule } from '@iqser/common-ui'; import { IqserButtonsModule, IqserHelpModeModule, IqserListingModule, IqserPermissionsModule, IqserUsersModule } from '@iqser/common-ui';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
const components = [TableItemComponent]; const components = [TableItemComponent];
@ -24,6 +24,7 @@ const screens = [ArchivedDossiersScreenComponent];
TranslateModule, TranslateModule,
IqserListingModule, IqserListingModule,
IqserButtonsModule, IqserButtonsModule,
IqserPermissionsModule,
], ],
providers: [ConfigService], providers: [ConfigService],
}) })

View File

@ -16,11 +16,16 @@
<div class="action-buttons"> <div class="action-buttons">
<iqser-circle-button <iqser-circle-button
(action)="openEditDossierDialog($event, dossier.id)" (action)="openEditDossierDialog($event, dossier.id)"
*ngIf="currentUser.isUser" *allow="roles.dossiers.read"
[icon]="currentUser.isManager ? 'iqser:edit' : 'red:info'" [icon]="(permissionsService.has$(roles.dossiers.edit) | async) ? 'iqser:edit' : 'red:info'"
[iqserHelpMode]="'edit_dossier_dossier_info'" [iqserHelpMode]="'edit_dossier_dossier_info'"
[scrollableParentView]="scrollableParentView" [scrollableParentView]="scrollableParentView"
[tooltip]="(currentUser.isManager ? 'dossier-listing.edit.action' : 'dossier-listing.dossier-info.action') | translate" [tooltip]="
((permissionsService.has$(roles.dossiers.edit) | async)
? 'dossier-listing.edit.action'
: 'dossier-listing.dossier-info.action'
) | translate
"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"
></iqser-circle-button> ></iqser-circle-button>
</div> </div>

View File

@ -3,9 +3,9 @@ import { Dossier, DossierStats } from '@red/domain';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { DossierStatsService } from '@services/dossiers/dossier-stats.service'; import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
import { switchMap } from 'rxjs/operators'; import { switchMap } from 'rxjs/operators';
import { CircleButtonTypes, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui'; import { CircleButtonTypes, IqserPermissionsService, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui';
import { UserService } from '@users/user.service';
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-table-item [dossier]', selector: 'redaction-table-item [dossier]',
@ -14,7 +14,7 @@ import { DossiersDialogService } from '../../../shared-dossiers/services/dossier
}) })
export class TableItemComponent implements OnChanges { export class TableItemComponent implements OnChanges {
readonly circleButtonTypes = CircleButtonTypes; readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = this._userService.currentUser; readonly roles = ROLES;
@Input() dossier!: Dossier; @Input() dossier!: Dossier;
readonly stats$: Observable<DossierStats>; readonly stats$: Observable<DossierStats>;
@ -22,8 +22,8 @@ export class TableItemComponent implements OnChanges {
constructor( constructor(
readonly dossierStatsService: DossierStatsService, readonly dossierStatsService: DossierStatsService,
readonly permissionsService: IqserPermissionsService,
private readonly _dialogService: DossiersDialogService, private readonly _dialogService: DossiersDialogService,
private readonly _userService: UserService,
) { ) {
this.stats$ = this.#ngOnChanges$.pipe(switchMap(dossierId => this.dossierStatsService.watch$(dossierId))); this.stats$ = this.#ngOnChanges$.pipe(switchMap(dossierId => this.dossierStatsService.watch$(dossierId)));
} }

View File

@ -19,7 +19,7 @@
<iqser-circle-button <iqser-circle-button
(action)="editingOwner = true" (action)="editingOwner = true"
*ngIf="currentUser.isManager" *allow="roles.dossiers.edit"
[icon]="'iqser:edit'" [icon]="'iqser:edit'"
[iqserHelpMode]="'dashboard_in_dossier'" [iqserHelpMode]="'dashboard_in_dossier'"
[tooltipPosition]="'below'" [tooltipPosition]="'below'"
@ -42,6 +42,7 @@
<ng-container *ngIf="ctx.dossierStats as stats"> <ng-container *ngIf="ctx.dossierStats as stats">
<div *ngIf="stats.hasFiles" class="mt-24"> <div *ngIf="stats.hasFiles" class="mt-24">
<redaction-donut-chart <redaction-donut-chart
(subtitleChanged)="onSubtitleChanged($event)"
[config]="chartConfig" [config]="chartConfig"
[filterKey]="'statusFilters'" [filterKey]="'statusFilters'"
[helpModeKey]="'filter_document_list'" [helpModeKey]="'filter_document_list'"
@ -51,7 +52,6 @@
'dossier-overview.dossier-details.charts.documents-in-dossier' | translate, 'dossier-overview.dossier-details.charts.documents-in-dossier' | translate,
'dossier-overview.dossier-details.charts.pages-in-dossier' | translate 'dossier-overview.dossier-details.charts.pages-in-dossier' | translate
]" ]"
(subtitleChanged)="onSubtitleChanged($event)"
direction="row" direction="row"
></redaction-donut-chart> ></redaction-donut-chart>
</div> </div>

View File

@ -18,9 +18,10 @@ import { workflowFileStatusTranslations } from '@translations/file-status-transl
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { combineLatestWith, firstValueFrom, Observable } from 'rxjs'; import { combineLatestWith, firstValueFrom, Observable } from 'rxjs';
import { DossierStatsService } from '@services/dossiers/dossier-stats.service'; import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
import { map, tap } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { DossiersService } from '@services/dossiers/dossiers.service'; import { DossiersService } from '@services/dossiers/dossiers.service';
import { FilesMapService } from '@services/files/files-map.service'; import { FilesMapService } from '@services/files/files-map.service';
import { ROLES } from '@users/roles';
interface DossierDetailsContext { interface DossierDetailsContext {
needsWorkFilters: INestedFilter[] | undefined; needsWorkFilters: INestedFilter[] | undefined;
@ -42,20 +43,18 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
@Output() readonly toggleCollapse = new EventEmitter(); @Output() readonly toggleCollapse = new EventEmitter();
editingOwner = false; editingOwner = false;
#currentChartSubtitleIndex = 0; readonly roles = ROLES;
readonly #dossierId: string;
readonly collapseTooltip = _('dossier-details.collapse'); readonly collapseTooltip = _('dossier-details.collapse');
readonly expandTooltip = _('dossier-details.expand'); readonly expandTooltip = _('dossier-details.expand');
readonly needsWorkFilters$ = this.filterService.getFilterModels$('needsWorkFilters'); readonly needsWorkFilters$ = this.filterService.getFilterModels$('needsWorkFilters');
readonly currentUser = this._userService.currentUser;
readonly dossier$: Observable<Dossier>; readonly dossier$: Observable<Dossier>;
readonly dossierStats$: Observable<DossierStats>; readonly dossierStats$: Observable<DossierStats>;
readonly filesChanged$: Observable<boolean>; readonly filesChanged$: Observable<boolean>;
readonly chartConfig$: Observable<void>; readonly chartConfig$: Observable<void>;
readonly statusConfig$: Observable<ProgressBarConfigModel[]>; readonly statusConfig$: Observable<ProgressBarConfigModel[]>;
chartConfig: DonutChartConfig[] = []; chartConfig: DonutChartConfig[] = [];
#currentChartSubtitleIndex = 0;
readonly #dossierId: string;
constructor( constructor(
private readonly _toaster: Toaster, private readonly _toaster: Toaster,
@ -78,6 +77,10 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
this.statusConfig$ = this.dossierStats$.pipe(map(stats => this.#calculateStatusConfig(stats))); this.statusConfig$ = this.dossierStats$.pipe(map(stats => this.#calculateStatusConfig(stats)));
} }
get managers() {
return this._userService.all.filter(u => u.has(ROLES.dossiers.write) || u.isManager).map(u => u.id);
}
ngOnInit() { ngOnInit() {
super._initContext({ super._initContext({
needsWorkFilters: this.needsWorkFilters$, needsWorkFilters: this.needsWorkFilters$,
@ -89,10 +92,6 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
}); });
} }
get managers() {
return this._userService.managerUsers.map(manager => manager.id);
}
async assignOwner(user: User | string, dossier: Dossier) { async assignOwner(user: User | string, dossier: Dossier) {
const owner = typeof user === 'string' ? this._userService.find(user) : user; const owner = typeof user === 'string' ? this._userService.find(user) : user;
const dossierRequest: IDossierRequest = { ...dossier, ownerId: owner.id }; const dossierRequest: IDossierRequest = { ...dossier, ownerId: owner.id };
@ -103,6 +102,11 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
this._toaster.success(_('assignment.owner'), { params: { ownerName, dossierName } }); this._toaster.success(_('assignment.owner'), { params: { ownerName, dossierName } });
} }
onSubtitleChanged(subtitleIndex: number) {
this.#currentChartSubtitleIndex = subtitleIndex;
this.#calculateChartConfig(this.dossierStatsService.get(this.#dossierId));
}
#calculateChartConfig(stats: DossierStats): void { #calculateChartConfig(stats: DossierStats): void {
const documentsChartConfig: DonutChartConfig[] = Object.keys(stats.fileCountPerWorkflowStatus).map(status => ({ const documentsChartConfig: DonutChartConfig[] = Object.keys(stats.fileCountPerWorkflowStatus).map(status => ({
value: !this.#currentChartSubtitleIndex value: !this.#currentChartSubtitleIndex
@ -155,9 +159,4 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
}, },
].filter(config => config.count > 0); ].filter(config => config.count > 0);
} }
onSubtitleChanged(subtitleIndex: number) {
this.#currentChartSubtitleIndex = subtitleIndex;
this.#calculateChartConfig(this.dossierStatsService.get(this.#dossierId));
}
} }

View File

@ -37,7 +37,7 @@
<iqser-circle-button <iqser-circle-button
(action)="upload.emit()" (action)="upload.emit()"
*allow="roles.files.upload; if: permissionsService.canUploadFiles(dossier)" *ngIf="permissionsService.canUploadFiles(dossier)"
[icon]="'iqser:upload'" [icon]="'iqser:upload'"
[id]="'upload-document-btn'" [id]="'upload-document-btn'"
[iqserHelpMode]="'edit_dossier_in_dossier'" [iqserHelpMode]="'edit_dossier_in_dossier'"

View File

@ -4,6 +4,7 @@ import {
getParam, getParam,
IFilterGroup, IFilterGroup,
INestedFilter, INestedFilter,
IqserPermissionsService,
keyChecker, keyChecker,
List, List,
ListingMode, ListingMode,
@ -41,6 +42,7 @@ import { map } from 'rxjs/operators';
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
import { UserPreferenceService } from '@users/user-preference.service'; import { UserPreferenceService } from '@users/user-preference.service';
import { DossiersService } from '@services/dossiers/dossiers.service'; import { DossiersService } from '@services/dossiers/dossiers.service';
import { ROLES } from '@users/roles';
@Injectable() @Injectable()
export class ConfigService { export class ConfigService {
@ -59,6 +61,7 @@ export class ConfigService {
private readonly _dictionariesMapService: DictionariesMapService, private readonly _dictionariesMapService: DictionariesMapService,
private readonly _userPreferenceService: UserPreferenceService, private readonly _userPreferenceService: UserPreferenceService,
private readonly _dossiersService: DossiersService, private readonly _dossiersService: DossiersService,
private readonly _iqserPermissionsService: IqserPermissionsService,
) { ) {
this.listingMode$ = this._listingMode$.asObservable(); this.listingMode$ = this._listingMode$.asObservable();
@ -72,7 +75,7 @@ export class ConfigService {
set listingMode(listingMode: ListingMode) { set listingMode(listingMode: ListingMode) {
this._listingMode$.next(listingMode); this._listingMode$.next(listingMode);
this._userPreferenceService.saveFilesListingMode(listingMode); this._userPreferenceService.saveFilesListingMode(listingMode).then();
} }
get #dossier() { get #dossier() {
@ -152,7 +155,7 @@ export class ConfigService {
label: this._translateService.instant('dossier-overview.header-actions.edit'), label: this._translateService.instant('dossier-overview.header-actions.edit'),
action: $event => this._openEditDossierDialog($event, dossierId), action: $event => this._openEditDossierDialog($event, dossierId),
icon: 'iqser:edit', icon: 'iqser:edit',
hide: !this._userService.currentUser.isManager, hide: !this._iqserPermissionsService.has(ROLES.dossiers.edit),
helpModeKey: 'edit_dossier_in_dossier', helpModeKey: 'edit_dossier_in_dossier',
disabled$, disabled$,
}, },

View File

@ -1,11 +1,16 @@
<div (longPress)="forceReanalysisAction($event)" class="action-buttons" redactionLongPress> <div (longPress)="forceReanalysisAction($event)" class="action-buttons" redactionLongPress>
<iqser-circle-button <iqser-circle-button
(action)="openEditDossierDialog($event, dossier.id)" (action)="openEditDossierDialog($event, dossier.id)"
*ngIf="currentUser.isUser" *allow="roles.dossiers.read"
[icon]="currentUser.isManager ? 'iqser:edit' : 'red:info'" [icon]="(iqserPermissionsService.has$(roles.dossiers.edit) | async) ? 'iqser:edit' : 'red:info'"
[iqserHelpMode]="'edit_dossier_dossier_info'" [iqserHelpMode]="'edit_dossier_dossier_info'"
[scrollableParentView]="scrollableParentView" [scrollableParentView]="scrollableParentView"
[tooltip]="(currentUser.isManager ? 'dossier-listing.edit.action' : 'dossier-listing.dossier-info.action') | translate" [tooltip]="
((iqserPermissionsService.has$(roles.dossiers.edit) | async)
? 'dossier-listing.edit.action'
: 'dossier-listing.dossier-info.action'
) | translate
"
[type]="circleButtonTypes.dark" [type]="circleButtonTypes.dark"
></iqser-circle-button> ></iqser-circle-button>

View File

@ -1,7 +1,6 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
import { PermissionsService } from '@services/permissions.service'; import { PermissionsService } from '@services/permissions.service';
import { CircleButtonTypes, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui'; import { CircleButtonTypes, IqserPermissionsService, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui';
import { UserService } from '@users/user.service';
import { Dossier, DossierStats, File } from '@red/domain'; import { Dossier, DossierStats, File } from '@red/domain';
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
import { LongPressEvent } from '@shared/directives/long-press.directive'; import { LongPressEvent } from '@shared/directives/long-press.directive';
@ -9,6 +8,7 @@ import { UserPreferenceService } from '@users/user-preference.service';
import { FilesMapService } from '@services/files/files-map.service'; import { FilesMapService } from '@services/files/files-map.service';
import { ReanalysisService } from '@services/reanalysis.service'; import { ReanalysisService } from '@services/reanalysis.service';
import { firstValueFrom } from 'rxjs'; import { firstValueFrom } from 'rxjs';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-dossiers-listing-actions', selector: 'redaction-dossiers-listing-actions',
@ -17,7 +17,7 @@ import { firstValueFrom } from 'rxjs';
}) })
export class DossiersListingActionsComponent implements OnChanges { export class DossiersListingActionsComponent implements OnChanges {
readonly circleButtonTypes = CircleButtonTypes; readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = this._userService.currentUser; readonly roles = ROLES;
analysisForced: boolean; analysisForced: boolean;
files: File[]; files: File[];
@ -28,8 +28,8 @@ export class DossiersListingActionsComponent implements OnChanges {
constructor( constructor(
private readonly _reanalysisService: ReanalysisService, private readonly _reanalysisService: ReanalysisService,
private readonly _userService: UserService,
readonly permissionsService: PermissionsService, readonly permissionsService: PermissionsService,
readonly iqserPermissionsService: IqserPermissionsService,
readonly filesMapService: FilesMapService, readonly filesMapService: FilesMapService,
private readonly _dialogService: DossiersDialogService, private readonly _dialogService: DossiersDialogService,
private readonly _userPreferenceService: UserPreferenceService, private readonly _userPreferenceService: UserPreferenceService,

View File

@ -5,6 +5,7 @@ import {
IqserHelpModeModule, IqserHelpModeModule,
IqserIconsModule, IqserIconsModule,
IqserListingModule, IqserListingModule,
IqserPermissionsModule,
IqserScrollbarModule, IqserScrollbarModule,
IqserSharedModule, IqserSharedModule,
IqserUsersModule, IqserUsersModule,
@ -56,6 +57,7 @@ const routes: Routes = [
IqserListingModule, IqserListingModule,
IqserScrollbarModule, IqserScrollbarModule,
IqserSharedModule, IqserSharedModule,
IqserPermissionsModule,
], ],
}) })
export class DossiersListingModule {} export class DossiersListingModule {}

View File

@ -4,7 +4,7 @@ import { Dossier } from '@red/domain';
import { EditDossierGeneralInfoComponent } from './general-info/edit-dossier-general-info.component'; import { EditDossierGeneralInfoComponent } from './general-info/edit-dossier-general-info.component';
import { EditDossierDownloadPackageComponent } from './download-package/edit-dossier-download-package.component'; import { EditDossierDownloadPackageComponent } from './download-package/edit-dossier-download-package.component';
import { EditDossierSectionInterface } from './edit-dossier-section.interface'; import { EditDossierSectionInterface } from './edit-dossier-section.interface';
import { BaseDialogComponent, ConfirmOptions, IconButtonTypes, SaveOptions } from '@iqser/common-ui'; import { BaseDialogComponent, ConfirmOptions, IconButtonTypes, IqserPermissionsService, SaveOptions } from '@iqser/common-ui';
import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component'; import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component';
import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component'; import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component';
@ -13,9 +13,9 @@ import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators'; import { tap } from 'rxjs/operators';
import { EditDossierTeamComponent } from './edit-dossier-team/edit-dossier-team.component'; import { EditDossierTeamComponent } from './edit-dossier-team/edit-dossier-team.component';
import { PermissionsService } from '@services/permissions.service'; import { PermissionsService } from '@services/permissions.service';
import { getCurrentUser } from '@users/user.service';
import { DossiersService } from '@services/dossiers/dossiers.service'; import { DossiersService } from '@services/dossiers/dossiers.service';
import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider';
import { ROLES } from '@users/roles';
type Section = 'dossierInfo' | 'downloadPackage' | 'dossierDictionary' | 'members' | 'dossierAttributes'; type Section = 'dossierInfo' | 'downloadPackage' | 'dossierDictionary' | 'members' | 'dossierAttributes';
@ -42,12 +42,12 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
@ViewChild(EditDossierDictionaryComponent) dictionaryComponent: EditDossierDictionaryComponent; @ViewChild(EditDossierDictionaryComponent) dictionaryComponent: EditDossierDictionaryComponent;
@ViewChild(EditDossierTeamComponent) membersComponent: EditDossierTeamComponent; @ViewChild(EditDossierTeamComponent) membersComponent: EditDossierTeamComponent;
@ViewChild(EditDossierAttributesComponent) attributesComponent: EditDossierAttributesComponent; @ViewChild(EditDossierAttributesComponent) attributesComponent: EditDossierAttributesComponent;
readonly #currentUser = getCurrentUser();
private _dossier: Dossier; private _dossier: Dossier;
constructor( constructor(
private readonly _dossiersService: DossiersService, private readonly _dossiersService: DossiersService,
private readonly _permissionsService: PermissionsService, private readonly _permissionsService: PermissionsService,
private readonly _iqserPermissionsService: IqserPermissionsService,
protected readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>, protected readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>,
@Inject(MAT_DIALOG_DATA) @Inject(MAT_DIALOG_DATA)
private readonly _data: { private readonly _data: {
@ -89,7 +89,8 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
get showActionButtons(): boolean { get showActionButtons(): boolean {
return ( return (
(['members'].includes(this.activeNav) && this.#currentUser.isManager) || this._permissionsService.canEditDossier(this._dossier) (['members'].includes(this.activeNav) && this._iqserPermissionsService.has(ROLES.dossiers.edit)) ||
this._permissionsService.canEditDossier(this._dossier)
); );
} }

View File

@ -8,6 +8,7 @@ import { PermissionsService } from '@services/permissions.service';
import { DossiersService } from '@services/dossiers/dossiers.service'; import { DossiersService } from '@services/dossiers/dossiers.service';
import { compareLists } from '@utils/functions'; import { compareLists } from '@utils/functions';
import { FilesService } from '@services/files/files.service'; import { FilesService } from '@services/files/files.service';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-edit-dossier-team', selector: 'redaction-edit-dossier-team',
@ -23,7 +24,7 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
membersSelectOptions: string[] = []; membersSelectOptions: string[] = [];
readonly ownersSelectOptions = this.userService.managerUsers.map(m => m.id); readonly ownersSelectOptions = this.userService.all.filter(u => u.has(ROLES.dossiers.write) || u.isManager).map(m => m.id);
readonly selectedReviewers$ = new BehaviorSubject<string[]>([]); readonly selectedReviewers$ = new BehaviorSubject<string[]>([]);
constructor( constructor(
@ -137,7 +138,8 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
} }
setMembersSelectOptions(value = this.searchQuery): void { setMembersSelectOptions(value = this.searchQuery): void {
this.membersSelectOptions = this.userService.eligibleUsers const possibleMembers = this.userService.all.filter(user => user.has(ROLES.dossiers.read) || user.isUser || user.isManager);
this.membersSelectOptions = possibleMembers
.filter(user => this.userService.getName(user.id).toLowerCase().includes(value.toLowerCase())) .filter(user => this.userService.getName(user.id).toLowerCase().includes(value.toLowerCase()))
.filter(user => this.selectedOwnerId !== user.id) .filter(user => this.selectedOwnerId !== user.id)
.map(user => user.id); .map(user => user.id);

View File

@ -19,7 +19,7 @@
<iqser-circle-button <iqser-circle-button
(action)="openEditDossierDialog()" (action)="openEditDossierDialog()"
*ngIf="currentUser.isManager && canAdd" *allow="roles.dossiers.edit; if: canAdd"
[class.large-spacing]="largeSpacing" [class.large-spacing]="largeSpacing"
[icon]="'iqser:plus'" [icon]="'iqser:plus'"
[iqserHelpMode]="'edit_dossier_members'" [iqserHelpMode]="'edit_dossier_members'"

View File

@ -1,7 +1,7 @@
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'; import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { CircleButtonTypes, List } from '@iqser/common-ui'; import { CircleButtonTypes, List } from '@iqser/common-ui';
import { UserService } from '@users/user.service';
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
import { ROLES } from '@users/roles';
@Component({ @Component({
selector: 'redaction-team-members', selector: 'redaction-team-members',
@ -10,7 +10,7 @@ import { DossiersDialogService } from '../../../shared-dossiers/services/dossier
}) })
export class TeamMembersComponent { export class TeamMembersComponent {
readonly circleButtonTypes = CircleButtonTypes; readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = this._userService.currentUser; readonly roles = ROLES;
@Input() memberIds: List; @Input() memberIds: List;
@Input() perLine: number; @Input() perLine: number;
@ -25,7 +25,7 @@ export class TeamMembersComponent {
expandedTeam = false; expandedTeam = false;
constructor(private readonly _userService: UserService, private readonly _dialogService: DossiersDialogService) {} constructor(private readonly _dialogService: DossiersDialogService) {}
get maxTeamMembersBeforeExpand(): number { get maxTeamMembersBeforeExpand(): number {
return this.perLine - (this.canAdd ? 1 : 0); return this.perLine - (this.canAdd ? 1 : 0);

View File

@ -8,7 +8,14 @@ import { IconsModule } from '../icons/icons.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AnnotationIconComponent } from './components/annotation-icon/annotation-icon.component'; import { AnnotationIconComponent } from './components/annotation-icon/annotation-icon.component';
import { DonutChartComponent } from './components/donut-chart/donut-chart.component'; import { DonutChartComponent } from './components/donut-chart/donut-chart.component';
import { IqserButtonsModule, IqserHelpModeModule, IqserScrollbarModule, IqserSharedModule, IqserUsersModule } from '@iqser/common-ui'; import {
IqserButtonsModule,
IqserHelpModeModule,
IqserPermissionsModule,
IqserScrollbarModule,
IqserSharedModule,
IqserUsersModule,
} from '@iqser/common-ui';
import { SelectComponent } from './components/select/select.component'; import { SelectComponent } from './components/select/select.component';
import { NavigateLastDossiersScreenDirective } from './directives/navigate-last-dossiers-screen.directive'; import { NavigateLastDossiersScreenDirective } from './directives/navigate-last-dossiers-screen.directive';
import { DictionaryManagerComponent } from './components/dictionary-manager/dictionary-manager.component'; import { DictionaryManagerComponent } from './components/dictionary-manager/dictionary-manager.component';
@ -81,6 +88,7 @@ const modules = [MatConfigModule, ScrollingModule, IconsModule, FormsModule, Rea
IqserButtonsModule, IqserButtonsModule,
IqserSharedModule, IqserSharedModule,
IqserScrollbarModule, IqserScrollbarModule,
IqserPermissionsModule,
], ],
exports: [...modules, ...components, ...utils], exports: [...modules, ...components, ...utils],
providers: [ providers: [

View File

@ -3,6 +3,8 @@ import { UserService } from '@users/user.service';
import { DashboardStats, Dictionary, Dossier, DOSSIERS_ARCHIVE, DossierTemplate, File, IComment, IDossier } from '@red/domain'; import { DashboardStats, Dictionary, Dossier, DOSSIERS_ARCHIVE, DossierTemplate, File, IComment, IDossier } from '@red/domain';
import { FilesMapService } from '@services/files/files-map.service'; import { FilesMapService } from '@services/files/files-map.service';
import { FeaturesService } from '@services/features.service'; import { FeaturesService } from '@services/features.service';
import { IqserPermissionsService } from '@iqser/common-ui';
import { ROLES } from '@users/roles';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class PermissionsService { export class PermissionsService {
@ -10,6 +12,7 @@ export class PermissionsService {
private readonly _userService: UserService, private readonly _userService: UserService,
private readonly _filesMapService: FilesMapService, private readonly _filesMapService: FilesMapService,
private readonly _featuresService: FeaturesService, private readonly _featuresService: FeaturesService,
private readonly _iqserPermissionsService: IqserPermissionsService,
) {} ) {}
get #userId(): string { get #userId(): string {
@ -21,16 +24,16 @@ export class PermissionsService {
} }
canEditEntities(): boolean { canEditEntities(): boolean {
return this.isAdmin(); return this._iqserPermissionsService.has(ROLES.dictionaryTypes.write);
} }
canDeleteEntities(entity: Dictionary | Dictionary[]): boolean { canDeleteEntities(entity: Dictionary | Dictionary[]): boolean {
const entities = entity instanceof Dictionary ? [entity] : entity; const entities = entity instanceof Dictionary ? [entity] : entity;
return entities.length && this.canEditEntities() && entities.reduce((acc, _entity) => this._canDeleteEntity(_entity) && acc, true); return (
} entities.length &&
this._iqserPermissionsService.has(ROLES.dictionaryTypes.delete) &&
canPerformDossierStatesActions(): boolean { entities.reduce((acc, _entity) => this._canDeleteEntity(_entity) && acc, true)
return this.isAdmin(); );
} }
isAssigneeOrApprover(file: File, dossier: Dossier): boolean { isAssigneeOrApprover(file: File, dossier: Dossier): boolean {
@ -38,11 +41,15 @@ export class PermissionsService {
} }
displayReanalyseBtn(dossier: Dossier): boolean { displayReanalyseBtn(dossier: Dossier): boolean {
return this.isApprover(dossier) && !!this._filesMapService.get(dossier.id).find(f => f.analysisRequired); return (
this._iqserPermissionsService.has(ROLES.files.reanalyze) &&
this.isApprover(dossier) &&
!!this._filesMapService.get(dossier.id).find(f => f.analysisRequired)
);
} }
canUploadFiles(dossier: Dossier): boolean { canUploadFiles(dossier: Dossier): boolean {
return dossier.isActive; return this._iqserPermissionsService.has(ROLES.files.upload) && dossier.isActive;
} }
canDownloadCsvReport(dossier: Dossier): boolean { canDownloadCsvReport(dossier: Dossier): boolean {
@ -68,7 +75,10 @@ export class PermissionsService {
canReanalyseFile(file: File | File[], dossier: Dossier): boolean { canReanalyseFile(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file; const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canReanalyseFile(_file, dossier) && acc, true); return (
this._iqserPermissionsService.has(ROLES.files.reanalyze) &&
files.reduce((acc, _file) => this._canReanalyseFile(_file, dossier) && acc, true)
);
} }
canEnableAutoAnalysis(files: File[], dossier: Dossier): boolean { canEnableAutoAnalysis(files: File[], dossier: Dossier): boolean {
@ -85,7 +95,10 @@ export class PermissionsService {
canSoftDeleteFile(file: File | File[], dossier: Dossier): boolean { canSoftDeleteFile(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file; const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canSoftDeleteFile(_file, dossier) && acc, true); return (
this._iqserPermissionsService.has(ROLES.files.delete) &&
files.reduce((acc, _file) => this._canSoftDeleteFile(_file, dossier) && acc, true)
);
} }
canRestoreFile(file: File | File[], dossier: Dossier): boolean { canRestoreFile(file: File | File[], dossier: Dossier): boolean {
@ -95,27 +108,42 @@ export class PermissionsService {
canHardDeleteFile(file: File | File[], dossier: Dossier): boolean { canHardDeleteFile(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file; const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canHardDeleteFile(_file, dossier) && acc, true); return (
this._iqserPermissionsService.has(ROLES.files.delete) &&
files.reduce((acc, _file) => this._canHardDeleteFile(_file, dossier) && acc, true)
);
} }
canOcrFile(file: File | File[], dossier: Dossier): boolean { canOcrFile(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file; const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canOcrFile(_file, dossier) && acc, true); return (
this._iqserPermissionsService.has(ROLES.files.reanalyze) &&
files.reduce((acc, _file) => this._canOcrFile(_file, dossier) && acc, true)
);
} }
canAssignToSelf(file: File | File[], dossier: Dossier): boolean { canAssignToSelf(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file; const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canAssignToSelf(_file, dossier) && acc, true); return (
this._iqserPermissionsService.has(ROLES.setReviewer) &&
files.reduce((acc, _file) => this._canAssignToSelf(_file, dossier) && acc, true)
);
} }
canAssignUser(file: File | File[], dossier: Dossier): boolean { canAssignUser(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file; const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canAssignUser(_file, dossier) && acc, true); return (
this._iqserPermissionsService.has(ROLES.setReviewer) &&
files.reduce((acc, _file) => this._canAssignUser(_file, dossier) && acc, true)
);
} }
canUnassignUser(file: File | File[], dossier: Dossier): boolean { canUnassignUser(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file; const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canUnassignUser(_file, dossier) && acc, true); return (
this._iqserPermissionsService.has(ROLES.setReviewer) &&
files.reduce((acc, _file) => this._canUnassignUser(_file, dossier) && acc, true)
);
} }
canSetToNew(file: File | File[], dossier: Dossier): boolean { canSetToNew(file: File | File[], dossier: Dossier): boolean {
@ -185,11 +213,11 @@ export class PermissionsService {
} }
canSoftDeleteDossier(dossier: IDossier): boolean { canSoftDeleteDossier(dossier: IDossier): boolean {
return this.isOwner(dossier) || (this.isManager() && this.isDossierMember(dossier)); return this._iqserPermissionsService.has(ROLES.dossiers.delete) && (this.isOwner(dossier) || this.isDossierMember(dossier));
} }
canHardDeleteDossier(dossier: IDossier): boolean { canHardDeleteDossier(dossier: IDossier): boolean {
return this.isOwner(dossier); return this.isOwner(dossier) && this._iqserPermissionsService.has(ROLES.dossiers.delete);
} }
canRestoreDossier(dossier: IDossier): boolean { canRestoreDossier(dossier: IDossier): boolean {
@ -197,7 +225,7 @@ export class PermissionsService {
} }
canCreateDossier(dossierTemplate: DossierTemplate | DashboardStats): boolean { canCreateDossier(dossierTemplate: DossierTemplate | DashboardStats): boolean {
return dossierTemplate.isActive && this.isManager(); return dossierTemplate.isActive && this._iqserPermissionsService.has(ROLES.dossiers.write);
} }
canArchiveDossier(dossier: Dossier): boolean { canArchiveDossier(dossier: Dossier): boolean {
@ -205,7 +233,7 @@ export class PermissionsService {
} }
canEditDossier(dossier: Dossier): boolean { canEditDossier(dossier: Dossier): boolean {
return this.isManager() && !!dossier?.ownerId; return this._iqserPermissionsService.has(ROLES.dossiers.edit) && !!dossier?.ownerId;
} }
canEditDossierDictionary(dossier: Dossier): boolean { canEditDossierDictionary(dossier: Dossier): boolean {
@ -217,7 +245,7 @@ export class PermissionsService {
} }
canEditTeamMembers(): boolean { canEditTeamMembers(): boolean {
return this.isManager(); return this._iqserPermissionsService.has(ROLES.dossiers.edit);
} }
isAdmin(): boolean { isAdmin(): boolean {

View File

@ -20,11 +20,11 @@ export const ROLES = {
RED_REINDEX: 'red-reindex', RED_REINDEX: 'red-reindex',
RED_REQUEST_REDACTION: 'red-request-redaction', RED_REQUEST_REDACTION: 'red-request-redaction',
RED_ROTATE_PAGE: 'red-rotate-page', RED_ROTATE_PAGE: 'red-rotate-page',
RED_SET_REVIEWER: 'red-set-reviewer',
RED_SET_STATUS_APPROVED: 'red-set-status-approved', RED_SET_STATUS_APPROVED: 'red-set-status-approved',
RED_SET_STATUS_UNDER_APPROVAL: 'red-set-status-under-approval', RED_SET_STATUS_UNDER_APPROVAL: 'red-set-status-under-approval',
RED_UPDATE_MY_PROFILE: 'red-update-my-profile', RED_UPDATE_MY_PROFILE: 'red-update-my-profile',
RED_WRITE_RULES: 'red-write-rules', RED_WRITE_RULES: 'red-write-rules',
setReviewer: 'red-set-reviewer',
readDownloadStatus: 'red-read-download-status', readDownloadStatus: 'red-read-download-status',
readRedactionLog: 'red-read-redaction-log', readRedactionLog: 'red-read-redaction-log',
search: 'red-search', search: 'red-search',

View File

@ -11,14 +11,6 @@ export class UserService extends IqserUserService<IIqserUser, User> {
protected readonly _defaultModelPath = 'user'; protected readonly _defaultModelPath = 'user';
protected readonly _entityClass = User; protected readonly _entityClass = User;
get managerUsers(): User[] {
return this.all.filter(user => user.isManager);
}
get eligibleUsers(): User[] {
return this.all.filter(user => user.isUser || user.isManager);
}
async loadCurrentUser(): Promise<User | undefined> { async loadCurrentUser(): Promise<User | undefined> {
const currentUser = await super.loadCurrentUser(); const currentUser = await super.loadCurrentUser();

View File

@ -87,8 +87,6 @@ export const dossierTemplateChecker = (dw: Dossier, filter: INestedFilter) => dw
export const dossierStateChecker = (dw: Dossier, filter: INestedFilter) => export const dossierStateChecker = (dw: Dossier, filter: INestedFilter) =>
dw.dossierStatusId === (filter.id === 'undefined' ? null : filter.id); dw.dossierStatusId === (filter.id === 'undefined' ? null : filter.id);
export const dossierApproverChecker = (dw: Dossier, filter: INestedFilter) => dw.approverIds.includes(filter.id);
export const userTypeFilters: { [key in UserType]: (user: User) => boolean } = { export const userTypeFilters: { [key in UserType]: (user: User) => boolean } = {
INACTIVE: (user: User) => !user.hasAnyRole, INACTIVE: (user: User) => !user.hasAnyRole,
REGULAR: (user: User) => user.roles.length === 1 && user.roles[0] === 'RED_USER', REGULAR: (user: User) => user.roles.length === 1 && user.roles[0] === 'RED_USER',

View File

@ -6,7 +6,6 @@ export class User extends IqserUser {
readonly isUserAdmin = this.has('RED_USER_ADMIN'); readonly isUserAdmin = this.has('RED_USER_ADMIN');
readonly isUser = this.has('RED_USER'); readonly isUser = this.has('RED_USER');
readonly isAdmin = this.has('RED_ADMIN'); readonly isAdmin = this.has('RED_ADMIN');
readonly hasAnyREDRoles = this.isUser || this.isManager || this.isAdmin || this.isUserAdmin;
constructor(user: KeycloakProfile | IIqserUser, readonly roles: List, readonly userId: string) { constructor(user: KeycloakProfile | IIqserUser, readonly roles: List, readonly userId: string) {
super(user, roles, userId); super(user, roles, userId);