Files
debian af66d926e7 fase(27): advanced enterprise features complete
- 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>
2026-03-08 13:49:14 -04:00

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;