diff --git a/integration-tests/api/__tests__/store/order-edit.js b/integration-tests/api/__tests__/store/order-edit.js index 3d08294931..df98675547 100644 --- a/integration-tests/api/__tests__/store/order-edit.js +++ b/integration-tests/api/__tests__/store/order-edit.js @@ -213,6 +213,18 @@ describe("[MEDUSA_FF_ORDER_EDITING] /store/order-edits", () => { expect(response.data.order_edit.canceled_by).not.toBeDefined() expect(response.data.order_edit.confirmed_by).not.toBeDefined() }) + + it("fails to get an order edit with disallowed fields query params", async () => { + const api = useApi() + + const err = await api + .get(`/store/order-edits/${orderEditId}?fields=internal_note,order_id`) + .catch((e) => e) + + expect(err.response.data.message).toBe( + "Fields [internal_note] are not valid" + ) + }) }) describe("POST /store/order-edits/:id/decline", () => { diff --git a/packages/medusa/src/types/common.ts b/packages/medusa/src/types/common.ts index e4bb854f89..e6b9e85e88 100644 --- a/packages/medusa/src/types/common.ts +++ b/packages/medusa/src/types/common.ts @@ -91,6 +91,7 @@ export type QueryConfig = { defaultFields?: (keyof TEntity | string)[] defaultRelations?: string[] allowedFields?: string[] + allowedRelations?: string[] defaultLimit?: number isList?: boolean } diff --git a/packages/medusa/src/types/order-edit.ts b/packages/medusa/src/types/order-edit.ts index 7d759614b3..b727ff829a 100644 --- a/packages/medusa/src/types/order-edit.ts +++ b/packages/medusa/src/types/order-edit.ts @@ -46,7 +46,7 @@ export const defaultOrderEditFields: (keyof OrderEdit)[] = [ "internal_note", ] -export const storeOrderEditNotAllowedFields = [ +export const storeOrderEditNotAllowedFieldsAndRelations = [ "internal_note", "created_by", "confirmed_by", @@ -54,8 +54,8 @@ export const storeOrderEditNotAllowedFields = [ ] export const defaultStoreOrderEditRelations = defaultOrderEditRelations.filter( - (field) => !storeOrderEditNotAllowedFields.includes(field) + (field) => !storeOrderEditNotAllowedFieldsAndRelations.includes(field) ) export const defaultStoreOrderEditFields = defaultOrderEditFields.filter( - (field) => !storeOrderEditNotAllowedFields.includes(field) + (field) => !storeOrderEditNotAllowedFieldsAndRelations.includes(field) ) diff --git a/packages/medusa/src/utils/get-query-config.ts b/packages/medusa/src/utils/get-query-config.ts index e3d2a9bd85..76c83f4776 100644 --- a/packages/medusa/src/utils/get-query-config.ts +++ b/packages/medusa/src/utils/get-query-config.ts @@ -1,7 +1,7 @@ import { pick } from "lodash" import { FindConfig, QueryConfig, RequestQueryFields } from "../types/common" import { MedusaError } from "medusa-core-utils/dist" -import { BaseEntity } from "../interfaces/models/base-entity" +import { BaseEntity } from "../interfaces" import { isDefined } from "." export function pickByConfig( @@ -96,6 +96,14 @@ export function prepareListQuery< expandFields = fields.split(",") as (keyof TEntity)[] } + if (expandFields?.length && queryConfig?.allowedFields?.length) { + validateFields(expandFields as string[], queryConfig.allowedFields) + } + + if (expandRelations?.length && queryConfig?.allowedRelations?.length) { + validateRelations(expandRelations, queryConfig.allowedRelations) + } + let orderBy: { [k: symbol]: "DESC" | "ASC" } | undefined if (isDefined(order)) { let orderField = order @@ -145,15 +153,12 @@ export function prepareRetrieveQuery< expandFields = fields.split(",") as (keyof TEntity)[] } - if (queryConfig?.allowedFields?.length) { - expandFields?.forEach((field) => { - if (!queryConfig?.allowedFields?.includes(field as string)) { - throw new MedusaError( - MedusaError.Types.INVALID_DATA, - `Field ${field.toString()} is not valid` - ) - } - }) + if (expandFields?.length && queryConfig?.allowedFields?.length) { + validateFields(expandFields as string[], queryConfig.allowedFields) + } + + if (expandRelations?.length && queryConfig?.allowedRelations?.length) { + validateRelations(expandRelations, queryConfig.allowedRelations) } return getRetrieveConfig( @@ -163,3 +168,38 @@ export function prepareRetrieveQuery< expandRelations ) } + +function validateRelations( + relations: string[], + allowed: string[] +): void | never { + const disallowedRelationsFound: string[] = [] + relations?.forEach((field) => { + if (!allowed.includes(field as string)) { + disallowedRelationsFound.push(field) + } + }) + + if (disallowedRelationsFound.length) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Relations [${disallowedRelationsFound.join(", ")}] are not valid` + ) + } +} + +function validateFields(fields: string[], allowed: string[]): void | never { + const disallowedFieldsFound: string[] = [] + fields?.forEach((field) => { + if (!allowed.includes(field as string)) { + disallowedFieldsFound.push(field) + } + }) + + if (disallowedFieldsFound.length) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Fields [${disallowedFieldsFound.join(", ")}] are not valid` + ) + } +}