feat: add settings GET/POST controller

This commit is contained in:
Ricardo
2026-03-31 21:37:36 +02:00
parent 2721249ca3
commit 01549a085a
+92
View File
@@ -0,0 +1,92 @@
/**
* Settings controller — admin page for ActivityPub plugin configuration.
*
* GET: loads settings from ap_settings, renders form with defaults
* POST: validates, saves settings, redirects with success message
*/
import { getSettings, saveSettings, DEFAULTS } from "../settings.js";
import { getToken, validateToken } from "../csrf.js";
export function settingsGetController(mountPath) {
return async (request, response, next) => {
try {
const { application } = request.app.locals;
const settings = await getSettings(application.collections);
response.render("activitypub-settings", {
title: response.locals.__("activitypub.settings.title"),
settings,
defaults: DEFAULTS,
mountPath,
saved: request.query.saved === "true",
csrfToken: getToken(request.session),
});
} catch (error) {
next(error);
}
};
}
export function settingsPostController(mountPath) {
return async (request, response, next) => {
try {
if (!validateToken(request)) {
return response.status(403).render("error", {
title: "Error",
content: "Invalid CSRF token",
});
}
const { application } = request.app.locals;
const body = request.body;
const settings = {
// Instance & Client API
instanceLanguages: (body.instanceLanguages || "en")
.split(",")
.map((s) => s.trim())
.filter(Boolean),
maxCharacters:
parseInt(body.maxCharacters, 10) || DEFAULTS.maxCharacters,
maxMediaAttachments:
parseInt(body.maxMediaAttachments, 10) || DEFAULTS.maxMediaAttachments,
defaultVisibility: body.defaultVisibility || DEFAULTS.defaultVisibility,
defaultLanguage: (body.defaultLanguage || DEFAULTS.defaultLanguage).trim(),
// Federation & Delivery
timelineRetention: parseInt(body.timelineRetention, 10) || 0,
notificationRetentionDays:
parseInt(body.notificationRetentionDays, 10) || 0,
activityRetentionDays:
parseInt(body.activityRetentionDays, 10) || 0,
replyChainDepth:
parseInt(body.replyChainDepth, 10) || DEFAULTS.replyChainDepth,
broadcastBatchSize:
parseInt(body.broadcastBatchSize, 10) || DEFAULTS.broadcastBatchSize,
broadcastBatchDelay:
parseInt(body.broadcastBatchDelay, 10) || DEFAULTS.broadcastBatchDelay,
parallelWorkers:
parseInt(body.parallelWorkers, 10) || DEFAULTS.parallelWorkers,
logLevel: body.logLevel || DEFAULTS.logLevel,
// Migration
refollowBatchSize:
parseInt(body.refollowBatchSize, 10) || DEFAULTS.refollowBatchSize,
refollowDelay:
parseInt(body.refollowDelay, 10) || DEFAULTS.refollowDelay,
refollowBatchDelay:
parseInt(body.refollowBatchDelay, 10) || DEFAULTS.refollowBatchDelay,
// Security
refreshTokenTtlDays:
parseInt(body.refreshTokenTtlDays, 10) || DEFAULTS.refreshTokenTtlDays,
};
await saveSettings(application.collections, settings);
response.redirect(`${mountPath}/admin/settings?saved=true`);
} catch (error) {
next(error);
}
};
}