Ctrl K
ComunidadGuías…

scripts/member.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Getting back in, and getting somebody else in, from a terminal.
//
//   npm run member:list
//   npm run member:reset -- ada@example.com     new passphrase, printed once
//   npm run member:add   -- new@example.com "Their Name"
//
// The way back when the last passphrase is lost, short of erasing the database.
// It needs shell access, which is the point: the one door that does not open
// over HTTP.
//
// Cloudflare has no shell, so reach the same rows through D1 —
// `npx wrangler d1 execute whispers --remote --command "select email from
// members"` — or run this locally against the same Turso or Postgres URL.

import process from 'node:process';
import './../db.node.js';
import { add, list, resetPassphrase } from '../app/data/members.js';

const [command, ...rest] = process.argv.slice(2);

/**
 * Prints a member list, or says there is none.
 *
 * @param {{ email: string, name: string }[]} people
 * @returns {void}
 */
const show = (people) => {
  if (!people.length) {
    console.log('Nobody yet. The next visitor to /setup claims the site.');
    return;
  }
  for (const person of people) console.log(`  ${person.email.padEnd(32)} ${person.name}`);
};

if (command === 'list') {
  show(await list());
  process.exit(0);
}

if (command === 'reset') {
  const email = String(rest[0] ?? '').trim().toLowerCase();
  if (!email) {
    console.error('Which one?\n  npm run member:reset -- you@example.com');
    process.exit(1);
  }

  const people = await list();
  const person = people.find((row) => row.email === email);

  if (!person) {
    console.error(`No account for ${email}. There is:`);
    show(people);
    process.exit(1);
  }

  const secret = await resetPassphrase(person.id);
  console.log(`\n  ${person.name} <${person.email}>\n  ${secret}\n`);
  console.log('Shown once. It is stored only as a hash.');
  process.exit(0);
}

if (command === 'add') {
  const email = String(rest[0] ?? '').trim();
  const name = rest.slice(1).join(' ').trim();

  if (!email || !name) {
    console.error('Both are needed:\n  npm run member:add -- new@example.com "Their Name"');
    process.exit(1);
  }

  const result = await add({ email, name });
  if (!result.ok) {
    for (const [field, message] of Object.entries(result.errors)) {
      console.error(`  ${field}: ${message}`);
    }
    process.exit(1);
  }

  console.log(`\n  ${result.member.name} <${result.member.email}>\n  ${result.passphrase}\n`);
  console.log('Shown once. Send it to them.');
  process.exit(0);
}

console.error(
  'Usage:\n' +
    '  npm run member:list\n' +
    '  npm run member:reset -- you@example.com\n' +
    '  npm run member:add   -- new@example.com "Their Name"',
);
process.exit(1);