You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
senzapaura_es/scripts/db/hacer-admin.mjs

75 lines
2.3 KiB

La puerta del panel, y una portada que dice qué falta Fase 6. Está lo que todo lo demás necesita: quién entra y por dónde. El rol vive en `usuario.rol`, con un CHECK que impide inventarse uno, y se da con `npm run db:admin`. En una variable de entorno con correos habría sido más rápido, pero entonces revocar a alguien pide un despliegue y a la pregunta «quién administra esto» solo sabe contestar quien pueda leer la configuración del servidor. La guarda está en el `+layout.server.ts` de la carpeta y no en cada ruta: una pantalla nueva queda protegida por el hecho de estar dentro. Sin sesión, a entrar con la vuelta puesta; con sesión y sin el rol, 404 y no 403, porque un 403 confirma que el panel existe y dónde vive. Los tres casos, comprobados contra la aplicación de verdad. La portada contesta «qué falta» y no «cuánto hay». Cada sección trae lo que tiene, lo que está a medias y los nombres de lo que está a medias: decir «1 género sin ficha» obliga a ir a buscar cuál, y esa búsqueda ya la ha hecho la consulta. Dos viajes a la base para las siete filas. Fuera Sveltia CMS y `static/admin/`. Editaba los Markdown de `src/content/`, que desde la fase 4 no lee nadie: guardaba cambios que no salían en pantalla, y además tapaba la ruta nueva. Y de paso, la prueba de contacto que fallaba en la tanda completa y pasaba a solas. No era aislamiento: `page.goto` vuelve al cargar, no al hidratar, y al hidratar Svelte reescribe el valor de cada `input` con el del componente. Lo tecleado antes de ese instante se perdía, y solo le pasaba al primer campo y solo con la máquina cargada. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 weeks ago
/**
* 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@… --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.
*
* No crea la cuenta. Se da el rol a alguien que ya ha entrado alguna vez, para
* que el rol no pueda quedarse esperando en una dirección mal escrita.
*/
import pg from 'pg';
const argumentos = process.argv.slice(2);
const quitar = argumentos.includes('--quitar');
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) {
console.log(`No hay ninguna cuenta con «${email}».`);
console.log('Tiene que haber entrado al menos una vez para poder darle el rol.');
await c.end();
process.exit(1);
}
console.log(
quitar ? `${rows[0].email} ya no administra.` : `${rows[0].email} administra: /admin ya le abre.`
);
/*
* 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();

Powered by TurnKey Linux.