|
|
const express = require('express'); |
|
|
const nodemailer = require('nodemailer'); |
|
|
const crypto = require('crypto'); |
|
|
const cors = require('cors'); |
|
|
const https = require('https'); |
|
|
const cloudinary = require('cloudinary').v2; |
|
|
const sgMail = require('@sendgrid/mail'); |
|
|
require('dotenv').config({ path: process.cwd() + '/.env' }); |
|
|
|
|
|
const app = express(); |
|
|
app.use(express.json()); |
|
|
app.use(cors()); |
|
|
|
|
|
|
|
|
cloudinary.config({ |
|
|
cloud_name: process.env.CLOUDINARY_CLOUD_NAME, |
|
|
api_key: process.env.CLOUDINARY_API_KEY, |
|
|
api_secret: process.env.CLOUDINARY_API_SECRET |
|
|
}); |
|
|
|
|
|
console.log('Cloudinary configured with cloud_name:', process.env.CLOUDINARY_CLOUD_NAME); |
|
|
|
|
|
|
|
|
sgMail.setApiKey(process.env.SENDGRID_API_KEY); |
|
|
console.log('SendGrid configured'); |
|
|
|
|
|
|
|
|
const otpStore = new Map(); |
|
|
|
|
|
|
|
|
async function loadUsers() { |
|
|
try { |
|
|
console.log('Loading users from Cloudinary...'); |
|
|
const result = await cloudinary.api.resources({ resource_type: 'raw', type: 'upload', prefix: 'users/', max_results: 500 }); |
|
|
console.log('Cloudinary resources fetched:', result.resources.length); |
|
|
const users = {}; |
|
|
for (const resource of result.resources) { |
|
|
const publicId = resource.public_id; |
|
|
console.log('Processing user:', publicId); |
|
|
const downloadResult = await cloudinary.api.resource(publicId, { resource_type: 'raw' }); |
|
|
const url = downloadResult.secure_url; |
|
|
const userData = await new Promise((resolve, reject) => { |
|
|
https.get(url, (res) => { |
|
|
let data = ''; |
|
|
res.on('data', (chunk) => data += chunk); |
|
|
res.on('end', () => { |
|
|
try { |
|
|
resolve(JSON.parse(data)); |
|
|
} catch (e) { |
|
|
reject(e); |
|
|
} |
|
|
}); |
|
|
}).on('error', reject); |
|
|
}); |
|
|
if (userData.email) { |
|
|
users[userData.email] = userData; |
|
|
} |
|
|
} |
|
|
console.log('Users loaded:', Object.keys(users).length); |
|
|
return users; |
|
|
} catch (error) { |
|
|
console.error('Erreur chargement utilisateurs:', error); |
|
|
return {}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
async function saveUser(email, userData) { |
|
|
try { |
|
|
const hash = crypto.createHash('md5').update(email).digest('hex'); |
|
|
const dataStr = JSON.stringify({ ...userData, email }); |
|
|
const dataBase64 = Buffer.from(dataStr).toString('base64'); |
|
|
await cloudinary.uploader.upload(`data:text/plain;base64,${dataBase64}`, { |
|
|
public_id: `users/${hash}`, |
|
|
resource_type: 'raw' |
|
|
}); |
|
|
} catch (error) { |
|
|
console.error('Erreur sauvegarde utilisateur:', error); |
|
|
} |
|
|
} |
|
|
|
|
|
let users = {}; |
|
|
|
|
|
|
|
|
loadUsers().then(loadedUsers => { |
|
|
users = loadedUsers; |
|
|
}); |
|
|
|
|
|
|
|
|
app.post('/register', async (req, res) => { |
|
|
const { email } = req.body; |
|
|
|
|
|
if (!email) { |
|
|
return res.status(400).json({ error: 'Email requis' }); |
|
|
} |
|
|
|
|
|
if (users[email]) { |
|
|
console.log(`Tentative d'inscription pour email déjà enregistré: ${email}`); |
|
|
return res.status(400).json({ error: 'Utilisateur déjà enregistré' }); |
|
|
} |
|
|
|
|
|
const otp = crypto.randomInt(100000, 999999).toString(); |
|
|
otpStore.set(email, { otp, expires: Date.now() + 5 * 60 * 1000 }); |
|
|
|
|
|
try { |
|
|
const msg = { |
|
|
to: email, |
|
|
from: process.env.EMAIL_USER, |
|
|
subject: 'Code de vérification - Inscription', |
|
|
text: `Votre code de vérification est: ${otp}` |
|
|
}; |
|
|
await sgMail.send(msg); |
|
|
console.log('OTP email sent successfully for registration'); |
|
|
res.json({ message: 'Code envoyé à votre email' }); |
|
|
} catch (error) { |
|
|
console.error('Erreur envoi email:', error); |
|
|
res.status(500).json({ error: 'Erreur envoi email' }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
app.post('/login', async (req, res) => { |
|
|
const { email } = req.body; |
|
|
|
|
|
if (!email) { |
|
|
return res.status(400).json({ error: 'Email requis' }); |
|
|
} |
|
|
|
|
|
if (!users[email]) { |
|
|
console.log(`Tentative de connexion pour email non enregistré: ${email}`); |
|
|
return res.status(400).json({ error: 'Utilisateur non trouvé' }); |
|
|
} |
|
|
|
|
|
const otp = crypto.randomInt(100000, 999999).toString(); |
|
|
otpStore.set(email, { otp, expires: Date.now() + 5 * 60 * 1000 }); |
|
|
|
|
|
try { |
|
|
const msg = { |
|
|
to: email, |
|
|
from: process.env.EMAIL_USER, |
|
|
subject: 'Code de vérification - Connexion', |
|
|
text: `Votre code de vérification est: ${otp}` |
|
|
}; |
|
|
await sgMail.send(msg); |
|
|
console.log('Login OTP email sent successfully'); |
|
|
res.json({ message: 'Code envoyé à votre email' }); |
|
|
} catch (error) { |
|
|
console.error('Erreur envoi email:', error); |
|
|
res.status(500).json({ error: 'Erreur envoi email' }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
app.post('/verify', async (req, res) => { |
|
|
const { email, otp } = req.body; |
|
|
|
|
|
if (!email || !otp) { |
|
|
return res.status(400).json({ error: 'Email et OTP requis' }); |
|
|
} |
|
|
|
|
|
const stored = otpStore.get(email); |
|
|
|
|
|
if (!stored || stored.otp !== otp || Date.now() > stored.expires) { |
|
|
console.log(`OTP invalide ou expiré pour ${email}`); |
|
|
return res.status(400).json({ error: 'OTP invalide ou expiré' }); |
|
|
} |
|
|
|
|
|
otpStore.delete(email); |
|
|
|
|
|
|
|
|
if (!users[email]) { |
|
|
users[email] = { email, registeredAt: new Date() }; |
|
|
console.log(`Nouveau utilisateur enregistré: ${email}`); |
|
|
await saveUser(email, users[email]); |
|
|
console.log(`Utilisateur ${email} sauvegardé dans Cloudinary`); |
|
|
} else { |
|
|
console.log(`Utilisateur existant connecté: ${email}`); |
|
|
} |
|
|
|
|
|
res.json({ message: 'Authentification réussie', token: 'dummy-token' }); |
|
|
}); |
|
|
|
|
|
|
|
|
app.post('/send-notification', async (req, res) => { |
|
|
try { |
|
|
const { to, subject, html, action_type, entity_type, entity_id, user_info, timestamp } = req.body; |
|
|
|
|
|
if (!to || !subject || !html) { |
|
|
return res.status(400).json({ error: 'Destinataire, sujet et contenu HTML requis' }); |
|
|
} |
|
|
|
|
|
|
|
|
const msg = { |
|
|
to: to, |
|
|
from: process.env.EMAIL_USER, |
|
|
subject: subject, |
|
|
html: html |
|
|
}; |
|
|
|
|
|
|
|
|
const result = await sgMail.send(msg); |
|
|
console.log('Email de notification envoyé:', result[0].statusCode); |
|
|
|
|
|
res.json({ |
|
|
message: 'Notification envoyée avec succès', |
|
|
statusCode: result[0].statusCode, |
|
|
action_type, |
|
|
entity_type, |
|
|
entity_id, |
|
|
user_info, |
|
|
timestamp |
|
|
}); |
|
|
|
|
|
} catch (error) { |
|
|
console.error('Erreur envoi notification:', error); |
|
|
res.status(500).json({ error: 'Erreur envoi notification: ' + error.message }); |
|
|
} |
|
|
}); |
|
|
|
|
|
const PORT = process.env.PORT || 3000; |
|
|
app.listen(PORT, () => { |
|
|
console.log(`Serveur démarré sur le port ${PORT}`); |
|
|
}); |