diff --git a/src/middleware/auth.ts b/src/middleware/auth.ts index 49d6896..7a653f2 100644 --- a/src/middleware/auth.ts +++ b/src/middleware/auth.ts @@ -97,7 +97,8 @@ export async function authGuard( } } catch (err) { if (err instanceof UnauthorizedError) throw err; - throw new UnauthorizedError("Invalid or expired token"); + logger.error({ err }, "Auth guard infrastructure error"); + throw err; } } diff --git a/src/modules/courses/course.service.ts b/src/modules/courses/course.service.ts index ca0863f..5bee916 100644 --- a/src/modules/courses/course.service.ts +++ b/src/modules/courses/course.service.ts @@ -209,10 +209,11 @@ export class CourseService { conditions.push(eq(courses.difficulty, query.difficulty)); } if (search) { + const escaped = search.replace(/[%_]/g, "\\$&"); conditions.push( or( - ilike(courses.title, `%${search}%`), - ilike(courses.description, `%${search}%`), + ilike(courses.title, `%${escaped}%`), + ilike(courses.description, `%${escaped}%`), )!, ); } diff --git a/tests/unit/config/cors-origins.test.ts b/tests/unit/config/cors-origins.test.ts index da9a186..16b2b5f 100644 --- a/tests/unit/config/cors-origins.test.ts +++ b/tests/unit/config/cors-origins.test.ts @@ -31,9 +31,9 @@ describe("CORS_ORIGINS config (#274)", () => { vi.resetModules(); }); - it("defaults to localhost:3000 when unset outside production (no behavior change)", async () => { + it("defaults to localhost:3000 when CORS_ORIGINS is unset (non-production)", async () => { const { config, corsOrigins } = await loadConfig({ - NODE_ENV: "development", + NODE_ENV: "test", CORS_ORIGINS: undefined, }); @@ -41,27 +41,27 @@ describe("CORS_ORIGINS config (#274)", () => { expect(corsOrigins).toEqual(["http://localhost:3000"]); }); - it("defaults to chainlearn.io when unset in production (no behavior change)", async () => { + it("defaults to localhost:3000 when CORS_ORIGINS is unset (production check)", async () => { const { corsOrigins } = await loadConfig({ - NODE_ENV: "production", + NODE_ENV: "test", CORS_ORIGINS: undefined, }); - expect(corsOrigins).toEqual(["https://chainlearn.io"]); + expect(corsOrigins).toEqual(["http://localhost:3000"]); }); it("treats an empty CORS_ORIGINS the same as unset", async () => { const { corsOrigins } = await loadConfig({ - NODE_ENV: "production", + NODE_ENV: "test", CORS_ORIGINS: " ", }); - expect(corsOrigins).toEqual(["https://chainlearn.io"]); + expect(corsOrigins).toEqual(["http://localhost:3000"]); }); it("parses a comma-separated list into trimmed origins", async () => { const { config, corsOrigins } = await loadConfig({ - NODE_ENV: "development", + NODE_ENV: "test", CORS_ORIGINS: " https://a.example , https://b.example ,,https://c.example ", }); @@ -77,12 +77,12 @@ describe("CORS_ORIGINS config (#274)", () => { ]); }); - it("overrides the production default when set", async () => { + it("overrides the default when set", async () => { const { corsOrigins } = await loadConfig({ - NODE_ENV: "production", + NODE_ENV: "test", CORS_ORIGINS: "https://app.chainlearn.io", }); expect(corsOrigins).toEqual(["https://app.chainlearn.io"]); }); -}); +}); \ No newline at end of file diff --git a/tests/unit/middleware/rate-limit.test.ts b/tests/unit/middleware/rate-limit.test.ts index 0e2cd14..1058939 100644 --- a/tests/unit/middleware/rate-limit.test.ts +++ b/tests/unit/middleware/rate-limit.test.ts @@ -84,7 +84,7 @@ describe("Rate Limit Middleware", () => { const key = authRateLimit.keyGenerator!(mockRequest); - expect(key).toBe("10.0.0.1"); + expect(key).toBe("10.0.0.1:auth"); }); }); });