Actualizar server.js
This commit is contained in:
50
server.js
50
server.js
@@ -40,8 +40,8 @@ async function autoUpdateDB() {
|
|||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
full_name TEXT NOT NULL,
|
full_name TEXT NOT NULL,
|
||||||
phone TEXT NOT NULL, -- ELIMINADO 'UNIQUE' EN DEFINICIÓN (Se gestiona abajo)
|
phone TEXT NOT NULL,
|
||||||
email TEXT UNIQUE NOT NULL,
|
email TEXT NOT NULL, -- MODIFICADO: YA NO ES UNIQUE GLOBALMENTE
|
||||||
dni TEXT,
|
dni TEXT,
|
||||||
address TEXT,
|
address TEXT,
|
||||||
password_hash TEXT NOT NULL,
|
password_hash TEXT NOT NULL,
|
||||||
@@ -80,16 +80,10 @@ async function autoUpdateDB() {
|
|||||||
);
|
);
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// --- CORRECCIÓN MULTITENANT ---
|
// Parches y correcciones de restricciones (Multitenancy)
|
||||||
// Eliminamos la restricción global de teléfono único si existe para permitir
|
try { await client.query(`ALTER TABLE users DROP CONSTRAINT IF EXISTS users_phone_key`); } catch (e) {}
|
||||||
// que el mismo teléfono esté en varias empresas.
|
try { await client.query(`ALTER TABLE users DROP CONSTRAINT IF EXISTS users_email_key`); } catch (e) {} // NUEVO: Elimina restricción global de email
|
||||||
try {
|
|
||||||
await client.query(`ALTER TABLE users DROP CONSTRAINT IF EXISTS users_phone_key`);
|
|
||||||
} catch (e) {
|
|
||||||
// Ignoramos si no existe o hay error menor
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parches
|
|
||||||
await client.query(`
|
await client.query(`
|
||||||
DO $$ BEGIN
|
DO $$ BEGIN
|
||||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='users' AND column_name='role') THEN
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='users' AND column_name='role') THEN
|
||||||
@@ -165,18 +159,16 @@ app.post("/auth/register", async (req, res) => {
|
|||||||
const passwordHash = await bcrypt.hash(password, 10);
|
const passwordHash = await bcrypt.hash(password, 10);
|
||||||
await client.query('BEGIN');
|
await client.query('BEGIN');
|
||||||
|
|
||||||
// Verificamos Email (Que debe ser único globalmente para login)
|
const checkUser = await client.query("SELECT * FROM users WHERE email = $1 OR phone = $2", [email, p]);
|
||||||
const checkUser = await client.query("SELECT * FROM users WHERE email = $1", [email]);
|
|
||||||
let userId;
|
let userId;
|
||||||
|
|
||||||
if (checkUser.rowCount > 0) {
|
if (checkUser.rowCount > 0) {
|
||||||
const existing = checkUser.rows[0];
|
const existing = checkUser.rows[0];
|
||||||
// Si existe y ya está verificado, error.
|
|
||||||
if (existing.is_verified) {
|
if (existing.is_verified) {
|
||||||
await client.query('ROLLBACK');
|
await client.query('ROLLBACK');
|
||||||
return res.status(409).json({ ok: false, error: "El email ya está registrado." });
|
return res.status(409).json({ ok: false, error: "Usuario ya registrado." });
|
||||||
}
|
}
|
||||||
await client.query("UPDATE users SET full_name=$1, address=$2, dni=$3, password_hash=$4, phone=$5 WHERE id=$6", [fullName, address, dni, passwordHash, p, existing.id]);
|
await client.query("UPDATE users SET full_name=$1, address=$2, dni=$3, password_hash=$4 WHERE id=$5", [fullName, address, dni, passwordHash, existing.id]);
|
||||||
userId = existing.id;
|
userId = existing.id;
|
||||||
} else {
|
} else {
|
||||||
const insert = await client.query(
|
const insert = await client.query(
|
||||||
@@ -220,12 +212,23 @@ app.post("/auth/verify", async (req, res) => {
|
|||||||
app.post("/auth/login", async (req, res) => {
|
app.post("/auth/login", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { email, password } = req.body;
|
const { email, password } = req.body;
|
||||||
|
// Buscamos TODOS los usuarios con ese email (puede haber varios en distintas empresas)
|
||||||
const q = await pool.query("SELECT * FROM users WHERE email=$1", [email]);
|
const q = await pool.query("SELECT * FROM users WHERE email=$1", [email]);
|
||||||
|
|
||||||
if (q.rowCount === 0) return res.status(401).json({ ok: false, error: "Datos incorrectos" });
|
if (q.rowCount === 0) return res.status(401).json({ ok: false, error: "Datos incorrectos" });
|
||||||
const u = q.rows[0];
|
|
||||||
if (!(await bcrypt.compare(password, u.password_hash))) return res.status(401).json({ ok: false, error: "Datos incorrectos" });
|
// Probamos la contraseña con cada usuario encontrado
|
||||||
res.json({ ok: true, token: signToken(u) });
|
let user = null;
|
||||||
} catch(e) { res.status(500).json({ ok: false, error: "Error login" }); }
|
for (const u of q.rows) {
|
||||||
|
if (await bcrypt.compare(password, u.password_hash)) {
|
||||||
|
user = u;
|
||||||
|
break; // ¡Encontrado el correcto!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user) return res.status(401).json({ ok: false, error: "Datos incorrectos" });
|
||||||
|
res.json({ ok: true, token: signToken(user) });
|
||||||
|
} catch(e) { console.error(e); res.status(500).json({ ok: false, error: "Error login" }); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// RECUPERAR CONTRASEÑA
|
// RECUPERAR CONTRASEÑA
|
||||||
@@ -342,7 +345,6 @@ app.get("/admin/users", authMiddleware, async (req, res) => {
|
|||||||
} catch (e) { res.status(500).json({ ok: false, error: "Error listar users" }); }
|
} catch (e) { res.status(500).json({ ok: false, error: "Error listar users" }); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// CREAR USUARIO (CORREGIDO MULTITENANT)
|
|
||||||
app.post("/admin/users", authMiddleware, async (req, res) => {
|
app.post("/admin/users", authMiddleware, async (req, res) => {
|
||||||
const client = await pool.connect();
|
const client = await pool.connect();
|
||||||
try {
|
try {
|
||||||
@@ -373,10 +375,8 @@ app.post("/admin/users", authMiddleware, async (req, res) => {
|
|||||||
res.json({ ok: true, msg: "Usuario creado" });
|
res.json({ ok: true, msg: "Usuario creado" });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await client.query('ROLLBACK');
|
await client.query('ROLLBACK');
|
||||||
// Mantenemos el check global de email único, pero permitimos teléfonos duplicados en distintas empresas
|
// El DB ya no dará error 23505 por email/phone global porque eliminamos la restricción
|
||||||
if (e.code === '23505' && e.constraint.includes('email')) {
|
console.error(e);
|
||||||
return res.status(400).json({ ok: false, error: "❌ El Email ya está usado en el sistema." });
|
|
||||||
}
|
|
||||||
res.status(500).json({ ok: false, error: "Error creando usuario" });
|
res.status(500).json({ ok: false, error: "Error creando usuario" });
|
||||||
} finally { client.release(); }
|
} finally { client.release(); }
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user