/** * Da o quita el rol de administrador. * * npm run db:admin # quién administra ahora * npm run db:admin -- hola@senzapaura.es # se lo da * npm run db:admin -- hola@… --crear # y crea la cuenta si no existe * npm run db:admin -- hola@… --quitar # se lo quita * * Es un script y no una pantalla del panel a propósito: el primer administrador * no puede nombrarse desde un panel al que todavía no puede entrar nadie. Y * mientras administre una sola persona, una pantalla para gestionar permisos * sería mantener un sistema de permisos para un usuario. * * Por defecto **no crea la cuenta**: se le da el rol a alguien que ya ha entrado * alguna vez, y así el permiso no puede quedarse esperando en una dirección mal * escrita. `--crear` es para el arranque en frío —una base recién puesta donde * todavía no ha entrado nadie—, y por eso hay que pedirlo: escribir mal el * correo con `--crear` da de alta una cuenta administradora que no es de nadie. */ import pg from 'pg'; const argumentos = process.argv.slice(2); const quitar = argumentos.includes('--quitar'); const crear = argumentos.includes('--crear'); const email = argumentos .find((a) => !a.startsWith('--')) ?.trim() .toLowerCase(); const c = new pg.Client({ connectionString: process.env.DATABASE_URL, query_timeout: 15_000 }); await c.connect(); if (!email) { const { rows } = await c.query( `select email, ultimo_acceso_en from usuario where rol = 'admin' order by email` ); if (rows.length === 0) { console.log('No administra nadie.'); console.log('Para dárselo a alguien: npm run db:admin -- correo@ejemplo.es'); } else { console.log(`Administran ${rows.length}:`); for (const f of rows) { const visto = f.ultimo_acceso_en ? f.ultimo_acceso_en.toISOString().slice(0, 10) : 'no ha entrado'; console.log(` ${f.email.padEnd(34)} último acceso ${visto}`); } } await c.end(); process.exit(0); } const { rows } = await c.query( `update usuario set rol = $2 where email = $1 returning email, rol`, [email, quitar ? 'persona' : 'admin'] ); if (rows.length === 0) { if (quitar) { console.log(`No hay ninguna cuenta con «${email}», así que no administra.`); await c.end(); process.exit(0); } if (!crear) { console.log(`No hay ninguna cuenta con «${email}».`); console.log('Tiene que haber entrado al menos una vez para poder darle el rol,'); console.log('o pásale --crear si es el primer administrador de esta base.'); await c.end(); process.exit(1); } const { rows: creada } = await c.query( `insert into usuario (id, email, rol) values (gen_random_uuid(), $1, 'admin') returning email`, [email] ); console.log(`${creada[0].email} creado y administrando.`); console.log('Entra por el panel: te mandará un código de un solo uso a ese correo.'); await c.end(); process.exit(0); } console.log( quitar ? `${rows[0].email} ya no administra.` : `${rows[0].email} ya administra el sitio.` ); /* * Las sesiones abiertas siguen valiendo, y es lo correcto: el rol se lee de la * base en cada petición —la sesión solo guarda a quién pertenece—, así que dar * o quitar el permiso surte efecto en la siguiente página que se pida, sin * tener que echar a nadie fuera. */ await c.end();