From 6d1f423a0c753f84562aa3efafaaa110062cfdad Mon Sep 17 00:00:00 2001 From: Lucas Di Pentima Date: Wed, 5 Feb 2020 18:05:08 -0300 Subject: [PATCH] 16067: Ignores certain fields on create & update api calls. Some fields like 'etag', 'kind', 'uuid' and others are read-only, so they shouldn't be sent to the API server. Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima --- .../collection-service/collection-service.ts | 6 ++++- .../common-resource-service.test.ts | 16 ++++++++++++++ .../common-service/common-resource-service.ts | 22 +++++++++++++++++-- src/services/common-service/common-service.ts | 4 +++- .../trashable-resource-service.ts | 4 ++-- .../collections/collection-copy-actions.ts | 7 ++---- 6 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/services/collection-service/collection-service.ts b/src/services/collection-service/collection-service.ts index 6eb9b5ba..f7955fba 100644 --- a/src/services/collection-service/collection-service.ts +++ b/src/services/collection-service/collection-service.ts @@ -15,7 +15,11 @@ export type UploadProgress = (fileId: number, loaded: number, total: number, cur export class CollectionService extends TrashableResourceService { constructor(serverApi: AxiosInstance, private webdavClient: WebDAV, private authService: AuthService, actions: ApiActions) { - super(serverApi, "collections", actions); + super(serverApi, "collections", actions, [ + 'unsignedManifestText', + 'storageClassesConfirmed', + 'storageClassesConfirmedAt' + ]); } async files(uuid: string) { diff --git a/src/services/common-service/common-resource-service.test.ts b/src/services/common-service/common-resource-service.test.ts index 2a18ce23..038c6943 100644 --- a/src/services/common-service/common-resource-service.test.ts +++ b/src/services/common-service/common-resource-service.test.ts @@ -48,6 +48,22 @@ describe("CommonResourceService", () => { expect(axiosInstance.post).toHaveBeenCalledWith("/resource", {owner_uuid: "ownerUuidValue"}); }); + it("#create ignores fields listed as readonly", async () => { + axiosInstance.post = jest.fn(() => Promise.resolve({data: {}})); + const commonResourceService = new CommonResourceService(axiosInstance, "resource", actions); + // UUID fields are read-only on all resources. + await commonResourceService.create({ uuid: "this should be ignored", ownerUuid: "ownerUuidValue" }); + expect(axiosInstance.post).toHaveBeenCalledWith("/resource", {owner_uuid: "ownerUuidValue"}); + }); + + it("#update ignores fields listed as readonly", async () => { + axiosInstance.put = jest.fn(() => Promise.resolve({data: {}})); + const commonResourceService = new CommonResourceService(axiosInstance, "resource", actions); + // UUID fields are read-only on all resources. + await commonResourceService.update('resource-uuid', { uuid: "this should be ignored", ownerUuid: "ownerUuidValue" }); + expect(axiosInstance.put).toHaveBeenCalledWith("/resource/resource-uuid", {owner_uuid: "ownerUuidValue"}); + }); + it("#delete", async () => { axiosMock .onDelete("/resource/uuid") diff --git a/src/services/common-service/common-resource-service.ts b/src/services/common-service/common-resource-service.ts index d29ea156..bc24f227 100644 --- a/src/services/common-service/common-resource-service.ts +++ b/src/services/common-service/common-resource-service.ts @@ -17,8 +17,26 @@ export enum CommonResourceServiceError { } export class CommonResourceService extends CommonService { - constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions) { - super(serverApi, resourceType, actions); + constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions, readOnlyFields: string[] = []) { + super(serverApi, resourceType, actions, readOnlyFields.concat([ + 'uuid', + 'etag', + 'kind' + ])); + } + + create(data?: Partial) { + if (data !== undefined) { + this.readOnlyFields.forEach( field => delete data[field] ); + } + return super.create(data); + } + + update(uuid: string, data: Partial) { + if (data !== undefined) { + this.readOnlyFields.forEach( field => delete data[field] ); + } + return super.update(uuid, data); } } diff --git a/src/services/common-service/common-service.ts b/src/services/common-service/common-service.ts index d8117821..44233eb1 100644 --- a/src/services/common-service/common-service.ts +++ b/src/services/common-service/common-service.ts @@ -36,11 +36,13 @@ export class CommonService { protected serverApi: AxiosInstance; protected resourceType: string; protected actions: ApiActions; + protected readOnlyFields: string[]; - constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions) { + constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions, readOnlyFields: string[] = []) { this.serverApi = serverApi; this.resourceType = '/' + resourceType; this.actions = actions; + this.readOnlyFields = readOnlyFields; } static mapResponseKeys = (response: { data: any }) => diff --git a/src/services/common-service/trashable-resource-service.ts b/src/services/common-service/trashable-resource-service.ts index 5746bffb..63be3ab8 100644 --- a/src/services/common-service/trashable-resource-service.ts +++ b/src/services/common-service/trashable-resource-service.ts @@ -10,8 +10,8 @@ import { ApiActions } from "~/services/api/api-actions"; export class TrashableResourceService extends CommonResourceService { - constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions) { - super(serverApi, resourceType, actions); + constructor(serverApi: AxiosInstance, resourceType: string, actions: ApiActions, readOnlyFields: string[] = []) { + super(serverApi, resourceType, actions, readOnlyFields); } trash(uuid: string): Promise { diff --git a/src/store/collections/collection-copy-actions.ts b/src/store/collections/collection-copy-actions.ts index b13d08aa..cf87f3f1 100644 --- a/src/store/collections/collection-copy-actions.ts +++ b/src/store/collections/collection-copy-actions.ts @@ -28,13 +28,9 @@ export const copyCollection = (resource: CopyFormDialogData) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { dispatch(startSubmit(COLLECTION_COPY_FORM_NAME)); try { - dispatch(progressIndicatorActions.START_WORKING(COLLECTION_COPY_FORM_NAME)); const collection = await services.collectionService.get(resource.uuid); - const uuidKey = 'uuid'; - delete collection[uuidKey]; const newCollection = await services.collectionService.create({ ...collection, ownerUuid: resource.ownerUuid, name: resource.name }); dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_COPY_FORM_NAME })); - dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_COPY_FORM_NAME)); return newCollection; } catch (e) { const error = getCommonResourceServiceError(e); @@ -47,7 +43,8 @@ export const copyCollection = (resource: CopyFormDialogData) => dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_COPY_FORM_NAME })); throw new Error('Could not copy the collection.'); } - dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_COPY_FORM_NAME)); return; + } finally { + dispatch(progressIndicatorActions.STOP_WORKING(COLLECTION_COPY_FORM_NAME)); } }; -- 2.30.2