changemaker.lite/api/dist/modules/email-templates/email-templates-admin.routes.js

272 lines
11 KiB
JavaScript

"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