From faa7bf54426eea1f175509c516f232eaf7c01562 Mon Sep 17 00:00:00 2001 From: Aydan Pirani Date: Sun, 21 Jan 2024 10:54:29 -0600 Subject: [PATCH] Converted static CORS into middleware, and added to all routers (#161) * Added CORS stuff * Format + Lint --- src/app.ts | 3 ++- src/config.ts | 2 +- src/middleware/cors-selector.ts | 24 ++++++++++++++++++++ src/services/newsletter/newsletter-lib.ts | 11 --------- src/services/newsletter/newsletter-router.ts | 21 ----------------- 5 files changed, 27 insertions(+), 34 deletions(-) create mode 100644 src/middleware/cors-selector.ts delete mode 100644 src/services/newsletter/newsletter-lib.ts diff --git a/src/app.ts b/src/app.ts index 2c3c7248..c807cf76 100644 --- a/src/app.ts +++ b/src/app.ts @@ -19,11 +19,12 @@ import { ErrorHandler } from "./middleware/error-handler.js"; import { StatusCode } from "status-code-enum"; import Config from "./config.js"; import database from "./middleware/database.js"; +import corsSelector from "./middleware/cors-selector.js"; const app: Application = express(); // Utility packages (detailed in the readme) -// app.use(helmet({ crossOriginResourcePolicy: false })); +app.use(corsSelector); // Enable request output when not a test if (!Config.TEST) { diff --git a/src/config.ts b/src/config.ts index 06af9fcb..32d36a35 100644 --- a/src/config.ts +++ b/src/config.ts @@ -83,7 +83,7 @@ const Config = { JWT_SECRET: requireEnv("JWT_SECRET"), - NEWSLETTER_CORS: { + CORS: { PROD_REGEX: requireEnv("PROD_REGEX"), DEPLOY_REGEX: requireEnv("DEPLOY_REGEX"), }, diff --git a/src/middleware/cors-selector.ts b/src/middleware/cors-selector.ts new file mode 100644 index 00000000..2dd1b199 --- /dev/null +++ b/src/middleware/cors-selector.ts @@ -0,0 +1,24 @@ +import cors, { CorsOptions } from "cors"; +import Config from "../config.js"; + +// Only allow a certain set of regexes to be allowed via CORS +const allowedOrigins: RegExp[] = [new RegExp(Config.CORS.PROD_REGEX), new RegExp(Config.CORS.DEPLOY_REGEX)]; + +function regexPasses(target: string, patterns: RegExp[]): boolean { + return patterns.some((pattern: RegExp) => { + return pattern.test(target); + }); +} + +// CORS options configuration +const corsOptions: CorsOptions = { + origin: (origin: string | undefined, callback: (error: Error | null, allow?: boolean) => void) => { + if (!origin || regexPasses(origin, allowedOrigins)) { + callback(null, true); + } else { + callback(new Error("Not allowed by CORS")); + } + }, +}; + +export default cors(corsOptions); diff --git a/src/services/newsletter/newsletter-lib.ts b/src/services/newsletter/newsletter-lib.ts deleted file mode 100644 index 83706a98..00000000 --- a/src/services/newsletter/newsletter-lib.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Check if a string falls in a set of regex patterns - * @param target String to verify - * @param patterns Array of regex patterns to check against - * @returns Whether or not the string fits AT LEAST one of the patterns - */ -export function regexPasses(target: string, patterns: RegExp[]): boolean { - return patterns.some((pattern: RegExp) => { - return pattern.test(target); - }); -} diff --git a/src/services/newsletter/newsletter-router.ts b/src/services/newsletter/newsletter-router.ts index 3c50a887..c6fa9c89 100644 --- a/src/services/newsletter/newsletter-router.ts +++ b/src/services/newsletter/newsletter-router.ts @@ -1,35 +1,14 @@ import { Request, Response, Router } from "express"; -import { regexPasses } from "./newsletter-lib.js"; -import cors, { CorsOptions } from "cors"; - import { SubscribeRequest } from "./newsletter-formats.js"; import { NewsletterSubscription } from "../../database/newsletter-db.js"; import Models from "../../database/models.js"; import { UpdateQuery } from "mongoose"; import { StatusCode } from "status-code-enum"; -import Config from "../../config.js"; import { RouterError } from "../../middleware/error-handler.js"; import { NextFunction } from "express-serve-static-core"; const newsletterRouter: Router = Router(); -// Only allow a certain set of regexes to be allowed via CORS -const allowedOrigins: RegExp[] = [new RegExp(Config.NEWSLETTER_CORS.PROD_REGEX), new RegExp(Config.NEWSLETTER_CORS.DEPLOY_REGEX)]; - -// CORS options configuration -const corsOptions: CorsOptions = { - origin: (origin: string | undefined, callback: (error: Error | null, allow?: boolean) => void) => { - if (!origin || regexPasses(origin, allowedOrigins)) { - callback(null, true); - } else { - callback(new Error("Not allowed by CORS")); - } - }, -}; - -// Use CORS for exclusively the newsletter - public access -newsletterRouter.use(cors(corsOptions)); - /** * @api {post} /newsletter/subscribe/ POST /newsletter/subscribe/ * @apiGroup Newsletter