Protected profiles: recovery email and Discord contacts with reset codes (Gmail SMTP, Discord relay)

This commit is contained in:
Jonathan Sykes
2026-10-15 17:28:10 +08:00
parent dbcee5d5f8
commit ca47528581
8 changed files with 477 additions and 6 deletions

View File

@@ -70,6 +70,7 @@ import QRCode from 'qrcode';
import { createYtdlpPool } from './ytdlp-pool.js';
import { createWarmQueue } from './warm-queue.js';
import { registerDeepSearchRoutes } from './deep-search.js';
import { registerProfileRecoveryRoutes } from './profile-recovery.js';
import { dirname, join as pathJoin } from 'node:path';
import { createRequestMonitor, registerRequestMonitorRoutes } from './request-monitor.js';
import { registerP2pAdminRoutes } from './p2p-admin.js';
@@ -1881,10 +1882,13 @@ app.get('/api/profile/info', async (c) => {
const name = (c.req.query('name') || '').trim().toLowerCase();
if (!name) return c.json({ ok: false, error: 'missing name' }, 400);
const row = await getProfile(name);
return c.json({ ok: true, exists: !!row, protected: !!(row && row.secretHash), kind: row ? row.secretKind : null },
return c.json({ ok: true, exists: !!row, protected: !!(row && row.secretHash), kind: row ? row.secretKind : null,
recovery: row && row.secretHash ? profileRecovery.channels(row) : null },
200, { 'Cache-Control': 'no-store' });
});
const profileRecovery = registerProfileRecoveryRoutes(app, { db: notesDb.db, getProfile, setProfileSecret, profileGate });
// POST /api/profile/secret
// Body: { name, current?, secret: <new password/key> | null, kind: 'password'|'key' }
// Adds, changes or (secret: null) removes protection. Changing or removing an