description authz changes

This commit is contained in:
Efstratios Giannopoulos 2024-04-30 14:06:24 +03:00
parent 965af355d8
commit da8efe5130
19 changed files with 78 additions and 36 deletions

View File

@ -73,6 +73,7 @@ public final class Permission {
//Dmp //Dmp
public static String BrowseDmp = "BrowseDmp"; public static String BrowseDmp = "BrowseDmp";
public static String EditDmp = "EditDmp"; public static String EditDmp = "EditDmp";
public static String ReviewDmp = "ReviewDmp";
public static String NewDmp = "NewDmp"; public static String NewDmp = "NewDmp";
public static String DepositDmp = "DepositDmp"; public static String DepositDmp = "DepositDmp";
public static String DeleteDmp = "DeleteDmp"; public static String DeleteDmp = "DeleteDmp";
@ -105,6 +106,7 @@ public final class Permission {
//Description //Description
public static String BrowseDescription = "BrowseDescription"; public static String BrowseDescription = "BrowseDescription";
public static String ReviewDescription = "ReviewDescription";
public static String EditDescription = "EditDescription"; public static String EditDescription = "EditDescription";
public static String FinalizeDescription = "FinalizeDescription"; public static String FinalizeDescription = "FinalizeDescription";
public static String DeleteDescription = "DeleteDescription"; public static String DeleteDescription = "DeleteDescription";

View File

@ -179,6 +179,18 @@ permissions:
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
ReviewDescription:
roles:
- TenantAdmin
dmp:
roles:
- Owner
- User
- DescriptionContributor
- Reviewer
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
EditDescription: EditDescription:
roles: roles:
- TenantAdmin - TenantAdmin
@ -408,6 +420,18 @@ permissions:
clients: [ ] clients: [ ]
allowAnonymous: false allowAnonymous: false
allowAuthenticated: false allowAuthenticated: false
ReviewDmp:
roles:
- TenantAdmin
dmp:
roles:
- Owner
- User
- DescriptionContributor
- Reviewer
clients: [ ]
allowAnonymous: false
allowAuthenticated: false
NewDmp: NewDmp:
roles: roles:
- TenantAdmin - TenantAdmin

View File

@ -71,6 +71,7 @@ export enum AppPermission {
//Dmp //Dmp
BrowseDmp = "BrowseDmp", BrowseDmp = "BrowseDmp",
EditDmp = "EditDmp", EditDmp = "EditDmp",
ReviewDmp = "ReviewDmp",
NewDmp = "NewDmp", NewDmp = "NewDmp",
DepositDmp = "DepositDmp", DepositDmp = "DepositDmp",
DeleteDmp = "DeleteDmp", DeleteDmp = "DeleteDmp",
@ -103,10 +104,12 @@ export enum AppPermission {
//Description //Description
BrowseDescription = "BrowseDescription", BrowseDescription = "BrowseDescription",
ReviewDescription = "ReviewDescription",
EditDescription = "EditDescription", EditDescription = "EditDescription",
FinalizeDescription = "FinalizeDescription", FinalizeDescription = "FinalizeDescription",
DeleteDescription = "DeleteDescription", DeleteDescription = "DeleteDescription",
CloneDescription = "CloneDescription", CloneDescription = "CloneDescription",
ExportDescription = "ExportDescription",
//DescriptionTag //DescriptionTag
BrowseDescriptionTag = "BrowseDescriptionTag", BrowseDescriptionTag = "BrowseDescriptionTag",

View File

@ -8,7 +8,7 @@
<mat-progress-bar color="primary" mode="indeterminate"></mat-progress-bar> <mat-progress-bar color="primary" mode="indeterminate"></mat-progress-bar>
</div> </div>
<div mat-dialog-content class="definition-content"> <div mat-dialog-content class="definition-content">
<app-description-form *ngIf="formGroup && formGroup.get('properties')" [propertiesFormGroup]="previewPropertiesFormGroup" [descriptionId]="descriptionId" [descriptionTemplate]="descriptionTemplate" [visibilityRulesService]="visibilityRulesService" [isNew]="true"></app-description-form> <app-description-form *ngIf="formGroup && formGroup.get('properties')" [propertiesFormGroup]="previewPropertiesFormGroup" [descriptionId]="descriptionId" [descriptionTemplate]="descriptionTemplate" [canReview]="false" [visibilityRulesService]="visibilityRulesService" [isNew]="true"></app-description-form>
</div> </div>
<div mat-mat-dialog-actions *ngIf="formGroup"> <div mat-mat-dialog-actions *ngIf="formGroup">
<div class="col-auto d-flex pb-4 pt-2"> <div class="col-auto d-flex pb-4 pt-2">

View File

@ -104,7 +104,7 @@
</div> </div>
<div [id]="'preview_container'+ form.get('id').value" class="row"> <div [id]="'preview_container'+ form.get('id').value" class="row">
<div *ngIf="previewFieldSet && showPreview && firstField?.get('data')?.get('fieldType')?.value" class="col-12" [@fade-in-fast]> <div *ngIf="previewFieldSet && showPreview && firstField?.get('data')?.get('fieldType')?.value" class="col-12" [@fade-in-fast]>
<app-description-form-field-set class="w-100" [propertiesFormGroup]="previewPropertiesFormGroup" [fieldSet]="previewFieldSet" [visibilityRulesService]="visibilityRulesService" [hideAnnotations]="true"></app-description-form-field-set> <app-description-form-field-set class="w-100" [canReview]="false" [propertiesFormGroup]="previewPropertiesFormGroup" [fieldSet]="previewFieldSet" [visibilityRulesService]="visibilityRulesService" [hideAnnotations]="true"></app-description-form-field-set>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1 +1 @@
<app-description-form *ngIf="previewPropertiesFormGroup" [propertiesFormGroup]="previewPropertiesFormGroup" [descriptionTemplate]="descriptionTemplate" [visibilityRulesService]="visibilityRulesService" [isNew]="true"></app-description-form> <app-description-form *ngIf="previewPropertiesFormGroup" [canReview]="false" [propertiesFormGroup]="previewPropertiesFormGroup" [descriptionTemplate]="descriptionTemplate" [visibilityRulesService]="visibilityRulesService" [isNew]="true"></app-description-form>

View File

@ -150,6 +150,7 @@
[linkToScroll]="linkToScroll" [linkToScroll]="linkToScroll"
[validationErrorModel]="editorModel.validationErrorModel" [validationErrorModel]="editorModel.validationErrorModel"
[isNew]="isNew || isCopy" [isNew]="isNew || isCopy"
[canReview]="canReview"
(fieldsetFocusChange)="fieldsetIdWithFocus = $event" (fieldsetFocusChange)="fieldsetIdWithFocus = $event"
></app-description-form> ></app-description-form>
</div> </div>

View File

@ -63,6 +63,7 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
isNew = true; isNew = true;
isDeleted = false; isDeleted = false;
isCopy = false; isCopy = false;
canReview = false;
item: Description; item: Description;
fieldsetIdWithFocus: string; fieldsetIdWithFocus: string;
fileTransformerEntityTypeEnum = FileTransformerEntityType; fileTransformerEntityTypeEnum = FileTransformerEntityType;
@ -582,19 +583,20 @@ export class DescriptionEditorComponent extends BaseEditor<DescriptionEditorMode
const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = { const descriptionSectionPermissionResolverModel: DescriptionSectionPermissionResolver = {
dmpId: this.item.dmp.id, dmpId: this.item.dmp.id,
sectionIds: [this.item.dmpDescriptionTemplate.sectionId], sectionIds: [this.item.dmpDescriptionTemplate.sectionId],
permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription] permissions: [AppPermission.EditDescription, AppPermission.DeleteDescription, AppPermission.FinalizeDescription, AppPermission.ReviewDescription]
} }
this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel) this.descriptionService.getDescriptionSectionPermissions(descriptionSectionPermissionResolverModel)
.pipe(takeUntil(this._destroyed)).subscribe( .pipe(takeUntil(this._destroyed)).subscribe(
permissionPerSection => { permissionPerSection => {
const canedit = permissionPerSection && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()] && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()].some(x => x === AppPermission.EditDescription); const canedit = permissionPerSection && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()] && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()].some(x => x === AppPermission.EditDescription);
this.canReview = permissionPerSection && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()] && permissionPerSection[this.item.dmpDescriptionTemplate.sectionId.toString()].some(x => x === AppPermission.ReviewDescription);
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !canedit); this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !canedit);
if (this.item.descriptionTemplate?.definition) this.visibilityRulesService.setContext(this.item.descriptionTemplate.definition, this.formGroup.get('properties')); if (this.item.descriptionTemplate?.definition) this.visibilityRulesService.setContext(this.item.descriptionTemplate.definition, this.formGroup.get('properties'));
if (this.item.descriptionTemplate?.definition) this.pageToFieldSetMap = this.mapPageToFieldSet(this.item.descriptionTemplate);; if (this.item.descriptionTemplate?.definition) this.pageToFieldSetMap = this.mapPageToFieldSet(this.item.descriptionTemplate);;
// this.selectedSystemFields = this.selectedSystemFieldDisabled(); // this.selectedSystemFields = this.selectedSystemFieldDisabled();
this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel); this.descriptionEditorService.setValidationErrorModel(this.editorModel.validationErrorModel);
if (this.editorModel.status == DescriptionStatus.Finalized || this.isDeleted) { if (this.editorModel.status == DescriptionStatus.Finalized || this.isDeleted || !canedit) {
this.viewOnly = true; this.viewOnly = true;
this.isFinalized = true; this.isFinalized = true;
this.formGroup.disable(); this.formGroup.disable();

View File

@ -55,6 +55,7 @@ export class DescriptionEditorResolver extends BaseEditorResolver {
[nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'), [nameof<Description>(x => x.authorizationFlags), AppPermission.EditDescription].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'), [nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.FinalizeDescription].join('.'), [nameof<Description>(x => x.authorizationFlags), AppPermission.FinalizeDescription].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.ReviewDescription].join('.'),
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.id)].join('.'), [nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.id)].join('.'),
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'), [nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),

