RED-5482: wip permissions

This commit is contained in:
Dan Percic 2022-11-13 00:30:14 +02:00
parent 0d2b816263
commit 0b4de15f07
53 changed files with 227 additions and 121 deletions

View File

@ -27,6 +27,15 @@ import { ROLES } from '@users/roles';
const dossierTemplateIdRoutes: IqserRoutes = [
{
path: `${DOSSIERS_ROUTE}`,
canActivate: [CompositeRouteGuard, IqserPermissionsGuard],
data: {
routeGuards: [DossiersGuard],
dossiersService: ACTIVE_DOSSIERS_SERVICE,
permissions: {
allow: [ROLES.files.readStatus],
redirectTo: '/auth-error',
},
},
children: [
{
path: `:${DOSSIER_ID}`,
@ -65,15 +74,6 @@ const dossierTemplateIdRoutes: IqserRoutes = [
},
},
],
canActivate: [CompositeRouteGuard, IqserPermissionsGuard],
data: {
routeGuards: [DossiersGuard],
dossiersService: ACTIVE_DOSSIERS_SERVICE,
permissions: {
allow: [ROLES.files.readStatus],
redirectTo: '/auth-error',
},
},
},
{
path: `${ARCHIVE_ROUTE}`,

View File

@ -112,14 +112,14 @@ export const appModuleFactory = (config: AppConfig) => {
features: {
ANNOTATIONS: {
color: 'aqua',
enabled: true,
enabled: false,
level: NgxLoggerLevel.DEBUG,
},
FILTERS: {
enabled: false,
},
PDF: {
enabled: true,
enabled: false,
},
FILE: {
enabled: false,

View File

@ -5,7 +5,7 @@
<div class="menu-placeholder"></div>
</ng-template>
<div *allow="roles.templates.read; else menuPlaceholder" class="flex-2 visible-lg breadcrumbs-container">
<div *allow="roles.templates.read; if: currentUser.isUser; else: menuPlaceholder" class="flex-2 visible-lg breadcrumbs-container">
<redaction-breadcrumbs></redaction-breadcrumbs>
</div>
@ -21,7 +21,7 @@
<div class="actions flex-2">
<div class="buttons">
<redaction-spotlight-search
*allow="roles.search; if: (isSearchScreen$ | async) === false"
*allow="roles.search; if: (isSearchScreen$ | async) === false && (currentUser.isUser || currentUser.isManager)"
[actions]="searchActions"
[iqserHelpMode]="'search_in_entire_application'"
[placeholder]="'search.placeholder' | translate"

View File

@ -43,19 +43,19 @@ export class BaseScreenComponent {
id: 'admin',
name: _('top-bar.navigation-items.my-account.children.admin'),
routerLink: '/main/admin',
show: this._permissionsService.has([ROLES.templates.read]),
show: (this.currentUser.isManager || this.currentUser.isUserAdmin) && this._permissionsService.has([ROLES.templates.read]),
},
{
id: 'downloads',
name: _('top-bar.navigation-items.my-account.children.downloads'),
routerLink: '/main/downloads',
show: this._permissionsService.has(ROLES.readDownloadStatus),
show: this.currentUser.isUser && this._permissionsService.has(ROLES.readDownloadStatus),
},
{
id: 'trash',
name: _('top-bar.navigation-items.my-account.children.trash'),
routerLink: '/main/trash',
show: this._permissionsService.has([ROLES.dossiers.read, ROLES.files.readStatus]),
show: this.currentUser.isUser && this._permissionsService.has([ROLES.dossiers.read, ROLES.files.readStatus]),
},
];
readonly searchActions: readonly SpotlightSearchAction[] = [

View File

@ -54,7 +54,7 @@ export class AnnotationWrapper implements IListable, Record<string, unknown> {
imported?: boolean;
image?: boolean;
manual?: boolean;
pending?: boolean;
pending = false;
hintDictionary?: boolean;
textAfter?: string;
textBefore?: string;

View File

@ -1,7 +1,8 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { UserPreferenceService } from '@users/user-preference.service';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { BaseFormComponent } from '@iqser/common-ui';
import { BaseFormComponent, IqserPermissionsService } from '@iqser/common-ui';
import { ROLES } from '@users/roles';
interface PreferencesForm {
autoExpandFiltersOnActions: boolean;
@ -22,12 +23,21 @@ export class PreferencesComponent extends BaseFormComponent {
readonly form: FormGroup<AsControl<PreferencesForm>>;
initialFormValue: PreferencesForm;
constructor(readonly userPreferenceService: UserPreferenceService, private readonly _formBuilder: FormBuilder) {
constructor(
readonly userPreferenceService: UserPreferenceService,
private readonly _formBuilder: FormBuilder,
private readonly _permissionsService: IqserPermissionsService,
) {
super();
this.form = this._formBuilder.group({
autoExpandFiltersOnActions: [this.userPreferenceService.getAutoExpandFiltersOnActions()],
showSuggestionsInPreview: [this.userPreferenceService.getShowSuggestionsInPreview()],
});
if (!this._permissionsService.has(ROLES.managePreferences)) {
this.form.disable();
}
this.initialFormValue = this.form.getRawValue();
}

View File

@ -2,14 +2,14 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { BaseFormComponent, LanguageService, LoadingService } from '@iqser/common-ui';
import { BaseFormComponent, IqserPermissionsService, LanguageService, LoadingService } from '@iqser/common-ui';
import { IProfile } from '@red/domain';
import { languagesTranslations } from '@translations/languages-translations';
import { PermissionsService } from '@services/permissions.service';
import { UserService } from '@users/user.service';
import { ConfigService } from '@services/config.service';
import { firstValueFrom } from 'rxjs';
import { UserPreferenceService } from '@users/user-preference.service';
import { ROLES } from '@users/roles';
@Component({
selector: 'redaction-user-profile-screen',
@ -28,12 +28,12 @@ export class UserProfileScreenComponent extends BaseFormComponent implements OnI
domSanitizer: DomSanitizer,
configService: ConfigService,
private readonly _userService: UserService,
readonly permissionsService: PermissionsService,
readonly userPreferences: UserPreferenceService,
private readonly _loadingService: LoadingService,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _languageService: LanguageService,
protected readonly _translateService: TranslateService,
private readonly _permissionsService: IqserPermissionsService,
protected readonly _userPreferenceService: UserPreferenceService,
) {
super();
@ -112,6 +112,9 @@ export class UserProfileScreenComponent extends BaseFormComponent implements OnI
private _initializeForm(): void {
try {
this.form = this._getForm();
if (!this._permissionsService.has(ROLES.updateMyProfile)) {
this.form.disable();
}
this.#profileModel = {
email: this._userService.currentUser.email ?? '',
firstName: this._userService.currentUser.firstName ?? '',

View File

@ -162,10 +162,13 @@ const routes: IqserRoutes = [
component: UserListingScreenComponent,
},
],
canActivate: [CompositeRouteGuard],
canActivate: [CompositeRouteGuard, IqserPermissionsGuard],
data: {
routeGuards: [IqserAuthGuard, RedRoleGuard],
requiredRoles: ['RED_USER_ADMIN'],
permissions: {
allow: [ROLES.users.read],
redirectTo: '/',
},
},
},
{

View File

@ -4,9 +4,9 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { adminSideNavTranslations } from '@translations/admin-side-nav-translations';
import { UserService } from '@users/user.service';
import { ActivatedRoute } from '@angular/router';
import { AdminSideNavType, AdminSideNavTypes, ENTITY_TYPE } from '@red/domain';
import { AdminSideNavType, AdminSideNavTypes, ENTITY_TYPE, User } from '@red/domain';
import { ROLES } from '@users/roles';
import { IqserPermissionsService } from '@iqser/common-ui';
import { getCurrentUser, IqserPermissionsService } from '@iqser/common-ui';
interface NavItem {
readonly label: string;
@ -24,6 +24,7 @@ export class AdminSideNavComponent implements OnInit {
@Input() type: AdminSideNavType;
@Input() disabledItems: string[] = [];
readonly translations = adminSideNavTranslations;
readonly currentUser = getCurrentUser<User>();
readonly roles = ROLES;
prefix: string;
@ -32,7 +33,7 @@ export class AdminSideNavComponent implements OnInit {
{
screen: 'dossier-templates',
label: _('admin-side-nav.dossier-templates'),
hideIf: !this._permissionsService.has(ROLES.templates.read),
hideIf: !this.currentUser.isManager && !this.currentUser.isAdmin && !this._permissionsService.has(ROLES.templates.read),
helpModeKey: 'dossier_templates',
},
{
@ -56,7 +57,7 @@ export class AdminSideNavComponent implements OnInit {
{
screen: 'users',
label: _('admin-side-nav.user-management'),
hideIf: !this._userService.currentUser.isUserAdmin,
hideIf: !this._permissionsService.has(ROLES.users.read) && !this._userService.currentUser.isUserAdmin,
helpModeKey: 'user_management',
},
{

View File

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

View File

@ -1,10 +1,17 @@
import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import { IqserPermissionsService, ListingComponent, listingProvidersFactory, LoadingService, TableColumnConfig } from '@iqser/common-ui';
import {
getCurrentUser,
IqserPermissionsService,
ListingComponent,
listingProvidersFactory,
LoadingService,
TableColumnConfig,
} from '@iqser/common-ui';
import { auditCategoriesTranslations } from '@translations/audit-categories-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { Audit, IAudit, IAuditResponse, IAuditSearchRequest } from '@red/domain';
import { Audit, IAudit, IAuditResponse, IAuditSearchRequest, User } from '@red/domain';
import { AuditService } from '../../services/audit.service';
import { firstValueFrom } from 'rxjs';
import { Dayjs } from 'dayjs';
@ -26,6 +33,7 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
readonly routerHistoryService = inject(RouterHistoryService);
readonly permissionsService = inject(IqserPermissionsService);
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
categories: string[] = [];
userIds: Set<string>;

View File

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

View File

@ -1,5 +1,5 @@
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { IconButtonTypes, IqserPermissionsService, LoadingService, Toaster } from '@iqser/common-ui';
import { getCurrentUser, IconButtonTypes, IqserPermissionsService, LoadingService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { RouterHistoryService } from '@services/router-history.service';
import { DigitalSignatureService } from '../../services/digital-signature.service';
@ -7,7 +7,7 @@ import { firstValueFrom } from 'rxjs';
import { AdminDialogService } from '../../services/admin-dialog.service';
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 { DigitalSignatureOptions, IKmsDigitalSignatureRequest, IPkcsDigitalSignatureRequest } from '@red/domain';
import { DigitalSignatureOptions, IKmsDigitalSignatureRequest, IPkcsDigitalSignatureRequest, User } from '@red/domain';
import { ROLES } from '@users/roles';
@Component({
@ -22,6 +22,7 @@ export class DigitalSignatureScreenComponent implements OnInit {
readonly certificateType = DigitalSignatureOptions;
readonly iconButtonTypes = IconButtonTypes;
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
digitalSignature: IPkcsDigitalSignatureRequest | IKmsDigitalSignatureRequest;

View File

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

View File

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

View File

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

View File

@ -1,9 +1,10 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { UserPreferenceService } from '@users/user-preference.service';
import { AdminDialogService } from '../../../services/admin-dialog.service';
import { DossierTemplate } from '@red/domain';
import { DossierTemplate, User } from '@red/domain';
import {
CircleButtonTypes,
getCurrentUser,
IconButtonTypes,
IqserPermissionsService,
ListingComponent,
@ -30,6 +31,7 @@ export class DossierTemplatesListingScreenComponent extends ListingComponent<Dos
readonly iconButtonTypes = IconButtonTypes;
readonly circleButtonTypes = CircleButtonTypes;
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
readonly tableHeaderLabel = _('dossier-templates-listing.table-header.title');
readonly tableColumnConfigs: TableColumnConfig<DossierTemplate>[] = [
{ label: _('dossier-templates-listing.table-col-names.name'), sortByKey: 'searchKey', width: '3fr' },

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
<div class="heading-l" translate="general-config-screen.general.title"></div>
<div translate="general-config-screen.general.subtitle"></div>
</div>
<form (submit)="save()" [formGroup]="form" *ngIf="form">
<form (submit)="save()" *ngIf="form" [formGroup]="form">
<div class="dialog-content">
<div class="dialog-content-left">
<div class="iqser-input-group">
@ -22,13 +22,14 @@
</div>
</div>
</div>
<div class="dialog-actions">
<button
[disabled]="form?.invalid || !changed"
[iqserHelpMode]="'general_configurations'"
color="primary"
mat-flat-button
type="submit"
[iqserHelpMode]="'general_configurations'"
>
{{ 'general-config-screen.actions.save' | translate }}
</button>

View File

@ -1,10 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { BaseFormComponent, LoadingService } from '@iqser/common-ui';
import { BaseFormComponent, IqserPermissionsService, LoadingService } from '@iqser/common-ui';
import { GeneralSettingsService } from '@services/general-settings.service';
import { IGeneralConfiguration } from '@red/domain';
import { ConfigService } from '@services/config.service';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { firstValueFrom } from 'rxjs';
import { ROLES } from '@users/roles';
@Component({
selector: 'redaction-general-config-form',
@ -18,9 +19,13 @@ export class GeneralConfigFormComponent extends BaseFormComponent implements OnI
private readonly _generalSettingsService: GeneralSettingsService,
private readonly _configService: ConfigService,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _permissionsService: IqserPermissionsService,
) {
super();
this.form = this._getForm();
if (!_permissionsService.has(ROLES.generalConfiguration.write)) {
this.form.disable();
}
}
async ngOnInit(): Promise<void> {

View File

@ -1,11 +1,12 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { ISmtpConfiguration } from '@red/domain';
import { BaseFormComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { BaseFormComponent, IconButtonTypes, IqserPermissionsService, LoadingService, Toaster } from '@iqser/common-ui';
import { AdminDialogService } from '../../../services/admin-dialog.service';
import { SmtpConfigService } from '../../../services/smtp-config.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { firstValueFrom } from 'rxjs';
import { ROLES } from '@users/roles';
@Component({
selector: 'redaction-smtp-form',
@ -21,9 +22,13 @@ export class SmtpFormComponent extends BaseFormComponent implements OnInit {
private readonly _smtpConfigService: SmtpConfigService,
private readonly _loadingService: LoadingService,
private readonly _toaster: Toaster,
private readonly _permissionsService: IqserPermissionsService,
) {
super();
this.form = this._getForm();
if (!_permissionsService.has(ROLES.smtp.write)) {
this.form.disable();
}
}
async ngOnInit(): Promise<void> {

View File

@ -1,10 +1,11 @@
import { Component } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { SystemPreferences } from '@red/domain';
import { BaseFormComponent, KeysOf, LoadingService } from '@iqser/common-ui';
import { BaseFormComponent, IqserPermissionsService, KeysOf, LoadingService } from '@iqser/common-ui';
import { firstValueFrom } from 'rxjs';
import { SystemPreferencesService } from '@services/system-preferences.service';
import { systemPreferencesTranslations } from '@translations/system-preferences-translations';
import { ROLES } from '@users/roles';
export type ValueType = 'number' | 'string' | 'boolean';
@ -25,10 +26,14 @@ export class SystemPreferencesFormComponent extends BaseFormComponent {
private readonly _loadingService: LoadingService,
private readonly _systemPreferencesService: SystemPreferencesService,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _permissionsService: IqserPermissionsService,
) {
super();
this.form = this._getForm();
this._loadData();
if (!_permissionsService.has(ROLES.appConfiguration.write)) {
this.form.disable();
}
}
async save(): Promise<void> {

View File

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

View File

@ -1,12 +1,13 @@
import { Component, OnInit } from '@angular/core';
import { ConfigService } from '@services/config.service';
import { TranslateService } from '@ngx-translate/core';
import { ButtonConfig, IconButtonTypes, IqserPermissionsService, LoadingService } from '@iqser/common-ui';
import { ButtonConfig, getCurrentUser, IconButtonTypes, IqserPermissionsService, LoadingService } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { RouterHistoryService } from '@services/router-history.service';
import { LicenseService } from '@services/license.service';
import { map } from 'rxjs/operators';
import { ROLES } from '@users/roles';
import { User } from '@red/domain';
@Component({
templateUrl: './license-screen.component.html',
@ -14,6 +15,7 @@ import { ROLES } from '@users/roles';
})
export class LicenseScreenComponent implements OnInit {
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
readonly currentYear = new Date().getFullYear();
readonly buttonConfigs: readonly ButtonConfig[] = [
{

View File

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

View File

@ -1,5 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import {
getCurrentUser,
IqserPermissionsService,
ListingComponent,
listingProvidersFactory,
@ -7,7 +8,7 @@ import {
SortingOrders,
TableColumnConfig,
} from '@iqser/common-ui';
import { PermissionsMapping } from '@red/domain';
import { PermissionsMapping, User } from '@red/domain';
import { ConfigService } from '../config.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { EntityPermissionsService } from '@services/entity-permissions/entity-permissions.service';
@ -30,6 +31,7 @@ import { ROLES } from '@users/roles';
})
export class PermissionsScreenComponent extends ListingComponent<PermissionsMapping> {
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
readonly translations = permissionsTranslations;
readonly tableColumnConfigs: TableColumnConfig<PermissionsMapping>[];
readonly tableHeaderLabel = _('permissions-screen.table-header.title');

View File

@ -59,14 +59,14 @@
></mat-slide-toggle>
</div>
<div class="cell" [ngClass]="!user.hasAnyRole && 'no-role-alignment'">
<div [ngClass]="!user.hasAnyRole && 'no-role-alignment'" class="cell">
<mat-icon *ngIf="!user.hasAnyRole" [svgIcon]="'red:alert-circle'" class="icon"></mat-icon>
<span class="small-label opacity-1">{{ getDisplayRoles(user) }}</span>
</div>
<div class="cell">
<div class="action-buttons">
<div [iqserHelpMode]="'edit_delete_user'">
<div *allow="roles.users.write" [iqserHelpMode]="'edit_delete_user'">
<iqser-circle-button
(action)="openAddEditUserDialog($event, user)"
[tooltip]="'user-listing.action.edit' | translate"

View File

@ -21,6 +21,7 @@ import { rolesTranslations } from '@translations/roles-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { userTypeChecker, userTypeFilters } from '../../../../utils';
import { RouterHistoryService } from '@services/router-history.service';
import { ROLES } from '@users/roles';
function configToFilter({ key, label }: DonutChartConfig) {
return new NestedFilter({
@ -43,6 +44,7 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
readonly translations = rolesTranslations;
readonly iconButtonTypes = IconButtonTypes;
readonly circleButtonTypes = CircleButtonTypes;
readonly roles = ROLES;
readonly currentUser = this._userService.currentUser;
readonly canDeleteSelected$ = this.#canDeleteSelected$;
readonly tableHeaderLabel = _('user-listing.table-header.title');
@ -101,11 +103,9 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
}
getDisplayRoles(user: User) {
const separator = ', ';
return (
user.roles.map(role => this._translateService.instant(this.translations[role])).join(separator) ||
this._translateService.instant(this.translations['NO_ROLE'])
);
const oldRedRoles = user.roles.filter(role => role.startsWith('RED_'));
const translatedRoles = oldRedRoles.map(role => this._translateService.instant(this.translations[role]));
return translatedRoles.join(', ') || this._translateService.instant(this.translations['NO_ROLE']);
}
async toggleActive(user: User) {

View File

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

View File

@ -1,9 +1,9 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
import { Dossier, DossierStats } from '@red/domain';
import { Dossier, DossierStats, User } from '@red/domain';
import { BehaviorSubject, Observable } from 'rxjs';
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
import { switchMap } from 'rxjs/operators';
import { CircleButtonTypes, IqserPermissionsService, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui';
import { CircleButtonTypes, getCurrentUser, IqserPermissionsService, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui';
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
import { ROLES } from '@users/roles';
@ -15,6 +15,7 @@ import { ROLES } from '@users/roles';
export class TableItemComponent implements OnChanges {
readonly circleButtonTypes = CircleButtonTypes;
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
@Input() dossier!: Dossier;
readonly stats$: Observable<DossierStats>;

View File

@ -71,7 +71,7 @@
<iqser-icon-button
(action)="newDossier()"
*allow="roles.dossiers.write; if: dossierTemplate.isEmpty"
*ngIf="permissionsService.canCreateDossier(dossierTemplate)"
[iqserHelpMode]="'new_dossier_button'"
[label]="'dashboard.empty-template.new-dossier' | translate"
[type]="iconButtonTypes.primary"

View File

@ -4,6 +4,7 @@ import { IconButtonTypes } from '@iqser/common-ui';
import { TranslateChartService } from '@services/translate-chart.service';
import { SharedDialogService } from '@shared/services/dialog.service';
import { ROLES } from '@users/roles';
import { PermissionsService } from '@services/permissions.service';
@Component({
selector: 'redaction-template-stats [stats]',
@ -17,7 +18,11 @@ export class TemplateStatsComponent {
@Input() stats: DashboardStats;
constructor(private readonly _dialogService: SharedDialogService, readonly translateChartService: TranslateChartService) {}
constructor(
private readonly _dialogService: SharedDialogService,
readonly translateChartService: TranslateChartService,
readonly permissionsService: PermissionsService,
) {}
newDossier(): void {
this._dialogService.openDialog('addDossier', null, { dossierTemplateId: this.stats.dossierTemplateId });

View File

@ -19,7 +19,7 @@
<iqser-circle-button
(action)="editingOwner = true"
*allow="roles.dossiers.edit"
*allow="roles.dossiers.edit; if: currentUser.isManager"
[icon]="'iqser:edit'"
[iqserHelpMode]="'dashboard_in_dossier'"
[tooltipPosition]="'below'"

View File

@ -13,7 +13,16 @@ import {
} from '@red/domain';
import { TranslateChartService } from '@services/translate-chart.service';
import { UserService } from '@users/user.service';
import { ContextComponent, FilterService, getParam, INestedFilter, ProgressBarConfigModel, shareLast, Toaster } from '@iqser/common-ui';
import {
ContextComponent,
FilterService,
getCurrentUser,
getParam,
INestedFilter,
ProgressBarConfigModel,
shareLast,
Toaster,
} from '@iqser/common-ui';
import { workflowFileStatusTranslations } from '@translations/file-status-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { combineLatestWith, firstValueFrom, Observable } from 'rxjs';
@ -44,6 +53,7 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
editingOwner = false;
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
readonly collapseTooltip = _('dossier-details.collapse');
readonly expandTooltip = _('dossier-details.expand');
readonly needsWorkFilters$ = this.filterService.getFilterModels$('needsWorkFilters');
@ -78,7 +88,7 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
}
get managers() {
return this._userService.all.filter(u => u.has(ROLES.dossiers.write) || u.isManager).map(u => u.id);
return this._userService.all.filter(u => u.isManager).map(u => u.id);
}
ngOnInit() {

View File

@ -1,6 +1,7 @@
import { Injectable, TemplateRef } from '@angular/core';
import {
ActionConfig,
getCurrentUser,
getParam,
IFilterGroup,
INestedFilter,
@ -22,6 +23,7 @@ import {
IFileAttributeConfig,
ProcessingType,
StatusSorter,
User,
WorkflowFileStatus,
WorkflowFileStatuses,
} from '@red/domain';
@ -48,6 +50,7 @@ import { ROLES } from '@users/roles';
export class ConfigService {
readonly listingMode$: Observable<ListingMode>;
readonly dossierId = getParam(DOSSIER_ID);
readonly currentUser = getCurrentUser<User>();
private readonly _listingMode$ = new BehaviorSubject<ListingMode>(ListingModes.table);
constructor(
@ -155,7 +158,7 @@ export class ConfigService {
label: this._translateService.instant('dossier-overview.header-actions.edit'),
action: $event => this._openEditDossierDialog($event, dossierId),
icon: 'iqser:edit',
hide: !this._iqserPermissionsService.has(ROLES.dossiers.edit),
hide: !this.currentUser.isManager && !this._iqserPermissionsService.has(ROLES.dossiers.edit),
helpModeKey: 'edit_dossier_in_dossier',
disabled$,
},

View File

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

View File

@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { CircleButtonTypes, IqserPermissionsService, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui';
import { Dossier, DossierStats, File } from '@red/domain';
import { CircleButtonTypes, getCurrentUser, IqserPermissionsService, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui';
import { Dossier, DossierStats, File, User } from '@red/domain';
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
import { LongPressEvent } from '@shared/directives/long-press.directive';
import { UserPreferenceService } from '@users/user-preference.service';
@ -18,6 +18,7 @@ import { ROLES } from '@users/roles';
export class DossiersListingActionsComponent implements OnChanges {
readonly circleButtonTypes = CircleButtonTypes;
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
analysisForced: boolean;
files: File[];

View File

@ -9,6 +9,7 @@ import {
IqserScrollbarModule,
IqserSharedModule,
IqserUsersModule,
LogPipe,
} from '@iqser/common-ui';
import { TranslateModule } from '@ngx-translate/core';
import { DossiersListingScreenComponent } from './screen/dossiers-listing-screen.component';
@ -58,6 +59,7 @@ const routes: Routes = [
IqserScrollbarModule,
IqserSharedModule,
IqserPermissionsModule,
LogPipe,
],
})
export class DossiersListingModule {}

View File

@ -82,7 +82,7 @@
<iqser-circle-button
(action)="annotationActionsService.undoDirectAction($event, annotations)"
*ngIf="annotationPermissions.canUndo"
*allow="roles.redactions.deleteManual; if: annotationPermissions.canUndo"
[tooltipPosition]="tooltipPosition"
[tooltip]="'annotation-actions.undo' | translate"
[type]="buttonType"

View File

@ -9,6 +9,7 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi
import { HelpModeService } from '@iqser/common-ui';
import { ViewModeService } from '../../services/view-mode.service';
import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service';
import { ROLES } from '@users/roles';
export const AnnotationButtonTypes = {
dark: 'dark',
@ -29,6 +30,7 @@ export class AnnotationActionsComponent implements OnChanges {
@Input() canPerformAnnotationActions: boolean;
@Input() alwaysVisible: boolean;
annotationPermissions: AnnotationPermissions;
readonly roles = ROLES;
constructor(
readonly viewModeService: ViewModeService,

View File

@ -11,7 +11,7 @@ import type {
ManualRedactionActions,
} from '@red/domain';
import { type AnnotationWrapper } from '@models/file/annotation.wrapper';
import { GenericService, List, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
import { GenericService, IqserPermissionsService, List, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
import { map, tap } from 'rxjs/operators';
import { PermissionsService } from '@services/permissions.service';
import { dictionaryActionsTranslations, manualRedactionActionsTranslations } from '@translations/annotation-actions-translations';
@ -20,6 +20,8 @@ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { type ManualRedactionEntryType } from '@models/file/manual-redaction-entry.wrapper';
import { NGXLogger } from 'ngx-logger';
import { ROLES } from '@users/roles';
import { of } from 'rxjs';
function getResponseType(error: boolean, isConflict: boolean) {
const isConflictError = isConflict ? 'conflictError' : 'error';
@ -45,6 +47,7 @@ export class ManualRedactionService extends GenericService<IManualAddResponse> {
private readonly _toaster: Toaster,
private readonly _logger: NGXLogger,
private readonly _permissionsService: PermissionsService,
private readonly _iqaerPermissionsService: IqserPermissionsService,
private readonly _activeDossiersService: ActiveDossiersService,
) {
super();
@ -93,11 +96,17 @@ export class ManualRedactionService extends GenericService<IManualAddResponse> {
addAnnotation(requests: List<IAddRedactionRequest>, dossierId: string, fileId: string, dictionaryLabel?: string) {
const toast = requests[0].addToDictionary ? this.#showAddToDictionaryToast(requests, dictionaryLabel) : this.#showToast('add');
if (this._permissionsService.isApprover(this.#dossier(dossierId))) {
const canAddRedaction = this._iqaerPermissionsService.has(ROLES.redactions.write);
if (canAddRedaction && this._permissionsService.isApprover(this.#dossier(dossierId))) {
return this.add(requests, dossierId, fileId).pipe(toast);
}
return this.requestAdd(requests, dossierId, fileId).pipe(toast);
const canRequestRedaction = this._iqaerPermissionsService.has(ROLES.redactions.request);
if (canRequestRedaction) {
return this.requestAdd(requests, dossierId, fileId).pipe(toast);
}
return of(undefined);
}
bulkForce(requests: List<ILegalBasisChangeRequest>, dossierId: string, fileId: string) {

View File

@ -5,9 +5,10 @@ import { PermissionsService } from '../../../services/permissions.service';
import { FilePreviewStateService } from './file-preview-state.service';
import { TranslateService } from '@ngx-translate/core';
import { AnnotationActionsService } from './annotation-actions.service';
import { BASE_HREF_FN } from '@iqser/common-ui';
import { BASE_HREF_FN, IqserPermissionsService } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { IHeaderElement } from '@red/domain';
import { ROLES } from '@users/roles';
@Injectable()
export class PdfAnnotationActionsService {
@ -17,6 +18,7 @@ export class PdfAnnotationActionsService {
readonly #ngZone = inject(NgZone);
readonly #convertPath = inject(BASE_HREF_FN);
readonly #annotationActionsService = inject(AnnotationActionsService);
readonly #iqserPermissionsService = inject(IqserPermissionsService);
get(annotations: AnnotationWrapper[]): IHeaderElement[] {
const availableActions: IHeaderElement[] = [];
@ -152,7 +154,9 @@ export class PdfAnnotationActionsService {
),
canAcceptRecommendation: permissions.reduce((acc, next) => acc && next.canAcceptRecommendation, true),
canAcceptSuggestion: permissions.reduce((acc, next) => acc && next.canAcceptSuggestion, true),
canUndo: permissions.reduce((acc, next) => acc && next.canUndo, true),
canUndo:
this.#iqserPermissionsService.has(ROLES.redactions.deleteManual) &&
permissions.reduce((acc, next) => acc && next.canUndo, true),
canMarkAsFalsePositive: permissions.reduce((acc, next) => acc && next.canMarkAsFalsePositive, true),
canForceRedaction: permissions.reduce((acc, next) => acc && next.canForceRedaction, true),
canForceHint: permissions.reduce((acc, next) => acc && next.canForceHint, true),

View File

@ -9,7 +9,7 @@ import {
} from '@models/file/manual-redaction-entry.wrapper';
import { AnnotationDrawService } from '../../pdf-viewer/services/annotation-draw.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { BASE_HREF_FN, BaseHrefFn, shareDistinctLast } from '@iqser/common-ui';
import { BASE_HREF_FN, BaseHrefFn, IqserPermissionsService, shareDistinctLast } from '@iqser/common-ui';
import { toPosition } from '../utils/pdf-calculation.utils';
import { MultiSelectService } from './multi-select.service';
import { FilePreviewStateService } from './file-preview-state.service';
@ -28,6 +28,7 @@ import { PermissionsService } from '@services/permissions.service';
import { AnnotationsListingService } from './annotations-listing.service';
import { PdfAnnotationActionsService } from './pdf-annotation-actions.service';
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
import { ROLES } from '@users/roles';
import Annotation = Core.Annotations.Annotation;
import Quad = Core.Math.Quad;
@ -70,6 +71,7 @@ export class PdfProxyService {
private readonly _listingService: AnnotationsListingService,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _dictionariesMapService: DictionariesMapService,
private readonly _iqserPermissionsService: IqserPermissionsService,
) {
this.canPerformAnnotationActions$ = this.#canPerformAnnotationActions$;
}
@ -240,20 +242,23 @@ export class PdfProxyService {
});
}
popups.push({
type: 'actionButton',
dataElement: TextPopups.ADD_REDACTION,
img: this.#addRedactionIcon,
title: this.#getTitle(ManualRedactionEntryTypes.REDACTION),
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.REDACTION),
});
popups.push({
type: 'actionButton',
dataElement: TextPopups.ADD_DICTIONARY,
img: this.#addDictIcon,
title: this.#getTitle(ManualRedactionEntryTypes.DICTIONARY),
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.DICTIONARY),
});
if (this._iqserPermissionsService.has(ROLES.redactions.write) || this._iqserPermissionsService.has(ROLES.redactions.request)) {
popups.push({
type: 'actionButton',
dataElement: TextPopups.ADD_REDACTION,
img: this.#addRedactionIcon,
title: this.#getTitle(ManualRedactionEntryTypes.REDACTION),
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.REDACTION),
});
popups.push({
type: 'actionButton',
dataElement: TextPopups.ADD_DICTIONARY,
img: this.#addDictIcon,
title: this.#getTitle(ManualRedactionEntryTypes.DICTIONARY),
onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.DICTIONARY),
});
}
this._pdf.configureTextPopups(popups);

View File

@ -1,10 +1,17 @@
import { AfterViewInit, Component, Inject, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Dossier } from '@red/domain';
import { Dossier, User } from '@red/domain';
import { EditDossierGeneralInfoComponent } from './general-info/edit-dossier-general-info.component';
import { EditDossierDownloadPackageComponent } from './download-package/edit-dossier-download-package.component';
import { EditDossierSectionInterface } from './edit-dossier-section.interface';
import { BaseDialogComponent, ConfirmOptions, IconButtonTypes, IqserPermissionsService, SaveOptions } from '@iqser/common-ui';
import {
BaseDialogComponent,
ConfirmOptions,
getCurrentUser,
IconButtonTypes,
IqserPermissionsService,
SaveOptions,
} from '@iqser/common-ui';
import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component';
import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component';
@ -42,6 +49,7 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
@ViewChild(EditDossierDictionaryComponent) dictionaryComponent: EditDossierDictionaryComponent;
@ViewChild(EditDossierTeamComponent) membersComponent: EditDossierTeamComponent;
@ViewChild(EditDossierAttributesComponent) attributesComponent: EditDossierAttributesComponent;
readonly #currentUser = getCurrentUser<User>();
private _dossier: Dossier;
constructor(
@ -89,7 +97,9 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
get showActionButtons(): boolean {
return (
(['members'].includes(this.activeNav) && this._iqserPermissionsService.has(ROLES.dossiers.edit)) ||
(['members'].includes(this.activeNav) &&
this.#currentUser.isManager &&
this._iqserPermissionsService.has(ROLES.dossiers.edit)) ||
this._permissionsService.canEditDossier(this._dossier)
);
}

View File

@ -1,14 +1,14 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { UserService } from '@users/user.service';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Dossier, IDossierRequest } from '@red/domain';
import { Dossier, IDossierRequest, User } from '@red/domain';
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { PermissionsService } from '@services/permissions.service';
import { DossiersService } from '@services/dossiers/dossiers.service';
import { compareLists } from '@utils/functions';
import { FilesService } from '@services/files/files.service';
import { ROLES } from '@users/roles';
import { getCurrentUser } from '@iqser/common-ui';
@Component({
selector: 'redaction-edit-dossier-team',
@ -23,9 +23,9 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
@Input() dossier: Dossier;
membersSelectOptions: string[] = [];
readonly ownersSelectOptions = this.userService.all.filter(u => u.has(ROLES.dossiers.write) || u.isManager).map(m => m.id);
readonly ownersSelectOptions = this.userService.all.filter(u => u.isManager).map(m => m.id);
readonly selectedReviewers$ = new BehaviorSubject<string[]>([]);
readonly #currentUser = getCurrentUser<User>();
constructor(
readonly userService: UserService,
@ -138,7 +138,7 @@ export class EditDossierTeamComponent implements EditDossierSectionInterface, On
}
setMembersSelectOptions(value = this.searchQuery): void {
const possibleMembers = this.userService.all.filter(user => user.has(ROLES.dossiers.read) || user.isUser || user.isManager);
const possibleMembers = this.userService.all.filter(user => user.isUser || user.isManager);
this.membersSelectOptions = possibleMembers
.filter(user => this.userService.getName(user.id).toLowerCase().includes(value.toLowerCase()))
.filter(user => this.selectedOwnerId !== user.id)

View File

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

View File

@ -1,7 +1,8 @@
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { CircleButtonTypes, List } from '@iqser/common-ui';
import { CircleButtonTypes, getCurrentUser, List } from '@iqser/common-ui';
import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service';
import { ROLES } from '@users/roles';
import { User } from '@red/domain';
@Component({
selector: 'redaction-team-members',
@ -11,6 +12,7 @@ import { ROLES } from '@users/roles';
export class TeamMembersComponent {
readonly circleButtonTypes = CircleButtonTypes;
readonly roles = ROLES;
readonly currentUser = getCurrentUser<User>();
@Input() memberIds: List;
@Input() perLine: number;

View File

@ -23,14 +23,19 @@ export class PermissionsService {
return this.isAdmin() || this.isManager();
}
canPerformDossierStatesActions() {
return this.isAdmin() && this._iqserPermissionsService.has(ROLES.states.write);
}
canEditEntities(): boolean {
return this._iqserPermissionsService.has(ROLES.dictionaryTypes.write);
return this._iqserPermissionsService.has(ROLES.dictionaryTypes.write) && this.isAdmin();
}
canDeleteEntities(entity: Dictionary | Dictionary[]): boolean {
const entities = entity instanceof Dictionary ? [entity] : entity;
return (
entities.length &&
this.isAdmin() &&
this._iqserPermissionsService.has(ROLES.dictionaryTypes.delete) &&
entities.reduce((acc, _entity) => this._canDeleteEntity(_entity) && acc, true)
);
@ -239,7 +244,10 @@ export class PermissionsService {
}
canSoftDeleteDossier(dossier: IDossier): boolean {
return this._iqserPermissionsService.has(ROLES.dossiers.delete) && (this.isOwner(dossier) || this.isDossierMember(dossier));
return (
this._iqserPermissionsService.has(ROLES.dossiers.delete) &&
(this.isOwner(dossier) || (this.isManager() && this.isDossierMember(dossier)))
);
}
canHardDeleteDossier(dossier: IDossier): boolean {
@ -251,7 +259,7 @@ export class PermissionsService {
}
canCreateDossier(dossierTemplate: DossierTemplate | DashboardStats): boolean {
return this._iqserPermissionsService.has(ROLES.dossiers.write) && dossierTemplate.isActive;
return this._iqserPermissionsService.has(ROLES.dossiers.write) && this.isManager() && dossierTemplate.isActive;
}
canArchiveDossier(dossier: Dossier): boolean {
@ -264,7 +272,7 @@ export class PermissionsService {
}
canEditDossier(dossier: Dossier): boolean {
return this._iqserPermissionsService.has(ROLES.dossiers.edit) && !!dossier?.ownerId;
return this._iqserPermissionsService.has(ROLES.dossiers.edit) && this.isManager() && !!dossier?.ownerId;
}
canEditDossierDictionary(dossier: Dossier): boolean {
@ -276,7 +284,7 @@ export class PermissionsService {
}
canEditTeamMembers(): boolean {
return this._iqserPermissionsService.has(ROLES.dossiers.edit);
return this._iqserPermissionsService.has(ROLES.dossiers.edit) && this.isManager();
}
isAdmin(): boolean {

View File

@ -2,15 +2,15 @@ export const ROLES = {
RED_CREATE_TENANT: 'red-create-tenant',
RED_DEPLOYMENT_INFO: 'red-deployment-info',
RED_GET_TENANTS: 'red-get-tenants',
RED_MANAGE_USER_PREFERENCES: 'red-manage-user-preferences',
RED_PROCESS_DOWNLOAD: 'red-process-download',
RED_PROCESS_MANUAL_REDACTION_REQUEST: 'red-process-manual-redaction-request',
RED_READ_RULES: 'red-read-rules',
RED_READ_VERSIONS: 'red-read-versions',
RED_REINDEX: 'red-reindex',
RED_ROTATE_PAGE: 'red-rotate-page',
RED_UPDATE_MY_PROFILE: 'red-update-my-profile',
RED_WRITE_RULES: 'red-write-rules',
managePreferences: 'red-manage-user-preferences',
updateMyProfile: 'red-update-my-profile',
getRss: 'red-get-rss',
excludeIncludeFile: 'red-exclude-include-file',
excludeIncludePages: 'red-exclude-include-pages',

View File

@ -17,7 +17,7 @@ export class UserService extends IqserUserService<IIqserUser, User> {
this._permissionsService.add({
[ROLES.any]: (permission, all) => {
console.log('all roles: ', Object.keys(all));
return Object.keys(all).some(key => key.startsWith('red-'));
return Object.keys(all).some(key => key.startsWith('red-') || key.startsWith('RED_'));
},
});