"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = require("express"); const email_templates_service_1 = require("./email-templates.service"); const email_service_1 = require("../../services/email.service"); const validate_1 = require("../../middleware/validate"); const email_templates_schemas_1 = require("./email-templates.schemas"); const logger_1 = require("../../utils/logger"); const auth_middleware_1 = require("../../middleware/auth.middleware"); const rbac_middleware_1 = require("../../middleware/rbac.middleware"); const client_1 = require("@prisma/client"); const roles_1 = require("../../utils/roles"); const express_rate_limit_1 = __importDefault(require("express-rate-limit")); const rate_limit_redis_1 = __importDefault(require("rate-limit-redis")); const redis_1 = require("../../config/redis"); const seed_email_templates_1 = require("../../scripts/seed-email-templates"); const router = (0, express_1.Router)(); // All email template routes require authentication router.use(auth_middleware_1.authenticate); // All routes require broadcast admin role const requireBroadcastRole = (0, rbac_middleware_1.requireRole)(...roles_1.BROADCAST_ROLES); /** * List email templates * GET /email-templates */ router.get('/', requireBroadcastRole, (0, validate_1.validate)(email_templates_schemas_1.listEmailTemplatesSchema, 'query'), async (req, res) => { try { const result = await email_templates_service_1.emailTemplatesService.list(req.query); res.json(result); } catch (error) { logger_1.logger.error('Error listing email templates:', error); res.status(500).json({ error: 'Failed to list email templates' }); } }); /** * Get single email template * GET /email-templates/:id */ router.get('/:id', requireBroadcastRole, async (req, res) => { try { const template = await email_templates_service_1.emailTemplatesService.getById(req.params.id); res.json(template); } catch (error) { if (error instanceof Error && error.message === 'Template not found') { res.status(404).json({ error: 'Template not found' }); return; } logger_1.logger.error('Error getting email template:', error); res.status(500).json({ error: 'Failed to get email template' }); } }); /** * Create email template * POST /email-templates */ router.post('/', requireBroadcastRole, (0, validate_1.validate)(email_templates_schemas_1.createEmailTemplateSchema), async (req, res) => { try { const template = await email_templates_service_1.emailTemplatesService.create(req.body, req.user.id); res.status(201).json(template); } catch (error) { if (error instanceof Error && error.message.includes('already exists')) { res.status(409).json({ error: error.message }); return; } if (error instanceof Error && error.message.includes('validation failed')) { res.status(400).json({ error: error.message }); return; } logger_1.logger.error('Error creating email template:', error); res.status(500).json({ error: 'Failed to create email template' }); } }); /** * Update email template * PUT /email-templates/:id */ router.put('/:id', requireBroadcastRole, (0, validate_1.validate)(email_templates_schemas_1.updateEmailTemplateSchema), async (req, res) => { try { const template = await email_templates_service_1.emailTemplatesService.update(req.params.id, req.body, req.user.id); // Clear cache so changes take effect immediately email_service_1.emailService.clearDatabaseCache(template.key); logger_1.logger.info(`Cleared template cache for: ${template.key}`); res.json(template); } catch (error) { if (error instanceof Error && error.message === 'Template not found') { res.status(404).json({ error: 'Template not found' }); return; } if (error instanceof Error && error.message.includes('validation failed')) { res.status(400).json({ error: error.message }); return; } logger_1.logger.error('Error updating email template:', error); res.status(500).json({ error: 'Failed to update email template' }); } }); /** * Delete email template * DELETE /email-templates/:id */ router.delete('/:id', requireBroadcastRole, async (req, res) => { try { // Fetch template before deleting to get the key const template = await email_templates_service_1.emailTemplatesService.getById(req.params.id); await email_templates_service_1.emailTemplatesService.delete(req.params.id); // Clear cache for deleted template email_service_1.emailService.clearDatabaseCache(template.key); logger_1.logger.info(`Cleared template cache for deleted template: ${template.key}`); res.status(204).send(); } catch (error) { if (error instanceof Error && error.message === 'Template not found') { res.status(404).json({ error: 'Template not found' }); return; } if (error instanceof Error && error.message.includes('Cannot delete system templates')) { res.status(403).json({ error: error.message }); return; } logger_1.logger.error('Error deleting email template:', error); res.status(500).json({ error: 'Failed to delete email template' }); } }); /** * Get version history * GET /email-templates/:id/versions */ router.get('/:id/versions', requireBroadcastRole, async (req, res) => { try { const versions = await email_templates_service_1.emailTemplatesService.getVersions(req.params.id); res.json(versions); } catch (error) { logger_1.logger.error('Error getting template versions:', error); res.status(500).json({ error: 'Failed to get template versions' }); } }); /** * Get specific version * GET /email-templates/:id/versions/:versionNumber */ router.get('/:id/versions/:versionNumber', requireBroadcastRole, async (req, res) => { try { const version = await email_templates_service_1.emailTemplatesService.getVersion(req.params.id, parseInt(req.params.versionNumber, 10)); res.json(version); } catch (error) { if (error instanceof Error && error.message === 'Version not found') { res.status(404).json({ error: 'Version not found' }); return; } logger_1.logger.error('Error getting template version:', error); res.status(500).json({ error: 'Failed to get template version' }); } }); /** * Rollback to previous version * POST /email-templates/:id/rollback */ router.post('/:id/rollback', requireBroadcastRole, (0, validate_1.validate)(email_templates_schemas_1.rollbackToVersionSchema), async (req, res) => { try { const template = await email_templates_service_1.emailTemplatesService.rollbackToVersion(req.params.id, req.body, req.user.id); res.json(template); } catch (error) { if (error instanceof Error && (error.message === 'Template not found' || error.message === 'Version not found')) { res.status(404).json({ error: error.message }); return; } logger_1.logger.error('Error rolling back template:', error); res.status(500).json({ error: 'Failed to rollback template' }); } }); /** * Validate template syntax * POST /email-templates/validate */ router.post('/validate', requireBroadcastRole, (0, validate_1.validate)(email_templates_schemas_1.validateTemplateSchema), async (req, res) => { try { const result = email_templates_service_1.emailTemplatesService.validateTemplate(req.body); res.json(result); } catch (error) { logger_1.logger.error('Error validating template:', error); res.status(500).json({ error: 'Failed to validate template' }); } }); /** * Send test email * POST /email-templates/:id/test * Rate limited to 10 per 15 minutes per user */ router.post('/:id/test', requireBroadcastRole, (0, express_rate_limit_1.default)({ windowMs: 15 * 60 * 1000, // 15 minutes max: 10, standardHeaders: true, legacyHeaders: false, store: new rate_limit_redis_1.default({ sendCommand: (command, ...args) => redis_1.redis.call(command, ...args), prefix: 'rl:email-template-test:', }), keyGenerator: (req) => req.user.id, }), (0, validate_1.validate)(email_templates_schemas_1.sendTestEmailSchema), async (req, res) => { try { const result = await email_templates_service_1.emailTemplatesService.sendTestEmail(req.params.id, req.body, req.user.id); res.json(result); } catch (error) { if (error instanceof Error && error.message === 'Template not found') { res.status(404).json({ error: 'Template not found' }); return; } logger_1.logger.error('Error sending test email:', error); res.status(500).json({ error: 'Failed to send test email' }); } }); /** * Get test logs for template * GET /email-templates/:id/test-logs */ router.get('/:id/test-logs', requireBroadcastRole, async (req, res) => { try { const limit = req.query.limit ? parseInt(req.query.limit, 10) : 10; const logs = await email_templates_service_1.emailTemplatesService.getTestLogs(req.params.id, limit); res.json(logs); } catch (error) { logger_1.logger.error('Error getting test logs:', error); res.status(500).json({ error: 'Failed to get test logs' }); } }); /** * Seed templates from filesystem (SUPER_ADMIN only) * POST /email-templates/seed */ router.post('/seed', (0, rbac_middleware_1.requireRole)(client_1.UserRole.SUPER_ADMIN), async (req, res) => { try { await (0, seed_email_templates_1.seedEmailTemplates)(); logger_1.logger.info('Email templates seeded via API'); res.json({ success: true, message: 'Templates seeded successfully' }); } catch (error) { logger_1.logger.error('Error seeding templates:', error); res.status(500).json({ error: 'Failed to seed templates' }); } }); /** * Clear template cache (SUPER_ADMIN only) * POST /email-templates/clear-cache * Body: { key?: string } - Optional template key to clear. If not provided, clears all. */ router.post('/clear-cache', (0, rbac_middleware_1.requireRole)(client_1.UserRole.SUPER_ADMIN), async (req, res) => { try { const { key } = req.body; email_service_1.emailService.clearDatabaseCache(key); logger_1.logger.info(`Template cache cleared${key ? ` for: ${key}` : ' (all)'}`); res.json({ success: true, cleared: key || 'all' }); } catch (error) { logger_1.logger.error('Error clearing template cache:', error); res.status(500).json({ error: 'Failed to clear template cache' }); } }); exports.default = router; //# sourceMappingURL=email-templates-admin.routes.js.map