rename old hasPermission as allowableOperation and introduce the real hasPermissions (#4294)

This commit is contained in:
Eugenio Romano
2019-02-11 10:44:37 +00:00
committed by GitHub
parent 324e86aaf3
commit 3263659ac2
39 changed files with 256 additions and 178 deletions

View File

@@ -17,16 +17,16 @@
import { ChangeDetectorRef, Component, ElementRef, SimpleChange } from '@angular/core';
import { ContentService } from './../services/content.service';
import { NodePermissionDirective, NodePermissionSubject } from './node-permission.directive';
import { CheckAllowableOperationDirective, NodeAllowableOperationSubject } from './check-allowable-operation.directive';
@Component({
selector: 'adf-text-subject'
})
class TestComponent implements NodePermissionSubject {
class TestComponent implements NodeAllowableOperationSubject {
disabled: boolean = false;
}
describe('NodePermissionDirective', () => {
describe('CheckAllowableOperationDirective', () => {
let changeDetectorMock: ChangeDetectorRef;
@@ -37,7 +37,7 @@ describe('NodePermissionDirective', () => {
describe('HTML nativeElement as subject', () => {
it('updates element once it is loaded', () => {
const directive = new NodePermissionDirective(null, null, null, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(null, null, null, changeDetectorMock);
spyOn(directive, 'updateElement').and.stub();
const nodes = [{}, {}];
@@ -48,7 +48,7 @@ describe('NodePermissionDirective', () => {
});
it('updates element on nodes change', () => {
const directive = new NodePermissionDirective(null, null, null, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(null, null, null, changeDetectorMock);
spyOn(directive, 'updateElement').and.stub();
const nodes = [{}, {}];
@@ -59,7 +59,7 @@ describe('NodePermissionDirective', () => {
});
it('updates element only on subsequent change', () => {
const directive = new NodePermissionDirective(null, null, null, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(null, null, null, changeDetectorMock);
spyOn(directive, 'updateElement').and.stub();
const nodes = [{}, {}];
@@ -72,7 +72,7 @@ describe('NodePermissionDirective', () => {
it('enables decorated element', () => {
const renderer = jasmine.createSpyObj('renderer', ['removeAttribute']);
const elementRef = new ElementRef({});
const directive = new NodePermissionDirective(elementRef, renderer, null, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(elementRef, renderer, null, changeDetectorMock);
directive.enableElement();
@@ -82,7 +82,7 @@ describe('NodePermissionDirective', () => {
it('disables decorated element', () => {
const renderer = jasmine.createSpyObj('renderer', ['setAttribute']);
const elementRef = new ElementRef({});
const directive = new NodePermissionDirective(elementRef, renderer, null, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(elementRef, renderer, null, changeDetectorMock);
directive.disableElement();
@@ -90,7 +90,7 @@ describe('NodePermissionDirective', () => {
});
it('disables element when nodes not available', () => {
const directive = new NodePermissionDirective(null, null, null, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(null, null, null, changeDetectorMock);
spyOn(directive, 'disableElement').and.stub();
directive.nodes = null;
@@ -102,9 +102,9 @@ describe('NodePermissionDirective', () => {
it('enables element when all nodes have expected permission', () => {
const contentService = new ContentService(null, null, null, null);
spyOn(contentService, 'hasPermission').and.returnValue(true);
spyOn(contentService, 'hasAllowableOperations').and.returnValue(true);
const directive = new NodePermissionDirective(null, null, contentService, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(null, null, contentService, changeDetectorMock);
spyOn(directive, 'enableElement').and.stub();
directive.nodes = <any> [{}, {}];
@@ -115,9 +115,9 @@ describe('NodePermissionDirective', () => {
it('disables element when one of the nodes have no permission', () => {
const contentService = new ContentService(null, null, null, null);
spyOn(contentService, 'hasPermission').and.returnValue(false);
spyOn(contentService, 'hasAllowableOperations').and.returnValue(false);
const directive = new NodePermissionDirective(null, null, contentService, changeDetectorMock);
const directive = new CheckAllowableOperationDirective(null, null, contentService, changeDetectorMock);
spyOn(directive, 'disableElement').and.stub();
directive.nodes = <any> [{}, {}];
@@ -131,12 +131,12 @@ describe('NodePermissionDirective', () => {
it('disables decorated component', () => {
const contentService = new ContentService(null, null, null, null);
spyOn(contentService, 'hasPermission').and.returnValue(false);
spyOn(contentService, 'hasAllowableOperations').and.returnValue(false);
spyOn(changeDetectorMock, 'detectChanges');
let testComponent = new TestComponent();
testComponent.disabled = false;
const directive = new NodePermissionDirective(null, null, contentService, changeDetectorMock, testComponent);
const directive = new CheckAllowableOperationDirective(null, null, contentService, changeDetectorMock, testComponent);
directive.nodes = <any> [{}, {}];
directive.updateElement();
@@ -147,12 +147,12 @@ describe('NodePermissionDirective', () => {
it('enables decorated component', () => {
const contentService = new ContentService(null, null, null, null);
spyOn(contentService, 'hasPermission').and.returnValue(true);
spyOn(contentService, 'hasAllowableOperations').and.returnValue(true);
spyOn(changeDetectorMock, 'detectChanges');
let testComponent = new TestComponent();
testComponent.disabled = true;
const directive = new NodePermissionDirective(null, null, contentService, changeDetectorMock, testComponent);
const directive = new CheckAllowableOperationDirective(null, null, contentService, changeDetectorMock, testComponent);
directive.nodes = <any> [{}, {}];
directive.updateElement();

View File

@@ -22,19 +22,19 @@ import { NodeEntry } from '@alfresco/js-api';
import { ContentService } from './../services/content.service';
import { EXTENDIBLE_COMPONENT } from './../interface/injection.tokens';
export interface NodePermissionSubject {
export interface NodeAllowableOperationSubject {
disabled: boolean;
}
@Directive({
selector: '[adf-node-permission]'
selector: '[adf-check-allowable-operation]'
})
export class NodePermissionDirective implements OnChanges {
export class CheckAllowableOperationDirective implements OnChanges {
/** Node permission to check (create, delete, update, updatePermissions,
* !create, !delete, !update, !updatePermissions).
*/
@Input('adf-node-permission')
@Input('adf-check-allowable-operation')
permission: string = null;
/** Nodes to check permission for. */
@@ -48,7 +48,7 @@ export class NodePermissionDirective implements OnChanges {
@Host()
@Optional()
@Inject(EXTENDIBLE_COMPONENT) private parentComponent?: NodePermissionSubject) {
@Inject(EXTENDIBLE_COMPONENT) private parentComponent?: NodeAllowableOperationSubject) {
}
ngOnChanges(changes: SimpleChanges) {
@@ -60,10 +60,10 @@ export class NodePermissionDirective implements OnChanges {
/**
* Updates disabled state for the decorated element
*
* @memberof NodePermissionDirective
* @memberof CheckAllowableOperationDirective
*/
updateElement(): boolean {
let enable = this.hasPermission(this.nodes, this.permission);
let enable = this.hasAllowableOperations(this.nodes, this.permission);
if (enable) {
this.enable();
@@ -95,7 +95,7 @@ export class NodePermissionDirective implements OnChanges {
/**
* Enables decorated element
*
* @memberof NodePermissionDirective
* @memberof CheckAllowableOperationDirective
*/
enableElement(): void {
this.renderer.removeAttribute(this.elementRef.nativeElement, 'disabled');
@@ -104,7 +104,7 @@ export class NodePermissionDirective implements OnChanges {
/**
* Disables decorated element
*
* @memberof NodePermissionDirective
* @memberof CheckAllowableOperationDirective
*/
disableElement(): void {
this.renderer.setAttribute(this.elementRef.nativeElement, 'disabled', 'true');
@@ -115,11 +115,11 @@ export class NodePermissionDirective implements OnChanges {
*
* @param nodes Node collection to check
* @param permission Permission to check for each node
* @memberof NodePermissionDirective
* @memberof CheckAllowableOperationDirective
*/
hasPermission(nodes: NodeEntry[], permission: string): boolean {
hasAllowableOperations(nodes: NodeEntry[], permission: string): boolean {
if (nodes && nodes.length > 0) {
return nodes.every((node) => this.contentService.hasPermission(node.entry, permission));
return nodes.every((node) => this.contentService.hasAllowableOperations(node.entry, permission));
}
return false;

View File

@@ -23,7 +23,7 @@ import { HighlightDirective } from './highlight.directive';
import { LogoutDirective } from './logout.directive';
import { NodeDeleteDirective } from './node-delete.directive';
import { NodeFavoriteDirective } from './node-favorite.directive';
import { NodePermissionDirective } from './node-permission.directive';
import { CheckAllowableOperationDirective } from './check-allowable-operation.directive';
import { NodeRestoreDirective } from './node-restore.directive';
import { UploadDirective } from './upload.directive';
import { NodeDownloadDirective } from './node-download.directive';
@@ -38,7 +38,7 @@ import { NodeDownloadDirective } from './node-download.directive';
LogoutDirective,
NodeDeleteDirective,
NodeFavoriteDirective,
NodePermissionDirective,
CheckAllowableOperationDirective,
NodeRestoreDirective,
NodeDownloadDirective,
UploadDirective
@@ -48,7 +48,7 @@ import { NodeDownloadDirective } from './node-download.directive';
LogoutDirective,
NodeDeleteDirective,
NodeFavoriteDirective,
NodePermissionDirective,
CheckAllowableOperationDirective,
NodeRestoreDirective,
NodeDownloadDirective,
UploadDirective

View File

@@ -44,7 +44,7 @@ class TestComponent {
@Component({
template: `
<div id="delete-component" [adf-node-permission]="selection"
<div id="delete-component" [adf-check-allowable-operation]="selection"
[adf-delete]="selection"
(delete)="onDelete($event)">
</div>`
@@ -335,7 +335,7 @@ describe('NodeDeleteDirective', () => {
});
});
it('should not enable the button if adf-node-permission is present', (done) => {
it('should not enable the button if adf-check-allowable-operation is present', (done) => {
elementWithPermissions.nativeElement.disabled = false;
componentWithPermissions.selection = [];

View File

@@ -76,7 +76,7 @@ export class NodeDeleteDirective implements OnChanges {
if (!this.selection || (this.selection && this.selection.length === 0)) {
this.setDisableAttribute(true);
} else {
if (!this.elementRef.nativeElement.hasAttribute('adf-node-permission')) {
if (!this.elementRef.nativeElement.hasAttribute('adf-check-allowable-operation')) {
this.setDisableAttribute(false);
}
}

View File

@@ -19,7 +19,7 @@ export * from './highlight.directive';
export * from './logout.directive';
export * from './node-delete.directive';
export * from './node-favorite.directive';
export * from './node-permission.directive';
export * from './check-allowable-operation.directive';
export * from './node-restore.directive';
export * from './node-download.directive';
export * from './upload.directive';

View File

@@ -0,0 +1,30 @@
/*!
* @license
* Copyright 2016 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* spellchecker: disable */
export class AllowableOperationsEnum extends String {
static DELETE: string = 'delete';
static UPDATE: string = 'update';
static CREATE: string = 'create';
static COPY: string = 'copy';
static LOCK: string = 'lock';
static UPDATEPERMISSIONS: string = 'updatePermissions';
static NOT_DELETE: string = '!delete';
static NOT_UPDATE: string = '!update';
static NOT_CREATE: string = '!create';
static NOT_UPDATEPERMISSIONS: string = '!updatePermissions';
}

View File

@@ -17,14 +17,12 @@
/* spellchecker: disable */
export class PermissionsEnum extends String {
static DELETE: string = 'delete';
static UPDATE: string = 'update';
static CREATE: string = 'create';
static COPY: string = 'copy';
static LOCK: string = 'lock';
static UPDATEPERMISSIONS: string = 'updatePermissions';
static NOT_DELETE: string = '!delete';
static NOT_UPDATE: string = '!update';
static NOT_CREATE: string = '!create';
static NOT_UPDATEPERMISSIONS: string = '!updatePermissions';
static CONTRIBUTOR: string = 'Contributor';
static CONSUMER: string = 'Consumer';
static COLLABORATOR: string = 'Collaborator';
static MANAGER: string = 'Manager';
static NOT_CONTRIBUTOR: string = '!Contributor';
static NOT_CONSUMER: string = '!Consumer';
static NOT_COLLABORATOR: string = '!Collaborator';
static NOT_MANAGER: string = '!Manager';
}

View File

@@ -16,6 +16,7 @@
*/
export * from './file.model';
export * from './allowable-operations.enum';
export * from './permissions.enum';
export * from './product-version.model';
export * from './user-process.model';

View File

@@ -106,35 +106,67 @@ describe('ContentService', () => {
});
});
it('should havePermission be false if allowableOperation is not present in the node', () => {
let permissionNode = new Node({});
expect(contentService.hasPermission(permissionNode, 'create')).toBeFalsy();
describe('AllowableOperations', () => {
it('should hasAllowableOperations be false if allowableOperation is not present in the node', () => {
let permissionNode = new Node({});
expect(contentService.hasAllowableOperations(permissionNode, 'create')).toBeFalsy();
});
it('should hasAllowableOperations be true if allowableOperation is present and you have the permission for the request operation', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'create', 'updatePermissions'] });
expect(contentService.hasAllowableOperations(permissionNode, 'create')).toBeTruthy();
});
it('should hasAllowableOperations be false if allowableOperation is present but you don\'t have the permission for the request operation', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] });
expect(contentService.hasAllowableOperations(permissionNode, 'create')).toBeFalsy();
});
it('should hasAllowableOperations works in the opposite way with negate value', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] });
expect(contentService.hasAllowableOperations(permissionNode, '!create')).toBeTruthy();
});
it('should hasAllowableOperations return false if no permission parameter are passed', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] });
expect(contentService.hasAllowableOperations(permissionNode, null)).toBeFalsy();
});
it('should havePermission return true if permission parameter is copy', () => {
let permissionNode = null;
expect(contentService.hasAllowableOperations(permissionNode, 'copy')).toBeTruthy();
});
});
it('should havePermission be true if allowableOperation is present and you have the permission for the request operation', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'create', 'updatePermissions'] });
describe('Permissions', () => {
expect(contentService.hasPermission(permissionNode, 'create')).toBeTruthy();
});
it('should havePermission be false if allowableOperation is not present in the node', () => {
let permissionNode = new Node({});
expect(contentService.hasPermissions(permissionNode, 'manager')).toBeFalsy();
});
it('should havePermission be false if allowableOperation is present but you don\'t have the permission for the request operation', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] });
expect(contentService.hasPermission(permissionNode, 'create')).toBeFalsy();
});
it('should havePermission be true if permissions is present and you have the permission for the request operation', () => {
let permissionNode = new Node({ permissions: { locallySet: [{ name: 'manager' }, { name: 'collaborator' }, { name: 'consumer' }] } });
it('should havePermission works in the opposite way with negate value', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] });
expect(contentService.hasPermission(permissionNode, '!create')).toBeTruthy();
});
expect(contentService.hasPermissions(permissionNode, 'manager')).toBeTruthy();
});
it('should havePermission return false id no permission parameter are passed', () => {
let permissionNode = new Node({ allowableOperations: ['delete', 'update', 'updatePermissions'] });
expect(contentService.hasPermission(permissionNode, null)).toBeFalsy();
});
it('should havePermission be false if permissions is present but you don\'t have the permission for the request operation', () => {
let permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } });
expect(contentService.hasPermissions(permissionNode, 'manager')).toBeFalsy();
});
it('should havePermission return true if permission parameter is copy', () => {
let permissionNode = null;
expect(contentService.hasPermission(permissionNode, 'copy')).toBeTruthy();
it('should havePermission works in the opposite way with negate value', () => {
let permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } });
expect(contentService.hasPermissions(permissionNode, '!manager')).toBeTruthy();
});
it('should havePermission return false if no permission parameter are passed', () => {
let permissionNode = new Node({ permissions: { locallySet: [{ name: 'collaborator' }, { name: 'consumer' }] } });
expect(contentService.hasPermissions(permissionNode, null)).toBeFalsy();
});
});
describe('Download blob', () => {

View File

@@ -20,11 +20,12 @@ import { DomSanitizer } from '@angular/platform-browser';
import { ContentApi, MinimalNode, Node, NodeEntry } from '@alfresco/js-api';
import { Observable, Subject, from, throwError } from 'rxjs';
import { FolderCreatedEvent } from '../events/folder-created.event';
import { PermissionsEnum } from '../models/permissions.enum';
import { AlfrescoApiService } from './alfresco-api.service';
import { AuthenticationService } from './authentication.service';
import { LogService } from './log.service';
import { catchError } from 'rxjs/operators';
import { PermissionsEnum } from '../models/permissions.enum';
import { AllowableOperationsEnum } from '../models/allowable-operations.enum';
@Injectable({
providedIn: 'root'
@@ -171,50 +172,66 @@ export class ContentService {
return from(this.apiService.getInstance().nodes.getNode(nodeId, opts));
}
/**
* Checks if the user has permission on that node
* @param node Node to check permissions
* @param permission
* @returns True if the user has the required permissions, false otherwise
*/
hasPermissions(node: Node, permission: PermissionsEnum | string): boolean {
let hasPermissions = false;
if (node && node.permissions && node.permissions.locallySet) {
if (permission && permission.startsWith('!')) {
hasPermissions = node.permissions.locallySet.find((currentPermission) => currentPermission.name === permission.replace('!', '')) ? false : true;
} else {
hasPermissions = node.permissions.locallySet.find((currentPermission) => currentPermission.name === permission) ? true : false;
}
} else {
if (permission && permission.startsWith('!')) {
hasPermissions = true;
}
}
return hasPermissions;
}
/**
* Checks if the user has permissions on that node
* @param node Node to check allowableOperations
* @param permission Create, delete, update, updatePermissions, !create, !delete, !update, !updatePermissions
* @returns True if the user has the required permissions, false otherwise
*/
hasPermission(node: Node, permission: PermissionsEnum | string): boolean {
let hasPermission = false;
hasAllowableOperations(node: Node, allowableOperation: AllowableOperationsEnum | string): boolean {
let hasAllowableOperations = false;
if (this.hasAllowableOperations(node)) {
if (permission && permission.startsWith('!')) {
hasPermission = node.allowableOperations.find((currentPermission) => currentPermission === permission.replace('!', '')) ? false : true;
if (node && node.allowableOperations) {
if (allowableOperation && allowableOperation.startsWith('!')) {
hasAllowableOperations = node.allowableOperations.find((currentOperation) => currentOperation === allowableOperation.replace('!', '')) ? false : true;
} else {
hasPermission = node.allowableOperations.find((currentPermission) => currentPermission === permission) ? true : false;
hasAllowableOperations = node.allowableOperations.find((currentOperation) => currentOperation === allowableOperation) ? true : false;
}
} else {
if (permission && permission.startsWith('!')) {
hasPermission = true;
if (allowableOperation && allowableOperation.startsWith('!')) {
hasAllowableOperations = true;
}
}
if (permission === PermissionsEnum.COPY) {
hasPermission = true;
if (allowableOperation === AllowableOperationsEnum.COPY) {
hasAllowableOperations = true;
}
if (permission === PermissionsEnum.LOCK) {
hasPermission = node.isFile;
if (allowableOperation === AllowableOperationsEnum.LOCK) {
hasAllowableOperations = node.isFile;
if (node.isLocked && this.hasAllowableOperations(node)) {
hasPermission = !!~node.allowableOperations.indexOf('updatePermissions');
if (node.isLocked && node.allowableOperations) {
hasAllowableOperations = !!~node.allowableOperations.indexOf('updatePermissions');
}
}
return hasPermission;
}
/**
* Checks if the node has the properties allowableOperations
* @param node Node to check allowableOperations
* @returns True if the node has the property, false otherwise
*/
hasAllowableOperations(node: any): boolean {
return node && node.allowableOperations ? true : false;
return hasAllowableOperations;
}
private handleError(error: any) {