feat: agregar sistema de autenticación con usuarios y roles

- Agregar Login con autenticación por DNI y contraseña
- Crear tabla de usuarios con roles (admin, médico, enfermero)
- Implementar gestión de usuarios (CRUD) para administradores
- Agregar control de permisos basado en roles en el menú
- Persistir estado de sesión en backend
- Inicializar usuario admin por defecto (DNI: 12345678, pass: admin123)
- Corregir inicialización de arrays en el store para evitar errores al cargar estado
This commit is contained in:
2026-04-23 01:09:29 -03:00
parent 1d7a5e893f
commit 76e01bfd79
11 changed files with 869 additions and 31 deletions
+98
View File
@@ -2,6 +2,7 @@ import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import bcrypt from 'bcryptjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const DB_PATH = __dirname + '/data/hospital.db';
@@ -19,6 +20,22 @@ export async function openDb() {
);
`);
await db.exec(`
CREATE TABLE IF NOT EXISTS usuarios (
id TEXT PRIMARY KEY,
apellido TEXT NOT NULL,
nombre TEXT NOT NULL,
dni TEXT UNIQUE NOT NULL,
fechaNacimiento TEXT NOT NULL,
email TEXT NOT NULL,
rol TEXT NOT NULL CHECK(rol IN ('admin', 'medico', 'enfermero')),
matriculaProfesional TEXT,
passwordHash TEXT NOT NULL,
areaId TEXT,
fechaCreacion TEXT NOT NULL
);
`);
return db;
}
@@ -34,3 +51,84 @@ export async function setValue(key, value) {
await db.run('INSERT INTO kv (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value', key, value);
await db.close();
}
export async function getUsuarioByDni(dni) {
const db = await openDb();
const row = await db.get('SELECT * FROM usuarios WHERE dni = ?', dni);
await db.close();
return row || null;
}
export async function getUsuarioById(id) {
const db = await openDb();
const row = await db.get('SELECT * FROM usuarios WHERE id = ?', id);
await db.close();
return row || null;
}
export async function getAllUsuarios() {
const db = await openDb();
const rows = await db.all('SELECT * FROM usuarios ORDER BY apellido, nombre');
await db.close();
return rows;
}
export async function createUsuario(usuario) {
const db = await openDb();
await db.run(
`INSERT INTO usuarios (id, apellido, nombre, dni, fechaNacimiento, email, rol, matriculaProfesional, passwordHash, areaId, fechaCreacion)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
usuario.id,
usuario.apellido,
usuario.nombre,
usuario.dni,
usuario.fechaNacimiento,
usuario.email,
usuario.rol,
usuario.matriculaProfesional || null,
usuario.passwordHash,
usuario.areaId || null,
usuario.fechaCreacion
);
await db.close();
}
export async function updateUsuario(id, datos) {
const db = await openDb();
const fields = [];
const values = [];
if (datos.apellido !== undefined) { fields.push('apellido = ?'); values.push(datos.apellido); }
if (datos.nombre !== undefined) { fields.push('nombre = ?'); values.push(datos.nombre); }
if (datos.fechaNacimiento !== undefined) { fields.push('fechaNacimiento = ?'); values.push(datos.fechaNacimiento); }
if (datos.email !== undefined) { fields.push('email = ?'); values.push(datos.email); }
if (datos.rol !== undefined) { fields.push('rol = ?'); values.push(datos.rol); }
if (datos.matriculaProfesional !== undefined) { fields.push('matriculaProfesional = ?'); values.push(datos.matriculaProfesional); }
if (datos.passwordHash !== undefined) { fields.push('passwordHash = ?'); values.push(datos.passwordHash); }
if (datos.areaId !== undefined) { fields.push('areaId = ?'); values.push(datos.areaId); }
if (fields.length > 0) {
values.push(id);
await db.run(`UPDATE usuarios SET ${fields.join(', ')} WHERE id = ?`, values);
}
await db.close();
}
export async function deleteUsuario(id) {
const db = await openDb();
await db.run('DELETE FROM usuarios WHERE id = ?', id);
await db.close();
}
export async function verifyPassword(dni, password) {
const db = await openDb();
const row = await db.get('SELECT passwordHash FROM usuarios WHERE dni = ?', dni);
await db.close();
if (!row) return false;
return bcrypt.compareSync(password, row.passwordHash);
}
export async function hashPassword(password) {
return bcrypt.hashSync(password, 10);
}