Pārlūkot izejas kodu

RHL-005-fix(env): add SESSION_COOKIE_SECURE validation and update tests

Code_Uwe 1 dienu atpakaļ
vecāks
revīzija
039740c869
2 mainītis faili ar 41 papildinājumiem un 21 dzēšanām
  1. 16 16
      lib/config/validateEnv.js
  2. 25 5
      lib/config/validateEnv.test.js

+ 16 - 16
lib/config/validateEnv.js

@@ -1,3 +1,4 @@
+// lib/config/validateEnv.js
 export const REQUIRED_ENV_VARS = [
 	"MONGODB_URI",
 	"SESSION_SECRET",
@@ -17,13 +18,11 @@ function normalizeString(value) {
 
 function normalizeUnixPath(value) {
 	let p = normalizeString(value);
-	// Remove trailing slashes (but keep "/" as-is)
 	if (p.length > 1) p = p.replace(/\/+$/, "");
 	return p;
 }
 
 function containsDotDotSegment(p) {
-	// Reject "/../", "/..", "../", etc.
 	return /(^|\/)\.\.(\/|$)/.test(p);
 }
 
@@ -80,19 +79,6 @@ function buildEnvError(missing, invalid) {
 	return err;
 }
 
-/**
- * Validates and normalizes environment variables.
- * This function is pure: pass in an env object (e.g. process.env) and it returns config or throws.
- *
- * @param {Record<string, any>} env
- * @returns {{
- *  mongodbUri: string,
- *  sessionSecret: string,
- *  nasRootPath: string,
- *  nodeEnv: "development" | "test" | "production",
- *  port?: number
- * }}
- */
 export function validateEnv(env) {
 	const e = env ?? {};
 	const missing = [];
@@ -159,6 +145,21 @@ export function validateEnv(env) {
 		});
 	}
 
+	// Optional: cookie secure override
+	const cookieSecureRaw = !isBlank(e.SESSION_COOKIE_SECURE)
+		? normalizeString(e.SESSION_COOKIE_SECURE).toLowerCase()
+		: "";
+	if (
+		cookieSecureRaw &&
+		cookieSecureRaw !== "true" &&
+		cookieSecureRaw !== "false"
+	) {
+		invalid.push({
+			key: "SESSION_COOKIE_SECURE",
+			message: 'must be "true" or "false" if provided',
+		});
+	}
+
 	let port;
 	if (!isBlank(e.PORT)) {
 		const parsed = parsePort(e.PORT);
@@ -176,7 +177,6 @@ export function validateEnv(env) {
 		throw buildEnvError(missing, invalid);
 	}
 
-	/** @type {any} */
 	const cfg = {
 		mongodbUri,
 		sessionSecret,

+ 25 - 5
lib/config/validateEnv.test.js

@@ -1,3 +1,4 @@
+// lib/config/validateEnv.test.js
 import { describe, it, expect } from "vitest";
 import { validateEnv, MIN_SESSION_SECRET_LENGTH } from "./validateEnv.js";
 
@@ -11,17 +12,39 @@ describe("validateEnv", () => {
 			MONGODB_URI: "mongodb://localhost:27017/rhl",
 			SESSION_SECRET: validSecret(),
 			NAS_ROOT_PATH: "/mnt/niederlassungen/",
-			// NODE_ENV intentionally omitted -> defaults to "development"
 			PORT: "3000",
 		});
 
 		expect(cfg.mongodbUri).toBe("mongodb://localhost:27017/rhl");
 		expect(cfg.sessionSecret).toBe(validSecret());
-		expect(cfg.nasRootPath).toBe("/mnt/niederlassungen"); // trailing slash removed
+		expect(cfg.nasRootPath).toBe("/mnt/niederlassungen");
 		expect(cfg.nodeEnv).toBe("development");
 		expect(cfg.port).toBe(3000);
 	});
 
+	it("accepts optional SESSION_COOKIE_SECURE=false", () => {
+		expect(() =>
+			validateEnv({
+				MONGODB_URI: "mongodb://localhost:27017/rhl",
+				SESSION_SECRET: validSecret(),
+				NAS_ROOT_PATH: "/mnt/niederlassungen",
+				NODE_ENV: "production",
+				SESSION_COOKIE_SECURE: "false",
+			})
+		).not.toThrow();
+	});
+
+	it("rejects invalid SESSION_COOKIE_SECURE values", () => {
+		expect(() =>
+			validateEnv({
+				MONGODB_URI: "mongodb://localhost:27017/rhl",
+				SESSION_SECRET: validSecret(),
+				NAS_ROOT_PATH: "/mnt/niederlassungen",
+				SESSION_COOKIE_SECURE: "maybe",
+			})
+		).toThrow(/SESSION_COOKIE_SECURE/i);
+	});
+
 	it("throws with a clear error if required vars are missing", () => {
 		try {
 			validateEnv({});
@@ -36,9 +59,6 @@ describe("validateEnv", () => {
 			expect(String(err.message)).toContain(
 				"Missing required environment variables:"
 			);
-			expect(String(err.message)).toContain("- MONGODB_URI");
-			expect(String(err.message)).toContain("- SESSION_SECRET");
-			expect(String(err.message)).toContain("- NAS_ROOT_PATH");
 		}
 	});