Actualizar server.js
This commit is contained in:
103
server.js
103
server.js
@@ -461,6 +461,109 @@ app.get("/auth/me", authMiddleware, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// 📝 REGISTRO DE NUEVAS EMPRESAS (SAAS)
|
||||
// ==========================================
|
||||
app.post("/auth/register", async (req, res) => {
|
||||
try {
|
||||
const { fullName, email, phone, password, dni, address } = req.body;
|
||||
|
||||
if (!email || !password || !fullName || !phone) {
|
||||
return res.status(400).json({ ok: false, error: "Faltan datos obligatorios" });
|
||||
}
|
||||
|
||||
const p = normalizePhone(phone);
|
||||
|
||||
// 1. Verificamos si el email o teléfono ya están en uso
|
||||
const check = await pool.query("SELECT id FROM users WHERE email = $1 OR phone = $2", [email, p]);
|
||||
if (check.rowCount > 0) {
|
||||
return res.status(400).json({ ok: false, error: "El email o teléfono ya están registrados" });
|
||||
}
|
||||
|
||||
const hash = await bcrypt.hash(password, 10);
|
||||
|
||||
// 2. Creamos al usuario como ADMIN (dueño de su propia empresa/instancia)
|
||||
// Lo creamos como NO verificado hasta que ponga el código
|
||||
const insert = await pool.query(`
|
||||
INSERT INTO users (full_name, email, phone, password_hash, dni, address, role, status, is_verified)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, 'admin', 'active', FALSE)
|
||||
RETURNING id
|
||||
`, [fullName, email, p, hash, dni || null, address || null]);
|
||||
|
||||
const newUserId = insert.rows[0].id;
|
||||
|
||||
// 3. Le asignamos su propio ID como owner_id (es el jefe de su panel)
|
||||
await pool.query("UPDATE users SET owner_id = $1 WHERE id = $2", [newUserId, newUserId]);
|
||||
|
||||
// 4. Generamos el código de 6 dígitos para el WhatsApp
|
||||
const code = genCode6();
|
||||
const codeHash = await bcrypt.hash(code, 10);
|
||||
|
||||
await pool.query(`
|
||||
INSERT INTO login_codes (user_id, phone, code_hash, purpose, expires_at)
|
||||
VALUES ($1, $2, $3, 'register_verify', NOW() + INTERVAL '15 minutes')
|
||||
`, [newUserId, p, codeHash]);
|
||||
|
||||
// 5. Enviamos el WhatsApp usando la instancia principal (Aviso en consola por si Evolution no está listo)
|
||||
console.log(`🔐 [SISTEMA] Código de verificación para ${p}: ${code}`);
|
||||
const msg = `👋 *¡Bienvenido a IntegraRepara!*\n\nTu código de verificación es: *${code}*\n\nTiene una validez de 15 minutos.`;
|
||||
|
||||
// Intentamos enviarlo si la variable EVOLUTION_INSTANCE existe
|
||||
if (process.env.EVOLUTION_INSTANCE) {
|
||||
sendWhatsAppAuto(p, msg, process.env.EVOLUTION_INSTANCE, false).catch(console.error);
|
||||
}
|
||||
|
||||
res.json({ ok: true, message: "Código enviado" });
|
||||
} catch (e) {
|
||||
console.error("Error en Registro:", e);
|
||||
res.status(500).json({ ok: false, error: "Error interno del servidor" });
|
||||
}
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// ✅ VERIFICACIÓN DEL CÓDIGO (OTP)
|
||||
// ==========================================
|
||||
app.post("/auth/verify", async (req, res) => {
|
||||
try {
|
||||
const { phone, code } = req.body;
|
||||
const p = normalizePhone(phone);
|
||||
|
||||
// Buscamos códigos pendientes para ese teléfono
|
||||
const q = await pool.query(`
|
||||
SELECT c.*, u.id as u_id, u.full_name, u.role, u.owner_id
|
||||
FROM login_codes c
|
||||
JOIN users u ON c.user_id = u.id
|
||||
WHERE c.phone = $1 AND c.consumed_at IS NULL AND c.expires_at > NOW()
|
||||
ORDER BY c.created_at DESC LIMIT 1
|
||||
`, [p]);
|
||||
|
||||
if (q.rowCount === 0) return res.status(400).json({ ok: false, error: "Código inválido o caducado" });
|
||||
|
||||
const codeRecord = q.rows[0];
|
||||
const valid = await bcrypt.compare(code, codeRecord.code_hash);
|
||||
|
||||
if (!valid) return res.status(400).json({ ok: false, error: "Código incorrecto" });
|
||||
|
||||
// Marcamos código como usado y usuario como verificado
|
||||
await pool.query("UPDATE login_codes SET consumed_at = NOW() WHERE id = $1", [codeRecord.id]);
|
||||
await pool.query("UPDATE users SET is_verified = TRUE WHERE id = $1", [codeRecord.u_id]);
|
||||
|
||||
// Generamos su token de sesión para que entre directo
|
||||
const token = signToken({
|
||||
id: codeRecord.u_id,
|
||||
email: codeRecord.email, // Aquí si usaras email en el token
|
||||
phone: codeRecord.phone,
|
||||
role: codeRecord.role,
|
||||
owner_id: codeRecord.owner_id
|
||||
});
|
||||
|
||||
res.json({ ok: true, token, user: { id: codeRecord.u_id, full_name: codeRecord.full_name, role: codeRecord.role } });
|
||||
} catch (e) {
|
||||
console.error("Error en Verificación:", e);
|
||||
res.status(500).json({ ok: false, error: "Error en el servidor" });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ==========================================
|
||||
// 🕵️ ROBOT NOTARIO (TRAZABILIDAD TOTAL)
|
||||
|
||||
Reference in New Issue
Block a user