diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index a7b36adf1..2b8d19b89 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -63,6 +63,7 @@ import { VersionManagerDialogAdapterComponent } from './components/versions-dial
import { BrowsingFilesService } from './common/services/browsing-files.service';
import { ContentManagementService } from './common/services/content-management.service';
import { NodeActionsService } from './common/services/node-actions.service';
+import { NodePermissionService } from './common/services/node-permission.service';
import { MatMenuModule, MatIconModule, MatButtonModule, MatDialogModule, MatInputModule } from '@angular/material';
import { SearchComponent } from './components/search/search.component';
@@ -125,7 +126,8 @@ import { SearchComponent } from './components/search/search.component';
},
BrowsingFilesService,
ContentManagementService,
- NodeActionsService
+ NodeActionsService,
+ NodePermissionService
],
entryComponents: [
VersionManagerDialogAdapterComponent
diff --git a/src/app/common/services/node-permission.service.spec.ts b/src/app/common/services/node-permission.service.spec.ts
new file mode 100644
index 000000000..50752ae6b
--- /dev/null
+++ b/src/app/common/services/node-permission.service.spec.ts
@@ -0,0 +1,190 @@
+/*!
+ * @license
+ * Alfresco Example Content Application
+ *
+ * Copyright (C) 2005 - 2018 Alfresco Software Limited
+ *
+ * This file is part of the Alfresco Example Content Application.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * The Alfresco Example Content Application is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Alfresco Example Content Application is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+import { NodePermissionService } from './node-permission.service';
+
+describe('NodePermissionService', () => {
+ let permission: NodePermissionService;
+
+ beforeEach(() => {
+ permission = new NodePermissionService();
+ });
+
+
+ it('should return false when source is null', () => {
+ const source = null;
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+
+ describe('Multiple source permission', () => {
+ it('should return true when source has allowableOperations permission', () => {
+ const source = [
+ { entry: { allowableOperations: ['update'] } },
+ { entry: { allowableOperations: ['update'] } },
+ { entry: { allowableOperations: ['update'] } }
+ ];
+
+ expect(permission.check(source, ['update'])).toBe(true);
+ });
+
+ it('should return true when source has allowableOperationsOnTarget permission', () => {
+ const source = [
+ { entry: { allowableOperationsOnTarget: ['update'] } },
+ { entry: { allowableOperationsOnTarget: ['update'] } },
+ { entry: { allowableOperationsOnTarget: ['update'] } }
+ ];
+
+ expect(permission.check(source, ['update'])).toBe(true);
+ });
+
+ it('should return false when source does not have allowableOperations permission', () => {
+ const source = [
+ { entry: { allowableOperations: ['update'] } },
+ { entry: { allowableOperations: ['update'] } },
+ { entry: { allowableOperations: ['delete'] } }
+ ];
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+
+ it('should return false when source does not have allowableOperationsOnTarget permission', () => {
+ const source = [
+ { entry: { allowableOperationsOnTarget: ['update'] } },
+ { entry: { allowableOperationsOnTarget: ['update'] } },
+ { entry: { allowableOperationsOnTarget: ['delete'] } }
+ ];
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+
+ it('should return true when source has `OR` allowableOperations permission', () => {
+ const source = [
+ { entry: { allowableOperations: ['update' , 'delete'] } },
+ { entry: { allowableOperations: ['update', 'create'] } },
+ { entry: { allowableOperations: ['update', 'updatePermissions'] } }
+ ];
+
+ expect(permission.check(source, ['update', 'create'])).toBe(true);
+ });
+
+ it('should return true when source has `AND` allowableOperations permission', () => {
+ const source = [
+ { entry: { allowableOperations: ['update' , 'delete', 'other'] } },
+ { entry: { allowableOperations: ['update', 'create', 'other'] } },
+ { entry: { allowableOperations: ['update', 'updatePermissions', 'other'] } }
+ ];
+
+ expect(permission.check(source, ['update', 'other'], 'AND')).toBe(true);
+ });
+
+ it('should return false when source has no `AND` allowableOperations permission', () => {
+ const source = [
+ { entry: { allowableOperations: ['update' , 'delete', 'other'] } },
+ { entry: { allowableOperations: ['update', 'create', 'other'] } },
+ { entry: { allowableOperations: ['update', 'updatePermissions', 'other'] } }
+ ];
+
+ expect(permission.check(source, ['update', 'bogus'], 'AND')).toBe(false);
+ });
+
+ it('should return false when source has no allowableOperations', () => {
+ const source = [
+ { entry: { allowableOperations: [] } },
+ { entry: { allowableOperations: [] } },
+ { entry: { allowableOperations: ['update'] } }
+ ];
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+
+ it('should return false when source has no allowableOperations property', () => {
+ const source = [
+ { entry: { } },
+ { entry: { } },
+ { entry: { allowableOperations: ['update'] } }
+ ];
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+ });
+
+
+ describe('Single source permission', () => {
+ it('should return true when source has allowableOperations permission', () => {
+ const source = { entry: { allowableOperations: ['update'] } };
+
+ expect(permission.check(source, ['update'])).toBe(true);
+ });
+
+ it('should return true when source has allowableOperationsOnTarget permission', () => {
+ const source = { entry: { allowableOperationsOnTarget: ['update'] } };
+
+ expect(permission.check(source, ['update'])).toBe(true);
+ });
+
+ it('should return false when source does not have allowableOperations permission', () => {
+ const source = { entry: { allowableOperations: ['delete'] } };
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+
+ it('should return false when source does not have allowableOperationsOnTarget permission', () => {
+ const source = { entry: { allowableOperationsOnTarget: ['delete'] } };
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+
+ it('should return true when source has `OR` allowableOperations permission', () => {
+ const source = { entry: { allowableOperations: ['update'] } };
+
+ expect(permission.check(source, ['update', 'create'])).toBe(true);
+ });
+
+ it('should return true when source has `AND` allowableOperations permission', () => {
+ const source = { entry: { allowableOperations: ['update', 'other'] } };
+
+ expect(permission.check(source, ['update', 'other'], 'AND')).toBe(true);
+ });
+
+ it('should return false when source has no `AND` allowableOperations permission', () => {
+ const source = { entry: { allowableOperations: ['update', 'updatePermissions', 'other'] } };
+
+ expect(permission.check(source, ['update', 'bogus'], 'AND')).toBe(false);
+ });
+
+ it('should return false when source has no allowableOperations', () => {
+ const source = { entry: { allowableOperations: [] } };
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+
+ it('should return false when source has no allowableOperations property', () => {
+ const source = { entry: { } };
+
+ expect(permission.check(source, ['update'])).toBe(false);
+ });
+ });
+});
diff --git a/src/app/common/services/node-permission.service.ts b/src/app/common/services/node-permission.service.ts
new file mode 100644
index 000000000..9c8089745
--- /dev/null
+++ b/src/app/common/services/node-permission.service.ts
@@ -0,0 +1,77 @@
+/*!
+ * @license
+ * Alfresco Example Content Application
+ *
+ * Copyright (C) 2005 - 2018 Alfresco Software Limited
+ *
+ * This file is part of the Alfresco Example Content Application.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * The Alfresco Example Content Application is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Alfresco Example Content Application is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Alfresco. If not, see .
+ */
+
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class NodePermissionService {
+ static DEFAULT_OPERATION = 'OR';
+
+ check(source: any, permissions: string[], operation: string = NodePermissionService.DEFAULT_OPERATION): boolean {
+ if (source) {
+ if (Array.isArray(source) && source.length) {
+ const arr = this.sanitize(source);
+
+ return !!arr.length && source.every(node => this.hasPermission(node, permissions, operation));
+ }
+
+ return this.hasPermission(source, permissions, operation);
+ }
+
+ return false;
+ }
+
+ private hasPermission(node, permissions, operation): boolean {
+ const allowableOperations = this.getAllowableOperations(node);
+
+ if (allowableOperations.length) {
+ if (operation === NodePermissionService.DEFAULT_OPERATION) {
+ return permissions.some(permission => allowableOperations.includes(permission));
+ } else {
+ return permissions.every(permission => allowableOperations.includes(permission));
+ }
+ }
+
+ return false;
+ }
+
+ private getAllowableOperations(node): string[] {
+ const entry = node.entry || node;
+
+ if (entry.allowableOperationsOnTarget) {
+ return entry.allowableOperationsOnTarget;
+ }
+
+ if (entry.allowableOperations) {
+ return entry.allowableOperations;
+ }
+
+ return [];
+ }
+
+ private sanitize(selection): any[] {
+ return (selection || []).filter(item => item);
+ }
+}
diff --git a/src/app/components/preview/preview.component.html b/src/app/components/preview/preview.component.html
index 346c29a3f..87b732839 100644
--- a/src/app/components/preview/preview.component.html
+++ b/src/app/components/preview/preview.component.html
@@ -1,7 +1,23 @@
+
+
+
+
+
+
+
+
+
+
-
+
{{ selection.hasFavorites() ? 'star' :'star_border' }}
{{ 'APP.ACTIONS.FAVORITE' | translate }}
@@ -23,33 +42,32 @@
diff --git a/src/app/components/preview/preview.component.spec.ts b/src/app/components/preview/preview.component.spec.ts
index c52b49ee1..bbd5dfb88 100644
--- a/src/app/components/preview/preview.component.spec.ts
+++ b/src/app/components/preview/preview.component.spec.ts
@@ -36,7 +36,7 @@ import { HttpClientModule } from '@angular/common/http';
import { PreviewComponent } from './preview.component';
import { Observable } from 'rxjs/Rx';
-import { ContentManagementService } from '../../common/services/content-management.service';
+import { NodePermissionService } from '../../common/services/node-permission.service';
import { MatSnackBarModule } from '@angular/material';
describe('PreviewComponent', () => {
@@ -64,7 +64,7 @@ describe('PreviewComponent', () => {
CookieService,
NotificationService,
UserPreferencesService,
- ContentManagementService
+ NodePermissionService
],
declarations: [
PreviewComponent,
diff --git a/src/app/components/preview/preview.component.ts b/src/app/components/preview/preview.component.ts
index 20cda82e4..adc97d31e 100644
--- a/src/app/components/preview/preview.component.ts
+++ b/src/app/components/preview/preview.component.ts
@@ -27,7 +27,7 @@ import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AlfrescoApiService, UserPreferencesService, ObjectUtils } from '@alfresco/adf-core';
import { Node, MinimalNodeEntity } from 'alfresco-js-api';
-import { ContentManagementService } from '../../common/services/content-management.service';
+import { NodePermissionService } from '../../common/services/node-permission.service';
@Component({
selector: 'app-preview',
@@ -54,10 +54,10 @@ export class PreviewComponent implements OnInit {
selectedEntities: MinimalNodeEntity[] = [];
constructor(private router: Router,
- private route: ActivatedRoute,
- private apiService: AlfrescoApiService,
- private preferences: UserPreferencesService,
- private content: ContentManagementService) {
+ private route: ActivatedRoute,
+ private apiService: AlfrescoApiService,
+ private preferences: UserPreferencesService,
+ public permission: NodePermissionService) {
}
ngOnInit() {
@@ -324,28 +324,11 @@ export class PreviewComponent implements OnInit {
return path;
}
- canDeleteFile(): boolean {
- return this.content.canDeleteNode(this.node);
- }
-
async deleteFile() {
try {
- await this.content.deleteNode(this.node);
+ await this.permission.check(this.node, ['delete']);
this.onVisibilityChanged(false);
} catch {
}
}
-
- canMoveFile(): boolean {
- return this.content.canMoveNode(this.node);
- }
-
- canCopyFile(): boolean {
- return this.content.canCopyNode(this.node);
- }
-
- canManageVersions(): boolean {
- return this.node.isFile && this.content.nodeHasPermission(this.node, 'update');
- }
-
}
diff --git a/src/app/ui/application.scss b/src/app/ui/application.scss
index 6500f96b6..d7122b7bf 100644
--- a/src/app/ui/application.scss
+++ b/src/app/ui/application.scss
@@ -27,5 +27,6 @@ ng-component {
@import './overrides/alfresco-upload-button';
@import './overrides/alfresco-upload-dialog';
@import './overrides/toolbar';
+@import './overrides/adf-viewer-more-actions';
@import './overrides/breadcrumb';
@import './overrides/adf-info-drawer';
diff --git a/src/app/ui/custom-theme.scss b/src/app/ui/custom-theme.scss
index d84615b8f..9cd3784d1 100644
--- a/src/app/ui/custom-theme.scss
+++ b/src/app/ui/custom-theme.scss
@@ -3,6 +3,7 @@
@import '../components/sidenav/sidenav.component.theme';
@import './overrides/toolbar';
+@import './overrides/adf-viewer-more-actions';
$grey-scale: (
50 : #e0e0e0,
@@ -47,4 +48,5 @@ $custom-theme: mat-light-theme($custom-theme-primary, $custom-theme-accent);
@mixin custom-theme($theme) {
@include sidenav-component-theme($custom-theme);
@include toolbar-component-theme($custom-theme);
+ @include viewer-more-actions-component-theme($custom-theme);
}
diff --git a/src/app/ui/overrides/_adf-viewer-more-actions.scss b/src/app/ui/overrides/_adf-viewer-more-actions.scss
new file mode 100644
index 000000000..fc9a7cc62
--- /dev/null
+++ b/src/app/ui/overrides/_adf-viewer-more-actions.scss
@@ -0,0 +1,18 @@
+@mixin viewer-more-actions-component-theme($theme) {
+ $primary: map-get($theme, primary);
+ $accent: map-get($theme, accent);
+ $background: map-get($theme, background);
+
+ .adf-viewer-more-actions {
+ @include angular-material-theme($theme);
+
+ .toolbar__option--active {
+ color: mat-color($accent) !important;
+ }
+
+ .toolbar__option--default {
+ color: mat-color($primary, .87) !important;
+ }
+ }
+
+}