import { Router, Request, Response, NextFunction } from 'express'; import { campaignEmailsService } from './campaign-emails.service'; import { campaignsService } from '../campaigns/campaigns.service'; import { sendCampaignEmailSchema, trackMailtoSchema, listCampaignEmailsSchema, } from './campaign-emails.schemas'; import { validate } from '../../../middleware/validate'; import { authenticate } from '../../../middleware/auth.middleware'; import { requireRole } from '../../../middleware/rbac.middleware'; import { emailRateLimit } from '../../../middleware/rate-limit'; import { INFLUENCE_ROLES } from '../../../utils/roles'; // --- Public Routes (no auth) --- const publicRouter = Router(); // POST /api/campaigns/:slug/send-email publicRouter.post( '/:slug/send-email', emailRateLimit, validate(sendCampaignEmailSchema), async (req: Request, res: Response, next: NextFunction) => { try { const slug = req.params.slug as string; const senderIp = req.ip || req.socket.remoteAddress; const result = await campaignEmailsService.sendEmail(slug, req.body, senderIp); res.status(201).json(result); } catch (err) { next(err); } } ); // POST /api/campaigns/:slug/track-mailto publicRouter.post( '/:slug/track-mailto', emailRateLimit, validate(trackMailtoSchema), async (req: Request, res: Response, next: NextFunction) => { try { const slug = req.params.slug as string; const senderIp = req.ip || req.socket.remoteAddress; const result = await campaignEmailsService.trackMailto(slug, req.body, senderIp); res.status(201).json(result); } catch (err) { next(err); } } ); // --- Admin Routes (auth required) --- const adminRouter = Router(); adminRouter.use(authenticate); adminRouter.use(requireRole(...INFLUENCE_ROLES)); // GET /api/campaigns/:id/emails — requires ownership (SUPER_ADMIN bypasses) adminRouter.get( '/:id/emails', validate(listCampaignEmailsSchema, 'query'), async (req: Request, res: Response, next: NextFunction) => { try { const id = req.params.id as string; // Access check via campaignsService — throws 404 if not owned. await campaignsService.findById(id, req.user!); const result = await campaignEmailsService.listByCampaign(id, req.query as any); res.json(result); } catch (err) { next(err); } } ); // GET /api/campaigns/:id/email-stats — requires ownership (SUPER_ADMIN bypasses) adminRouter.get( '/:id/email-stats', async (req: Request, res: Response, next: NextFunction) => { try { const id = req.params.id as string; await campaignsService.findById(id, req.user!); const stats = await campaignEmailsService.getStats(id); res.json(stats); } catch (err) { next(err); } } ); export { publicRouter as campaignEmailsPublicRouter, adminRouter as campaignEmailsAdminRouter };