#!/usr/bin/env node /** * ───────────────────────────────────────────── * SPB Drive — Personal Cloud Drive * ───────────────────────────────────────────── * Author : Simon-Pierre Boucher * Contact : contact@spboucher.ai * File : scripts/reset-password.mjs * Purpose : Break-glass local password reset (interactive, server-side only) * License : MIT © Simon-Pierre Boucher * ───────────────────────────────────────────── */ import readline from 'node:readline'; import { resetPassword } from '../src/auth/password.mjs'; import { ensureDataDirs } from '../src/config.mjs'; function ask(question, { hidden = false } = {}) { return new Promise((resolve) => { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); if (hidden) { const orig = rl._writeToOutput.bind(rl); rl._writeToOutput = (s) => { if (s.includes(question)) orig(question); }; rl.question(question, (answer) => { rl._writeToOutput = orig; process.stdout.write('\n'); rl.close(); resolve(answer); }); } else { rl.question(question, (answer) => { rl.close(); resolve(answer); }); } }); } if (!process.stdin.isTTY) { console.error('reset-password must be run interactively on the server.'); process.exit(2); } ensureDataDirs(); const pw1 = await ask('New SPB Drive password: ', { hidden: true }); if (!pw1 || pw1.length < 6) { console.error('Password must be at least 6 characters.'); process.exit(1); } const pw2 = await ask('Repeat: ', { hidden: true }); if (pw1 !== pw2) { console.error('Passwords do not match.'); process.exit(1); } await resetPassword(pw1); console.log('✓ Password updated. Existing sessions remain valid — revoke them from Settings if needed.');