View File

@ -6,7 +6,7 @@
<app-description-form-field-set-title class="row" [fieldSet]="fieldSet" [path]="path" [isChild]="isChild"></app-description-form-field-set-title> <app-description-form-field-set-title class="row" [fieldSet]="fieldSet" [path]="path" [isChild]="isChild"></app-description-form-field-set-title>
</div> </div>
<div *ngIf="!hideAnnotations" class="col-auto"> <div *ngIf="!hideAnnotations" class="col-auto">
<button mat-icon-button class="col-auto annotation-icon" (click)="showAnnotations(fieldSet.id)" [disabled]="propertiesFormGroup.disabled"> <button mat-icon-button class="col-auto annotation-icon" (click)="showAnnotations(fieldSet.id)" [disabled]="!canReview">
<mat-icon matTooltip="{{'DATASET-EDITOR.QUESTION.EXTENDED-DESCRIPTION.ANNOTATIONS' | translate}}" [matBadge]="annotationsCount" [matBadgeHidden]="annotationsCount <= 0" matBadgeColor="warn">comment</mat-icon> <mat-icon matTooltip="{{'DATASET-EDITOR.QUESTION.EXTENDED-DESCRIPTION.ANNOTATIONS' | translate}}" [matBadge]="annotationsCount" [matBadgeHidden]="annotationsCount <= 0" matBadgeColor="warn">comment</mat-icon>
</button> </button>
</div> </div>

