Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ACA-213] Edit Offline - permissions #911

Merged
merged 10 commits into from
Feb 5, 2019
12 changes: 8 additions & 4 deletions e2e/suites/actions/copy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in destination folder`);
});

it('Copy items into a library - [C280282]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Copy items into a library - [C280282]', async () => {
await dataTable.selectMultipleItems([file1, folder1]);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
Expand Down Expand Up @@ -323,7 +324,8 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(true, `${existingFile}-1.txt not present in destination folder`);
});

it('Copy items into a library - [C291899]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Copy items into a library - [C291899]', async () => {
await dataTable.selectItem(file1, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
Expand Down Expand Up @@ -401,7 +403,8 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(true, `${existingFile}-1.txt not present in destination folder`);
});

it('Copy items into a library - [C291900]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Copy items into a library - [C291900]', async () => {
await dataTable.selectItem(file1, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
Expand Down Expand Up @@ -526,7 +529,8 @@ describe('Copy content', () => {
expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in destination folder`);
});

it('Copy items into a library - [C291901]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Copy items into a library - [C291901]', async () => {
await dataTable.selectMultipleItems([file1, folder1], source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
Expand Down
12 changes: 8 additions & 4 deletions e2e/suites/actions/move.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ describe('Move content', () => {
expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in destination folder`);
});

it('Move items into a library - [C291969]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Move items into a library - [C291969]', async () => {
await dataTable.selectMultipleItems([file4, folder2]);
await toolbar.clickMoreActionsMove();
await moveDialog.selectLocation('File Libraries');
Expand Down Expand Up @@ -370,7 +371,8 @@ describe('Move content', () => {
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(false, `${existingFile}-1.txt is present in destination folder`);
});

it('Move items into a library - [C291971]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Move items into a library - [C291971]', async () => {
await dataTable.selectItem(file4, sourceRF);
await toolbar.clickMoreActionsMove();
await moveDialog.selectLocation('File Libraries');
Expand Down Expand Up @@ -492,7 +494,8 @@ describe('Move content', () => {
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(false, `${existingFile}-1.txt not present in destination folder`);
});

it('Move items into a library - [C291978]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Move items into a library - [C291978]', async () => {
await dataTable.selectItem(file4, sourceSF);
await toolbar.clickMoreActionsMove();
await moveDialog.selectLocation('File Libraries');
Expand Down Expand Up @@ -682,7 +685,8 @@ describe('Move content', () => {
expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in destination folder`);
});

it('Move items into a library - [C291979]', async () => {
// TODO disabled until ACA-2171 is fixed
xit('Move items into a library - [C291979]', async () => {
await dataTable.selectMultipleItems([file4, folder2], sourceFav);
await toolbar.clickMoreActionsMove();
await moveDialog.selectLocation('File Libraries');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/

import { ToggleEditOfflineComponent } from './toggle-edit-offline.component';
import { EditOfflineDirective } from '../../../directives/edit-offline.directive';
import { LockNodeDirective } from '../../../directives/lock-node.directive';
import { setupTestBed, CoreModule } from '@alfresco/adf-core';
import { TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
Expand All @@ -44,7 +44,7 @@ describe('ToggleEditOfflineComponent', () => {

setupTestBed({
imports: [CoreModule],
declarations: [ToggleEditOfflineComponent, EditOfflineDirective],
declarations: [ToggleEditOfflineComponent, LockNodeDirective],
providers: [
{
provide: Store,
Expand Down Expand Up @@ -115,12 +115,12 @@ describe('ToggleEditOfflineComponent', () => {
]);
});

it('should raise notification on error', () => {
it('should raise notification on lock error', () => {
component.selection = {
entry: { name: 'test' }
};

component.onError();
component.onLockError();
fixture.detectChanges();

expect(dispatchSpy.calls.argsFor(0)).toEqual([
Expand All @@ -129,4 +129,19 @@ describe('ToggleEditOfflineComponent', () => {
})
]);
});

it('should raise notification on unlock error', () => {
component.selection = {
entry: { name: 'test' }
};

component.onUnlockLockError();
fixture.detectChanges();

expect(dispatchSpy.calls.argsFor(0)).toEqual([
new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', {
fileName: 'test'
})
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,24 @@ import { MinimalNodeEntity } from '@alfresco/js-api';
selector: 'app-toggle-edit-offline',
template: `
<button
#editOffline="editOffline"
#lock="lockNode"
mat-menu-item
(toggle)="onToggleEvent($event)"
(error)="onError()"
[acaEditOffline]="selection"
(lockError)="onLockError()"
(unlockError)="onUnlockLockError()"
[acaLockNode]="selection"
[attr.title]="
editOffline.isNodeLocked()
lock.isNodeLocked()
? ('APP.ACTIONS.EDIT_OFFLINE_CANCEL' | translate)
: ('APP.ACTIONS.EDIT_OFFLINE' | translate)
"
>
<ng-container *ngIf="editOffline.isNodeLocked()">
<ng-container *ngIf="lock.isNodeLocked()">
<mat-icon>cancel</mat-icon>
<span>{{ 'APP.ACTIONS.EDIT_OFFLINE_CANCEL' | translate }}</span>
</ng-container>

<ng-container *ngIf="!editOffline.isNodeLocked()">
<ng-container *ngIf="!lock.isNodeLocked()">
<mat-icon>edit</mat-icon>
<span>{{ 'APP.ACTIONS.EDIT_OFFLINE' | translate }}</span>
</ng-container>
Expand All @@ -81,11 +82,19 @@ export class ToggleEditOfflineComponent implements OnInit {
this.store.dispatch(new EditOfflineAction(this.selection));
}

onError() {
onLockError() {
this.store.dispatch(
new SnackbarErrorAction('APP.MESSAGES.ERRORS.LOCK_NODE', {
fileName: this.selection.entry.name
})
);
}

onUnlockLockError() {
this.store.dispatch(
new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', {
fileName: this.selection.entry.name
})
);
}
}
4 changes: 2 additions & 2 deletions src/app/directives/directives.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { DocumentListDirective } from './document-list.directive';
import { PaginationDirective } from './pagination.directive';
import { LibraryMembershipDirective } from './library-membership.directive';
import { LibraryFavoriteDirective } from './library-favorite.directive';
import { EditOfflineDirective } from './edit-offline.directive';
import { LockNodeDirective } from './lock-node.directive';

export function directives() {
return [
Expand All @@ -38,7 +38,7 @@ export function directives() {
PaginationDirective,
LibraryMembershipDirective,
LibraryFavoriteDirective,
EditOfflineDirective
LockNodeDirective
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/

import { Component, ViewChild } from '@angular/core';
import { EditOfflineDirective } from './edit-offline.directive';
import { LockNodeDirective } from './lock-node.directive';
import {
AlfrescoApiService,
AlfrescoApiServiceMock,
Expand All @@ -36,24 +36,24 @@ import { TestBed, fakeAsync, tick } from '@angular/core/testing';
@Component({
selector: 'app-test-component',
template: `
<button #editOffline="editOffline" [acaEditOffline]="selection"></button>
<button #lock="lockNode" [acaLockNode]="selection"></button>
`
})
class TestComponent {
@ViewChild('editOffline')
directive: EditOfflineDirective;
@ViewChild('lock')
directive: LockNodeDirective;

selection = null;
}

describe('EditOfflineDirective', () => {
describe('LockNodeDirective', () => {
let fixture;
let api;
let component;

setupTestBed({
imports: [CoreModule],
declarations: [TestComponent, EditOfflineDirective],
declarations: [TestComponent, LockNodeDirective],
providers: [
{
provide: AlfrescoApiService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,20 @@ import { NodeEntry, NodeBodyLock, SharedLinkEntry } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';

@Directive({
selector: '[acaEditOffline]',
exportAs: 'editOffline'
selector: '[acaLockNode]',
exportAs: 'lockNode'
})
export class EditOfflineDirective {
@Input('acaEditOffline')
export class LockNodeDirective {
@Input('acaLockNode')
node: NodeEntry = null;

@Output() toggle: EventEmitter<any> = new EventEmitter();
@Output() error: EventEmitter<any> = new EventEmitter();
@Output() lockError: EventEmitter<any> = new EventEmitter();
@Output() unlockError: EventEmitter<any> = new EventEmitter();

@HostListener('click')
onClick() {
this.toggleEdit(this.node);
this.toggleLock(this.node);
}

constructor(private alfrescoApiService: AlfrescoApiService) {}
Expand All @@ -59,7 +60,7 @@ export class EditOfflineDirective {
);
}

private async toggleEdit(node: NodeEntry | SharedLinkEntry) {
private async toggleLock(node: NodeEntry | SharedLinkEntry) {
const id = (<SharedLinkEntry>node).entry.nodeId || node.entry.id;
if (this.isNodeLocked()) {
try {
Expand All @@ -69,7 +70,7 @@ export class EditOfflineDirective {
this.update(response.entry);
this.toggle.emit(isLocked);
} catch (error) {
this.error.emit(error);
this.unlockError.emit(error);
}
} else {
try {
Expand All @@ -79,7 +80,7 @@ export class EditOfflineDirective {
this.update(response.entry);
this.toggle.emit(isLocked);
} catch (error) {
this.error.emit(error);
this.lockError.emit(error);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/app/extensions/core.extensions.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ export class CoreExtensionsModule {

extensions.setEvaluators({
'app.selection.canDelete': app.canDeleteSelection,
'app.selection.canEditLockedFile': app.canEditLockedFile,
'app.selection.canUnlockFile': app.canUnlockFile,
'app.selection.canLockFile': app.canLockFile,
'app.selection.canDownload': app.canDownloadSelection,
'app.selection.notEmpty': app.hasSelection,
'app.selection.canUnshare': app.canUnshareNodes,
Expand Down
27 changes: 24 additions & 3 deletions src/app/extensions/evaluators/app.evaluators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,14 +308,35 @@ export function isWriteLocked(
);
}

export function canEditLockedFile(
export function isUserWriteLock(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would suggest isUserWriteLockOwner as name

context: AppRuleContext,
...args: RuleParameter[]
): boolean {
return !!(
!isWriteLocked(context, ...args) ||
return (
isWriteLocked(context, ...args) &&
(context.selection.file.entry.properties['cm:lockOwner'] &&
context.selection.file.entry.properties['cm:lockOwner'].id ===
context.profile.id)
);
}

export function canLockFile(
context: AppRuleContext,
...args: RuleParameter[]
): boolean {
return (
!isWriteLocked(context, ...args) && canUpdateSelectedNode(context, ...args)
);
}

export function canUnlockFile(
context: AppRuleContext,
...args: RuleParameter[]
): boolean {
const { file } = context.selection;
return (
(isWriteLocked(context, ...args) &&
context.permissions.check(file.entry, ['delete'])) ||
isUserWriteLock(context, ...args)
);
}
Loading