diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 083976f28..01f721622 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -125,6 +125,9 @@ const components = [AppComponent, AuthErrorComponent, NotificationsComponent, Sp PDF: { enabled: false, }, + STATS: { + enabled: false, + }, }, } as ILoggerConfig, }, diff --git a/apps/red-ui/src/app/guards/permissions-guard.ts b/apps/red-ui/src/app/guards/permissions-guard.ts new file mode 100644 index 000000000..10ce0bf34 --- /dev/null +++ b/apps/red-ui/src/app/guards/permissions-guard.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate } from '@angular/router'; +import { firstValueFrom } from 'rxjs'; +import { EntityPermissionsService } from '../services/entity-services/entity-permissions.service'; + +@Injectable({ providedIn: 'root' }) +export class PermissionsGuard implements CanActivate { + constructor(private readonly _entityPermissionsService: EntityPermissionsService) {} + + async canActivate(route: ActivatedRouteSnapshot): Promise { + const targetObject = route.data.permissionsObject; + await firstValueFrom(this._entityPermissionsService.loadPermissionsMappingFor(targetObject)); + return true; + } +} diff --git a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts index 0f1446a68..5387a4017 100644 --- a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts @@ -24,6 +24,8 @@ import { DossierStatesListingScreenComponent } from './screens/dossier-states-li import { DossiersGuard } from '@guards/dossiers.guard'; import { ACTIVE_DOSSIERS_SERVICE } from '../../tokens'; import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component'; +import { TargetObjects } from '@red/domain'; +import { PermissionsGuard } from '../../guards/permissions-guard'; const routes: Routes = [ { path: '', redirectTo: 'dossier-templates', pathMatch: 'full' }, @@ -159,6 +161,16 @@ const routes: Routes = [ requiredRoles: ['RED_USER_ADMIN'], }, }, + { + path: 'dossier-permissions', + component: BaseAdminScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, PermissionsGuard], + permissionsObject: TargetObjects.Dossier, + }, + loadChildren: () => import('./screens/permissions/permissions.module').then(m => m.PermissionsModule), + }, { path: 'license-info', component: LicenseInformationScreenComponent, diff --git a/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts b/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts index 94d8f5d60..b5a1672de 100644 --- a/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts +++ b/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts @@ -44,6 +44,7 @@ export class AdminSideNavComponent implements OnInit { }, { screen: 'audit', label: _('admin-side-nav.audit'), hideIf: !this.currentUser.isAdmin }, { screen: 'users', label: _('admin-side-nav.user-management'), hideIf: !this.currentUser.isUserAdmin }, + { screen: 'dossier-permissions', label: _('dossier-permissions'), hideIf: !this.currentUser.isAdmin }, { screen: 'general-config', label: _('admin-side-nav.configurations'), diff --git a/apps/red-ui/src/app/modules/admin/screens/permissions/config.service.ts b/apps/red-ui/src/app/modules/admin/screens/permissions/config.service.ts new file mode 100644 index 000000000..66116c6d8 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/permissions/config.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import { TableColumnConfig } from '@iqser/common-ui'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { EntityPermissionsService } from '@services/entity-services/entity-permissions.service'; +import { TargetObjects } from '@red/domain'; + +@Injectable() +export class ConfigService { + constructor(private readonly _entityPermissionsService: EntityPermissionsService) {} + + get tableConfig(): TableColumnConfig[] { + const columns = this._entityPermissionsService.getPermissionsMapping(TargetObjects.Dossier)[0].mappedPermissions.map(c => ({ + label: c.name, + notTranslatable: true, + })); + + return [ + { + label: _('dossier-overview.table-col-names.name'), + width: '3fr', + }, + ...columns, + ]; + } +} diff --git a/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.html new file mode 100644 index 000000000..831ec43fd --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.html @@ -0,0 +1,17 @@ + + + +
+
+ + + + + + + +
+ +
abc
+
+
diff --git a/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.scss b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.scss new file mode 100644 index 000000000..fdab5672e --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.scss @@ -0,0 +1,4 @@ +:host { + flex-grow: 1; + overflow: hidden; +} diff --git a/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.ts new file mode 100644 index 000000000..970945725 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component, forwardRef, Injector } from '@angular/core'; +import { DefaultListingServices, ListingComponent, TableColumnConfig } from '@iqser/common-ui'; +import { User } from '@red/domain'; +import { ConfigService } from '../config.service'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { EntityPermissionsService } from '@services/entity-services/entity-permissions.service'; + +@Component({ + templateUrl: './permissions-screen.component.html', + styleUrls: ['./permissions-screen.component.scss'], + providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => PermissionsScreenComponent) }], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class PermissionsScreenComponent extends ListingComponent { + readonly tableColumnConfigs: TableColumnConfig[] = this._configService.tableConfig; + readonly tableHeaderLabel = _('dossier-permissions.table-header.title'); + + constructor( + protected readonly _injector: Injector, + private readonly _configService: ConfigService, + private readonly _entityPermissionsService: EntityPermissionsService, + ) { + super(_injector); + } +} diff --git a/apps/red-ui/src/app/modules/admin/screens/permissions/permissions.module.ts b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions.module.ts new file mode 100644 index 000000000..f96d895c5 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; +import { SharedModule } from '@shared/shared.module'; +import { PermissionsScreenComponent } from './permissions-screen/permissions-screen.component'; +import { ConfigService } from './config.service'; +import { CommonUiModule } from '@iqser/common-ui'; + +const routes = [{ path: '', component: PermissionsScreenComponent }]; + +@NgModule({ + declarations: [PermissionsScreenComponent], + imports: [RouterModule.forChild(routes), CommonModule, SharedModule, CommonUiModule], + providers: [ConfigService], +}) +export class PermissionsModule {} diff --git a/apps/red-ui/src/app/services/entity-services/entity-permissions.service.ts b/apps/red-ui/src/app/services/entity-services/entity-permissions.service.ts new file mode 100644 index 000000000..4c6408a3f --- /dev/null +++ b/apps/red-ui/src/app/services/entity-services/entity-permissions.service.ts @@ -0,0 +1,33 @@ +import { Injectable, Injector } from '@angular/core'; +import { GenericService } from '@iqser/common-ui'; +import { IPermissionsMapping, TargetObject } from '@red/domain'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root', +}) +export class EntityPermissionsService extends GenericService { + readonly #permissionsMapping$ = new BehaviorSubject>>({}); + + constructor(protected readonly _injector: Injector) { + super(_injector, 'permissions'); + } + + getPermissionsMapping(targetObject: TargetObject): IPermissionsMapping[] { + return this.#permissionsMapping$.value[targetObject]; + } + + loadPermissionsMappingFor(targetObject: TargetObject, params = ''): Observable { + return this._http.get(`/${this._defaultModelPath}/${targetObject}${params}`).pipe( + tap(mapping => { + this.#permissionsMapping$.next({ ...this.#permissionsMapping$.value, [targetObject]: mapping }); + }), + ); + } + + // + // getTargetObjects(): Observable { + // return this._http.get(`/${this._defaultModelPath}/target-object`); + // } +} diff --git a/libs/red-domain/src/index.ts b/libs/red-domain/src/index.ts index 99077ba8e..bd2f2a0df 100644 --- a/libs/red-domain/src/index.ts +++ b/libs/red-domain/src/index.ts @@ -23,3 +23,4 @@ export * from './lib/dossier-stats'; export * from './lib/dossier-state'; export * from './lib/trash'; export * from './lib/text-highlight'; +export * from './lib/permissions'; diff --git a/libs/red-domain/src/lib/permissions/index.ts b/libs/red-domain/src/lib/permissions/index.ts new file mode 100644 index 000000000..c85954d3e --- /dev/null +++ b/libs/red-domain/src/lib/permissions/index.ts @@ -0,0 +1 @@ +export * from './permissions'; diff --git a/libs/red-domain/src/lib/permissions/permissions.ts b/libs/red-domain/src/lib/permissions/permissions.ts new file mode 100644 index 000000000..5d49152d1 --- /dev/null +++ b/libs/red-domain/src/lib/permissions/permissions.ts @@ -0,0 +1,16 @@ +export const TargetObjects = { + Dossier: 'Dossier', +} as const; + +export type TargetObject = keyof typeof TargetObjects; + +export interface IPermission { + mask: number; + name: string; + sort: number; +} + +export interface IPermissionsMapping { + mappedPermissions: IPermission[]; + targetPermission: IPermission; +}