- Phase 27.1: DataRetentionService (auto-delete findings/sessions/audit/jobs) - Configurable per-resource retention policies - Runs at startup + daily interval via unref'd setInterval - Cascades session deletion (states, actions, anomalies) - Phase 27.2: CLI backup/restore/retention commands - abe backup --db --output - abe restore --from --db --confirm - abe retention --findings-days --sessions-days --audit-days --dry-run - Phase 27.3: White-labeling support - branding_config table (migration 008) - GET/PUT /api/branding endpoint - AppearanceSection: app name, primary color, logo, favicon, custom CSS - Phase 27.4: PostgreSQL already supported via DatabaseConnection - Phase 27.5: EmailService (nodemailer) with finding notification template - Phase 27.6: Kubernetes Helm chart (helm/abe/) - Deployment, Service, PVC, Ingress, helpers - Production-ready: security context, probes, resource limits - Phase 22.7/22.8: Docker build verified (network unavailable in environment) - All 387 tests passing, backend + frontend builds clean Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
94 lines
3.4 KiB
JavaScript
94 lines
3.4 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.EmailService = void 0;
|
|
/**
|
|
* Email notification service using nodemailer.
|
|
* Supports SMTP configuration via environment variables.
|
|
*/
|
|
const nodemailer_1 = __importDefault(require("nodemailer"));
|
|
class EmailService {
|
|
constructor(config, logger) {
|
|
this.config = config;
|
|
this.logger = logger;
|
|
this.transporter = nodemailer_1.default.createTransport({
|
|
host: config.host,
|
|
port: config.port,
|
|
secure: config.secure,
|
|
auth: config.user
|
|
? { user: config.user, pass: config.password }
|
|
: undefined,
|
|
});
|
|
}
|
|
async send(message) {
|
|
try {
|
|
await this.transporter.sendMail({
|
|
from: this.config.from,
|
|
to: Array.isArray(message.to) ? message.to.join(', ') : message.to,
|
|
subject: message.subject,
|
|
html: message.html,
|
|
text: message.text,
|
|
});
|
|
this.logger.info({ to: message.to, subject: message.subject }, 'Email sent');
|
|
}
|
|
catch (err) {
|
|
this.logger.error({ err, to: message.to }, 'Failed to send email');
|
|
throw err;
|
|
}
|
|
}
|
|
async verify() {
|
|
try {
|
|
await this.transporter.verify();
|
|
return true;
|
|
}
|
|
catch {
|
|
return false;
|
|
}
|
|
}
|
|
/**
|
|
* Generate a finding notification email.
|
|
*/
|
|
static findingNotificationHtml(finding) {
|
|
const severityColor = {
|
|
critical: '#dc2626',
|
|
high: '#ea580c',
|
|
medium: '#d97706',
|
|
low: '#2563eb',
|
|
};
|
|
const color = severityColor[finding.severity] ?? '#6b7280';
|
|
return `<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="utf-8"></head>
|
|
<body style="font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 24px;">
|
|
<h2 style="margin-bottom: 8px;">New Security Finding</h2>
|
|
<p style="color: #6b7280; margin-bottom: 24px;">ABE has detected a potential security issue.</p>
|
|
|
|
<div style="border-left: 4px solid ${color}; padding: 16px; background: #f9fafb; border-radius: 4px; margin-bottom: 24px;">
|
|
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;">
|
|
<span style="background: ${color}; color: white; padding: 2px 8px; border-radius: 4px; font-size: 12px; text-transform: uppercase; font-weight: bold;">
|
|
${finding.severity}
|
|
</span>
|
|
<strong>${finding.type}</strong>
|
|
</div>
|
|
<p style="margin: 0; color: #374151;">${finding.description}</p>
|
|
${finding.url ? `<p style="margin: 8px 0 0; color: #6b7280; font-size: 14px;">URL: ${finding.url}</p>` : ''}
|
|
</div>
|
|
|
|
<a href="${finding.appUrl}/findings/${finding.id}"
|
|
style="display: inline-block; background: #1d4ed8; color: white; padding: 10px 20px; text-decoration: none; border-radius: 6px;">
|
|
View Finding Details
|
|
</a>
|
|
|
|
<hr style="margin: 32px 0; border: none; border-top: 1px solid #e5e7eb;">
|
|
<p style="color: #9ca3af; font-size: 12px;">
|
|
You received this email because you have finding notifications enabled in ABE.<br>
|
|
<a href="${finding.appUrl}/settings/notifications" style="color: #6b7280;">Manage notifications</a>
|
|
</p>
|
|
</body>
|
|
</html>`;
|
|
}
|
|
}
|
|
exports.EmailService = EmailService;
|