From 2e41f030f02a336c2e9866d3d56b0494da5a622e Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Mon, 15 Dec 2025 00:58:43 -0800 Subject: Remove admin route in favor of a simpler toml format --- test/storage.test.ts | 67 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 27 deletions(-) (limited to 'test/storage.test.ts') diff --git a/test/storage.test.ts b/test/storage.test.ts index 200c81a..985ba48 100644 --- a/test/storage.test.ts +++ b/test/storage.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest'; -import { mkdtemp, readFile, rm } from 'fs/promises'; +import { mkdtemp, readFile, rm, writeFile } from 'fs/promises'; import { tmpdir } from 'os'; import { join } from 'path'; @@ -9,56 +9,69 @@ import { ContentType, type RouteConfig } from '../src/types/index.js'; describe('Storage', () => { let dataDir: string; + let configPath: string; beforeEach(async () => { dataDir = await mkdtemp(join(tmpdir(), 'posthook-test-')); + configPath = join(dataDir, 'routes.toml'); }); afterEach(async () => { await rm(dataDir, { recursive: true, force: true }); }); - it('persists routes to routes.json and loads them on init', async () => { + it('loads routes from routes.toml on init', async () => { const route: RouteConfig = { name: 'route1', contentType: ContentType.JSON, hcaptchaProtected: false, }; - const storage1 = new Storage(dataDir); - expect((await storage1.init()).left().present()).toBe(false); - expect((await storage1.registerRoute(route)).left().present()).toBe(false); + // Create a TOML config file + const toml = ` +[[route]] +name = "route1" +contentType = "json" +hcaptchaProtected = false +`; + await writeFile(configPath, toml); - const storage2 = new Storage(dataDir); - expect((await storage2.init()).left().present()).toBe(false); - expect(storage2.getRoute('route1')).toEqual(route); - expect(storage2.listRoutes()).toEqual([route]); + const storage = new Storage(dataDir, configPath); + expect((await storage.init()).left().present()).toBe(false); + expect(storage.getRoute('route1')).toEqual(route); + expect(storage.listRoutes()).toEqual([route]); }); - it('rejects unsafe route names', async () => { - const storage = new Storage(dataDir); - expect((await storage.init()).left().present()).toBe(false); + it('returns undefined for unsafe route names', async () => { + const toml = ` +[[route]] +name = "safe-route" +contentType = "json" +hcaptchaProtected = false +`; + await writeFile(configPath, toml); - const result = await storage.registerRoute({ - name: '../bad', - contentType: ContentType.JSON, - hcaptchaProtected: false, - }); + const storage = new Storage(dataDir, configPath); + expect((await storage.init()).left().present()).toBe(false); - expect(result.left().present()).toBe(true); - expect(result.left().get().message).toBe('Invalid route name'); + // getRoute should reject unsafe names + expect(storage.getRoute('../bad')).toBeUndefined(); + expect(storage.getRoute('.')).toBeUndefined(); + expect(storage.getRoute('..')).toBeUndefined(); + expect(storage.getRoute('path/with/slash')).toBeUndefined(); }); it('stores a request and sanitizes uploaded filenames', async () => { - const route: RouteConfig = { - name: 'route1', - contentType: ContentType.JSON, - hcaptchaProtected: false, - }; - - const storage = new Storage(dataDir); + const toml = ` +[[route]] +name = "route1" +contentType = "json" +hcaptchaProtected = false +`; + await writeFile(configPath, toml); + + const storage = new Storage(dataDir, configPath); expect((await storage.init()).left().present()).toBe(false); - expect((await storage.registerRoute(route)).left().present()).toBe(false); const upload = { fieldName: 'file', -- cgit v1.2.3-70-g09d2