diff --git a/index.js b/index.js index 15fa500..eec2615 100644 --- a/index.js +++ b/index.js @@ -969,6 +969,9 @@ export default class ActivityPubEndpoint { Indiekit.addCollection("ap_filters"); Indiekit.addCollection("ap_filter_keywords"); + // Plugin settings (single document, admin UI at /admin/settings) + Indiekit.addCollection("ap_settings"); + // Store collection references (posts resolved lazily) const indiekitCollections = Indiekit.collections; this._collections = { diff --git a/lib/settings.js b/lib/settings.js new file mode 100644 index 0000000..cd10693 --- /dev/null +++ b/lib/settings.js @@ -0,0 +1,72 @@ +/** + * Plugin settings — stored in ap_settings MongoDB collection. + * + * getSettings() merges DB values over hardcoded defaults. + * Consumers call this once per operation (or use cached middleware for hot paths). + */ + +export const DEFAULTS = { + // Instance & Client API + instanceLanguages: ["en"], + maxCharacters: 5000, + maxMediaAttachments: 4, + defaultVisibility: "public", + defaultLanguage: "en", + + // Federation & Delivery + timelineRetention: 1000, + notificationRetentionDays: 30, + activityRetentionDays: 90, + replyChainDepth: 5, + broadcastBatchSize: 25, + broadcastBatchDelay: 5000, + parallelWorkers: 5, + logLevel: "warning", + + // Migration + refollowBatchSize: 10, + refollowDelay: 3000, + refollowBatchDelay: 30000, + + // Security + refreshTokenTtlDays: 90, +}; + +/** + * Load settings from MongoDB, merged over defaults. + * + * @param {Map|object} collections - Indiekit collections map or plain object with ap_settings + * @returns {Promise} Settings object with all keys guaranteed present + */ +export async function getSettings(collections) { + const col = collections?.get + ? collections.get("ap_settings") + : collections?.ap_settings; + if (!col) return { ...DEFAULTS }; + + try { + const doc = await col.findOne({}); + return { ...DEFAULTS, ...(doc?.settings || {}) }; + } catch { + return { ...DEFAULTS }; + } +} + +/** + * Save settings to MongoDB. + * + * @param {Map|object} collections - Indiekit collections map or plain object + * @param {object} settings - Settings object (all keys from DEFAULTS) + */ +export async function saveSettings(collections, settings) { + const col = collections?.get + ? collections.get("ap_settings") + : collections?.ap_settings; + if (!col) return; + + await col.updateOne( + {}, + { $set: { settings, updatedAt: new Date().toISOString() } }, + { upsert: true }, + ); +}