| 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}`); |
| }); |