Merge pull request #1756 from atmire/Admin-export-all-fields

Add admin option to export all fields in the metadata export
This commit is contained in:
Tim Donohue
2022-08-19 13:10:48 -05:00
committed by GitHub
2 changed files with 86 additions and 22 deletions

View File

@@ -20,6 +20,7 @@ import {
createSuccessfulRemoteDataObject$ createSuccessfulRemoteDataObject$
} from '../../../remote-data.utils'; } from '../../../remote-data.utils';
import { ExportMetadataSelectorComponent } from './export-metadata-selector.component'; import { ExportMetadataSelectorComponent } from './export-metadata-selector.component';
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
// No way to add entryComponents yet to testbed; alternative implemented; source: https://stackoverflow.com/questions/41689468/how-to-shallow-test-a-component-with-an-entrycomponents // No way to add entryComponents yet to testbed; alternative implemented; source: https://stackoverflow.com/questions/41689468/how-to-shallow-test-a-component-with-an-entrycomponents
@NgModule({ @NgModule({
@@ -47,6 +48,7 @@ describe('ExportMetadataSelectorComponent', () => {
let router; let router;
let notificationService: NotificationsServiceStub; let notificationService: NotificationsServiceStub;
let scriptService; let scriptService;
let authorizationDataService;
const mockItem = Object.assign(new Item(), { const mockItem = Object.assign(new Item(), {
id: 'fake-id', id: 'fake-id',
@@ -95,6 +97,9 @@ describe('ExportMetadataSelectorComponent', () => {
invoke: createSuccessfulRemoteDataObject$({ processId: '45' }) invoke: createSuccessfulRemoteDataObject$({ processId: '45' })
} }
); );
authorizationDataService = jasmine.createSpyObj('authorizationDataService', {
isAuthorized: observableOf(true)
});
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), ModelTestModule], imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([]), ModelTestModule],
declarations: [ExportMetadataSelectorComponent], declarations: [ExportMetadataSelectorComponent],
@@ -102,6 +107,7 @@ describe('ExportMetadataSelectorComponent', () => {
{ provide: NgbActiveModal, useValue: modalStub }, { provide: NgbActiveModal, useValue: modalStub },
{ provide: NotificationsService, useValue: notificationService }, { provide: NotificationsService, useValue: notificationService },
{ provide: ScriptDataService, useValue: scriptService }, { provide: ScriptDataService, useValue: scriptService },
{ provide: AuthorizationDataService, useValue: authorizationDataService },
{ {
provide: ActivatedRoute, provide: ActivatedRoute,
useValue: { useValue: {
@@ -150,7 +156,7 @@ describe('ExportMetadataSelectorComponent', () => {
}); });
}); });
describe('if collection is selected', () => { describe('if collection is selected and is admin', () => {
let scriptRequestSucceeded; let scriptRequestSucceeded;
beforeEach((done) => { beforeEach((done) => {
spyOn((component as any).modalService, 'open').and.returnValue(modalRef); spyOn((component as any).modalService, 'open').and.returnValue(modalRef);
@@ -159,7 +165,32 @@ describe('ExportMetadataSelectorComponent', () => {
done(); done();
}); });
}); });
it('should invoke the metadata-export script with option -i uuid', () => { it('should invoke the metadata-export script with option -i uuid and -a option', () => {
const parameterValues: ProcessParameter[] = [
Object.assign(new ProcessParameter(), { name: '-i', value: mockCollection.uuid }),
Object.assign(new ProcessParameter(), { name: '-a' }),
];
expect(scriptService.invoke).toHaveBeenCalledWith(METADATA_EXPORT_SCRIPT_NAME, parameterValues, []);
});
it('success notification is shown', () => {
expect(scriptRequestSucceeded).toBeTrue();
expect(notificationService.success).toHaveBeenCalled();
});
it('redirected to process page', () => {
expect(router.navigateByUrl).toHaveBeenCalledWith('/processes/45');
});
});
describe('if collection is selected and is not admin', () => {
let scriptRequestSucceeded;
beforeEach((done) => {
(authorizationDataService.isAuthorized as jasmine.Spy).and.returnValue(observableOf(false));
spyOn((component as any).modalService, 'open').and.returnValue(modalRef);
component.navigate(mockCollection).subscribe((succeeded: boolean) => {
scriptRequestSucceeded = succeeded;
done();
});
});
it('should invoke the metadata-export script with option -i uuid without the -a option', () => {
const parameterValues: ProcessParameter[] = [ const parameterValues: ProcessParameter[] = [
Object.assign(new ProcessParameter(), { name: '-i', value: mockCollection.uuid }), Object.assign(new ProcessParameter(), { name: '-i', value: mockCollection.uuid }),
]; ];
@@ -174,7 +205,7 @@ describe('ExportMetadataSelectorComponent', () => {
}); });
}); });
describe('if community is selected', () => { describe('if community is selected and is an admin', () => {
let scriptRequestSucceeded; let scriptRequestSucceeded;
beforeEach((done) => { beforeEach((done) => {
spyOn((component as any).modalService, 'open').and.returnValue(modalRef); spyOn((component as any).modalService, 'open').and.returnValue(modalRef);
@@ -183,7 +214,32 @@ describe('ExportMetadataSelectorComponent', () => {
done(); done();
}); });
}); });
it('should invoke the metadata-export script with option -i uuid', () => { it('should invoke the metadata-export script with option -i uuid and -a option if the user is an admin', () => {
const parameterValues: ProcessParameter[] = [
Object.assign(new ProcessParameter(), { name: '-i', value: mockCommunity.uuid }),
Object.assign(new ProcessParameter(), { name: '-a' }),
];
expect(scriptService.invoke).toHaveBeenCalledWith(METADATA_EXPORT_SCRIPT_NAME, parameterValues, []);
});
it('success notification is shown', () => {
expect(scriptRequestSucceeded).toBeTrue();
expect(notificationService.success).toHaveBeenCalled();
});
it('redirected to process page', () => {
expect(router.navigateByUrl).toHaveBeenCalledWith('/processes/45');
});
});
describe('if community is selected and is not an admin', () => {
let scriptRequestSucceeded;
beforeEach((done) => {
(authorizationDataService.isAuthorized as jasmine.Spy).and.returnValue(observableOf(false));
spyOn((component as any).modalService, 'open').and.returnValue(modalRef);
component.navigate(mockCommunity).subscribe((succeeded: boolean) => {
scriptRequestSucceeded = succeeded;
done();
});
});
it('should invoke the metadata-export script with option -i uuid without the -a option', () => {
const parameterValues: ProcessParameter[] = [ const parameterValues: ProcessParameter[] = [
Object.assign(new ProcessParameter(), { name: '-i', value: mockCommunity.uuid }), Object.assign(new ProcessParameter(), { name: '-i', value: mockCommunity.uuid }),
]; ];

View File

@@ -19,6 +19,8 @@ import { getFirstCompletedRemoteData } from '../../../../core/shared/operators';
import { Process } from '../../../../process-page/processes/process.model'; import { Process } from '../../../../process-page/processes/process.model';
import { RemoteData } from '../../../../core/data/remote-data'; import { RemoteData } from '../../../../core/data/remote-data';
import { getProcessDetailRoute } from '../../../../process-page/process-page-routing.paths'; import { getProcessDetailRoute } from '../../../../process-page/process-page-routing.paths';
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../../../../core/data/feature-authorization/feature-id';
/** /**
* Component to wrap a list of existing dso's inside a modal * Component to wrap a list of existing dso's inside a modal
@@ -36,6 +38,7 @@ export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComp
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router, constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router,
protected notificationsService: NotificationsService, protected translationService: TranslateService, protected notificationsService: NotificationsService, protected translationService: TranslateService,
protected scriptDataService: ScriptDataService, protected scriptDataService: ScriptDataService,
protected authorizationDataService: AuthorizationDataService,
private modalService: NgbModal) { private modalService: NgbModal) {
super(activeModal, route); super(activeModal, route);
} }
@@ -82,24 +85,29 @@ export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComp
const parameterValues: ProcessParameter[] = [ const parameterValues: ProcessParameter[] = [
Object.assign(new ProcessParameter(), { name: '-i', value: dso.uuid }), Object.assign(new ProcessParameter(), { name: '-i', value: dso.uuid }),
]; ];
return this.scriptDataService.invoke(METADATA_EXPORT_SCRIPT_NAME, parameterValues, []) return this.authorizationDataService.isAuthorized(FeatureID.AdministratorOf).pipe(
.pipe( switchMap((isAdmin) => {
getFirstCompletedRemoteData(), if (isAdmin) {
map((rd: RemoteData<Process>) => { parameterValues.push(Object.assign(new ProcessParameter(), {name: '-a'}));
if (rd.hasSucceeded) { }
const title = this.translationService.get('process.new.notification.success.title'); return this.scriptDataService.invoke(METADATA_EXPORT_SCRIPT_NAME, parameterValues, []);
const content = this.translationService.get('process.new.notification.success.content'); }),
this.notificationsService.success(title, content); getFirstCompletedRemoteData(),
if (isNotEmpty(rd.payload)) { map((rd: RemoteData<Process>) => {
this.router.navigateByUrl(getProcessDetailRoute(rd.payload.processId)); if (rd.hasSucceeded) {
} const title = this.translationService.get('process.new.notification.success.title');
return true; const content = this.translationService.get('process.new.notification.success.content');
} else { this.notificationsService.success(title, content);
const title = this.translationService.get('process.new.notification.error.title'); if (isNotEmpty(rd.payload)) {
const content = this.translationService.get('process.new.notification.error.content'); this.router.navigateByUrl(getProcessDetailRoute(rd.payload.processId));
this.notificationsService.error(title, content);
return false;
} }
})); return true;
} else {
const title = this.translationService.get('process.new.notification.error.title');
const content = this.translationService.get('process.new.notification.error.content');
this.notificationsService.error(title, content);
return false;
}
}));
} }
} }