From c24e1f42a694623ef12670a009032331e685488a Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 22 Feb 2024 11:39:11 -0600 Subject: [PATCH] Make Pleroma config more resilient to corrupted events --- src/controllers/api/pleroma.ts | 59 +++++++++++----------------------- src/schemas/pleroma-api.ts | 6 ++-- 2 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/controllers/api/pleroma.ts b/src/controllers/api/pleroma.ts index 6e4c026..f76df01 100644 --- a/src/controllers/api/pleroma.ts +++ b/src/controllers/api/pleroma.ts @@ -1,26 +1,14 @@ import { type AppController } from '@/app.ts'; import { Conf } from '@/config.ts'; import { z } from '@/deps.ts'; -import { configSchema, elixirTupleSchema } from '@/schemas/pleroma-api.ts'; +import { configSchema, elixirTupleSchema, type PleromaConfig } from '@/schemas/pleroma-api.ts'; import { AdminSigner } from '@/signers/AdminSigner.ts'; import { eventsDB } from '@/storages.ts'; import { createAdminEvent } from '@/utils/api.ts'; import { jsonSchema } from '@/schema.ts'; const frontendConfigController: AppController = async (c) => { - const { signal } = c.req.raw; - - const [event] = await eventsDB.query([{ - kinds: [30078], - authors: [Conf.pubkey], - '#d': ['pub.ditto.pleroma.config'], - limit: 1, - }], { signal }); - - const configs = jsonSchema.pipe(z.array(configSchema)).catch([]).parse( - event?.content ? await new AdminSigner().nip44.decrypt(Conf.pubkey, event.content) : '', - ); - + const configs = await getConfigs(c.req.raw.signal); const frontendConfig = configs.find(({ group, key }) => group === ':pleroma' && key === ':frontend_configurations'); if (frontendConfig) { @@ -36,39 +24,15 @@ const frontendConfigController: AppController = async (c) => { }; const configController: AppController = async (c) => { - const { pubkey } = Conf; - const { signal } = c.req.raw; - - const [event] = await eventsDB.query([{ - kinds: [30078], - authors: [pubkey], - '#d': ['pub.ditto.pleroma.config'], - limit: 1, - }], { signal }); - - const configs = jsonSchema.pipe(z.array(configSchema)).catch([]).parse( - event?.content ? await new AdminSigner().nip44.decrypt(pubkey, event.content) : '', - ); - + const configs = await getConfigs(c.req.raw.signal); return c.json({ configs, need_reboot: false }); }; /** Pleroma admin config controller. */ const updateConfigController: AppController = async (c) => { const { pubkey } = Conf; - const { signal } = c.req.raw; - - const [event] = await eventsDB.query([{ - kinds: [30078], - authors: [pubkey], - '#d': ['pub.ditto.pleroma.config'], - limit: 1, - }], { signal }); - - const configs = jsonSchema.pipe(z.array(configSchema)).catch([]).parse( - event?.content ? await await new AdminSigner().nip44.decrypt(pubkey, event.content) : '', - ); + const configs = await getConfigs(c.req.raw.signal); const { configs: newConfigs } = z.object({ configs: z.array(configSchema) }).parse(await c.req.json()); for (const { group, key, value } of newConfigs) { @@ -98,4 +62,19 @@ const pleromaAdminDeleteStatusController: AppController = async (c) => { return c.json({}); }; +async function getConfigs(signal: AbortSignal): Promise { + const { pubkey } = Conf; + + const [event] = await eventsDB.query([{ + kinds: [30078], + authors: [pubkey], + '#d': ['pub.ditto.pleroma.config'], + limit: 1, + }], { signal }); + + return jsonSchema.pipe(configSchema.array()).catch([]).parse( + await new AdminSigner().nip44.decrypt(Conf.pubkey, event.content).catch(() => ''), + ); +} + export { configController, frontendConfigController, pleromaAdminDeleteStatusController, updateConfigController }; diff --git a/src/schemas/pleroma-api.ts b/src/schemas/pleroma-api.ts index 839b442..7ccd87d 100644 --- a/src/schemas/pleroma-api.ts +++ b/src/schemas/pleroma-api.ts @@ -13,7 +13,7 @@ interface ElixirTuple { tuple: [string, ElixirValue]; } -interface Config { +interface PleromaConfig { group: string; key: string; value: ElixirValue; @@ -37,10 +37,10 @@ const elixirValueSchema: z.ZodType = z.union([ elixirTupleSchema, ]); -const configSchema: z.ZodType = z.object({ +const configSchema: z.ZodType = z.object({ group: z.string(), key: z.string(), value: elixirValueSchema, }); -export { type Config, configSchema, type ElixirTuple, elixirTupleSchema, type ElixirValue }; +export { configSchema, type ElixirTuple, elixirTupleSchema, type ElixirValue, type PleromaConfig };