| | |
| | |
| | |
| | |
| | |
| | import { assert, assertEquals } from "./deps.ts"; |
| | import { parseConfig } from "../lib/helpers/config.ts"; |
| |
|
| | Deno.test("Secret key validation in Invidious companion config", async (t) => { |
| | |
| | Deno.env.delete("SERVER_SECRET_KEY"); |
| |
|
| | await t.step("accepts valid alphanumeric keys", async () => { |
| | const validKeys = [ |
| | "aaaaaaaaaaaaaaaa", |
| | "AAAAAAAAAAAAAAAA", |
| | "1234567890123456", |
| | "Aa1Bb2Cc3Dd4Ee5F", |
| | "ABC123DEF456789A", |
| | ]; |
| |
|
| | for (const key of validKeys) { |
| | |
| | Deno.env.set("SERVER_SECRET_KEY", key); |
| |
|
| | try { |
| | const config = await parseConfig(); |
| | assertEquals( |
| | config.server.secret_key, |
| | key, |
| | `Key "${key}" should be accepted and stored correctly`, |
| | ); |
| | } catch (error) { |
| | assert( |
| | false, |
| | `Key "${key}" should be valid but config parsing failed: ${ |
| | error instanceof Error ? error.message : String(error) |
| | }`, |
| | ); |
| | } |
| | } |
| | }); |
| |
|
| | await t.step("rejects keys with special characters", async () => { |
| | const invalidKeys = [ |
| | "my#key!123456789", |
| | "test@key12345678", |
| | "key-with-dashes1", |
| | "key_with_under_s", |
| | "key with spaces1", |
| | "key$with$dollar$", |
| | "key+with+plus+12", |
| | "key=with=equals=", |
| | "key(with)parens1", |
| | "key[with]bracket", |
| | ]; |
| |
|
| | for (const key of invalidKeys) { |
| | |
| | Deno.env.set("SERVER_SECRET_KEY", key); |
| |
|
| | try { |
| | await parseConfig(); |
| | assert( |
| | false, |
| | `Key "${key}" should be invalid but config parsing succeeded`, |
| | ); |
| | } catch (error) { |
| | |
| | assert( |
| | error instanceof Error && |
| | error.message.includes("Failed to parse configuration"), |
| | `Should get config parsing error, got: ${ |
| | error instanceof Error ? error.message : String(error) |
| | }`, |
| | ); |
| |
|
| | |
| | const errorStr = error instanceof Error |
| | ? error.toString() |
| | : String(error); |
| | assert( |
| | errorStr.includes( |
| | "SERVER_SECRET_KEY contains invalid characters", |
| | ) || |
| | errorStr.includes("alphanumeric characters"), |
| | `Error should mention invalid characters or alphanumeric, got: ${errorStr}`, |
| | ); |
| | } |
| | } |
| | }); |
| |
|
| | await t.step("rejects keys with wrong length", async () => { |
| | const wrongLengthKeys = [ |
| | "short", |
| | "thiskeyistoolongtobevalid", |
| | "", |
| | "a", |
| | "exactly15chars", |
| | "exactly17charss", |
| | ]; |
| |
|
| | for (const key of wrongLengthKeys) { |
| | |
| | Deno.env.set("SERVER_SECRET_KEY", key); |
| |
|
| | try { |
| | await parseConfig(); |
| | assert( |
| | false, |
| | `Key "${key}" (length ${key.length}) should be invalid but config parsing succeeded`, |
| | ); |
| | } catch (error) { |
| | |
| | assert( |
| | error instanceof Error && |
| | error.message.includes("Failed to parse configuration"), |
| | `Should get config parsing error, got: ${ |
| | error instanceof Error ? error.message : String(error) |
| | }`, |
| | ); |
| |
|
| | |
| | const errorStr = error instanceof Error |
| | ? error.toString() |
| | : String(error); |
| | assert( |
| | errorStr.includes("exactly 16 character") || |
| | errorStr.includes( |
| | "String must contain exactly 16 character", |
| | ), |
| | `Error should mention 16 characters, got: ${errorStr}`, |
| | ); |
| | } |
| | } |
| | }); |
| |
|
| | await t.step("validates error message content", async () => { |
| | |
| | Deno.env.set("SERVER_SECRET_KEY", "my#key!123456789"); |
| |
|
| | try { |
| | await parseConfig(); |
| | assert(false, "Should have failed with special character key"); |
| | } catch (error) { |
| | const errorStr = error instanceof Error |
| | ? error.toString() |
| | : String(error); |
| |
|
| | |
| | assert( |
| | errorStr.includes( |
| | "SERVER_SECRET_KEY contains invalid characters", |
| | ) || |
| | errorStr.includes("alphanumeric characters"), |
| | "Should mention SERVER_SECRET_KEY and character validation", |
| | ); |
| | } |
| |
|
| | |
| | Deno.env.set("SERVER_SECRET_KEY", "short"); |
| |
|
| | try { |
| | await parseConfig(); |
| | assert(false, "Should have failed with short key"); |
| | } catch (error) { |
| | const errorStr = error instanceof Error |
| | ? error.toString() |
| | : String(error); |
| | assert( |
| | errorStr.includes("exactly 16 character") || |
| | errorStr.includes( |
| | "String must contain exactly 16 character", |
| | ), |
| | `Should mention 16 characters: ${errorStr}`, |
| | ); |
| | } |
| | }); |
| |
|
| | await t.step( |
| | "validates precedence - length vs character validation", |
| | async () => { |
| | |
| | |
| | Deno.env.set("SERVER_SECRET_KEY", "bad#"); |
| |
|
| | try { |
| | await parseConfig(); |
| | assert( |
| | false, |
| | "Should have failed with short key containing special chars", |
| | ); |
| | } catch (error) { |
| | const errorStr = error instanceof Error |
| | ? error.toString() |
| | : String(error); |
| | |
| | assert( |
| | errorStr.includes("exactly 16 character") || |
| | errorStr.includes( |
| | "String must contain exactly 16 character", |
| | ), |
| | `Should get length error first: ${errorStr}`, |
| | ); |
| | } |
| | }, |
| | ); |
| |
|
| | |
| | await t.step("validates missing SERVER_SECRET_KEY fails", async () => { |
| | |
| | Deno.env.delete("SERVER_SECRET_KEY"); |
| |
|
| | try { |
| | await parseConfig(); |
| | assert( |
| | false, |
| | "Should have failed with missing/empty SERVER_SECRET_KEY", |
| | ); |
| | } catch (error) { |
| | const errorStr = error instanceof Error |
| | ? error.toString() |
| | : String(error); |
| | assert( |
| | errorStr.includes("exactly 16 character") || |
| | errorStr.includes( |
| | "String must contain exactly 16 character", |
| | ), |
| | `Should get length error for empty key: ${errorStr}`, |
| | ); |
| | } |
| | }); |
| |
|
| | await t.step("cleanup", () => { |
| | Deno.env.delete("SERVER_SECRET_KEY"); |
| | }); |
| | }); |
| |
|