mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACA-2864] Site Managers are not able to disable inherit permissions … (#7021)
* [ACA-2864] Site Managers are not able to disable inherit permissions in DW/ACA * * added test cases * * fixed lints * * [force ci] remove mispell
This commit is contained in:
@@ -124,7 +124,8 @@ export const fakeNodeInheritedOnly = {
|
||||
},
|
||||
{
|
||||
'id': 'e002c740-b8f9-482a-a554-8fff4e4c9dc0',
|
||||
'name': 'testsite'
|
||||
'name': 'testsite',
|
||||
'nodeType': 'st:site'
|
||||
},
|
||||
{
|
||||
'id': '71626fae-0c04-4d0c-a129-20fa4c178716',
|
||||
@@ -579,3 +580,83 @@ export const fakeEmptyResponse: any = {
|
||||
'entries': []
|
||||
}
|
||||
};
|
||||
|
||||
export const fakeNodeLocalSiteManager = {
|
||||
'allowableOperations': [ 'updatePermissions' ],
|
||||
'aspectNames': [
|
||||
'cm:auditable',
|
||||
'cm:taggable',
|
||||
'cm:author',
|
||||
'cm:titled',
|
||||
'app:uifacets'
|
||||
],
|
||||
'createdAt': '2017-11-16T16:29:38.638+0000',
|
||||
'path': {
|
||||
'name': '/Company Home/Sites/testsite/documentLibrary',
|
||||
'isComplete': true,
|
||||
'elements': [
|
||||
{
|
||||
'id': '2be275a1-b00d-4e45-83d8-66af43ac2252',
|
||||
'name': 'Company Home'
|
||||
},
|
||||
{
|
||||
'id': '1be10a97-6eb9-4b60-b6c6-1673900e9631',
|
||||
'name': 'Sites'
|
||||
},
|
||||
{
|
||||
'id': 'e002c740-b8f9-482a-a554-8fff4e4c9dc0',
|
||||
'name': 'testsite',
|
||||
'nodeType': 'st:site'
|
||||
},
|
||||
{
|
||||
'id': '71626fae-0c04-4d0c-a129-20fa4c178716',
|
||||
'name': 'documentLibrary'
|
||||
}
|
||||
]
|
||||
},
|
||||
'isFolder': true,
|
||||
'isFile': false,
|
||||
'createdByUser': {
|
||||
'id': 'System',
|
||||
'displayName': 'System'
|
||||
},
|
||||
'modifiedAt': '2018-03-21T03:17:58.783+0000',
|
||||
'permissions': {
|
||||
'locallySet': [
|
||||
{
|
||||
'authorityId': 'GROUP_site_testsite_SiteManager',
|
||||
'name': 'SiteManager',
|
||||
'accessStatus': 'ALLOWED'
|
||||
},
|
||||
{
|
||||
'authorityId': 'superadminuser',
|
||||
'name': 'SiteCollaborator',
|
||||
'accessStatus': 'ALLOWED'
|
||||
}
|
||||
],
|
||||
'settable': [
|
||||
'Contributor',
|
||||
'Collaborator',
|
||||
'Coordinator',
|
||||
'Editor',
|
||||
'Consumer'
|
||||
],
|
||||
'isInheritanceEnabled': false
|
||||
},
|
||||
'modifiedByUser': {
|
||||
'id': 'admin',
|
||||
'displayName': 'PedroH Hernandez'
|
||||
},
|
||||
'name': 'test',
|
||||
'id': 'f472543f-7218-403d-917b-7a5861257244',
|
||||
'nodeType': 'cm:folder',
|
||||
'properties': {
|
||||
'cm:title': 'test',
|
||||
'cm:author': 'yagud',
|
||||
'cm:taggable': [
|
||||
'e8c8fbba-03ba-4fa6-86b1-f7ad7c296409'
|
||||
],
|
||||
'cm:description': 'sleepery',
|
||||
'app:icon': 'space-icon-default'
|
||||
}
|
||||
};
|
||||
|
@@ -34,7 +34,7 @@
|
||||
key="name"
|
||||
sortable="false">
|
||||
<ng-template let-entry="$implicit">
|
||||
<adf-user-role-column [readonly]="isReadOnly"
|
||||
<adf-user-role-column [readonly]="entry.row.obj.readonly || isReadOnly"
|
||||
[placeholder]="entry.data.getValue(entry.row, entry.col)"
|
||||
[value]="entry.data.getValue(entry.row, entry.col)"
|
||||
[roles]="roles"
|
||||
@@ -59,6 +59,7 @@
|
||||
<data-column class="adf-datatable-cell adf-delete-permission-column" key="" *ngIf="!isReadOnly" [sortable]="false">
|
||||
<ng-template let-entry="$implicit">
|
||||
<button mat-icon-button
|
||||
[disabled]="entry.row.obj.readonly"
|
||||
(click)="removePermission($event, entry.row.obj)"
|
||||
[attr.data-automation-id]="'adf-delete-permission-button-' + entry.row.obj.authorityId">
|
||||
<mat-icon>delete_outline</mat-icon>
|
||||
|
@@ -25,6 +25,7 @@ import { NodePermissionService } from '../../services/node-permission.service';
|
||||
import {
|
||||
fakeEmptyResponse,
|
||||
fakeNodeInheritedOnly,
|
||||
fakeNodeLocalSiteManager,
|
||||
fakeNodeWithOnlyLocally,
|
||||
fakeNodeWithoutPermissions,
|
||||
fakeNodeWithPermissions,
|
||||
@@ -206,6 +207,19 @@ describe('PermissionListComponent', () => {
|
||||
expect(options[3].nativeElement.innerText).toContain('ADF.ROLES.SITEMANAGER');
|
||||
});
|
||||
|
||||
it('should show readonly member for site manager to toggle the inherit permission', async() => {
|
||||
getNodeSpy.and.returnValue(of(fakeNodeLocalSiteManager));
|
||||
component.ngOnInit();
|
||||
|
||||
await fixture.detectChanges();
|
||||
expect(element.querySelector('adf-user-name-column').textContent).toContain('GROUP_site_testsite_SiteManager');
|
||||
expect(element.querySelector('#adf-select-role-permission').textContent).toContain('ADF.ROLES.SITEMANAGER');
|
||||
const deleteButton: HTMLButtonElement = element.querySelector('[data-automation-id="adf-delete-permission-button-GROUP_site_testsite_SiteManager"]');
|
||||
expect(deleteButton.disabled).toBe(true);
|
||||
const otherDeleteButton: HTMLButtonElement = element.querySelector('[data-automation-id="adf-delete-permission-button-superadminuser"]');
|
||||
expect(otherDeleteButton.disabled).toBe(false);
|
||||
});
|
||||
|
||||
it('should update the role when another value is chosen', async () => {
|
||||
spyOn(nodeService, 'updateNode').and.returnValue(of({id: 'fake-uwpdated-node'}));
|
||||
searchQuerySpy.and.returnValue(of(fakeEmptyResponse));
|
||||
@@ -236,8 +250,8 @@ describe('PermissionListComponent', () => {
|
||||
expect(element.querySelector('adf-user-name-column').textContent).toContain('GROUP_EVERYONE');
|
||||
expect(element.querySelector('#adf-select-role-permission').textContent).toContain('Contributor');
|
||||
|
||||
const showButton: HTMLButtonElement = element.querySelector('[data-automation-id="adf-delete-permission-button-GROUP_EVERYONE"]');
|
||||
showButton.click();
|
||||
const deleteButton: HTMLButtonElement = element.querySelector('[data-automation-id="adf-delete-permission-button-GROUP_EVERYONE"]');
|
||||
deleteButton.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(nodeService.updateNode).toHaveBeenCalledWith('f472543f-7218-403d-917b-7a5861257244', { permissions: { locallySet: [ ] } });
|
||||
|
@@ -56,7 +56,7 @@ export class PermissionListComponent {
|
||||
}
|
||||
|
||||
onSelect(selections: ObjectDataRow[]) {
|
||||
this.selectedPermissions = selections.map((selection) => selection['obj']);
|
||||
this.selectedPermissions = selections.map((selection) => selection['obj']).filter((permission) => !permission.readonly);
|
||||
}
|
||||
|
||||
deleteSelection() {
|
||||
|
@@ -22,7 +22,7 @@ import { of, throwError } from 'rxjs';
|
||||
import { PermissionListService } from './permission-list.service';
|
||||
import { ContentTestingModule } from '../../../testing/content.testing.module';
|
||||
import { NodePermissionService } from '../../services/node-permission.service';
|
||||
import { fakeNodeInheritedOnly, fakeNodeWithOnlyLocally } from '../../../mock/permission-list.component.mock';
|
||||
import { fakeNodeInheritedOnly, fakeNodeLocalSiteManager, fakeNodeWithOnlyLocally } from '../../../mock/permission-list.component.mock';
|
||||
import { PermissionDisplayModel } from '../../models/permission.model';
|
||||
|
||||
describe('PermissionListService', () => {
|
||||
@@ -82,21 +82,50 @@ describe('PermissionListService', () => {
|
||||
expect(notificationService.showError).toHaveBeenCalledWith('PERMISSION_MANAGER.ERROR.NOT-ALLOWED');
|
||||
});
|
||||
|
||||
it('should show message after success toggle', () => {
|
||||
it('should include the local permission before toggle', (done) => {
|
||||
const node = JSON.parse(JSON.stringify(fakeNodeInheritedOnly)), event = { source: { checked: false } };
|
||||
spyOn(nodePermissionService, 'getNodeWithRoles').and.returnValue(of({node , roles: []}));
|
||||
spyOn(nodePermissionService, 'updatePermissions').and.returnValue(of(null));
|
||||
spyOn(nodesApiService, 'updateNode').and.returnValue(of(JSON.parse(JSON.stringify(fakeNodeLocalSiteManager))));
|
||||
service.fetchPermission('fetch node');
|
||||
|
||||
const subscription = service.data$.subscribe(({ localPermissions }) => {
|
||||
expect(localPermissions[0].authorityId).toBe('GROUP_site_testsite_SiteManager');
|
||||
expect(localPermissions[0].readonly).toBe(true);
|
||||
expect(localPermissions[1].authorityId).toBe('superadminuser');
|
||||
expect(localPermissions[1].readonly).toBe(undefined);
|
||||
expect(nodePermissionService.updatePermissions).toHaveBeenCalled();
|
||||
expect(nodesApiService.updateNode).toHaveBeenCalled();
|
||||
expect(notificationService.showInfo).toHaveBeenCalledWith('PERMISSION_MANAGER.MESSAGE.INHERIT-DISABLE-SUCCESS');
|
||||
subscription.unsubscribe();
|
||||
done();
|
||||
});
|
||||
service.toggleInherited(event as any);
|
||||
});
|
||||
|
||||
it('should not update local permission before toggle', () => {
|
||||
const node = JSON.parse(JSON.stringify(fakeNodeInheritedOnly)), event = { source: { checked: false } };
|
||||
const updateNode = JSON.parse(JSON.stringify(fakeNodeInheritedOnly));
|
||||
node.permissions.locallySet = [{
|
||||
'authorityId': 'GROUP_site_testsite_SiteManager',
|
||||
'name': 'SiteManager',
|
||||
'accessStatus': 'ALLOWED'
|
||||
}];
|
||||
updateNode.permissions.isInheritanceEnabled = false;
|
||||
spyOn(nodePermissionService, 'getNodeWithRoles').and.returnValue(of({node , roles: []}));
|
||||
spyOn(nodePermissionService, 'updatePermissions').and.returnValue(of(null));
|
||||
spyOn(nodesApiService, 'updateNode').and.returnValue(of(updateNode));
|
||||
service.fetchPermission('fetch node');
|
||||
|
||||
service.toggleInherited(event as any);
|
||||
expect(nodePermissionService.updatePermissions).not.toHaveBeenCalled();
|
||||
expect(nodesApiService.updateNode).toHaveBeenCalled();
|
||||
expect(notificationService.showInfo).toHaveBeenCalledWith('PERMISSION_MANAGER.MESSAGE.INHERIT-DISABLE-SUCCESS');
|
||||
});
|
||||
|
||||
it('should show message for errored toggle', () => {
|
||||
const node = JSON.parse(JSON.stringify(fakeNodeInheritedOnly)), event = { source: { checked: false } };
|
||||
node.permissions.isInheritanceEnabled = true;
|
||||
spyOn(nodesApiService, 'updateNode').and.returnValue(throwError('Failed to update'));
|
||||
spyOn(nodePermissionService, 'getNodeWithRoles').and.returnValue(of({node , roles: []}));
|
||||
service.fetchPermission('fetch node');
|
||||
@@ -104,6 +133,7 @@ describe('PermissionListService', () => {
|
||||
service.toggleInherited(event as any);
|
||||
expect(nodesApiService.updateNode).toHaveBeenCalled();
|
||||
expect(notificationService.showWarning).toHaveBeenCalledWith('PERMISSION_MANAGER.MESSAGE.TOGGLE-PERMISSION-FAILED');
|
||||
expect(event.source.checked).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -39,18 +39,20 @@ export class PermissionListService {
|
||||
nodeWithRoles$: Subject<{ node: Node, roles: RoleModel[] }> = new Subject();
|
||||
data$: Observable<NodePermissionsModel> = this.nodeWithRoles$.pipe(
|
||||
map(({ node, roles}) => {
|
||||
const nodeLocalPermissions = this.nodePermissionService.getLocalPermissions(node);
|
||||
const localPermissions = this.updateReadOnlyPermission(node, nodeLocalPermissions);
|
||||
return {
|
||||
node,
|
||||
roles,
|
||||
inheritedPermissions: this.nodePermissionService.getInheritedPermission(node),
|
||||
localPermissions: this.nodePermissionService.getLocalPermissions(node),
|
||||
allPermission: this.nodePermissionService.getNodePermissions(node)
|
||||
localPermissions,
|
||||
inheritedPermissions: this.nodePermissionService.getInheritedPermission(node)
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
private node: Node;
|
||||
private roles: RoleModel[];
|
||||
private SITE_MANAGER_ROLE = 'SiteManager';
|
||||
|
||||
constructor(
|
||||
private nodeService: NodesApiService,
|
||||
@@ -76,12 +78,23 @@ export class PermissionListService {
|
||||
|
||||
toggleInherited(change: MatSlideToggleChange) {
|
||||
if (this.contentService.hasAllowableOperations(this.node, AllowableOperationsEnum.UPDATEPERMISSIONS)) {
|
||||
let updateLocalPermission$ = of(null);
|
||||
const nodeBody = {
|
||||
permissions: {
|
||||
isInheritanceEnabled: !this.node.permissions.isInheritanceEnabled
|
||||
}
|
||||
};
|
||||
this.nodeService.updateNode(this.node.id, nodeBody, {include: ['permissions']})
|
||||
|
||||
const authorityId = this.getManagerAuthority(this.node);
|
||||
if (authorityId) {
|
||||
const permissions = [
|
||||
...(this.node.permissions.locallySet || []),
|
||||
{ authorityId, name: this.SITE_MANAGER_ROLE, accessStatus: 'ALLOWED' }
|
||||
];
|
||||
updateLocalPermission$ = this.nodePermissionService.updatePermissions(this.node, permissions);
|
||||
}
|
||||
|
||||
updateLocalPermission$.pipe(switchMap(() => this.nodeService.updateNode(this.node.id, nodeBody, {include: ['permissions']})))
|
||||
.subscribe(
|
||||
(nodeUpdated: Node) => {
|
||||
const message = nodeUpdated.permissions.isInheritanceEnabled ? 'PERMISSION_MANAGER.MESSAGE.INHERIT-ENABLE-SUCCESS' : 'PERMISSION_MANAGER.MESSAGE.INHERIT-DISABLE-SUCCESS';
|
||||
@@ -157,7 +170,7 @@ export class PermissionListService {
|
||||
}
|
||||
|
||||
bulkRoleUpdate(role: string) {
|
||||
const permissions = [...this.node.permissions.locallySet] .map((permission) => this.buildUpdatedPermission(role, permission));
|
||||
const permissions = [...this.node.permissions.locallySet].map((permission) => this.buildUpdatedPermission(role, permission));
|
||||
this.nodePermissionService.updatePermissions(this.node, permissions)
|
||||
.subscribe((node) => {
|
||||
const total = permissions.length;
|
||||
@@ -173,10 +186,14 @@ export class PermissionListService {
|
||||
}
|
||||
|
||||
deletePermission(permission: PermissionDisplayModel) {
|
||||
const cloneNode = { ...this.node, permissions: { ...this.node.permissions, locallySet: [ ...this.node.permissions.locallySet ] } };
|
||||
this.nodePermissionService
|
||||
.removePermission(this.node, permission)
|
||||
.removePermission(cloneNode, permission)
|
||||
.subscribe((node) => {
|
||||
this.notificationService.showInfo('PERMISSION_MANAGER.MESSAGE.PERMISSION-DELETE-SUCCESS');
|
||||
if (!node.permissions.locallySet) {
|
||||
node.permissions.locallySet = [];
|
||||
}
|
||||
this.reloadNode(node);
|
||||
},
|
||||
() => {
|
||||
@@ -189,7 +206,7 @@ export class PermissionListService {
|
||||
private buildUpdatedPermission(role: string, permission: PermissionElement): PermissionElement {
|
||||
return {
|
||||
accessStatus: permission.accessStatus,
|
||||
name: role,
|
||||
name: this.canUpdateThePermission(this.node, permission) ? role : permission.name,
|
||||
authorityId: permission.authorityId
|
||||
};
|
||||
}
|
||||
@@ -201,6 +218,38 @@ export class PermissionListService {
|
||||
this.nodeWithRoles$.next({ node: this.node, roles: this.roles });
|
||||
}
|
||||
|
||||
getManagerAuthority(node: Node): string {
|
||||
const sitePath = node.path.elements.find((path) => path.nodeType === 'st:site');
|
||||
let hasLocalManagerPermission = false, authorityId: string;
|
||||
if (sitePath) {
|
||||
authorityId = `GROUP_site_${sitePath.name}_${this.SITE_MANAGER_ROLE}`;
|
||||
hasLocalManagerPermission = !!node.permissions.locallySet?.find((permission) => permission.authorityId === authorityId && permission.name === this.SITE_MANAGER_ROLE);
|
||||
}
|
||||
|
||||
if (!hasLocalManagerPermission && authorityId) {
|
||||
return authorityId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
updateReadOnlyPermission(node: Node, permissions: PermissionDisplayModel[]): PermissionDisplayModel[] {
|
||||
permissions.forEach((permission) => {
|
||||
if (!this.canUpdateThePermission(node, permission)) {
|
||||
permission.readonly = true;
|
||||
}
|
||||
});
|
||||
return permissions;
|
||||
}
|
||||
|
||||
canUpdateThePermission(node: Node, permission: PermissionElement): boolean {
|
||||
const sitePath = node.path.elements.find((path) => path.nodeType === 'st:site');
|
||||
if (!node.permissions.isInheritanceEnabled && sitePath) {
|
||||
const authorityId = `GROUP_site_${sitePath.name}_${this.SITE_MANAGER_ROLE}`;
|
||||
return !(permission.authorityId === authorityId && permission.name === this.SITE_MANAGER_ROLE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private isGroup(authorityId) {
|
||||
return authorityId.startsWith('GROUP_') || authorityId.startsWith('ROLE_');
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ export class PermissionDisplayModel implements PermissionElement {
|
||||
accessStatus?: PermissionElement.AccessStatusEnum;
|
||||
isInherited: boolean = false;
|
||||
icon: string;
|
||||
readonly?: boolean;
|
||||
|
||||
constructor(obj?: any) {
|
||||
if (obj) {
|
||||
|
Reference in New Issue
Block a user