diff --git a/.changeset/wild-squids-watch.md b/.changeset/wild-squids-watch.md new file mode 100644 index 0000000000..cf5fffb1f7 --- /dev/null +++ b/.changeset/wild-squids-watch.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +Allow regular expression in CORS configuration diff --git a/packages/medusa-core-utils/src/__tests__/build-regexp-if-valid.spec.ts b/packages/medusa-core-utils/src/__tests__/build-regexp-if-valid.spec.ts new file mode 100644 index 0000000000..46449bff4c --- /dev/null +++ b/packages/medusa-core-utils/src/__tests__/build-regexp-if-valid.spec.ts @@ -0,0 +1,12 @@ +import { buildRegexpIfValid } from "../build-regexp-if-valid" + +describe("buildRegexpIfValid", function () { + it("should return either a regexp or undefined", () => { + expect(buildRegexpIfValid("abc")).not.toBeDefined() + expect(buildRegexpIfValid("/abc/")).toBeTruthy() + expect(buildRegexpIfValid("/ab#/[c]/ig")).toBeTruthy() + expect(buildRegexpIfValid("@ab#/[c]@ig")).toBeTruthy() + expect(buildRegexpIfValid("/ab/[c/ig")).not.toBeDefined() + expect(buildRegexpIfValid("/abc/gig")).not.toBeDefined() + }) +}) diff --git a/packages/medusa-core-utils/src/__tests__/parse-cors-origins.spec.ts b/packages/medusa-core-utils/src/__tests__/parse-cors-origins.spec.ts new file mode 100644 index 0000000000..4b89153937 --- /dev/null +++ b/packages/medusa-core-utils/src/__tests__/parse-cors-origins.spec.ts @@ -0,0 +1,16 @@ +import { parseCorsOrigins } from "../parse-cors-origins" + +describe("parseCorsOrigins", function () { + it("should return an array containing both string and regexp", () => { + const cors = "abc,/abc/,/ab#/[c]/ig,@ab#/[c]@ig,/ab/[c/ig,/abc/gig" + const [origin1, origin2, origin3, origin4, origin5, origin6] = + parseCorsOrigins(cors) + + expect(typeof origin1).toBe("string") + expect(origin2).toBeInstanceOf(RegExp) + expect(origin3).toBeInstanceOf(RegExp) + expect(origin4).toBeInstanceOf(RegExp) + expect(typeof origin5).toBe("string") + expect(typeof origin6).toBe("string") + }) +}) diff --git a/packages/medusa-core-utils/src/build-regexp-if-valid.ts b/packages/medusa-core-utils/src/build-regexp-if-valid.ts new file mode 100644 index 0000000000..e55a377caf --- /dev/null +++ b/packages/medusa-core-utils/src/build-regexp-if-valid.ts @@ -0,0 +1,10 @@ +export function buildRegexpIfValid(str: string): RegExp | undefined { + try { + const m = str.match(/^([\/~@;%#'])(.*?)\1([gimsuy]*)$/) + if (m) { + return new RegExp(m[2], m[3]) + } + } catch (e) {} + + return +} diff --git a/packages/medusa-core-utils/src/index.ts b/packages/medusa-core-utils/src/index.ts index ed48257759..0a5caa85b4 100644 --- a/packages/medusa-core-utils/src/index.ts +++ b/packages/medusa-core-utils/src/index.ts @@ -1,10 +1,13 @@ +export { buildRegexpIfValid } from "./build-regexp-if-valid" +export { default as computerizeAmount } from "./computerize-amount" export { countries, isoCountryLookup } from "./countries" export { default as createRequireFromPath } from "./create-require-from-path" export { default as MedusaError } from "./errors" export { default as getConfigFile } from "./get-config-file" export { default as humanizeAmount } from "./humanize-amount" -export { default as computerizeAmount } from "./computerize-amount" export { indexTypes } from "./index-types" +export { parseCorsOrigins } from "./parse-cors-origins" export { transformIdableFields } from "./transform-idable-fields" export { default as Validator } from "./validator" export { default as zeroDecimalCurrencies } from "./zero-decimal-currencies" + diff --git a/packages/medusa-core-utils/src/parse-cors-origins.ts b/packages/medusa-core-utils/src/parse-cors-origins.ts new file mode 100644 index 0000000000..86ea1a7df6 --- /dev/null +++ b/packages/medusa-core-utils/src/parse-cors-origins.ts @@ -0,0 +1,7 @@ +import { buildRegexpIfValid } from "./build-regexp-if-valid"; + +export function parseCorsOrigins(str: string): (string | RegExp)[] { + return str.split(",").map((subStr) => { + return buildRegexpIfValid(subStr) ?? subStr + }) +} diff --git a/packages/medusa-fulfillment-webshipper/src/api/index.js b/packages/medusa-fulfillment-webshipper/src/api/index.js index 9cbbe9b0e2..27626ce009 100644 --- a/packages/medusa-fulfillment-webshipper/src/api/index.js +++ b/packages/medusa-fulfillment-webshipper/src/api/index.js @@ -2,7 +2,7 @@ import { Router } from "express" import bodyParser from "body-parser" import crypto from "crypto" import cors from "cors" -import { getConfigFile } from "medusa-core-utils" +import { getConfigFile, parseCorsOrigins } from "medusa-core-utils" export default (rootDirectory) => { const app = Router() @@ -11,7 +11,7 @@ export default (rootDirectory) => { const { projectConfig } = configModule const corsOptions = { - origin: projectConfig.store_cors.split(","), + origin: parseCorsOrigins(projectConfig.store_cors), credentials: true, } diff --git a/packages/medusa-payment-adyen/src/api/routes/hooks/index.js b/packages/medusa-payment-adyen/src/api/routes/hooks/index.js index 807fec9612..526e4bf7fe 100644 --- a/packages/medusa-payment-adyen/src/api/routes/hooks/index.js +++ b/packages/medusa-payment-adyen/src/api/routes/hooks/index.js @@ -2,7 +2,7 @@ import { Router } from "express" import cors from "cors" import bodyParser from "body-parser" import middlewares from "../../middlewares" -import { getConfigFile } from "medusa-core-utils" +import { getConfigFile, parseCorsOrigins } from "medusa-core-utils" const route = Router() @@ -13,7 +13,7 @@ export default (app, rootDirectory) => { const storeCors = config.store_cors || "" route.use( cors({ - origin: storeCors.split(","), + origin: parseCorsOrigins(storeCors), credentials: true, }) ) diff --git a/packages/medusa-plugin-mailchimp/src/api/routes/index.js b/packages/medusa-plugin-mailchimp/src/api/routes/index.js index 599a82bc7a..6fb985db81 100644 --- a/packages/medusa-plugin-mailchimp/src/api/routes/index.js +++ b/packages/medusa-plugin-mailchimp/src/api/routes/index.js @@ -1,7 +1,7 @@ import { Router } from "express" import bodyParser from "body-parser" import middlewares from "../middleware" -import { getConfigFile } from "medusa-core-utils" +import { getConfigFile, parseCorsOrigins } from "medusa-core-utils" import cors from "cors" const route = Router() @@ -14,7 +14,7 @@ export default (app, rootDirectory) => { route.use( cors({ - origin: storeCors.split(","), + origin: parseCorsOrigins(storeCors), credentials: true, }) ) diff --git a/packages/medusa-plugin-restock-notification/src/api/routes/index.js b/packages/medusa-plugin-restock-notification/src/api/routes/index.js index 42d01e6ef8..1c0fdc8eb6 100644 --- a/packages/medusa-plugin-restock-notification/src/api/routes/index.js +++ b/packages/medusa-plugin-restock-notification/src/api/routes/index.js @@ -1,7 +1,7 @@ import { Router } from "express" import bodyParser from "body-parser" import cors from "cors" -import { getConfigFile } from "medusa-core-utils" +import { getConfigFile, parseCorsOrigins } from "medusa-core-utils" import middlewares from "../middleware" @@ -14,7 +14,7 @@ export default (app, rootDirectory) => { const { projectConfig } = configModule const corsOptions = { - origin: projectConfig.store_cors.split(","), + origin: parseCorsOrigins(projectConfig.store_cors), credentials: true, } diff --git a/packages/medusa-plugin-wishlist/src/api/index.js b/packages/medusa-plugin-wishlist/src/api/index.js index 2feb5ea241..87b7137aa5 100644 --- a/packages/medusa-plugin-wishlist/src/api/index.js +++ b/packages/medusa-plugin-wishlist/src/api/index.js @@ -1,15 +1,14 @@ -import { Router } from "express" +import express, { Router } from "express" import jwt from "jsonwebtoken" import cors from "cors" -import express from "express" -import { getConfigFile, MedusaError } from "medusa-core-utils" +import { getConfigFile, MedusaError, parseCorsOrigins } from "medusa-core-utils" const app = Router() export default (rootDirectory) => { const { configModule } = getConfigFile(rootDirectory, "medusa-config") const { projectConfig } = configModule const corsOptions = { - origin: projectConfig.store_cors.split(","), + origin: parseCorsOrigins(projectConfig.store_cors), credentials: true, } const JWT_SECRET = process.env.JWT_SECRET || "" diff --git a/packages/medusa/src/api/routes/admin/index.js b/packages/medusa/src/api/routes/admin/index.js index 66c5101234..d1b455f5bf 100644 --- a/packages/medusa/src/api/routes/admin/index.js +++ b/packages/medusa/src/api/routes/admin/index.js @@ -36,6 +36,7 @@ import userRoutes, { unauthenticatedUserRoutes } from "./users" import variantRoutes from "./variants" import paymentCollectionRoutes from "./payment-collections" import paymentRoutes from "./payments" +import { parseCorsOrigins } from "medusa-core-utils" const route = Router() @@ -45,7 +46,7 @@ export default (app, container, config) => { const adminCors = config.admin_cors || "" route.use( cors({ - origin: adminCors.split(","), + origin: parseCorsOrigins(adminCors), credentials: true, }) ) diff --git a/packages/medusa/src/api/routes/store/index.js b/packages/medusa/src/api/routes/store/index.js index e5cee0d1bc..9cd8a93a96 100644 --- a/packages/medusa/src/api/routes/store/index.js +++ b/packages/medusa/src/api/routes/store/index.js @@ -17,6 +17,7 @@ import shippingOptionRoutes from "./shipping-options" import swapRoutes from "./swaps" import variantRoutes from "./variants" import paymentCollectionRoutes from "./payment-collections" +import { parseCorsOrigins } from "medusa-core-utils" const route = Router() @@ -26,7 +27,7 @@ export default (app, container, config) => { const storeCors = config.store_cors || "" route.use( cors({ - origin: storeCors.split(","), + origin: parseCorsOrigins(storeCors), credentials: true, }) ) diff --git a/packages/medusa/src/index.js b/packages/medusa/src/index.js index bbef3b1412..d9012c50b5 100644 --- a/packages/medusa/src/index.js +++ b/packages/medusa/src/index.js @@ -4,3 +4,4 @@ export * from "./types/price-list" export * from "./types/batch-job" export * from "./models" export * from "./services" +export * from "./utils"