View File

@ -28,6 +28,7 @@ export class DescriptionFormFieldSetComponent extends BaseComponent {
@Input() propertiesFormGroup: UntypedFormGroup; @Input() propertiesFormGroup: UntypedFormGroup;
@Input() descriptionId: Guid; @Input() descriptionId: Guid;
@Input() hideAnnotations: boolean = false; @Input() hideAnnotations: boolean = false;
@Input() canReview: boolean = false;
get isMultiplicityEnabled() { get isMultiplicityEnabled() {
return this.fieldSet.hasMultiplicity && this.fieldSet.multiplicity != null; return this.fieldSet.hasMultiplicity && this.fieldSet.multiplicity != null;

View File

@ -23,6 +23,7 @@
[validationErrorModel]="validationErrorModel" [validationErrorModel]="validationErrorModel"
[isChild]="false" [isChild]="false"
[hideAnnotations]="isNew" [hideAnnotations]="isNew"
[canReview]="canReview"
></app-description-form-field-set> ></app-description-form-field-set>
</div> </div>
</div> </div>
@ -32,7 +33,7 @@
<div *ngIf="section?.sections?.length > 0" class="col-12"> <div *ngIf="section?.sections?.length > 0" class="col-12">
<ng-container *ngFor="let innerSection of section.sections; let j = index;"> <ng-container *ngFor="let innerSection of section.sections; let j = index;">
<div class="row" *ngIf="visibilityRulesService.isVisibleMap[innerSection.id]"> <div class="row" *ngIf="visibilityRulesService.isVisibleMap[innerSection.id]">
<app-description-form-section class="col-12" [section]="innerSection" [path]="path+'.'+(j+1)" [pathName]="pathName+'.sections.'+j" (askedToScroll)="onAskedToScroll($event)" [propertiesFormGroup]="propertiesFormGroup" [descriptionId]="descriptionId" [visibilityRulesService]="visibilityRulesService" [linkToScroll]="subsectionLinkToScroll"></app-description-form-section> <app-description-form-section class="col-12" [section]="innerSection" [canReview]="canReview" [path]="path+'.'+(j+1)" [pathName]="pathName+'.sections.'+j" (askedToScroll)="onAskedToScroll($event)" [propertiesFormGroup]="propertiesFormGroup" [descriptionId]="descriptionId" [visibilityRulesService]="visibilityRulesService" [linkToScroll]="subsectionLinkToScroll"></app-description-form-section>
</div> </div>
</ng-container> </ng-container>
</div> </div>

View File

@ -19,6 +19,7 @@ import { Guid } from '@common/types/guid';
export class DescriptionFormSectionComponent extends BaseComponent implements OnInit, OnChanges { export class DescriptionFormSectionComponent extends BaseComponent implements OnInit, OnChanges {
@Input() isNew: boolean = false; @Input() isNew: boolean = false;
@Input() canReview: boolean = false;
@Input() section: DescriptionTemplateSection; @Input() section: DescriptionTemplateSection;
@Input() propertiesFormGroup: UntypedFormGroup; @Input() propertiesFormGroup: UntypedFormGroup;
@Input() visibilityRulesService: VisibilityRulesService; @Input() visibilityRulesService: VisibilityRulesService;

View File

@ -15,7 +15,7 @@
</mat-expansion-panel-header> </mat-expansion-panel-header>
<ng-container *ngFor="let section of page.sections; let i = index;"> <ng-container *ngFor="let section of page.sections; let i = index;">
<div class="row" *ngIf="visibilityRulesService.isVisibleMap[section.id]"> <div class="row" *ngIf="visibilityRulesService.isVisibleMap[section.id]">
<app-description-form-section class="col-12" [section]="section" [path]="(z+1)+'.'+(i+1)" [pathName]="'pages.'+z+'.sections.'+i" [propertiesFormGroup]="propertiesFormGroup" [descriptionId]="descriptionId" [visibilityRulesService]="visibilityRulesService" (askedToScroll)="onAskedToScroll(expansionPanel, $event)" [linkToScroll]="linkToScroll" [validationErrorModel]="validationErrorModel" [isNew]="isNew"></app-description-form-section> <app-description-form-section class="col-12" [section]="section" [canReview]="canReview" [path]="(z+1)+'.'+(i+1)" [pathName]="'pages.'+z+'.sections.'+i" [propertiesFormGroup]="propertiesFormGroup" [descriptionId]="descriptionId" [visibilityRulesService]="visibilityRulesService" (askedToScroll)="onAskedToScroll(expansionPanel, $event)" [linkToScroll]="linkToScroll" [validationErrorModel]="validationErrorModel" [isNew]="isNew"></app-description-form-section>
</div> </div>
</ng-container> </ng-container>
</mat-expansion-panel> </mat-expansion-panel>

View File

@ -21,6 +21,7 @@ export class DescriptionFormComponent extends BaseComponent implements OnInit, A
@Input() visibilityRulesService: VisibilityRulesService; @Input() visibilityRulesService: VisibilityRulesService;
@Input() descriptionId: Guid; @Input() descriptionId: Guid;
@Input() isNew: boolean = false; @Input() isNew: boolean = false;
@Input() canReview: boolean = false;
// @ViewChild('stepper', { static: false }) stepper: MatStepper; // @ViewChild('stepper', { static: false }) stepper: MatStepper;
@Input() path: string; @Input() path: string;

View File

@ -37,7 +37,7 @@
</div> </div>
</div> </div>
<div class="row mb-4 pb-3"> <div class="row mb-4 pb-3">
<div *ngIf="canEdit && isDraftDescription(description) && !isLocked" class="col-auto pr-0"> <div *ngIf="(canEdit || canReview) && isDraftDescription(description) && !isLocked" class="col-auto pr-0">
<button (click)="editClicked(description)" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above"> <button (click)="editClicked(description)" mat-mini-fab class="mr-3 actions-btn" matTooltip="{{'DESCRIPTION-OVERVIEW.ACTIONS.EDIT' | translate}}" matTooltipPosition="above">
<mat-icon class="mat-mini-fab-icon">create</mat-icon> <mat-icon class="mat-mini-fab-icon">create</mat-icon>
</button> </button>

View File

@ -68,6 +68,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
canEdit = false; canEdit = false;
canDelete = false; canDelete = false;
canFinalize = false; canFinalize = false;
canReview = false;
canInviteDmpUsers = false; canInviteDmpUsers = false;
constructor( constructor(
@ -123,6 +124,9 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
this.canEdit = (this.authService.hasPermission(AppPermission.EditDescription) || this.canEdit = (this.authService.hasPermission(AppPermission.EditDescription) ||
this.description.authorizationFlags?.some(x => x === AppPermission.EditDescription)) && this.description.belongsToCurrentTenant != false; this.description.authorizationFlags?.some(x => x === AppPermission.EditDescription)) && this.description.belongsToCurrentTenant != false;
this.canReview = (this.authService.hasPermission(AppPermission.ReviewDescription) ||
this.description.authorizationFlags?.some(x => x === AppPermission.ReviewDescription)) && this.description.belongsToCurrentTenant != false;
this.canFinalize = (this.authService.hasPermission(AppPermission.FinalizeDescription) || this.canFinalize = (this.authService.hasPermission(AppPermission.FinalizeDescription) ||
this.description.authorizationFlags?.some(x => x === AppPermission.FinalizeDescription)) && this.description.belongsToCurrentTenant != false; this.description.authorizationFlags?.some(x => x === AppPermission.FinalizeDescription)) && this.description.belongsToCurrentTenant != false;
@ -479,6 +483,7 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
[nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'), [nameof<Description>(x => x.authorizationFlags), AppPermission.DeleteDescription].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.FinalizeDescription].join('.'), [nameof<Description>(x => x.authorizationFlags), AppPermission.FinalizeDescription].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.InviteDmpUsers].join('.'), [nameof<Description>(x => x.authorizationFlags), AppPermission.InviteDmpUsers].join('.'),
[nameof<Description>(x => x.authorizationFlags), AppPermission.ReviewDescription].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'), [nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.id)].join('.'),
[nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'), [nameof<Description>(x => x.descriptionTemplate), nameof<DescriptionTemplate>(x => x.label)].join('.'),