mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
DocumentList - Check permissions on delete folder/file (#1808)
* Add check permission on delete folder/file * Provide a way to disable the action when if there is no permission * Improve the code using the external permission inside the folder/document action service * Add basic documentation. - How disable the button when the permission is missing - How to show a notification message when the permission is missing * Resize the image * Change the value to true for demo purpose * Update folder-actions.service.ts * Update document-actions.service.ts
This commit is contained in:
parent
ab3d18e5c1
commit
f6102dfc07
@ -70,7 +70,10 @@
|
|||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="folder"
|
target="folder"
|
||||||
|
permission="delete"
|
||||||
|
[disableWithNoPermission]="true"
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.FOLDER.DELETE' | translate}}"
|
||||||
|
(permissionEvent)="onPermissionsFailed($event)"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
<!-- document actions -->
|
<!-- document actions -->
|
||||||
@ -91,6 +94,9 @@
|
|||||||
</content-action>
|
</content-action>
|
||||||
<content-action
|
<content-action
|
||||||
target="document"
|
target="document"
|
||||||
|
permission="delete"
|
||||||
|
[disableWithNoPermission]="true"
|
||||||
|
(permissionEvent)="onPermissionsFailed($event)"
|
||||||
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
title="{{'DOCUMENT_LIST.ACTIONS.DOCUMENT.DELETE' | translate}}"
|
||||||
handler="delete">
|
handler="delete">
|
||||||
</content-action>
|
</content-action>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
import { Component, OnInit, AfterViewInit, Optional, ViewChild, ViewChildren, ChangeDetectorRef } from '@angular/core';
|
import { Component, OnInit, AfterViewInit, Optional, ViewChild, ViewChildren, ChangeDetectorRef } from '@angular/core';
|
||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { AlfrescoAuthenticationService, LogService } from 'ng2-alfresco-core';
|
import { AlfrescoAuthenticationService, LogService, NotificationService } from 'ng2-alfresco-core';
|
||||||
import { DocumentActionsService, DocumentListComponent, ContentActionHandler, DocumentActionModel, FolderActionModel } from 'ng2-alfresco-documentlist';
|
import { DocumentActionsService, DocumentListComponent, ContentActionHandler, DocumentActionModel, FolderActionModel } from 'ng2-alfresco-documentlist';
|
||||||
import { FormService } from 'ng2-activiti-form';
|
import { FormService } from 'ng2-activiti-form';
|
||||||
import { UploadButtonComponent, UploadDragAreaComponent } from 'ng2-alfresco-upload';
|
import { UploadButtonComponent, UploadDragAreaComponent } from 'ng2-alfresco-upload';
|
||||||
@ -55,6 +55,7 @@ export class FilesComponent implements OnInit, AfterViewInit {
|
|||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private changeDetector: ChangeDetectorRef,
|
private changeDetector: ChangeDetectorRef,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
|
private notificationService: NotificationService,
|
||||||
@Optional() private route: ActivatedRoute) {
|
@Optional() private route: ActivatedRoute) {
|
||||||
documentActions.setHandler('my-handler', this.myDocumentActionHandler.bind(this));
|
documentActions.setHandler('my-handler', this.myDocumentActionHandler.bind(this));
|
||||||
}
|
}
|
||||||
@ -168,6 +169,10 @@ export class FilesComponent implements OnInit, AfterViewInit {
|
|||||||
}.bind(this);
|
}.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onPermissionsFailed(event: any) {
|
||||||
|
this.notificationService.openSnackMessage(`you don't have the ${event.permission} permission to ${event.action} the ${event.type} `, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
reload(event: any) {
|
reload(event: any) {
|
||||||
if (event && event.value && event.value.entry && event.value.entry.parentId) {
|
if (event && event.value && event.value.entry && event.value.entry.parentId) {
|
||||||
if (this.documentList.currentFolderId === event.value.entry.parentId) {
|
if (this.documentList.currentFolderId === event.value.entry.parentId) {
|
||||||
|
@ -34,14 +34,14 @@
|
|||||||
[class.alfresco-datatable__row--selected]="selectedRow === row"
|
[class.alfresco-datatable__row--selected]="selectedRow === row"
|
||||||
[adf-upload]="allowDropFiles" [adf-upload-data]="row">
|
[adf-upload]="allowDropFiles" [adf-upload-data]="row">
|
||||||
|
|
||||||
<!-- Actions (right) -->
|
<!-- Actions (left) -->
|
||||||
<td *ngIf="actions && actionsPosition === 'left'" class="alfresco-datatable__actions-cell">
|
<td *ngIf="actions && actionsPosition === 'left'" class="alfresco-datatable__actions-cell">
|
||||||
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon" [attr.data-automation-id]="actions_menu">
|
<button [id]="'action_menu_' + idx" alfresco-mdl-button class="mdl-button--icon" [attr.data-automation-id]="actions_menu">
|
||||||
<i class="material-icons">more_vert</i>
|
<i class="material-icons">more_vert</i>
|
||||||
</button>
|
</button>
|
||||||
<ul alfresco-mdl-menu class="mdl-menu--bottom-left"
|
<ul alfresco-mdl-menu class="mdl-menu--bottom-left"
|
||||||
[attr.for]="'action_menu_' + idx">
|
[attr.for]="'action_menu_' + idx">
|
||||||
<li class="mdl-menu__item"
|
<li class="mdl-menu__item" [attr.disabled]="action.disabled"
|
||||||
[attr.data-automation-id]="action.title"
|
[attr.data-automation-id]="action.title"
|
||||||
*ngFor="let action of getRowActions(row)"
|
*ngFor="let action of getRowActions(row)"
|
||||||
(click)="onExecuteRowAction(row, action)">
|
(click)="onExecuteRowAction(row, action)">
|
||||||
@ -90,7 +90,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<ul alfresco-mdl-menu class="mdl-menu--bottom-right"
|
<ul alfresco-mdl-menu class="mdl-menu--bottom-right"
|
||||||
[attr.for]="'action_menu_' + idx">
|
[attr.for]="'action_menu_' + idx">
|
||||||
<li class="mdl-menu__item"
|
<li class="mdl-menu__item" [attr.disabled]="action.disabled"
|
||||||
[attr.data-automation-id]="action.title"
|
[attr.data-automation-id]="action.title"
|
||||||
*ngFor="let action of getRowActions(row)"
|
*ngFor="let action of getRowActions(row)"
|
||||||
(click)="onExecuteRowAction(row, action)">
|
(click)="onExecuteRowAction(row, action)">
|
||||||
|
@ -414,4 +414,87 @@ describe('DataTable', () => {
|
|||||||
dataTable.onImageLoadingError(event);
|
dataTable.onImageLoadingError(event);
|
||||||
expect(event.target.src).toBe(originalSrc);
|
expect(event.target.src).toBe(originalSrc);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should disable the action if there is no permission and disableWithNoPermission true', () => {
|
||||||
|
|
||||||
|
dataTable.data = new ObjectDataTableAdapter(
|
||||||
|
[{id: 1, name: 'xyz', allowableOperations: ['create', 'update']}],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
let row = dataTable.data.getRows();
|
||||||
|
let actions = [
|
||||||
|
{
|
||||||
|
disableWithNoPermission: true,
|
||||||
|
permission: 'delete',
|
||||||
|
target: 'folder',
|
||||||
|
title: 'action2'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let updateActions = dataTable.checkPermissions(row[0], actions);
|
||||||
|
expect(updateActions[0].disabled).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not disable the action if there is no permission and disableWithNoPermission false', () => {
|
||||||
|
|
||||||
|
dataTable.data = new ObjectDataTableAdapter(
|
||||||
|
[{id: 1, name: 'xyz', allowableOperations: ['create', 'update']}],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
let row = dataTable.data.getRows();
|
||||||
|
let actions = [
|
||||||
|
{
|
||||||
|
disableWithNoPermission: false,
|
||||||
|
permission: 'delete',
|
||||||
|
target: 'folder',
|
||||||
|
title: 'action2'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let updateActions = dataTable.checkPermissions(row[0], actions);
|
||||||
|
expect(updateActions[0].disabled).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not disable the action if there is the right permission', () => {
|
||||||
|
|
||||||
|
dataTable.data = new ObjectDataTableAdapter(
|
||||||
|
[{ id: 1, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] }],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
let row = dataTable.data.getRows();
|
||||||
|
let actions = [
|
||||||
|
{
|
||||||
|
permission: 'delete',
|
||||||
|
target: 'folder',
|
||||||
|
title: 'action2'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let updateActions = dataTable.checkPermissions(row[0], actions);
|
||||||
|
expect(updateActions[0].disabled).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not disable the action if there are no permissions', () => {
|
||||||
|
|
||||||
|
dataTable.data = new ObjectDataTableAdapter(
|
||||||
|
[{id: 1, name: 'xyz', allowableOperations: null}],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
let row = dataTable.data.getRows();
|
||||||
|
let actions = [
|
||||||
|
{
|
||||||
|
permission: 'delete',
|
||||||
|
target: 'folder',
|
||||||
|
title: 'action2'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
let updateActions = dataTable.checkPermissions(row[0], actions);
|
||||||
|
expect(updateActions[0].disabled).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -236,10 +236,40 @@ export class DataTableComponent implements AfterContentInit, OnChanges {
|
|||||||
getRowActions(row: DataRow, col: DataColumn): any[] {
|
getRowActions(row: DataRow, col: DataColumn): any[] {
|
||||||
let event = new DataCellEvent(row, col, []);
|
let event = new DataCellEvent(row, col, []);
|
||||||
this.showRowActionsMenu.emit(event);
|
this.showRowActionsMenu.emit(event);
|
||||||
return event.value.actions;
|
|
||||||
|
return this.checkPermissions(row, event.value.actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermissions(row: DataRow, actions: any[]) {
|
||||||
|
let actionsPermission = [];
|
||||||
|
actions.forEach((action) => {
|
||||||
|
actionsPermission.push(this.checkPermission(row, action));
|
||||||
|
});
|
||||||
|
return actionsPermission;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(row: DataRow, action) {
|
||||||
|
if (action.permission) {
|
||||||
|
if (this.hasPermissions(row)) {
|
||||||
|
let permissions = row.getValue('allowableOperations');
|
||||||
|
let findPermission = permissions.find(permission => permission === action.permission);
|
||||||
|
if (!findPermission && action.disableWithNoPermission === true) {
|
||||||
|
action.disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
private hasPermissions(row: DataRow): boolean {
|
||||||
|
return row.getValue('allowableOperations') ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onExecuteRowAction(row: DataRow, action: any) {
|
onExecuteRowAction(row: DataRow, action: any) {
|
||||||
this.executeRowAction.emit(new DataRowActionEvent(row, action));
|
if (action.disabled) {
|
||||||
|
event.stopPropagation();
|
||||||
|
} else {
|
||||||
|
this.executeRowAction.emit(new DataRowActionEvent(row, action));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -612,6 +612,61 @@ The following action handlers are provided out-of-box:
|
|||||||
All system handler names are case-insensitive, `handler="download"` and `handler="DOWNLOAD"`
|
All system handler names are case-insensitive, `handler="download"` and `handler="DOWNLOAD"`
|
||||||
will trigger the same `download` action.
|
will trigger the same `download` action.
|
||||||
|
|
||||||
|
##### Delete - Show notification message with no permission
|
||||||
|
You can show a notification error when the user don't have the right permission to perform the action.
|
||||||
|
The ContentActionComponent provides the event permissionEvent that is raised when the permission specified in the permission property is missing
|
||||||
|
You can subscribe to this event from your component and use the NotificationService to show a message.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<alfresco-document-list ...>
|
||||||
|
<content-actions>
|
||||||
|
|
||||||
|
<content-action
|
||||||
|
target="document"
|
||||||
|
title="Delete"
|
||||||
|
permission="delete"
|
||||||
|
(permissionEvent)="onPermissionsFailed($event)"
|
||||||
|
handler="delete">
|
||||||
|
</content-action>
|
||||||
|
|
||||||
|
</content-actions>
|
||||||
|
</alfresco-document-list>
|
||||||
|
|
||||||
|
|
||||||
|
export class MyComponent {
|
||||||
|
|
||||||
|
onPermissionsFailed(event: any) {
|
||||||
|
this.notificationService.openSnackMessage(`you don't have the ${event.permission} permission to ${event.action} the ${event.type} `, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
##### Delete - Disable button checking the permission
|
||||||
|
You can easily disable a button when the user doesn't own the permission to perform the action related to the button.
|
||||||
|
The ContentActionComponent provides the property permission that must contain the permission to check and a property disableWithNoPermission that can be true if
|
||||||
|
you want see the button disabled.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<alfresco-document-list ...>
|
||||||
|
<content-actions>
|
||||||
|
|
||||||
|
<content-action
|
||||||
|
target="document"
|
||||||
|
title="Delete"
|
||||||
|
permission="delete"
|
||||||
|
disableWithNoPermission="true"
|
||||||
|
handler="delete">
|
||||||
|
</content-action>
|
||||||
|
|
||||||
|
</content-actions>
|
||||||
|
</alfresco-document-list>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
##### Download
|
##### Download
|
||||||
|
|
||||||
Initiates download of the corresponding document file.
|
Initiates download of the corresponding document file.
|
||||||
@ -632,7 +687,6 @@ Initiates download of the corresponding document file.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
#### Folder actions
|
#### Folder actions
|
||||||
|
|
||||||
Folder actions have the same declaration as document actions except ```taget="folder"``` attribute value.
|
Folder actions have the same declaration as document actions except ```taget="folder"``` attribute value.
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 133 KiB |
Binary file not shown.
After Width: | Height: | Size: 173 KiB |
@ -53,6 +53,7 @@ export * from './src/services/document-list.service';
|
|||||||
// models
|
// models
|
||||||
export * from './src/models/content-action.model';
|
export * from './src/models/content-action.model';
|
||||||
export * from './src/models/document-library.model';
|
export * from './src/models/document-library.model';
|
||||||
|
export * from './src/models/permissions.model';
|
||||||
|
|
||||||
export const DOCUMENT_LIST_DIRECTIVES: any[] = [
|
export const DOCUMENT_LIST_DIRECTIVES: any[] = [
|
||||||
DocumentListComponent,
|
DocumentListComponent,
|
||||||
|
@ -41,9 +41,18 @@ export class ContentActionComponent implements OnInit, OnChanges {
|
|||||||
@Input()
|
@Input()
|
||||||
target: string;
|
target: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
permission: string;
|
||||||
|
|
||||||
|
@Input()
|
||||||
|
disableWithNoPermission: boolean;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
execute = new EventEmitter();
|
execute = new EventEmitter();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
permissionEvent = new EventEmitter();
|
||||||
|
|
||||||
model: ContentActionModel;
|
model: ContentActionModel;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -57,6 +66,8 @@ export class ContentActionComponent implements OnInit, OnChanges {
|
|||||||
this.model = new ContentActionModel({
|
this.model = new ContentActionModel({
|
||||||
title: this.title,
|
title: this.title,
|
||||||
icon: this.icon,
|
icon: this.icon,
|
||||||
|
permission: this.permission,
|
||||||
|
disableWithNoPermission: this.disableWithNoPermission,
|
||||||
target: this.target
|
target: this.target
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,6 +109,9 @@ export class ContentActionComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
if (ltarget === 'folder') {
|
if (ltarget === 'folder') {
|
||||||
if (this.folderActions) {
|
if (this.folderActions) {
|
||||||
|
this.folderActions.permissionEvent.subscribe((permision) => {
|
||||||
|
this.permissionEvent.emit(permision);
|
||||||
|
});
|
||||||
return this.folderActions.getHandler(name);
|
return this.folderActions.getHandler(name);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -86,7 +86,22 @@ describe('DocumentList', () => {
|
|||||||
spyOn(action, 'handler').and.stub();
|
spyOn(action, 'handler').and.stub();
|
||||||
|
|
||||||
documentList.executeContentAction(node, action);
|
documentList.executeContentAction(node, action);
|
||||||
expect(action.handler).toHaveBeenCalledWith(node, documentList);
|
expect(action.handler).toHaveBeenCalledWith(node, documentList, undefined);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should execute action with node and permission', () => {
|
||||||
|
let node = new FileNode();
|
||||||
|
let action = new ContentActionModel();
|
||||||
|
action.handler = function () {
|
||||||
|
console.log('mock handler');
|
||||||
|
};
|
||||||
|
action.permission = 'fake-permission';
|
||||||
|
|
||||||
|
spyOn(action, 'handler').and.stub();
|
||||||
|
|
||||||
|
documentList.executeContentAction(node, action);
|
||||||
|
expect(action.handler).toHaveBeenCalledWith(node, documentList, 'fake-permission');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni
|
|||||||
*/
|
*/
|
||||||
executeContentAction(node: MinimalNodeEntity, action: ContentActionModel) {
|
executeContentAction(node: MinimalNodeEntity, action: ContentActionModel) {
|
||||||
if (node && node.entry && action) {
|
if (node && node.entry && action) {
|
||||||
action.handler(node, this);
|
action.handler(node, this, action.permission);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { PermissionModel } from './../models/permissions.model';
|
||||||
|
|
||||||
|
export class PermissionErrorEvent {
|
||||||
|
|
||||||
|
readonly error: PermissionModel;
|
||||||
|
|
||||||
|
constructor(error: PermissionModel) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,6 +20,8 @@ export class ContentActionModel {
|
|||||||
title: string;
|
title: string;
|
||||||
handler: ContentActionHandler;
|
handler: ContentActionHandler;
|
||||||
target: string;
|
target: string;
|
||||||
|
permission: string;
|
||||||
|
disableWithNoPermission: boolean;
|
||||||
|
|
||||||
constructor(obj?: any) {
|
constructor(obj?: any) {
|
||||||
if (obj) {
|
if (obj) {
|
||||||
@ -27,12 +29,14 @@ export class ContentActionModel {
|
|||||||
this.title = obj.title;
|
this.title = obj.title;
|
||||||
this.handler = obj.handler;
|
this.handler = obj.handler;
|
||||||
this.target = obj.target;
|
this.target = obj.target;
|
||||||
|
this.permission = obj.permission;
|
||||||
|
this.disableWithNoPermission = obj.disableWithNoPermission;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContentActionHandler {
|
export interface ContentActionHandler {
|
||||||
(obj: any, target?: any): any;
|
(obj: any, target?: any, permission?: string): any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DocumentActionModel extends ContentActionModel {
|
export class DocumentActionModel extends ContentActionModel {
|
||||||
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class PermissionModel {
|
||||||
|
type: string;
|
||||||
|
action: string;
|
||||||
|
permission: string;
|
||||||
|
|
||||||
|
constructor(obj?: any) {
|
||||||
|
if (obj) {
|
||||||
|
this.type = obj.type || null;
|
||||||
|
this.action = obj.action || null;
|
||||||
|
this.permission = obj.permission || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -101,6 +101,62 @@ describe('DocumentActionsService', () => {
|
|||||||
expect(service.getHandler('delete')).toBeDefined();
|
expect(service.getHandler('delete')).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not delete the file node if there are no permissions', (done) => {
|
||||||
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
service.permissionEvent.subscribe((permission) => {
|
||||||
|
expect(permission).toBeDefined();
|
||||||
|
expect(permission.type).toEqual('content');
|
||||||
|
expect(permission.action).toEqual('delete');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
let file = new FileNode();
|
||||||
|
service.getHandler('delete')(file);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete the file node if there is the delete permission', () => {
|
||||||
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
|
let file = new FileNode();
|
||||||
|
let fileWithPermission: any = file;
|
||||||
|
fileWithPermission.entry.allowableOperations = [permission];
|
||||||
|
service.getHandler('delete')(fileWithPermission, null, permission);
|
||||||
|
|
||||||
|
expect(documentListService.deleteNode).toHaveBeenCalledWith(file.entry.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not delete the file node if there is no delete permission', (done) => {
|
||||||
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
service.permissionEvent.subscribe((permission) => {
|
||||||
|
expect(permission).toBeDefined();
|
||||||
|
expect(permission.type).toEqual('content');
|
||||||
|
expect(permission.action).toEqual('delete');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
|
let file = new FileNode();
|
||||||
|
let fileWithPermission: any = file;
|
||||||
|
fileWithPermission.entry.allowableOperations = ['create', 'update'];
|
||||||
|
service.getHandler('delete')(fileWithPermission, null, permission);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete the file node if there is the delete and others permission ', () => {
|
||||||
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
|
let file = new FileNode();
|
||||||
|
let fileWithPermission: any = file;
|
||||||
|
fileWithPermission.entry.allowableOperations = ['create', 'update', permission];
|
||||||
|
service.getHandler('delete')(fileWithPermission, null, permission);
|
||||||
|
|
||||||
|
expect(documentListService.deleteNode).toHaveBeenCalledWith(file.entry.id);
|
||||||
|
});
|
||||||
|
|
||||||
it('should register download action', () => {
|
it('should register download action', () => {
|
||||||
expect(service.getHandler('download')).toBeDefined();
|
expect(service.getHandler('download')).toBeDefined();
|
||||||
});
|
});
|
||||||
@ -152,8 +208,11 @@ describe('DocumentActionsService', () => {
|
|||||||
it('should delete file node', () => {
|
it('should delete file node', () => {
|
||||||
spyOn(documentListService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file);
|
let fileWithPermission: any = file;
|
||||||
|
fileWithPermission.entry.allowableOperations = [permission];
|
||||||
|
service.getHandler('delete')(fileWithPermission, null, permission);
|
||||||
|
|
||||||
expect(documentListService.deleteNode).toHaveBeenCalledWith(file.entry.id);
|
expect(documentListService.deleteNode).toHaveBeenCalledWith(file.entry.id);
|
||||||
});
|
});
|
||||||
@ -165,8 +224,11 @@ describe('DocumentActionsService', () => {
|
|||||||
service.getHandler('delete')(folder);
|
service.getHandler('delete')(folder);
|
||||||
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file);
|
let fileWithPermission: any = file;
|
||||||
|
fileWithPermission.entry.allowableOperations = [permission];
|
||||||
|
service.getHandler('delete')(fileWithPermission, null, permission);
|
||||||
expect(documentListService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -184,8 +246,11 @@ describe('DocumentActionsService', () => {
|
|||||||
spyOn(documentListService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
let target = jasmine.createSpyObj('obj', ['reload']);
|
let target = jasmine.createSpyObj('obj', ['reload']);
|
||||||
|
let permission = 'delete';
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file, target);
|
let fileWithPermission: any = file;
|
||||||
|
fileWithPermission.entry.allowableOperations = [permission];
|
||||||
|
service.getHandler('delete')(fileWithPermission, target, permission);
|
||||||
|
|
||||||
expect(documentListService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
expect(target.reload).toHaveBeenCalled();
|
expect(target.reload).toHaveBeenCalled();
|
||||||
|
@ -19,9 +19,14 @@ import { Injectable } from '@angular/core';
|
|||||||
import { ContentActionHandler } from '../models/content-action.model';
|
import { ContentActionHandler } from '../models/content-action.model';
|
||||||
import { DocumentListService } from './document-list.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
import { AlfrescoContentService } from 'ng2-alfresco-core';
|
import { AlfrescoContentService } from 'ng2-alfresco-core';
|
||||||
|
import { PermissionModel } from '../models/permissions.model';
|
||||||
|
import { Subject } from 'rxjs/Rx';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DocumentActionsService {
|
export class DocumentActionsService {
|
||||||
|
|
||||||
|
permissionEvent: Subject<PermissionModel> = new Subject<PermissionModel>();
|
||||||
|
|
||||||
private handlers: { [id: string]: ContentActionHandler; } = {};
|
private handlers: { [id: string]: ContentActionHandler; } = {};
|
||||||
|
|
||||||
constructor(private documentListService?: DocumentListService,
|
constructor(private documentListService?: DocumentListService,
|
||||||
@ -82,13 +87,28 @@ export class DocumentActionsService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private deleteNode(obj: any, target?: any) {
|
private deleteNode(obj: any, target?: any, permission?: string) {
|
||||||
if (this.canExecuteAction(obj) && obj.entry && obj.entry.id) {
|
if (this.canExecuteAction(obj)) {
|
||||||
this.documentListService.deleteNode(obj.entry.id).subscribe(() => {
|
if (this.hasPermission(obj.entry, permission)) {
|
||||||
if (target && typeof target.reload === 'function') {
|
this.documentListService.deleteNode(obj.entry.id).subscribe(() => {
|
||||||
target.reload();
|
if (target && typeof target.reload === 'function') {
|
||||||
}
|
target.reload();
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.permissionEvent.next(new PermissionModel({type: 'content', action: 'delete', permission: permission}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private hasPermission(node: any, permission: string): boolean {
|
||||||
|
if (this.hasPermissions(node)) {
|
||||||
|
return node.allowableOperations.find(permision => permision === permission) ? true : false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private hasPermissions(node: any): boolean {
|
||||||
|
return node && node.allowableOperations ? true : false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ export class DocumentListService {
|
|||||||
|
|
||||||
let params: any = {
|
let params: any = {
|
||||||
includeSource: true,
|
includeSource: true,
|
||||||
include: ['path', 'properties']
|
include: ['path', 'properties', 'allowableOperations']
|
||||||
};
|
};
|
||||||
|
|
||||||
if (folder) {
|
if (folder) {
|
||||||
@ -121,7 +121,7 @@ export class DocumentListService {
|
|||||||
getFolderNode(nodeId: string): Promise<MinimalNodeEntryEntity> {
|
getFolderNode(nodeId: string): Promise<MinimalNodeEntryEntity> {
|
||||||
let opts: any = {
|
let opts: any = {
|
||||||
includeSource: true,
|
includeSource: true,
|
||||||
include: ['path', 'properties']
|
include: ['path', 'properties', 'allowableOperations']
|
||||||
};
|
};
|
||||||
|
|
||||||
let nodes: any = this.apiService.getInstance().nodes;
|
let nodes: any = this.apiService.getInstance().nodes;
|
||||||
|
@ -97,24 +97,73 @@ describe('FolderActionsService', () => {
|
|||||||
expect(service.getHandler('delete')).toBeDefined();
|
expect(service.getHandler('delete')).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete folder node', () => {
|
it('should not delete the folder node if there are no permissions', (done) => {
|
||||||
spyOn(documentListService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
service.permissionEvent.subscribe((permission) => {
|
||||||
|
expect(permission).toBeDefined();
|
||||||
|
expect(permission.type).toEqual('folder');
|
||||||
|
expect(permission.action).toEqual('delete');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
service.getHandler('delete')(folder);
|
service.getHandler('delete')(folder);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete the folder node if there is the delete permission', () => {
|
||||||
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
|
let folder = new FolderNode();
|
||||||
|
let folderWithPermission: any = folder;
|
||||||
|
folderWithPermission.entry.allowableOperations = [ permission ];
|
||||||
|
service.getHandler('delete')(folderWithPermission, null, permission);
|
||||||
|
|
||||||
|
expect(documentListService.deleteNode).toHaveBeenCalledWith(folder.entry.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not delete the folder node if there is no delete permission', (done) => {
|
||||||
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
service.permissionEvent.subscribe((permission) => {
|
||||||
|
expect(permission).toBeDefined();
|
||||||
|
expect(permission.type).toEqual('folder');
|
||||||
|
expect(permission.action).toEqual('delete');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
let folder = new FolderNode();
|
||||||
|
let folderWithPermission: any = folder;
|
||||||
|
folderWithPermission.entry.allowableOperations = ['create', 'update'];
|
||||||
|
service.getHandler('delete')(folderWithPermission);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete the folder node if there is the delete and others permission ', () => {
|
||||||
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
|
let folder = new FolderNode();
|
||||||
|
let folderWithPermission: any = folder;
|
||||||
|
folderWithPermission.entry.allowableOperations = ['create', 'update', permission];
|
||||||
|
service.getHandler('delete')(folderWithPermission, null, permission);
|
||||||
|
|
||||||
expect(documentListService.deleteNode).toHaveBeenCalledWith(folder.entry.id);
|
expect(documentListService.deleteNode).toHaveBeenCalledWith(folder.entry.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support deletion only folder node', () => {
|
it('should support deletion only folder node', () => {
|
||||||
spyOn(documentListService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
let file = new FileNode();
|
let file = new FileNode();
|
||||||
service.getHandler('delete')(file);
|
service.getHandler('delete')(file);
|
||||||
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
expect(documentListService.deleteNode).not.toHaveBeenCalled();
|
||||||
|
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
service.getHandler('delete')(folder);
|
let folderWithPermission: any = folder;
|
||||||
|
folderWithPermission.entry.allowableOperations = [permission];
|
||||||
|
service.getHandler('delete')(folderWithPermission, null, permission);
|
||||||
expect(documentListService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -131,9 +180,13 @@ describe('FolderActionsService', () => {
|
|||||||
it('should reload target upon node deletion', () => {
|
it('should reload target upon node deletion', () => {
|
||||||
spyOn(documentListService, 'deleteNode').and.callThrough();
|
spyOn(documentListService, 'deleteNode').and.callThrough();
|
||||||
|
|
||||||
|
let permission = 'delete';
|
||||||
let target = jasmine.createSpyObj('obj', ['reload']);
|
let target = jasmine.createSpyObj('obj', ['reload']);
|
||||||
let folder = new FolderNode();
|
let folder = new FolderNode();
|
||||||
service.getHandler('delete')(folder, target);
|
let folderWithPermission: any = folder;
|
||||||
|
folderWithPermission.entry.allowableOperations = [permission];
|
||||||
|
|
||||||
|
service.getHandler('delete')(folderWithPermission, target, permission);
|
||||||
|
|
||||||
expect(documentListService.deleteNode).toHaveBeenCalled();
|
expect(documentListService.deleteNode).toHaveBeenCalled();
|
||||||
expect(target.reload).toHaveBeenCalled();
|
expect(target.reload).toHaveBeenCalled();
|
||||||
|
@ -17,10 +17,15 @@
|
|||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { ContentActionHandler } from '../models/content-action.model';
|
import { ContentActionHandler } from '../models/content-action.model';
|
||||||
|
import { PermissionModel } from '../models/permissions.model';
|
||||||
import { DocumentListService } from './document-list.service';
|
import { DocumentListService } from './document-list.service';
|
||||||
|
import { Subject } from 'rxjs/Rx';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FolderActionsService {
|
export class FolderActionsService {
|
||||||
|
|
||||||
|
permissionEvent: Subject<PermissionModel> = new Subject<PermissionModel>();
|
||||||
|
|
||||||
private handlers: { [id: string]: ContentActionHandler; } = {};
|
private handlers: { [id: string]: ContentActionHandler; } = {};
|
||||||
|
|
||||||
constructor(private documentListService?: DocumentListService) {
|
constructor(private documentListService?: DocumentListService) {
|
||||||
@ -66,13 +71,28 @@ export class FolderActionsService {
|
|||||||
window.alert('standard folder action 2');
|
window.alert('standard folder action 2');
|
||||||
}
|
}
|
||||||
|
|
||||||
private deleteNode(obj: any, target?: any) {
|
private deleteNode(obj: any, target?: any, permission?: string) {
|
||||||
if (this.canExecuteAction(obj) && obj.entry && obj.entry.id) {
|
if (this.canExecuteAction(obj)) {
|
||||||
this.documentListService.deleteNode(obj.entry.id).subscribe(() => {
|
if (this.hasPermission(obj.entry, permission)) {
|
||||||
if (target && typeof target.reload === 'function') {
|
this.documentListService.deleteNode(obj.entry.id).subscribe(() => {
|
||||||
target.reload();
|
if (target && typeof target.reload === 'function') {
|
||||||
}
|
target.reload();
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.permissionEvent.next(new PermissionModel({type: 'folder', action: 'delete', permission: permission}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private hasPermission(node: any, permissionToCheck: string): boolean {
|
||||||
|
if (this.hasPermissions(node)) {
|
||||||
|
return node.allowableOperations.find(permision => permision === permissionToCheck) ? true : false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private hasPermissions(node: any): boolean {
|
||||||
|
return node && node.allowableOperations ? true : false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user