spb/drive Public
SPB Drive — self-hosted personal cloud drive (files, previews, sharing) on the MacLustr cluster.
JavaScript 82.7%
CSS 10.6%
Nunjucks 3.6%
Shell 1.8%
SQL 1.3%
1#!/usr/bin/env node2/**3 * ─────────────────────────────────────────────4 * SPB Drive — Personal Cloud Drive5 * ─────────────────────────────────────────────6 * Author : Simon-Pierre Boucher7 * Contact : contact@spboucher.ai8 * File : scripts/reset-password.mjs9 * Purpose : Break-glass local password reset (interactive, server-side only)10 * License : MIT © Simon-Pierre Boucher11 * ─────────────────────────────────────────────12 */1314import readline from 'node:readline';15import { resetPassword } from '../src/auth/password.mjs';16import { ensureDataDirs } from '../src/config.mjs';1718function ask(question, { hidden = false } = {}) {19 return new Promise((resolve) => {20 const rl = readline.createInterface({ input: process.stdin, output: process.stdout });21 if (hidden) {22 const orig = rl._writeToOutput.bind(rl);23 rl._writeToOutput = (s) => { if (s.includes(question)) orig(question); };24 rl.question(question, (answer) => {25 rl._writeToOutput = orig;26 process.stdout.write('\n');27 rl.close();28 resolve(answer);29 });30 } else {31 rl.question(question, (answer) => { rl.close(); resolve(answer); });32 }33 });34}3536if (!process.stdin.isTTY) {37 console.error('reset-password must be run interactively on the server.');38 process.exit(2);39}4041ensureDataDirs();42const pw1 = await ask('New SPB Drive password: ', { hidden: true });43if (!pw1 || pw1.length < 6) {44 console.error('Password must be at least 6 characters.');45 process.exit(1);46}47const pw2 = await ask('Repeat: ', { hidden: true });48if (pw1 !== pw2) {49 console.error('Passwords do not match.');50 process.exit(1);51}52await resetPassword(pw1);53console.log('✓ Password updated. Existing sessions remain valid — revoke them from Settings if needed.');54