mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
[ADF-510] Drag&Drop check permission to allow user to upload a file (#1948)
* [ADF-510] added permission check for drag&drop * Improved code for drag and drop side * Added test for drag and drop upload area changes * Added test for document list permissions check * [ADF-510] rebased branch after changes applied to upload * [ADF-510] rebased branch and fixed tests
This commit is contained in:
@@ -63,7 +63,8 @@
|
||||
<a class="mdl-navigation__link" href="" routerLink="/settings" (click)="hideDrawer()">Settings</a>
|
||||
</nav>
|
||||
</div>
|
||||
<main class="mdl-layout__content">
|
||||
<main class="mdl-layout__content" (dragover)="onDragOverMainPage($event)"
|
||||
(drop)="onDragOverMainPage($event)">
|
||||
<div class="page-content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
@@ -17,7 +17,13 @@
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { AlfrescoTranslationService, AlfrescoAuthenticationService, AlfrescoSettingsService, StorageService, LogService } from 'ng2-alfresco-core';
|
||||
import {
|
||||
AlfrescoTranslationService,
|
||||
AlfrescoAuthenticationService,
|
||||
AlfrescoSettingsService,
|
||||
StorageService,
|
||||
LogService
|
||||
} from 'ng2-alfresco-core';
|
||||
|
||||
declare var document: any;
|
||||
|
||||
@@ -117,4 +123,9 @@ export class AppComponent {
|
||||
this.settingsService.setProviders(this.storage.getItem(`providers`));
|
||||
}
|
||||
}
|
||||
|
||||
onDragOverMainPage(event: any): boolean {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,8 @@
|
||||
<div class="container">
|
||||
<alfresco-upload-drag-area
|
||||
[rootFolderId]="documentList.currentFolderId"
|
||||
[versioning] = "versioning">
|
||||
[rootFolderId]="documentList.currentFolderId"
|
||||
[versioning]="versioning"
|
||||
[enabled]="documentList.hasCreatePermission()">
|
||||
<alfresco-document-list-breadcrumb
|
||||
[target]="documentList"
|
||||
[folderNode]="documentList.folderNode">
|
||||
|
@@ -0,0 +1,117 @@
|
||||
/*!
|
||||
* @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 const fakeNodeWithCreatePermission = {
|
||||
isFile: false,
|
||||
createdByUser: { id: 'admin', displayName: 'Administrator' },
|
||||
modifiedAt: '2017-06-08T13:53:46.495Z',
|
||||
nodeType: 'cm:folder',
|
||||
parentId: '55052317-7e59-4058-8e07-769f41e615e1',
|
||||
createdAt: '2017-05-22T11:36:11.270Z',
|
||||
path: {
|
||||
name: '/Company Home/User Homes',
|
||||
isComplete: true,
|
||||
elements: [{
|
||||
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
|
||||
name: 'Company Home'
|
||||
}, { id: '55052317-7e59-4058-8e07-769f41e615e1', name: 'User Homes' }]
|
||||
},
|
||||
isFolder: true,
|
||||
modifiedByUser: { id: 'Test', displayName: 'Test' },
|
||||
name: 'Test',
|
||||
id: '70e1cc6a-6918-468a-b84a-1048093b06fd',
|
||||
properties: {},
|
||||
allowableOperations: ['delete', 'update', 'create']
|
||||
};
|
||||
|
||||
export const fakeNodeWithNoPermission = {
|
||||
isFile: false,
|
||||
createdByUser: { id: 'admin', displayName: 'Administrator' },
|
||||
modifiedAt: '2017-06-08T13:53:46.495Z',
|
||||
nodeType: 'cm:folder',
|
||||
parentId: '55052317-7e59-4058-8e07-769f41e615e1',
|
||||
aspectNames: ['cm:ownable', 'cm:auditable'],
|
||||
createdAt: '2017-05-22T11:36:11.270Z',
|
||||
path: {
|
||||
name: '/Company Home/User Homes',
|
||||
isComplete: true,
|
||||
elements: [{
|
||||
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
|
||||
name: 'Company Home'
|
||||
}, { id: '55052317-7e59-4058-8e07-769f41e615e1', name: 'User Homes' }]
|
||||
},
|
||||
isFolder: true,
|
||||
modifiedByUser: { id: 'Test', displayName: 'Test' },
|
||||
name: 'Test',
|
||||
id: '70e1cc6a-6918-468a-b84a-1048093b06fd',
|
||||
properties: {}
|
||||
};
|
||||
|
||||
export const fakeNodeAnswerWithEntries = {
|
||||
'list': {
|
||||
'pagination': {
|
||||
'count': 4,
|
||||
'hasMoreItems': false,
|
||||
'totalItems': 14,
|
||||
'skipCount': 10,
|
||||
'maxItems': 10
|
||||
},
|
||||
'entries': [{
|
||||
'entry': {
|
||||
'isFile': true,
|
||||
'createdByUser': { 'id': 'admin', 'displayName': 'Administrator' },
|
||||
'modifiedAt': '2017-05-24T15:08:55.640Z',
|
||||
'nodeType': 'cm:content',
|
||||
'content': {
|
||||
'mimeType': 'application/rtf',
|
||||
'mimeTypeName': 'Rich Text Format',
|
||||
'sizeInBytes': 14530,
|
||||
'encoding': 'UTF-8'
|
||||
},
|
||||
'parentId': 'd124de26-6ba0-4f40-8d98-4907da2d337a',
|
||||
'createdAt': '2017-05-24T15:08:55.640Z',
|
||||
'path': {
|
||||
'name': '/Company Home/Guest Home',
|
||||
'isComplete': true,
|
||||
'elements': [{
|
||||
'id': '94acfc73-7014-4475-9bd9-93a2162f0f8c',
|
||||
'name': 'Company Home'
|
||||
}, { 'id': 'd124de26-6ba0-4f40-8d98-4907da2d337a', 'name': 'Guest Home' }]
|
||||
},
|
||||
'isFolder': false,
|
||||
'modifiedByUser': { 'id': 'admin', 'displayName': 'Administrator' },
|
||||
'name': 'b_txt_file.rtf',
|
||||
'id': '67b80f77-dbca-4f58-be6c-71b9dd61ea53',
|
||||
'properties': { 'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR' },
|
||||
'allowableOperations': ['delete', 'update']
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
export const fakeNodeAnswerWithNOEntries = {
|
||||
'list': {
|
||||
'pagination': {
|
||||
'count': 4,
|
||||
'hasMoreItems': false,
|
||||
'totalItems': 14,
|
||||
'skipCount': 10,
|
||||
'maxItems': 10
|
||||
},
|
||||
'entries': []
|
||||
}
|
||||
};
|
@@ -28,68 +28,20 @@ import { ShareDataRow, RowFilter, ImageResolver } from './../data/share-datatabl
|
||||
import { DataTableModule } from 'ng2-alfresco-datatable';
|
||||
import { DocumentMenuActionComponent } from './document-menu-action.component';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import {
|
||||
fakeNodeAnswerWithNOEntries,
|
||||
fakeNodeAnswerWithEntries,
|
||||
fakeNodeWithCreatePermission,
|
||||
fakeNodeWithNoPermission
|
||||
} from '../assets/document-list.component.mock';
|
||||
import { MdProgressSpinnerModule } from '@angular/material';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
let fakeNodeAnswerWithEntries = {
|
||||
'list': {
|
||||
'pagination': {
|
||||
'count': 4,
|
||||
'hasMoreItems': false,
|
||||
'totalItems': 14,
|
||||
'skipCount': 10,
|
||||
'maxItems': 10
|
||||
},
|
||||
'entries': [{
|
||||
'entry': {
|
||||
'isFile': true,
|
||||
'createdByUser': {'id': 'admin', 'displayName': 'Administrator'},
|
||||
'modifiedAt': '2017-05-24T15:08:55.640Z',
|
||||
'nodeType': 'cm:content',
|
||||
'content': {
|
||||
'mimeType': 'application/rtf',
|
||||
'mimeTypeName': 'Rich Text Format',
|
||||
'sizeInBytes': 14530,
|
||||
'encoding': 'UTF-8'
|
||||
},
|
||||
'parentId': 'd124de26-6ba0-4f40-8d98-4907da2d337a',
|
||||
'createdAt': '2017-05-24T15:08:55.640Z',
|
||||
'path': {
|
||||
'name': '/Company Home/Guest Home',
|
||||
'isComplete': true,
|
||||
'elements': [{
|
||||
'id': '94acfc73-7014-4475-9bd9-93a2162f0f8c',
|
||||
'name': 'Company Home'
|
||||
}, {'id': 'd124de26-6ba0-4f40-8d98-4907da2d337a', 'name': 'Guest Home'}]
|
||||
},
|
||||
'isFolder': false,
|
||||
'modifiedByUser': {'id': 'admin', 'displayName': 'Administrator'},
|
||||
'name': 'b_txt_file.rtf',
|
||||
'id': '67b80f77-dbca-4f58-be6c-71b9dd61ea53',
|
||||
'properties': {'cm:versionLabel': '1.0', 'cm:versionType': 'MAJOR'},
|
||||
'allowableOperations': ['delete', 'update']
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
let fakeNodeAnswerWithNOEntries = {
|
||||
'list': {
|
||||
'pagination': {
|
||||
'count': 4,
|
||||
'hasMoreItems': false,
|
||||
'totalItems': 14,
|
||||
'skipCount': 10,
|
||||
'maxItems': 10
|
||||
},
|
||||
'entries': []
|
||||
}
|
||||
};
|
||||
|
||||
describe('DocumentList', () => {
|
||||
|
||||
let documentList: DocumentListComponent;
|
||||
let documentListService: DocumentListService;
|
||||
let fixture: ComponentFixture<DocumentListComponent>;
|
||||
let element: HTMLElement;
|
||||
let eventMock: any;
|
||||
@@ -110,7 +62,7 @@ describe('DocumentList', () => {
|
||||
],
|
||||
providers: [
|
||||
DocumentListService,
|
||||
{provide: NgZone, useValue: zone}
|
||||
{ provide: NgZone, useValue: zone }
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
@@ -137,6 +89,7 @@ describe('DocumentList', () => {
|
||||
|
||||
element = fixture.nativeElement;
|
||||
documentList = fixture.componentInstance;
|
||||
documentListService = TestBed.get(DocumentListService);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@@ -263,7 +216,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: ['create', 'update']}};
|
||||
let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -284,7 +237,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: ['create', 'update']}};
|
||||
let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update'] } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -305,7 +258,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: ['create', 'update']}};
|
||||
let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update'] } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -325,7 +278,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: ['create', 'update']}};
|
||||
let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update'] } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -345,7 +298,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete']}};
|
||||
let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -365,7 +318,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete']}};
|
||||
let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: ['create', 'update', 'delete'] } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -384,7 +337,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFile: true, name: 'xyz', allowableOperations: null}};
|
||||
let nodeFile = { entry: { isFile: true, name: 'xyz', allowableOperations: null } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -403,7 +356,7 @@ describe('DocumentList', () => {
|
||||
documentMenu
|
||||
];
|
||||
|
||||
let nodeFile = {entry: {isFolder: true, name: 'xyz', allowableOperations: null}};
|
||||
let nodeFile = { entry: { isFolder: true, name: 'xyz', allowableOperations: null } };
|
||||
|
||||
let actions = documentList.getNodeActions(nodeFile);
|
||||
expect(actions.length).toBe(1);
|
||||
@@ -707,7 +660,7 @@ describe('DocumentList', () => {
|
||||
});
|
||||
|
||||
documentList.currentFolderId = 'wrong-id';
|
||||
documentList.ngOnChanges({currentFolderId: new SimpleChange(null, documentList.currentFolderId, true)});
|
||||
documentList.ngOnChanges({ currentFolderId: new SimpleChange(null, documentList.currentFolderId, true) });
|
||||
});
|
||||
|
||||
it('should require dataTable to check empty template', () => {
|
||||
@@ -799,7 +752,7 @@ describe('DocumentList', () => {
|
||||
it('should load folder by ID on init', () => {
|
||||
documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692';
|
||||
spyOn(documentList, 'loadFolderNodesByFolderNodeId').and.returnValue(Promise.resolve());
|
||||
documentList.ngOnChanges({folderNode: new SimpleChange(null, documentList.currentFolderId, true)});
|
||||
documentList.ngOnChanges({ folderNode: new SimpleChange(null, documentList.currentFolderId, true) });
|
||||
expect(documentList.loadFolderNodesByFolderNodeId).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -834,4 +787,44 @@ describe('DocumentList', () => {
|
||||
responseText: JSON.stringify(fakeNodeAnswerWithEntries)
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true if current folder node has create permission', (done) => {
|
||||
documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692';
|
||||
documentList.folderNode = new NodeMinimal();
|
||||
documentList.folderNode.id = '1d26e465-dea3-42f3-b415-faa8364b9692';
|
||||
documentList.skipCount = 5;
|
||||
documentList.pageSize = 5;
|
||||
spyOn(documentListService, 'getFolderNode').and.returnValue(Promise.resolve(fakeNodeWithCreatePermission));
|
||||
spyOn(documentListService, 'getFolder').and.returnValue(Promise.resolve(fakeNodeAnswerWithNOEntries));
|
||||
|
||||
let change = new SimpleChange(null, '1d26e465-dea3-42f3-b415-faa8364b9692', true);
|
||||
documentList.ngOnChanges({ 'currentFolderId': change });
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(documentList.hasCreatePermission()).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return false if navigate to a folder with no create permission', (done) => {
|
||||
documentList.currentFolderId = '1d26e465-dea3-42f3-b415-faa8364b9692';
|
||||
documentList.folderNode = new NodeMinimal();
|
||||
documentList.folderNode.id = '1d26e465-dea3-42f3-b415-faa8364b9692';
|
||||
documentList.skipCount = 5;
|
||||
documentList.pageSize = 5;
|
||||
spyOn(documentListService, 'getFolderNode').and.returnValue(Promise.resolve(fakeNodeWithNoPermission));
|
||||
spyOn(documentListService, 'getFolder').and.returnValue(Promise.resolve(fakeNodeAnswerWithNOEntries));
|
||||
|
||||
documentList.loadFolder();
|
||||
let clickedFolderNode = new FolderNode('fake-folder-node');
|
||||
documentList.onNodeDblClick(clickedFolderNode);
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
expect(documentList.hasCreatePermission()).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -165,6 +165,8 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni
|
||||
data: ShareDataTableAdapter;
|
||||
|
||||
loading: boolean = false;
|
||||
private currentNodeAllowableOperations: string[] = [];
|
||||
private CREATE_PERMISSION = 'create';
|
||||
|
||||
constructor(private documentListService: DocumentListService,
|
||||
private ngZone: NgZone,
|
||||
@@ -329,6 +331,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni
|
||||
this.currentFolderId = node.entry.id;
|
||||
this.folderNode = node.entry;
|
||||
this.skipCount = 0;
|
||||
this.currentNodeAllowableOperations = node.entry['allowableOperations'] ? node.entry['allowableOperations'] : [];
|
||||
this.loadFolder();
|
||||
this.folderChange.emit(new NodeEntryEvent(node.entry));
|
||||
return true;
|
||||
@@ -359,11 +362,12 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni
|
||||
loadFolderByNodeId(nodeId: string) {
|
||||
this.loading = true;
|
||||
this.documentListService.getFolderNode(nodeId).then(node => {
|
||||
this.folderNode = node;
|
||||
this.currentFolderId = node.id;
|
||||
this.skipCount = 0;
|
||||
this.loadFolderNodesByFolderNodeId(node.id, this.pageSize, this.skipCount).catch(err => this.error.emit(err));
|
||||
})
|
||||
this.folderNode = node;
|
||||
this.currentFolderId = node.id;
|
||||
this.skipCount = 0;
|
||||
this.currentNodeAllowableOperations = node['allowableOperations'] ? node['allowableOperations'] : [];
|
||||
this.loadFolderNodesByFolderNodeId(node.id, this.pageSize, this.skipCount).catch(err => this.error.emit(err));
|
||||
})
|
||||
.catch(err => this.error.emit(err));
|
||||
}
|
||||
|
||||
@@ -381,7 +385,7 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni
|
||||
this.updateSkipCount(skipCount - maxItems);
|
||||
this.loadFolderNodesByFolderNodeId(id, maxItems, skipCount - maxItems).then(() => {
|
||||
resolve(true);
|
||||
}, () => {
|
||||
}, (error) => {
|
||||
reject(error);
|
||||
});
|
||||
} else {
|
||||
@@ -581,4 +585,17 @@ export class DocumentListComponent implements OnInit, OnChanges, AfterContentIni
|
||||
this.skipCount = newSkipCount;
|
||||
}
|
||||
|
||||
hasCurrentNodePermission(permission: string): boolean {
|
||||
let hasPermission: boolean = false;
|
||||
if (this.currentNodeAllowableOperations.length > 0) {
|
||||
let permFound = this.currentNodeAllowableOperations.find(element => element === permission);
|
||||
hasPermission = permFound ? true : false;
|
||||
}
|
||||
return hasPermission;
|
||||
}
|
||||
|
||||
hasCreatePermission() {
|
||||
return this.hasCurrentNodePermission(this.CREATE_PERMISSION);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -405,4 +405,26 @@ describe('ShareDataRow', () => {
|
||||
expect(row.hasValue('missing')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should be set as drop target when user has permission for that node', () => {
|
||||
let file = new FolderNode('test');
|
||||
file.entry['allowableOperations'] = ['create'];
|
||||
let row = new ShareDataRow(file);
|
||||
|
||||
expect(row.isDropTarget).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not be set as drop target when user has permission for that node', () => {
|
||||
let file = new FolderNode('test');
|
||||
let row = new ShareDataRow(file);
|
||||
|
||||
expect(row.isDropTarget).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not be set as drop target when element is not a Folder', () => {
|
||||
let file = new FileNode('test');
|
||||
let row = new ShareDataRow(file);
|
||||
|
||||
expect(row.isDropTarget).toBeFalsy();
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -236,7 +236,7 @@ export class ShareDataRow implements DataRow {
|
||||
|
||||
cache: { [key: string]: any } = {};
|
||||
isSelected: boolean = false;
|
||||
readonly isDropTarget;
|
||||
isDropTarget: boolean;
|
||||
|
||||
get node(): NodeMinimalEntry {
|
||||
return this.obj;
|
||||
@@ -247,7 +247,28 @@ export class ShareDataRow implements DataRow {
|
||||
throw new Error(ShareDataRow.ERR_OBJECT_NOT_FOUND);
|
||||
}
|
||||
|
||||
this.isDropTarget = obj.entry && obj.entry.isFolder;
|
||||
this.isDropTarget = this.isFolderAndHasPermissionToUpload(obj);
|
||||
}
|
||||
|
||||
isFolderAndHasPermissionToUpload(obj: NodeMinimalEntry): boolean {
|
||||
return this.isFolder(obj) && this.hasCreatePermission(obj);
|
||||
}
|
||||
|
||||
hasCreatePermission(obj: NodeMinimalEntry): boolean {
|
||||
return this.hasPermission(obj, 'create');
|
||||
}
|
||||
|
||||
private hasPermission(obj: NodeMinimalEntry, permission: string): boolean {
|
||||
let hasPermission: boolean = false;
|
||||
if (obj.entry && obj.entry['allowableOperations']) {
|
||||
let permFound = obj.entry['allowableOperations'].find(element => element === permission);
|
||||
hasPermission = permFound ? true : false;
|
||||
}
|
||||
return hasPermission;
|
||||
}
|
||||
|
||||
isFolder(obj: NodeMinimalEntry): boolean {
|
||||
return obj.entry && obj.entry.isFolder;
|
||||
}
|
||||
|
||||
cacheValue(key: string, value: any): any {
|
||||
|
@@ -25,6 +25,41 @@ import { TranslationMock } from '../assets/translation.service.mock';
|
||||
import { UploadService } from '../services/upload.service';
|
||||
import { FileModel } from '../models/file.model';
|
||||
|
||||
let fakeShareDataRow = {
|
||||
obj: {
|
||||
entry: {
|
||||
createdAt: '2017-06-04T04:32:15.597Z',
|
||||
path: {
|
||||
name: '/Company Home/User Homes/Test',
|
||||
isComplete: true,
|
||||
elements: [
|
||||
{
|
||||
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
|
||||
name: 'Company Home'
|
||||
},
|
||||
{
|
||||
id: '55052317-7e59-4058-8e07-769f41e615e1',
|
||||
name: 'User Homes'
|
||||
},
|
||||
{
|
||||
id: '70e1cc6a-6918-468a-b84a-1048093b06fd',
|
||||
name: 'Test'
|
||||
}
|
||||
]
|
||||
},
|
||||
isFolder: true,
|
||||
name: 'pippo',
|
||||
id: '7462d28e-bd43-4b91-9e7b-0d71598680ac',
|
||||
nodeType: 'cm:folder',
|
||||
allowableOperations: [
|
||||
'delete',
|
||||
'update',
|
||||
'create'
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
describe('UploadDragAreaComponent', () => {
|
||||
|
||||
let component: UploadDragAreaComponent;
|
||||
@@ -145,4 +180,37 @@ describe('UploadDragAreaComponent', () => {
|
||||
component.onFilesEntityDropped(itemEntity);
|
||||
expect(uploadService.uploadFilesInTheQueue).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('should upload a file when user has create permission on target folder', async(() => {
|
||||
component.currentFolderPath = '/root-fake-/sites-fake/document-library-fake';
|
||||
component.rootFolderId = '-my-';
|
||||
component.enabled = false;
|
||||
|
||||
let fakeItem = {
|
||||
fullPath: '/folder-fake/file-fake.png',
|
||||
isDirectory: false,
|
||||
isFile: true,
|
||||
name: 'file-fake.png',
|
||||
file: (callbackFile) => {
|
||||
let fileFake = new File(['fakefake'], 'file-fake.png', {type: 'image/png'});
|
||||
callbackFile(fileFake);
|
||||
}
|
||||
};
|
||||
|
||||
fixture.detectChanges();
|
||||
spyOn(uploadService, 'uploadFilesInTheQueue').and.returnValue(Promise.resolve(fakeItem));
|
||||
component.onSuccess.subscribe((val) => {
|
||||
expect(val).not.toBeNull();
|
||||
});
|
||||
|
||||
let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
|
||||
detail: {
|
||||
data: fakeShareDataRow,
|
||||
files: [fakeItem]
|
||||
}
|
||||
});
|
||||
|
||||
component.onUploadFiles(fakeCustomEvent);
|
||||
}));
|
||||
|
||||
});
|
||||
|
@@ -67,24 +67,25 @@ export class UploadDragAreaComponent {
|
||||
|
||||
/**
|
||||
* Handles 'upload-files' events raised by child components.
|
||||
* @param e DOM event
|
||||
* @param event DOM event
|
||||
*/
|
||||
onUploadFiles(e: CustomEvent) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (this.enabled) {
|
||||
let files: FileInfo[] = e.detail.files;
|
||||
onUploadFiles(event: CustomEvent) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
let isAllowed: boolean = this.isAllowed(event.detail.data.obj.entry);
|
||||
if (isAllowed) {
|
||||
let files: FileInfo[] = event.detail.files;
|
||||
if (files && files.length > 0) {
|
||||
let parentId = this.rootFolderId;
|
||||
if (e.detail.data && e.detail.data.obj.entry.isFolder) {
|
||||
parentId = e.detail.data.obj.entry.id || this.rootFolderId;
|
||||
if (event.detail.data && event.detail.data.obj.entry.isFolder) {
|
||||
parentId = event.detail.data.obj.entry.id || this.rootFolderId;
|
||||
}
|
||||
const fileModels = files.map(fileInfo => new FileModel(fileInfo.file, {
|
||||
newVersion: this.versioning,
|
||||
path: fileInfo.relativeFolder,
|
||||
parentId: parentId
|
||||
}));
|
||||
this.uploadFiles(fileModels);
|
||||
this.uploadFiles(fileModels, isAllowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,8 +169,17 @@ export class UploadDragAreaComponent {
|
||||
});
|
||||
}
|
||||
|
||||
private uploadFiles(files: FileModel[]): void {
|
||||
if (this.enabled && files.length) {
|
||||
/**
|
||||
* Show the error inside Notification bar
|
||||
* @param Error message
|
||||
* @private
|
||||
*/
|
||||
showErrorNotificationBar(errorMessage: string) {
|
||||
this.notificationService.openSnackMessage(errorMessage, 3000);
|
||||
}
|
||||
|
||||
private uploadFiles(files: FileModel[], isAllowed: boolean): void {
|
||||
if (isAllowed && files.length) {
|
||||
this.uploadService.addToQueue(...files);
|
||||
this.uploadService.uploadFilesInTheQueue(this.onSuccess);
|
||||
let latestFilesAdded = this.uploadService.getQueue();
|
||||
@@ -178,4 +188,17 @@ export class UploadDragAreaComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private hasCreatePermission(node: any): boolean {
|
||||
let isPermitted = false;
|
||||
if (node && node['allowableOperations']) {
|
||||
let permFound = node['allowableOperations'].find(element => element === 'create');
|
||||
isPermitted = permFound ? true : false;
|
||||
}
|
||||
return isPermitted;
|
||||
}
|
||||
|
||||
private isAllowed(node: any) {
|
||||
return this.enabled || this.hasCreatePermission(node);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user