Make Pleroma config more resilient to corrupted events
This commit is contained in:
parent
40c7f8b093
commit
c24e1f42a6
|
@ -1,26 +1,14 @@
|
||||||
import { type AppController } from '@/app.ts';
|
import { type AppController } from '@/app.ts';
|
||||||
import { Conf } from '@/config.ts';
|
import { Conf } from '@/config.ts';
|
||||||
import { z } from '@/deps.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 { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||||
import { eventsDB } from '@/storages.ts';
|
import { eventsDB } from '@/storages.ts';
|
||||||
import { createAdminEvent } from '@/utils/api.ts';
|
import { createAdminEvent } from '@/utils/api.ts';
|
||||||
import { jsonSchema } from '@/schema.ts';
|
import { jsonSchema } from '@/schema.ts';
|
||||||
|
|
||||||
const frontendConfigController: AppController = async (c) => {
|
const frontendConfigController: AppController = async (c) => {
|
||||||
const { signal } = c.req.raw;
|
const configs = await getConfigs(c.req.raw.signal);
|
||||||
|
|
||||||
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 frontendConfig = configs.find(({ group, key }) => group === ':pleroma' && key === ':frontend_configurations');
|
const frontendConfig = configs.find(({ group, key }) => group === ':pleroma' && key === ':frontend_configurations');
|
||||||
|
|
||||||
if (frontendConfig) {
|
if (frontendConfig) {
|
||||||
|
@ -36,39 +24,15 @@ const frontendConfigController: AppController = async (c) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const configController: AppController = async (c) => {
|
const configController: AppController = async (c) => {
|
||||||
const { pubkey } = Conf;
|
const configs = await getConfigs(c.req.raw.signal);
|
||||||
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) : '',
|
|
||||||
);
|
|
||||||
|
|
||||||
return c.json({ configs, need_reboot: false });
|
return c.json({ configs, need_reboot: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Pleroma admin config controller. */
|
/** Pleroma admin config controller. */
|
||||||
const updateConfigController: AppController = async (c) => {
|
const updateConfigController: AppController = async (c) => {
|
||||||
const { pubkey } = Conf;
|
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());
|
const { configs: newConfigs } = z.object({ configs: z.array(configSchema) }).parse(await c.req.json());
|
||||||
|
|
||||||
for (const { group, key, value } of newConfigs) {
|
for (const { group, key, value } of newConfigs) {
|
||||||
|
@ -98,4 +62,19 @@ const pleromaAdminDeleteStatusController: AppController = async (c) => {
|
||||||
return c.json({});
|
return c.json({});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function getConfigs(signal: AbortSignal): Promise<PleromaConfig[]> {
|
||||||
|
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 };
|
export { configController, frontendConfigController, pleromaAdminDeleteStatusController, updateConfigController };
|
||||||
|
|
|
@ -13,7 +13,7 @@ interface ElixirTuple {
|
||||||
tuple: [string, ElixirValue];
|
tuple: [string, ElixirValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Config {
|
interface PleromaConfig {
|
||||||
group: string;
|
group: string;
|
||||||
key: string;
|
key: string;
|
||||||
value: ElixirValue;
|
value: ElixirValue;
|
||||||
|
@ -37,10 +37,10 @@ const elixirValueSchema: z.ZodType<ElixirValue> = z.union([
|
||||||
elixirTupleSchema,
|
elixirTupleSchema,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const configSchema: z.ZodType<Config> = z.object({
|
const configSchema: z.ZodType<PleromaConfig> = z.object({
|
||||||
group: z.string(),
|
group: z.string(),
|
||||||
key: z.string(),
|
key: z.string(),
|
||||||
value: elixirValueSchema,
|
value: elixirValueSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
export { type Config, configSchema, type ElixirTuple, elixirTupleSchema, type ElixirValue };
|
export { configSchema, type ElixirTuple, elixirTupleSchema, type ElixirValue, type PleromaConfig };
|
||||||
|
|
Loading…
Reference in New Issue