fix(medusa): Allowed properties expand (#4600)

What:
The expand allowed properties should allow all the segments whereas the allowed fields should be specific
This commit is contained in:
Adrien de Peretti
2023-07-25 14:37:44 +00:00
committed by GitHub
parent f12299deb1
commit 9129ca08a7
7 changed files with 86 additions and 71 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
fix(medusa): Clean response data should takes the full path of sub relations
+55 -49
View File
@@ -215,33 +215,36 @@ describe("/store/carts", () => {
"/store/orders?display_id=111&email=test@email.com&fields=status,email" "/store/orders?display_id=111&email=test@email.com&fields=status,email"
) )
expect(Object.keys(response.data.order)).toEqual([ expect(Object.keys(response.data.order)).toHaveLength(20)
// fields expect(Object.keys(response.data.order)).toEqual(
"status", expect.arrayContaining([
"email", // fields
"status",
"email",
// relations // relations
"shipping_address", "shipping_address",
"fulfillments", "fulfillments",
"items", "items",
"shipping_methods", "shipping_methods",
"discounts", "discounts",
"customer", "customer",
"payments", "payments",
"region", "region",
// totals // totals
"shipping_total", "shipping_total",
"discount_total", "discount_total",
"tax_total", "tax_total",
"refunded_total", "refunded_total",
"total", "total",
"subtotal", "subtotal",
"paid_total", "paid_total",
"refundable_amount", "refundable_amount",
"gift_card_total", "gift_card_total",
"gift_card_tax_total", "gift_card_tax_total",
]) ])
)
}) })
it("get order response contains only fields defined with `fields` param", async () => { it("get order response contains only fields defined with `fields` param", async () => {
@@ -249,32 +252,35 @@ describe("/store/carts", () => {
const response = await api.get("/store/orders/order_test?fields=status") const response = await api.get("/store/orders/order_test?fields=status")
expect(Object.keys(response.data.order)).toEqual([ expect(Object.keys(response.data.order)).toHaveLength(19)
// fields expect(Object.keys(response.data.order)).toEqual(
"status", expect.arrayContaining([
// fields
"status",
// default relations // default relations
"shipping_address", "shipping_address",
"fulfillments", "fulfillments",
"items", "items",
"shipping_methods", "shipping_methods",
"discounts", "discounts",
"customer", "customer",
"payments", "payments",
"region", "region",
// totals // totals
"shipping_total", "shipping_total",
"discount_total", "discount_total",
"tax_total", "tax_total",
"refunded_total", "refunded_total",
"total", "total",
"subtotal", "subtotal",
"paid_total", "paid_total",
"refundable_amount", "refundable_amount",
"gift_card_total", "gift_card_total",
"gift_card_tax_total", "gift_card_tax_total",
]) ])
)
}) })
it("get order response contains only fields defined with `fields` and `expand` param", async () => { it("get order response contains only fields defined with `fields` and `expand` param", async () => {
@@ -212,18 +212,21 @@ describe("/store/products", () => {
expect(response.status).toEqual(200) expect(response.status).toEqual(200)
expect(Object.keys(response.data.products[0])).toEqual([ expect(Object.keys(response.data.products[0])).toHaveLength(8)
// fields expect(Object.keys(response.data.products[0])).toEqual(
"handle", expect.arrayContaining([
// relations // fields
"variants", "handle",
"options", // relations
"images", "variants",
"tags", "options",
"collection", "images",
"type", "tags",
"profiles", "collection",
]) "type",
"profiles",
])
)
}) })
it("returns a list of ordered products by id ASC and filtered with free text search", async () => { it("returns a list of ordered products by id ASC and filtered with free text search", async () => {
@@ -11,6 +11,7 @@ import { BaseEntity } from "../../interfaces"
import { FindConfig, QueryConfig, RequestQueryFields } from "../../types/common" import { FindConfig, QueryConfig, RequestQueryFields } from "../../types/common"
import { omit } from "lodash" import { omit } from "lodash"
import { removeUndefinedProperties } from "../../utils" import { removeUndefinedProperties } from "../../utils"
import { buildSelects, objectToStringPath } from "@medusajs/utils"
/** /**
* Middleware that transform the query input for the admin end points * Middleware that transform the query input for the admin end points
@@ -151,7 +152,7 @@ function getStoreAllowedProperties<TEntity extends BaseEntity>(
? [...(validated.expand?.split(",") || []), ...includeKeys] ? [...(validated.expand?.split(",") || []), ...includeKeys]
: queryConfig?.allowedRelations || [] : queryConfig?.allowedRelations || []
allowed.push(...fields, ...expand) allowed.push(...fields, ...objectToStringPath(buildSelects(expand)))
return allowed return allowed
} }
@@ -180,7 +181,7 @@ function getAllowedProperties<TEntity extends BaseEntity>(
? [...(validated.expand?.split(",") || []), ...includeKeys] ? [...(validated.expand?.split(",") || []), ...includeKeys]
: queryConfig?.defaultRelations || [] : queryConfig?.defaultRelations || []
allowed.push(...fields, ...expand) allowed.push(...fields, ...objectToStringPath(buildSelects(expand)))
return allowed as string[] return allowed as string[]
} }
@@ -50,7 +50,7 @@ describe("GET /admin/orders", () => {
} }
), ),
// TODO [MEDUSA_FF_SALES_CHANNELS]: Remove when sales channel flag is removed entirely // TODO [MEDUSA_FF_SALES_CHANNELS]: Remove when sales channel flag is removed entirely
relations: [...defaultAdminOrdersRelations, "sales_channel"], relations: [...defaultAdminOrdersRelations, "sales_channel"].sort(),
}, },
{ {
includes: undefined, includes: undefined,
@@ -72,7 +72,7 @@ export default async (req, res) => {
order = cleanResponseData(order, req.allowedProperties) order = cleanResponseData(order, req.allowedProperties)
res.json({ order: cleanResponseData(order, []) }) res.json({ order: order })
} }
export class AdminGetOrdersOrderParams extends FindParams {} export class AdminGetOrdersOrderParams extends FindParams {}
@@ -56,16 +56,16 @@ describe("GET /admin/products/:id", () => {
"metadata", "metadata",
], ],
relations: [ relations: [
"variants", "collection",
"variants.prices",
"variants.options",
"profiles",
"images", "images",
"options", "options",
"profiles",
"sales_channels",
"tags", "tags",
"type", "type",
"collection", "variants",
"sales_channels", "variants.options",
"variants.prices",
], ],
} }
) )