161 lines
4.8 KiB
JavaScript
161 lines
4.8 KiB
JavaScript
import express from "express";
|
||
import bcrypt from "bcrypt";
|
||
import jwt from "jsonwebtoken";
|
||
import passport from "passport";
|
||
import session from "express-session";
|
||
import { Strategy as GoogleStrategy } from "passport-google-oauth20";
|
||
import { Strategy as FacebookStrategy } from "passport-facebook";
|
||
import dotenv from "dotenv";
|
||
import { pool } from "../db.js";
|
||
|
||
dotenv.config();
|
||
const router = express.Router();
|
||
|
||
/* -------------------- SESSIONS -------------------- */
|
||
router.use(
|
||
session({
|
||
secret: process.env.SESSION_SECRET || "secret_key",
|
||
resave: false,
|
||
saveUninitialized: true,
|
||
})
|
||
);
|
||
router.use(passport.initialize());
|
||
router.use(passport.session());
|
||
|
||
passport.serializeUser((user, done) => done(null, user));
|
||
passport.deserializeUser((user, done) => done(null, user));
|
||
|
||
/* -------------------- GOOGLE STRATEGY -------------------- */
|
||
passport.use(
|
||
new GoogleStrategy(
|
||
{
|
||
clientID: process.env.GOOGLE_CLIENT_ID,
|
||
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||
callbackURL: "/api/auth/google/callback",
|
||
},
|
||
async (accessToken, refreshToken, profile, done) => {
|
||
try {
|
||
const email = profile.emails?.[0]?.value;
|
||
if (!email) return done(null, false);
|
||
|
||
// Vérifie si l’utilisateur existe déjà
|
||
let result = await pool.query("SELECT * FROM users WHERE email=$1", [email]);
|
||
|
||
if (!result.rows.length) {
|
||
// Crée un nouvel utilisateur
|
||
await pool.query("INSERT INTO users(email, password) VALUES($1,$2)", [
|
||
email,
|
||
null,
|
||
]);
|
||
result = await pool.query("SELECT * FROM users WHERE email=$1", [email]);
|
||
}
|
||
|
||
return done(null, result.rows[0]);
|
||
} catch (err) {
|
||
console.error("Erreur Google auth:", err);
|
||
return done(err, null);
|
||
}
|
||
}
|
||
)
|
||
);
|
||
|
||
/* -------------------- FACEBOOK STRATEGY -------------------- */
|
||
passport.use(
|
||
new FacebookStrategy(
|
||
{
|
||
clientID: process.env.FACEBOOK_APP_ID,
|
||
clientSecret: process.env.FACEBOOK_APP_SECRET,
|
||
callbackURL: "/api/auth/facebook/callback",
|
||
profileFields: ["id", "displayName", "emails"],
|
||
},
|
||
async (accessToken, refreshToken, profile, done) => {
|
||
try {
|
||
const email = profile.emails?.[0]?.value;
|
||
if (!email) return done(null, false);
|
||
|
||
let result = await pool.query("SELECT * FROM users WHERE email=$1", [email]);
|
||
if (!result.rows.length) {
|
||
await pool.query("INSERT INTO users(email, password) VALUES($1,$2)", [
|
||
email,
|
||
null,
|
||
]);
|
||
result = await pool.query("SELECT * FROM users WHERE email=$1", [email]);
|
||
}
|
||
|
||
return done(null, result.rows[0]);
|
||
} catch (err) {
|
||
console.error("Erreur Facebook auth:", err);
|
||
return done(err, null);
|
||
}
|
||
}
|
||
)
|
||
);
|
||
|
||
/* -------------------- ROUTES CLASSIQUES -------------------- */
|
||
|
||
// Inscription manuelle
|
||
router.post("/register", async (req, res) => {
|
||
const { email, password } = req.body;
|
||
if (!email || !password)
|
||
return res.status(400).json({ message: "Champs requis" });
|
||
|
||
const hashed = await bcrypt.hash(password, 10);
|
||
try {
|
||
await pool.query("INSERT INTO users(email, password) VALUES($1,$2)", [
|
||
email,
|
||
hashed,
|
||
]);
|
||
res.status(201).json({ message: "Utilisateur créé" });
|
||
} catch (e) {
|
||
res.status(400).json({ error: "Email déjà utilisé" });
|
||
}
|
||
});
|
||
|
||
// Connexion manuelle
|
||
router.post("/login", async (req, res) => {
|
||
const { email, password } = req.body;
|
||
const result = await pool.query("SELECT * FROM users WHERE email=$1", [email]);
|
||
if (!result.rows.length)
|
||
return res.status(400).json({ message: "Utilisateur introuvable" });
|
||
|
||
const match = await bcrypt.compare(password, result.rows[0].password);
|
||
if (!match) return res.status(401).json({ message: "Mot de passe incorrect" });
|
||
|
||
const token = jwt.sign(
|
||
{ id: result.rows[0].id, email },
|
||
process.env.JWT_SECRET,
|
||
{ expiresIn: "2h" }
|
||
);
|
||
res.json({ token });
|
||
});
|
||
|
||
/* -------------------- ROUTES GOOGLE -------------------- */
|
||
router.get("/google", passport.authenticate("google", { scope: ["email", "profile"] }));
|
||
|
||
router.get(
|
||
"/google/callback",
|
||
passport.authenticate("google", { failureRedirect: "/login" }),
|
||
(req, res) => {
|
||
const token = jwt.sign({ email: req.user.email }, process.env.JWT_SECRET, {
|
||
expiresIn: "2h",
|
||
});
|
||
res.json({ message: "Connexion via Google réussie", token });
|
||
}
|
||
);
|
||
|
||
/* -------------------- ROUTES FACEBOOK -------------------- */
|
||
router.get("/facebook", passport.authenticate("facebook", { scope: ["email"] }));
|
||
|
||
router.get(
|
||
"/facebook/callback",
|
||
passport.authenticate("facebook", { failureRedirect: "/login" }),
|
||
(req, res) => {
|
||
const token = jwt.sign({ email: req.user.email }, process.env.JWT_SECRET, {
|
||
expiresIn: "2h",
|
||
});
|
||
res.json({ message: "Connexion via Facebook réussie", token });
|
||
}
|
||
);
|
||
|
||
export default router;
|