From 3b704b4c8c9a8a7d8b6add70a38832b4eff230c3 Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Thu, 24 Oct 2024 18:41:11 +0200 Subject: [PATCH] fix(plugin): :bug: Fix misleading error message related to plugin initialization --- app.ts | 3 +- plugins/openid/index.ts | 83 ++++++++++++++++++++++++++--------------- utils/init.ts | 12 +++++- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/app.ts b/app.ts index 0846f82d..cb56fc4b 100644 --- a/app.ts +++ b/app.ts @@ -138,7 +138,8 @@ export const appFactory = async () => { serverLogger.fatal`Put your configuration at ${chalk.blueBright( "plugins.config.", )}`; - throw new Error("Plugin configuration is invalid"); + + await Bun.sleep(Number.POSITIVE_INFINITY); } // biome-ignore lint/complexity/useLiteralKeys: AddToApp is a private method diff --git a/plugins/openid/index.ts b/plugins/openid/index.ts index 1665e32d..3972f244 100644 --- a/plugins/openid/index.ts +++ b/plugins/openid/index.ts @@ -1,6 +1,7 @@ import { Hooks, Plugin } from "@versia/kit"; import chalk from "chalk"; import { z } from "zod"; +import { User } from "@versia/kit/db"; import authorizeRoute from "./routes/authorize.ts"; import jwksRoute from "./routes/jwks.ts"; import ssoLoginCallbackRoute from "./routes/oauth/callback.ts"; @@ -26,38 +27,60 @@ const plugin = new Plugin( }), ) .default([]), - keys: z.object({ - public: z.string().transform(async (v) => { - try { - return await crypto.subtle.importKey( - "spki", - Buffer.from(v, "base64"), - "Ed25519", - true, - ["verify"], - ); - } catch { - throw new Error( - `Public key at keys.public is invalid. Run the ${chalk.bold("generate-keys")} command to generate a new keypair`, - ); + keys: z + .object({ + public: z + .string() + .min(1) + .transform(async (v) => { + try { + return await crypto.subtle.importKey( + "spki", + Buffer.from(v, "base64"), + "Ed25519", + true, + ["verify"], + ); + } catch { + throw new Error( + "Public key at oidc.keys.public is invalid", + ); + } + }), + private: z + .string() + .min(1) + .transform(async (v) => { + try { + return await crypto.subtle.importKey( + "pkcs8", + Buffer.from(v, "base64"), + "Ed25519", + true, + ["sign"], + ); + } catch { + throw new Error( + "Private key at oidc.keys.private is invalid", + ); + } + }), + }) + .optional() + .transform(async (v, ctx) => { + if (!(v?.private && v?.public)) { + const { public_key, private_key } = + await User.generateKeys(); + + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `Keys are missing, please add the following to your config:\n\nkeys.public: ${chalk.gray(public_key)}\nkeys.private: ${chalk.gray(private_key)} + `, + }); } + + return v as Exclude; }), - private: z.string().transform(async (v) => { - try { - return await crypto.subtle.importKey( - "pkcs8", - Buffer.from(v, "base64"), - "Ed25519", - true, - ["sign"], - ); - } catch { - throw new Error( - `Private key at keys.private is invalid. Run the ${chalk.bold("generate-keys")} command to generate a new keypair`, - ); - } - }), - }), }), ); diff --git a/utils/init.ts b/utils/init.ts index 2749f83b..3a1fa502 100644 --- a/utils/init.ts +++ b/utils/init.ts @@ -1,5 +1,6 @@ import { getLogger } from "@logtape/logtape"; import chalk from "chalk"; +import { User } from "~/classes/database/user"; import type { Config } from "~/packages/config-manager"; export const checkConfig = async (config: Config) => { @@ -68,8 +69,15 @@ const checkFederationConfig = async (config: Config) => { const logger = getLogger("server"); if (!(config.instance.keys.public && config.instance.keys.private)) { - logger.fatal`The federation keys are not set in the config at instance.keys.public and instance.keys.private`; - logger.fatal`You can generate a keypair using the CLI command ${chalk.bold("generate-keys")}`; + logger.fatal`The federation keys are not set in the config`; + logger.fatal`Below are generated keys for you to copy in the config at instance.keys.public and instance.keys.private`; + + // Generate a key for them + const { public_key, private_key } = await User.generateKeys(); + + logger.fatal`Generated public key: ${chalk.gray(public_key)}`; + logger.fatal`Generated private key: ${chalk.gray(private_key)}`; + // Hang until Ctrl+C is pressed await Bun.sleep(Number.POSITIVE_INFINITY); }