feat: add settings GET/POST controller
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user