|
@@ -2,6 +2,7 @@ import { mkdirSync } from 'node:fs';
|
|
|
import crypto from 'node:crypto';
|
|
import crypto from 'node:crypto';
|
|
|
import path from 'node:path';
|
|
import path from 'node:path';
|
|
|
import { DatabaseSync } from 'node:sqlite';
|
|
import { DatabaseSync } from 'node:sqlite';
|
|
|
|
|
+import { dkimPublicFromPrivateKey } from './dkim.js';
|
|
|
|
|
|
|
|
let db;
|
|
let db;
|
|
|
let secretKey = '';
|
|
let secretKey = '';
|
|
@@ -108,6 +109,7 @@ export function initDatabase(dataDir, secret = '') {
|
|
|
CREATE INDEX IF NOT EXISTS idx_domains_user_id ON domains(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_domains_user_id ON domains(user_id);
|
|
|
CREATE INDEX IF NOT EXISTS idx_events_user_id ON send_events(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_events_user_id ON send_events(user_id);
|
|
|
`);
|
|
`);
|
|
|
|
|
+ normalizeDkimPublicKeys();
|
|
|
return db;
|
|
return db;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -590,6 +592,21 @@ function ensureColumn(table, column, definition) {
|
|
|
if (!columnExists(table, column)) requireDb().exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
if (!columnExists(table, column)) requireDb().exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function normalizeDkimPublicKeys() {
|
|
|
|
|
+ if (!tableExists('domains') || !columnExists('domains', 'dkim_private') || !columnExists('domains', 'dkim_public')) return;
|
|
|
|
|
+ const rows = requireDb().prepare('SELECT id, dkim_public, dkim_private FROM domains').all();
|
|
|
|
|
+ const update = requireDb().prepare('UPDATE domains SET dkim_public = ?, updated_at = ? WHERE id = ?');
|
|
|
|
|
+ for (const row of rows) {
|
|
|
|
|
+ if (!row.dkim_private) continue;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const publicKey = dkimPublicFromPrivateKey(row.dkim_private);
|
|
|
|
|
+ if (publicKey && publicKey !== row.dkim_public) update.run(publicKey, now(), row.id);
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ // Leave legacy or malformed rows untouched; rotating DKIM from the UI can repair them.
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function publicUser(row) {
|
|
function publicUser(row) {
|
|
|
if (!row) return null;
|
|
if (!row) return null;
|
|
|
return {
|
|
return {
|