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 (
|
||||
id SERIAL PRIMARY KEY,
|
||||
full_name TEXT NOT NULL,
|
||||
phone TEXT NOT NULL, -- ELIMINADO 'UNIQUE' EN DEFINICIÓN (Se gestiona abajo)
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
phone TEXT NOT NULL,
|
||||
email TEXT NOT NULL, -- MODIFICADO: YA NO ES UNIQUE GLOBALMENTE
|
||||
dni TEXT,
|
||||
address TEXT,
|
||||
password_hash TEXT NOT NULL,
|
||||
@@ -80,16 +80,10 @@ async function autoUpdateDB() {
|
||||
);
|
||||
`);
|
||||
|
||||
// --- CORRECCIÓN MULTITENANT ---
|
||||
// Eliminamos la restricción global de teléfono único si existe para permitir
|
||||
// que el mismo teléfono esté en varias empresas.
|
||||
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 y correcciones de restricciones (Multitenancy)
|
||||
try { await client.query(`ALTER TABLE users DROP CONSTRAINT IF EXISTS users_phone_key`); } catch (e) {}
|
||||
try { await client.query(`ALTER TABLE users DROP CONSTRAINT IF EXISTS users_email_key`); } catch (e) {} // NUEVO: Elimina restricción global de email
|
||||
|
||||
// Parches
|
||||
await client.query(`
|
||||
DO $$ BEGIN
|
||||
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);
|
||||
await client.query('BEGIN');
|
||||
|
||||
// Verificamos Email (Que debe ser único globalmente para login)
|
||||
const checkUser = await client.query("SELECT * FROM users WHERE email = $1", [email]);
|
||||
const checkUser = await client.query("SELECT * FROM users WHERE email = $1 OR phone = $2", [email, p]);
|
||||
let userId;
|
||||
|
||||
if (checkUser.rowCount > 0) {
|
||||
const existing = checkUser.rows[0];
|
||||
// Si existe y ya está verificado, error.
|
||||
if (existing.is_verified) {
|
||||
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;
|
||||
} else {
|
||||
const insert = await client.query(
|
||||
@@ -220,12 +212,23 @@ app.post("/auth/verify", async (req, res) => {
|
||||
app.post("/auth/login", async (req, res) => {
|
||||
try {
|
||||
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]);
|
||||
|
||||
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" });
|
||||
res.json({ ok: true, token: signToken(u) });
|
||||
} catch(e) { res.status(500).json({ ok: false, error: "Error login" }); }
|
||||
|
||||
// Probamos la contraseña con cada usuario encontrado
|
||||
let user = null;
|
||||
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
|
||||
@@ -342,7 +345,6 @@ app.get("/admin/users", authMiddleware, async (req, res) => {
|
||||
} catch (e) { res.status(500).json({ ok: false, error: "Error listar users" }); }
|
||||
});
|
||||
|
||||
// CREAR USUARIO (CORREGIDO MULTITENANT)
|
||||
app.post("/admin/users", authMiddleware, async (req, res) => {
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
@@ -373,10 +375,8 @@ app.post("/admin/users", authMiddleware, async (req, res) => {
|
||||
res.json({ ok: true, msg: "Usuario creado" });
|
||||
} catch (e) {
|
||||
await client.query('ROLLBACK');
|
||||
// Mantenemos el check global de email único, pero permitimos teléfonos duplicados en distintas empresas
|
||||
if (e.code === '23505' && e.constraint.includes('email')) {
|
||||
return res.status(400).json({ ok: false, error: "❌ El Email ya está usado en el sistema." });
|
||||
}
|
||||
// El DB ya no dará error 23505 por email/phone global porque eliminamos la restricción
|
||||
console.error(e);
|
||||
res.status(500).json({ ok: false, error: "Error creando usuario" });
|
||||
} finally { client.release(); }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user