From 88e74b1e2d34dec8d871d4157d02904c8b1d236f Mon Sep 17 00:00:00 2001 From: Suzana Dirla Date: Thu, 14 Mar 2019 17:42:22 +0200 Subject: [PATCH] [ACA-2259] Edit in Microsoft Office - check update permissions (#1015) * [ACA-2259] Edit in Microsoft Office - check update permissions * [ACA-2259] check update permissions - unit tests * [ACA-2259] refactor - check allowableOperationsOnTarget from service * [ACA-2259] add back check only on target for SharedFiles * [ACA-2259] SharedLinks are not folders * type-safe api for node permissions * workaround for shared files * use hasOwnProperty function --- .../src/lib/evaluators.spec.ts | 22 ++++++ .../src/lib/evaluators.ts | 21 +++++- .../extensions/evaluators/app.evaluators.ts | 6 -- src/app/services/node-permission.service.ts | 71 ++++++++++++------- src/app/store/reducers/app.reducer.ts | 9 +-- 5 files changed, 89 insertions(+), 40 deletions(-) diff --git a/projects/adf-office-services-ext/src/lib/evaluators.spec.ts b/projects/adf-office-services-ext/src/lib/evaluators.spec.ts index 66e5c97da9..e38843a5f7 100644 --- a/projects/adf-office-services-ext/src/lib/evaluators.spec.ts +++ b/projects/adf-office-services-ext/src/lib/evaluators.spec.ts @@ -189,6 +189,25 @@ describe('evaluators', () => { expect(canOpenWithOffice(context)).toBeFalsy(); }); + it('should return [false] if permissions check is false', () => { + const context: any = { + selection: { + file: { + entry: { + name: 'document.docx', + isLocked: false, + properties: {} + } + } + }, + permissions: { + check: () => false + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + it('should return [true] if all checks succeed', () => { const context: any = { selection: { @@ -199,6 +218,9 @@ describe('evaluators', () => { properties: {} } } + }, + permissions: { + check: () => true } }; diff --git a/projects/adf-office-services-ext/src/lib/evaluators.ts b/projects/adf-office-services-ext/src/lib/evaluators.ts index 9453ae1fc5..3a8dd0dcea 100644 --- a/projects/adf-office-services-ext/src/lib/evaluators.ts +++ b/projects/adf-office-services-ext/src/lib/evaluators.ts @@ -26,7 +26,24 @@ export function canOpenWithOffice( const { file } = context.selection; - if (!file || !file.entry || !file.entry.properties) { + if (!file || !file.entry) { + return false; + } + + // workaround for Shared files + if ( + context.navigation && + context.navigation.url && + context.navigation.url.startsWith('/shared') + ) { + if (file.entry.hasOwnProperty('allowableOperationsOnTarget')) { + return context.permissions.check(file, ['update'], { + target: 'allowableOperationsOnTarget' + }); + } + } + + if (!file.entry.properties) { return false; } @@ -63,5 +80,5 @@ export function canOpenWithOffice( return false; } - return true; + return context.permissions.check(file, ['update']); } diff --git a/src/app/extensions/evaluators/app.evaluators.ts b/src/app/extensions/evaluators/app.evaluators.ts index 2a65a530f9..a939f07539 100644 --- a/src/app/extensions/evaluators/app.evaluators.ts +++ b/src/app/extensions/evaluators/app.evaluators.ts @@ -321,12 +321,6 @@ export function canUpdateSelectedNode( return false; } - if (node.entry.hasOwnProperty('allowableOperationsOnTarget')) { - return context.permissions.check(node, ['update'], { - target: 'allowableOperationsOnTarget' - }); - } - return context.permissions.check(node, ['update']); } return false; diff --git a/src/app/services/node-permission.service.ts b/src/app/services/node-permission.service.ts index c6e2c09e53..0340cd4e6e 100644 --- a/src/app/services/node-permission.service.ts +++ b/src/app/services/node-permission.service.ts @@ -25,6 +25,14 @@ import { Injectable } from '@angular/core'; import { NodePermissions } from '@alfresco/adf-extensions'; +import { Node, SharedLink, SharedLinkEntry, NodeEntry } from '@alfresco/js-api'; + +export type PermissionSource = NodeEntry | SharedLinkEntry | Node; + +export interface PermissionOptions { + target?: string; + operation?: string; +} @Injectable({ providedIn: 'root' @@ -32,31 +40,41 @@ import { NodePermissions } from '@alfresco/adf-extensions'; export class NodePermissionService implements NodePermissions { static DEFAULT_OPERATION = 'OR'; - private defaultOptions = { + private defaultOptions: PermissionOptions = { operation: NodePermissionService.DEFAULT_OPERATION, target: null }; - check(source: any, permissions: string[], options?: any): boolean { + check( + source: PermissionSource | PermissionSource[], + permissions: string[], + options?: PermissionOptions + ): boolean { const opts = Object.assign({}, this.defaultOptions, options || {}); - if (source) { - if (Array.isArray(source) && source.length) { - const arr = this.sanitize(source); + if (!source) { + return false; + } + + if (Array.isArray(source)) { + source = source.filter(item => item); - return ( - !!arr.length && - source.every(node => this.hasPermission(node, permissions, opts)) + if (source.length > 0) { + return source.every(node => + this.isOperationAllowed(node, permissions, opts) ); } - - return this.hasPermission(source, permissions, opts); + return false; + } else { + return this.isOperationAllowed(source, permissions, opts); } - - return false; } - private hasPermission(node, permissions, options): boolean { + private isOperationAllowed( + node: PermissionSource, + permissions: string[], + options: PermissionOptions + ): boolean { const allowableOperations = this.getAllowableOperations( node, options.target @@ -77,21 +95,26 @@ export class NodePermissionService implements NodePermissions { return false; } - private getAllowableOperations(node, target): string[] { - const entry = node.entry || node; + private getAllowableOperations( + node: PermissionSource, + property?: string + ): string[] { + let entry: Node | SharedLink; - if (!target && entry.allowableOperations) { - return entry.allowableOperations; + if ('entry' in node) { + entry = node.entry; + } else { + entry = node; } - if (target && entry[target]) { - return entry[target]; + if (property) { + return entry[property] || []; } - return []; - } - - private sanitize(selection): any[] { - return (selection || []).filter(item => item); + if ('allowableOperationsOnTarget' in entry) { + return entry.allowableOperationsOnTarget || []; + } else { + return entry.allowableOperations || []; + } } } diff --git a/src/app/store/reducers/app.reducer.ts b/src/app/store/reducers/app.reducer.ts index 7b7e3a23eb..935b7ee86a 100644 --- a/src/app/store/reducers/app.reducer.ts +++ b/src/app/store/reducers/app.reducer.ts @@ -227,14 +227,7 @@ function updateSelectedNodes( ? true : false; }); - folder = nodes.find((entity: any) => - // workaround Shared - entity.entry.isFolder || - entity.entry.nodeId || - entity.entry.sharedByUser - ? true - : false - ); + folder = nodes.find((entity: any) => entity.entry.isFolder); } }