fix: Validate boolean query params (#8834)

This commit is contained in:
Oli Juhl
2024-08-28 13:14:15 +02:00
committed by GitHub
parent dbe931ab00
commit c2e7940f61
12 changed files with 109 additions and 36 deletions

View File

@@ -1092,6 +1092,58 @@ medusaIntegrationTestRunner({
}),
])
})
it("should get product variants filtered by manage_inventory", async () => {
const payload = {
title: "Test product - 1",
handle: "test-1",
variants: [
{
title: "Custom inventory 1",
prices: [{ currency_code: "usd", amount: 100 }],
manage_inventory: true,
inventory_items: [],
},
{
title: "Custom inventory 2",
prices: [{ currency_code: "usd", amount: 100 }],
manage_inventory: false,
},
],
}
const product = (
await api.post(`/admin/products`, payload, adminHeaders)
).data.product
let variants = (
await api.get(
`/admin/products/${product.id}/variants?manage_inventory=true`,
adminHeaders
)
).data.variants
expect(variants).toEqual([
expect.objectContaining({
title: "Custom inventory 1",
product_id: product.id,
}),
])
variants = (
await api.get(
`/admin/products/${product.id}/variants?manage_inventory=false`,
adminHeaders
)
).data.variants
expect(variants).toEqual([
expect.objectContaining({
title: "Custom inventory 2",
product_id: product.id,
}),
])
})
})
describe("POST /admin/products", () => {

View File

@@ -1,5 +1,5 @@
import { z } from "zod"
import { OptionalBooleanValidator } from "../../utils/common-validators"
import { booleanString } from "../../utils/common-validators"
import { createFindParams } from "../../utils/validators"
export type AdminFulfillmentProvidersParamsType = z.infer<
@@ -13,7 +13,7 @@ export const AdminFulfillmentProvidersParams = createFindParams({
z.object({
id: z.union([z.string(), z.array(z.string())]).optional(),
stock_location_id: z.union([z.string(), z.array(z.string())]).optional(),
is_enabled: OptionalBooleanValidator,
is_enabled: booleanString().optional(),
q: z.string().optional(),
})
)

View File

@@ -1,5 +1,5 @@
import { z } from "zod"
import { OptionalBooleanValidator } from "../../utils/common-validators"
import { booleanString } from "../../utils/common-validators"
import {
createFindParams,
createOperatorMap,
@@ -27,7 +27,7 @@ export const AdminGetInventoryItemsParams = createFindParams({
mid_code: z.union([z.string(), z.array(z.string())]).optional(),
hs_code: z.union([z.string(), z.array(z.string())]).optional(),
material: z.union([z.string(), z.array(z.string())]).optional(),
requires_shipping: OptionalBooleanValidator,
requires_shipping: booleanString().optional(),
weight: createOperatorMap(z.number(), parseFloat).optional(),
length: createOperatorMap(z.number(), parseFloat).optional(),
height: createOperatorMap(z.number(), parseFloat).optional(),

View File

@@ -1,4 +1,5 @@
import { z } from "zod"
import { booleanString } from "../../utils/common-validators"
import {
createFindParams,
createOperatorMap,
@@ -34,7 +35,7 @@ export const AdminGetPaymentProvidersParams = createFindParams({
}).merge(
z.object({
id: z.union([z.string(), z.array(z.string())]).optional(),
is_enabled: z.boolean().optional(),
is_enabled: booleanString().optional(),
$and: z.lazy(() => AdminGetPaymentProvidersParams.array()).optional(),
$or: z.lazy(() => AdminGetPaymentProvidersParams.array()).optional(),
})

View File

@@ -1,5 +1,5 @@
import { z } from "zod"
import { OptionalBooleanValidator } from "../../utils/common-validators"
import { booleanString } from "../../utils/common-validators"
import {
createFindParams,
createOperatorMap,
@@ -11,8 +11,8 @@ export type AdminProductCategoryParamsType = z.infer<
>
export const AdminProductCategoryParams = createSelectParams().merge(
z.object({
include_ancestors_tree: OptionalBooleanValidator,
include_descendants_tree: OptionalBooleanValidator,
include_ancestors_tree: booleanString().optional(),
include_descendants_tree: booleanString().optional(),
})
)
@@ -29,10 +29,10 @@ export const AdminProductCategoriesParams = createFindParams({
description: z.union([z.string(), z.array(z.string())]).optional(),
handle: z.union([z.string(), z.array(z.string())]).optional(),
parent_category_id: z.union([z.string(), z.array(z.string())]).optional(),
include_ancestors_tree: OptionalBooleanValidator,
include_descendants_tree: OptionalBooleanValidator,
is_internal: OptionalBooleanValidator,
is_active: OptionalBooleanValidator,
include_ancestors_tree: booleanString().optional(),
include_descendants_tree: booleanString().optional(),
is_internal: booleanString().optional(),
is_active: booleanString().optional(),
created_at: createOperatorMap().optional(),
updated_at: createOperatorMap().optional(),
deleted_at: createOperatorMap().optional(),

View File

@@ -1,4 +1,5 @@
import { z } from "zod"
import { booleanString } from "../../utils/common-validators"
import { createFindParams, createOperatorMap } from "../../utils/validators"
export type AdminGetProductVariantsParamsType = z.infer<
@@ -11,8 +12,8 @@ export const AdminGetProductVariantsParams = createFindParams({
z.object({
q: z.string().optional(),
id: z.union([z.string(), z.array(z.string())]).optional(),
manage_inventory: z.boolean().optional(),
allow_backorder: z.boolean().optional(),
manage_inventory: booleanString().optional(),
allow_backorder: booleanString().optional(),
created_at: createOperatorMap().optional(),
updated_at: createOperatorMap().optional(),
deleted_at: createOperatorMap().optional(),

View File

@@ -1,10 +1,11 @@
import { BatchMethodRequest } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { z } from "zod"
import {
booleanString,
GetProductsParams,
transformProductParams,
} from "../../utils/common-validators"
import { z } from "zod"
import {
createFindParams,
createOperatorMap,
@@ -28,8 +29,8 @@ export const AdminGetProductVariantsParams = createFindParams({
z.object({
q: z.string().optional(),
id: z.union([z.string(), z.array(z.string())]).optional(),
manage_inventory: z.boolean().optional(),
allow_backorder: z.boolean().optional(),
manage_inventory: booleanString().optional(),
allow_backorder: booleanString().optional(),
created_at: createOperatorMap().optional(),
updated_at: createOperatorMap().optional(),
deleted_at: createOperatorMap().optional(),
@@ -140,8 +141,8 @@ export const CreateProductVariant = z
barcode: z.string().nullish(),
hs_code: z.string().nullish(),
mid_code: z.string().nullish(),
allow_backorder: z.boolean().optional().default(false),
manage_inventory: z.boolean().optional().default(true),
allow_backorder: booleanString().optional().default(false),
manage_inventory: booleanString().optional().default(true),
variant_rank: z.number().optional(),
weight: z.number().nullish(),
length: z.number().nullish(),
@@ -177,8 +178,8 @@ export const UpdateProductVariant = z
barcode: z.string().nullish(),
hs_code: z.string().nullish(),
mid_code: z.string().nullish(),
allow_backorder: z.boolean().optional(),
manage_inventory: z.boolean().optional(),
allow_backorder: booleanString().optional(),
manage_inventory: booleanString().optional(),
variant_rank: z.number().optional(),
weight: z.number().nullish(),
length: z.number().nullish(),
@@ -211,8 +212,8 @@ export const CreateProduct = z
title: z.string(),
subtitle: z.string().nullish(),
description: z.string().nullish(),
is_giftcard: z.boolean().optional().default(false),
discountable: z.boolean().optional().default(true),
is_giftcard: booleanString().optional().default(false),
discountable: booleanString().optional().default(true),
images: z.array(z.object({ url: z.string() })).optional(),
thumbnail: z.string().nullish(),
handle: z.string().optional(),
@@ -242,8 +243,8 @@ export type AdminUpdateProductType = z.infer<typeof UpdateProduct>
export const UpdateProduct = z
.object({
title: z.string().optional(),
discountable: z.boolean().optional(),
is_giftcard: z.boolean().optional(),
discountable: booleanString().optional(),
is_giftcard: booleanString().optional(),
options: z.array(UpdateProductOption).optional(),
variants: z.array(UpdateProductVariant).optional(),
status: statusEnum.optional(),

View File

@@ -1,5 +1,5 @@
import { z } from "zod"
import { OptionalBooleanValidator } from "../../utils/common-validators"
import { booleanString } from "../../utils/common-validators"
import {
createFindParams,
createOperatorMap,
@@ -23,7 +23,7 @@ export const AdminGetSalesChannelsParams = createFindParams({
id: z.union([z.string(), z.array(z.string())]).optional(),
name: z.union([z.string(), z.array(z.string())]).optional(),
description: z.string().optional(),
is_disabled: OptionalBooleanValidator,
is_disabled: booleanString().optional(),
created_at: createOperatorMap().optional(),
updated_at: createOperatorMap().optional(),
deleted_at: createOperatorMap().optional(),

View File

@@ -1,4 +1,5 @@
import { z } from "zod"
import { booleanString } from "../../utils/common-validators"
import { createFindParams } from "../../utils/validators"
export type StoreGetPaymentProvidersParamsType = z.infer<
@@ -11,7 +12,7 @@ export const StoreGetPaymentProvidersParams = createFindParams({
z.object({
region_id: z.string(),
id: z.union([z.string(), z.array(z.string())]).optional(),
is_enabled: z.boolean().optional(),
is_enabled: booleanString().optional(),
$and: z.lazy(() => StoreGetPaymentProvidersParams.array()).optional(),
$or: z.lazy(() => StoreGetPaymentProvidersParams.array()).optional(),
})

View File

@@ -1,5 +1,5 @@
import { z } from "zod"
import { OptionalBooleanValidator } from "../../utils/common-validators"
import { booleanString } from "../../utils/common-validators"
import {
createFindParams,
createOperatorMap,
@@ -11,8 +11,8 @@ export type StoreProductCategoryParamsType = z.infer<
>
export const StoreProductCategoryParams = createSelectParams().merge(
z.object({
include_ancestors_tree: OptionalBooleanValidator,
include_descendants_tree: OptionalBooleanValidator,
include_ancestors_tree: booleanString().optional(),
include_descendants_tree: booleanString().optional(),
})
)
@@ -29,8 +29,8 @@ export const StoreProductCategoriesParams = createFindParams({
description: z.union([z.string(), z.array(z.string())]).optional(),
handle: z.union([z.string(), z.array(z.string())]).optional(),
parent_category_id: z.union([z.string(), z.array(z.string())]).optional(),
include_ancestors_tree: OptionalBooleanValidator,
include_descendants_tree: OptionalBooleanValidator,
include_ancestors_tree: booleanString().optional(),
include_descendants_tree: booleanString().optional(),
created_at: createOperatorMap().optional(),
updated_at: createOperatorMap().optional(),
deleted_at: createOperatorMap().optional(),

View File

@@ -32,7 +32,24 @@ const optionalBooleanMapper = new Map([
["false", false],
])
/**
* @deprecated Use `booleanString` instead
* It support the chainable API of zod. Please note it does not come with `.optional()` by default
*/
export const OptionalBooleanValidator = z.preprocess(
(val: any) => optionalBooleanMapper.get(val?.toLowerCase()),
z.boolean().optional()
)
/**
* Validates that a value is a boolean when it is passed as a string.
*/
export const booleanString = () =>
z
.union([z.boolean(), z.string()])
.refine((value) => {
return ["true", "false"].includes(value.toString().toLowerCase())
})
.transform((value) => {
return value.toString().toLowerCase() === "true"
})

View File

@@ -1,8 +1,8 @@
import { FilterableProductProps } from "@medusajs/types"
import { ProductStatus } from "@medusajs/utils"
import { z } from "zod"
import { createOperatorMap } from "../../validators"
import { OptionalBooleanValidator } from "../common"
import { FilterableProductProps } from "@medusajs/types"
import { booleanString } from "../common"
export const ProductStatusEnum = z.nativeEnum(ProductStatus)
@@ -11,7 +11,7 @@ export const GetProductsParams = z.object({
id: z.union([z.string(), z.array(z.string())]).optional(),
title: z.string().optional(),
handle: z.string().optional(),
is_giftcard: OptionalBooleanValidator,
is_giftcard: booleanString().optional(),
category_id: z.union([z.string(), z.array(z.string())]).optional(),
sales_channel_id: z.union([z.string(), z.array(z.string())]).optional(),
collection_id: z.union([z.string(), z.array(z.string())]).optional(),