"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.siteSettingsRouter = void 0; const express_1 = require("express"); const client_1 = require("@prisma/client"); const settings_service_1 = require("./settings.service"); const settings_schemas_1 = require("./settings.schemas"); const validate_1 = require("../../middleware/validate"); const auth_middleware_1 = require("../../middleware/auth.middleware"); const rbac_middleware_1 = require("../../middleware/rbac.middleware"); const email_service_1 = require("../../services/email.service"); const gitea_client_1 = require("../../services/gitea.client"); const gancio_settings_sync_service_1 = require("../../services/gancio-settings-sync.service"); const auto_upgrade_service_1 = require("../../services/auto-upgrade.service"); const header_builder_service_1 = require("../docs/header-builder.service"); const mkdocs_config_service_1 = require("../docs/mkdocs-config.service"); const logger_1 = require("../../utils/logger"); const router = (0, express_1.Router)(); exports.siteSettingsRouter = router; // GET /api/settings — public (needed by login page + public pages), strips SMTP credentials router.get('/', async (_req, res, next) => { try { const settings = await settings_service_1.siteSettingsService.getPublic(); res.json(settings); } catch (err) { next(err); } }); // GET /api/settings/admin — SUPER_ADMIN only, returns full settings including SMTP router.get('/admin', auth_middleware_1.authenticate, (0, rbac_middleware_1.requireRole)(client_1.UserRole.SUPER_ADMIN), async (_req, res, next) => { try { const settings = await settings_service_1.siteSettingsService.getEffective(); res.set('Cache-Control', 'no-store'); res.json(settings); } catch (err) { next(err); } }); // POST /api/settings/email/test-connection — SUPER_ADMIN only router.post('/email/test-connection', auth_middleware_1.authenticate, (0, rbac_middleware_1.requireRole)(client_1.UserRole.SUPER_ADMIN), async (_req, res, next) => { try { const success = await email_service_1.emailService.testConnection(); res.json({ success, message: success ? 'SMTP connection verified' : 'SMTP connection failed' }); } catch (err) { next(err); } }); // POST /api/settings/email/test-send — SUPER_ADMIN only router.post('/email/test-send', auth_middleware_1.authenticate, (0, rbac_middleware_1.requireRole)(client_1.UserRole.SUPER_ADMIN), async (req, res, next) => { try { const { to } = req.body; const settings = await settings_service_1.siteSettingsService.get(); const recipient = to || settings.testEmailRecipient || 'admin@cmlite.org'; const result = await email_service_1.emailService.sendEmail({ to: recipient, subject: 'Changemaker Lite — Test Email', html: `
This email confirms that your SMTP configuration is working correctly.
Sent at: ${new Date().toISOString()}
`, text: `SMTP Test Successful\n\nThis email confirms that your SMTP configuration is working correctly.\n\nSent at: ${new Date().toISOString()}`, }); res.json({ success: result.success, messageId: result.messageId, testMode: result.testMode, recipient, }); } catch (err) { next(err); } }); // PUT /api/settings — SUPER_ADMIN only router.put('/', auth_middleware_1.authenticate, (0, rbac_middleware_1.requireRole)(client_1.UserRole.SUPER_ADMIN), (0, validate_1.validate)(settings_schemas_1.updateSiteSettingsSchema), async (req, res, next) => { try { const settings = await settings_service_1.siteSettingsService.update(req.body); // If SMTP-related fields were updated, rebuild the transporter const smtpFields = ['smtpHost', 'smtpPort', 'smtpUser', 'smtpPass', 'smtpFromAddress', 'smtpActiveProvider', 'emailTestMode', 'testEmailRecipient']; const hasSmtpChanges = smtpFields.some((f) => f in req.body); if (hasSmtpChanges) { await email_service_1.emailService.rebuildTransporter(); } // If Gitea-related fields were updated, invalidate the config cache const giteaFields = ['enableDocsComments', 'giteaApiToken', 'giteaCommentsRepoOwner', 'giteaCommentsRepoName', 'giteaOauthClientId', 'giteaOauthClientSecret']; if (giteaFields.some((f) => f in req.body)) { gitea_client_1.giteaClient.clearConfigCache(); } // If Gancio-relevant fields were updated, sync to Gancio (fire-and-forget) if (gancio_settings_sync_service_1.gancioSettingsSyncService.hasGancioChanges(req.body)) { gancio_settings_sync_service_1.gancioSettingsSyncService.syncChanged(req.body).catch(() => { }); } // If auto-upgrade settings changed, restart the scheduler const autoUpgradeFields = ['enableAutoUpgrade', 'autoUpgradeSchedule', 'autoUpgradePullServices']; if (autoUpgradeFields.some((f) => f in req.body)) { auto_upgrade_service_1.autoUpgradeService.start().catch(() => { }); } // If navConfig or theme colors changed, trigger MkDocs header rebuild + docs build const headerTriggerFields = [ 'navConfig', 'publicHeaderGradient', 'publicColorBgBase', 'publicColorBgContainer', 'enableInfluence', 'enableMap', 'enableMediaFeatures', 'enablePayments', 'enableEvents', 'enableMeetingPlanner', 'enableTicketedEvents', 'enableSocial', 'enableMeet', 'enableLandingPages', ]; if (headerTriggerFields.some((f) => f in req.body)) { if ('navConfig' in req.body) { gancio_settings_sync_service_1.gancioSettingsSyncService.syncAll().catch(() => { }); } // Regenerate MkDocs header from navConfig, then trigger a docs build const navItems = settings.navConfig?.items; if (navItems?.length) { header_builder_service_1.headerBuilderService.regenerateFromNavConfig(navItems, { publicHeaderGradient: settings.publicHeaderGradient ?? undefined, publicColorBgBase: settings.publicColorBgBase ?? undefined, publicColorBgContainer: settings.publicColorBgContainer ?? undefined, enableInfluence: settings.enableInfluence, enableMap: settings.enableMap, enableMediaFeatures: settings.enableMediaFeatures, enablePayments: settings.enablePayments, enableEvents: settings.enableEvents, enableMeetingPlanner: settings.enableMeetingPlanner, enableTicketedEvents: settings.enableTicketedEvents, enableSocial: settings.enableSocial, enableMeet: settings.enableMeet, enableLandingPages: settings.enableLandingPages, }).then(() => { // Fire-and-forget docs build so the static site picks up the new header mkdocs_config_service_1.mkdocsConfigService.triggerBuild() .then((result) => { if (result.success) { logger_1.logger.info(`MkDocs rebuild after header change completed in ${result.duration}ms`); } else { logger_1.logger.warn(`MkDocs rebuild after header change failed: ${result.output}`); } }) .catch(() => { }); }).catch(() => { }); } } res.json(settings); } catch (err) { next(err); } }); //# sourceMappingURL=settings.routes.js.map