mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
[MNT-24923] legal hold hold capabilities are not verified properly (#4616)
* [MNT-24923] Added possibility to configure readonly for metadata sidebar by json config * [MNT-24923] Unit tests * [MNT-24923] Fixed sonar issues
This commit is contained in:
@@ -883,6 +883,20 @@
|
|||||||
"description": "Sidebar extensions",
|
"description": "Sidebar extensions",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"rules": {
|
||||||
|
"description": "Element rules",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"description": "Rule to evaluate the enabled state",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minItems": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"toolbar": {
|
"toolbar": {
|
||||||
"description": "Toolbar entries",
|
"description": "Toolbar entries",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@@ -32,7 +32,7 @@ import { By } from '@angular/platform-browser';
|
|||||||
import { AppExtensionService, NodePermissionService } from '@alfresco/aca-shared';
|
import { AppExtensionService, NodePermissionService } from '@alfresco/aca-shared';
|
||||||
import { Actions } from '@ngrx/effects';
|
import { Actions } from '@ngrx/effects';
|
||||||
import { of, Subject } from 'rxjs';
|
import { of, Subject } from 'rxjs';
|
||||||
import { ContentActionType } from '@alfresco/adf-extensions';
|
import { ContentActionType, ExtensionService } from '@alfresco/adf-extensions';
|
||||||
import { CategoryService, ContentMetadataComponent, ContentMetadataService, TagService } from '@alfresco/adf-content-services';
|
import { CategoryService, ContentMetadataComponent, ContentMetadataService, TagService } from '@alfresco/adf-content-services';
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
|
||||||
@@ -70,6 +70,7 @@ describe('MetadataTabComponent', () => {
|
|||||||
return permissions.some((permission) => source.allowableOperations.includes(permission));
|
return permissions.some((permission) => source.allowableOperations.includes(permission));
|
||||||
});
|
});
|
||||||
spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of());
|
spyOn(contentMetadataService, 'getGroupedProperties').and.returnValue(of());
|
||||||
|
extensions = TestBed.inject(AppExtensionService);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -79,7 +80,6 @@ describe('MetadataTabComponent', () => {
|
|||||||
describe('content-metadata configuration', () => {
|
describe('content-metadata configuration', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
appConfig = TestBed.inject(AppConfigService);
|
appConfig = TestBed.inject(AppConfigService);
|
||||||
extensions = TestBed.inject(AppExtensionService);
|
|
||||||
appConfig.config['content-metadata'] = { presets };
|
appConfig.config['content-metadata'] = { presets };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -102,9 +102,12 @@ describe('MetadataTabComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('readOnly', () => {
|
describe('readOnly', () => {
|
||||||
|
let extensionService: ExtensionService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(MetadataTabComponent);
|
fixture = TestBed.createComponent(MetadataTabComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
extensionService = TestBed.inject(ExtensionService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if node is not locked and has update permission', async () => {
|
it('should return false if node is not locked and has update permission', async () => {
|
||||||
@@ -146,6 +149,170 @@ describe('MetadataTabComponent', () => {
|
|||||||
expect(component.readOnly).toBe(true);
|
expect(component.readOnly).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to false if node is defined, is not locked and enabled rule for sidebar returns true, has update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: false,
|
||||||
|
allowableOperations: ['update']
|
||||||
|
} as Node;
|
||||||
|
const rule = 'someRule';
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue({
|
||||||
|
rules: {
|
||||||
|
enabled: [rule]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeFalse();
|
||||||
|
expect(extensionService.getFeature).toHaveBeenCalledWith('sidebar');
|
||||||
|
expect(extensionService.evaluateRule).toHaveBeenCalledWith(rule, extensions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to false if node is defined, is not locked and there is nothing for sidebar in configuration, has update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: false,
|
||||||
|
allowableOperations: ['update']
|
||||||
|
} as Node;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue(undefined);
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeFalse();
|
||||||
|
expect(extensionService.getFeature).toHaveBeenCalledWith('sidebar');
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is undefined and enabled rule for sidebar returns true, has update permission for node', () => {
|
||||||
|
component.node = undefined;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue({
|
||||||
|
rules: {
|
||||||
|
enabled: ['someRule']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).not.toHaveBeenCalled();
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is undefined and there is nothing for sidebar in configuration, has update permission for node', () => {
|
||||||
|
component.node = undefined;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue(undefined);
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).not.toHaveBeenCalled();
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is defined, is locked and enabled rule for sidebar returns true, has update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: true,
|
||||||
|
allowableOperations: ['update']
|
||||||
|
} as Node;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue({
|
||||||
|
rules: {
|
||||||
|
enabled: ['someRule']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).not.toHaveBeenCalled();
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is defined, is locked and there is nothing for sidebar in configuration, has update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: true,
|
||||||
|
allowableOperations: ['update']
|
||||||
|
} as Node;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue(undefined);
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).not.toHaveBeenCalled();
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is defined, is not locked and enabled rule for sidebar returns true, has not update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: false,
|
||||||
|
allowableOperations: []
|
||||||
|
} as Node;
|
||||||
|
const rule = 'someRule';
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue({
|
||||||
|
rules: {
|
||||||
|
enabled: [rule]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).toHaveBeenCalledWith('sidebar');
|
||||||
|
expect(extensionService.evaluateRule).toHaveBeenCalledWith(rule, extensions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is defined, is not locked and there is nothing for sidebar in configuration, has not update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: false,
|
||||||
|
allowableOperations: ['']
|
||||||
|
} as Node;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue(undefined);
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).toHaveBeenCalledWith('sidebar');
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is defined, is locked and enabled rule for sidebar returns true, has not update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: true,
|
||||||
|
allowableOperations: []
|
||||||
|
} as Node;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue({
|
||||||
|
rules: {
|
||||||
|
enabled: ['someRule']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).not.toHaveBeenCalled();
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set readOnly to true if node is defined, is locked and there is nothing for sidebar in configuration, has not update permission for node', () => {
|
||||||
|
component.node = {
|
||||||
|
id: 'some id',
|
||||||
|
isLocked: true,
|
||||||
|
allowableOperations: []
|
||||||
|
} as Node;
|
||||||
|
spyOn(extensionService, 'getFeature').and.returnValue(undefined);
|
||||||
|
spyOn(extensionService, 'evaluateRule').and.returnValue(true);
|
||||||
|
|
||||||
|
component.ngOnInit();
|
||||||
|
expect(component.readOnly).toBeTrue();
|
||||||
|
expect(extensionService.getFeature).not.toHaveBeenCalled();
|
||||||
|
expect(extensionService.evaluateRule).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
describe('set by triggering EditOfflineAction', () => {
|
describe('set by triggering EditOfflineAction', () => {
|
||||||
let editOfflineAction: EditOfflineAction;
|
let editOfflineAction: EditOfflineAction;
|
||||||
|
|
||||||
|
@@ -40,6 +40,7 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { Actions, ofType } from '@ngrx/effects';
|
import { Actions, ofType } from '@ngrx/effects';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
import { ExtensionService } from '@alfresco/adf-extensions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
@@ -81,15 +82,16 @@ export class MetadataTabComponent implements OnInit {
|
|||||||
private readonly destroyRef = inject(DestroyRef);
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private permission: NodePermissionService,
|
private readonly permission: NodePermissionService,
|
||||||
protected extensions: AppExtensionService,
|
protected readonly extensions: AppExtensionService,
|
||||||
private appConfig: AppConfigService,
|
private readonly appConfig: AppConfigService,
|
||||||
private notificationService: NotificationService,
|
private readonly notificationService: NotificationService,
|
||||||
private contentMetadataService: ContentMetadataService,
|
private readonly contentMetadataService: ContentMetadataService,
|
||||||
private actions$: Actions,
|
private readonly actions$: Actions,
|
||||||
private tagService: TagService,
|
private readonly tagService: TagService,
|
||||||
private categoryService: CategoryService,
|
private readonly categoryService: CategoryService,
|
||||||
private store: Store<AppStore>
|
private readonly store: Store<AppStore>,
|
||||||
|
private readonly extensionService: ExtensionService
|
||||||
) {
|
) {
|
||||||
if (this.extensions.contentMetadata) {
|
if (this.extensions.contentMetadata) {
|
||||||
this.appConfig.config['content-metadata'].presets = this.extensions.contentMetadata.presets;
|
this.appConfig.config['content-metadata'].presets = this.extensions.contentMetadata.presets;
|
||||||
@@ -128,6 +130,12 @@ export class MetadataTabComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private checkIfNodeIsUpdatable(node: Node) {
|
private checkIfNodeIsUpdatable(node: Node) {
|
||||||
this.readOnly = !(node && !isLocked({ entry: node }) ? this.permission.check(node, ['update']) : false);
|
this.readOnly = !(node &&
|
||||||
|
!isLocked({ entry: node }) &&
|
||||||
|
(this.extensionService.getFeature('sidebar')?.['rules']?.enabled ?? []).every((rule: string) =>
|
||||||
|
this.extensionService.evaluateRule(rule, this.extensions)
|
||||||
|
)
|
||||||
|
? this.permission.check(node, ['update'])
|
||||||
|
: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user