From 8c972dbabd0d93dbb053503b61853f57e69b8f12 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 8 Jan 2024 17:34:07 -0600 Subject: [PATCH] Actually implement Pleroma's configs API correctly (wow!) --- src/controllers/api/pleroma.ts | 66 ++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/src/controllers/api/pleroma.ts b/src/controllers/api/pleroma.ts index 91c6cc7c..e6709c9a 100644 --- a/src/controllers/api/pleroma.ts +++ b/src/controllers/api/pleroma.ts @@ -1,49 +1,71 @@ import { type AppController } from '@/app.ts'; +import { Conf } from '@/config.ts'; +import { decryptAdmin, encryptAdmin } from '@/crypto.ts'; import { z } from '@/deps.ts'; import { configSchema, elixirTupleSchema } from '@/schemas/pleroma-api.ts'; import { eventsDB } from '@/storages.ts'; import { createAdminEvent } from '@/utils/api.ts'; -import { Conf } from '@/config.ts'; +import { jsonSchema } from '@/schema.ts'; const frontendConfigController: AppController = async (c) => { const [event] = await eventsDB.filter([{ kinds: [30078], authors: [Conf.pubkey], - '#d': ['pub.ditto.frontendConfig'], + '#d': ['pub.ditto.pleroma.config'], limit: 1, }]); - if (event) { - const data = JSON.parse(event.content); - return c.json(data); - } + const configs = jsonSchema.pipe(z.array(configSchema)).parse( + event?.content ? await decryptAdmin(Conf.pubkey, event.content) : [], + ); - return c.json({}); + const frontendConfig = configs.find(({ group, key }) => group === ':pleroma' && key === ':frontend_configurations'); + + if (frontendConfig) { + const schema = elixirTupleSchema.transform(({ tuple }) => tuple).array(); + const data = schema.parse(frontendConfig.value).reduce>((result, [name, data]) => { + result[name.replace(/^:/, '')] = data; + return result; + }, {}); + return c.json(data); + } else { + return c.json({}); + } }; /** Pleroma admin config controller. */ const updateConfigController: AppController = async (c) => { - const json = await c.req.json(); - const { configs } = z.object({ configs: z.array(configSchema) }).parse(json); + const { pubkey } = Conf; - for (const { group, key, value } of configs) { - if (group === ':pleroma' && key === ':frontend_configurations') { - const schema = elixirTupleSchema.transform(({ tuple }) => tuple).array(); + const [event] = await eventsDB.filter([{ + kinds: [30078], + authors: [pubkey], + '#d': ['pub.ditto.pleroma.config'], + limit: 1, + }]); - const data = schema.parse(value).reduce>((result, [name, data]) => { - result[name.replace(/^:/, '')] = data; - return result; - }, {}); + const configs = jsonSchema.pipe(z.array(configSchema)).parse( + event?.content ? await decryptAdmin(pubkey, event.content) : [], + ); - await createAdminEvent({ - kind: 30078, - content: JSON.stringify(data), - tags: [['d', 'pub.ditto.frontendConfig']], - }, c); + const { configs: newConfigs } = z.object({ configs: z.array(configSchema) }).parse(await c.req.json()); + + for (const { group, key, value } of newConfigs) { + const index = configs.findIndex((c) => c.group === group && c.key === key); + if (index === -1) { + configs.push({ group, key, value }); + } else { + configs[index].value = value; } } - return c.json([]); + await createAdminEvent({ + kind: 30078, + content: await encryptAdmin(pubkey, JSON.stringify(configs)), + tags: [['d', 'pub.ditto.pleroma.config']], + }, c); + + return c.json({ configs: newConfigs, need_reboot: false }); }; export { frontendConfigController, updateConfigController };