mise a jour
This commit is contained in:
@@ -34,8 +34,8 @@ const register = async (req, res) => {
|
||||
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
|
||||
const emailVerifyToken = crypto.randomBytes(32).toString("hex");
|
||||
const emailVerifyExpires = new Date(Date.now() + 1000 * 60 * 60); // 1h
|
||||
const emailVerifyToken = String(Math.floor(1000 + Math.random() * 9000));
|
||||
const emailVerifyExpires = new Date(Date.now() + 1000 * 60 * 15); // 15 min
|
||||
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
@@ -62,23 +62,25 @@ const register = async (req, res) => {
|
||||
},
|
||||
});
|
||||
|
||||
const verifyUrl = `${process.env.APP_URL}/api/auth/verify-email/${emailVerifyToken}`;
|
||||
|
||||
await transporter.sendMail({
|
||||
from: process.env.MAIL_FROM,
|
||||
to: email,
|
||||
subject: "Validation de votre compte Thé Tip Top",
|
||||
subject: "Votre code de validation Thé Tip Top",
|
||||
html: `
|
||||
<h2>Bienvenue ${firstname}</h2>
|
||||
<p>Merci pour votre inscription.</p>
|
||||
<p>Veuillez cliquer sur le lien ci-dessous pour valider votre compte :</p>
|
||||
<a href="${verifyUrl}">Valider mon compte</a>
|
||||
<p>Ce lien expire dans 1 heure.</p>
|
||||
<div style="font-family:sans-serif;max-width:480px;margin:auto">
|
||||
<h2 style="color:#006B6B">Bienvenue ${firstname} !</h2>
|
||||
<p>Merci pour votre inscription sur Thé Tip Top.</p>
|
||||
<p>Voici votre code de validation à 4 chiffres :</p>
|
||||
<div style="font-size:36px;font-weight:bold;letter-spacing:12px;color:#006B6B;text-align:center;padding:20px 0">
|
||||
${emailVerifyToken}
|
||||
</div>
|
||||
<p style="color:#888;font-size:13px">Ce code expire dans <strong>15 minutes</strong>.</p>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
||||
return res.status(201).json({
|
||||
message: "Inscription réussie. Un email de validation a été envoyé.",
|
||||
message: "Inscription réussie. Un code de validation a été envoyé par email.",
|
||||
user,
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -148,7 +150,7 @@ const login = async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
if (!user.isEmailVerified) {
|
||||
if (!user.isEmailVerified && user.role === "CLIENT") {
|
||||
return res.status(403).json({
|
||||
message: "Veuillez valider votre adresse email avant de vous connecter.",
|
||||
});
|
||||
@@ -298,12 +300,106 @@ const resetPassword = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
const verifyCode = async (req, res) => {
|
||||
try {
|
||||
const { email, code } = req.body;
|
||||
|
||||
if (!email || !code) {
|
||||
return res.status(400).json({ message: "Email et code requis." });
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({ where: { email } });
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: "Compte introuvable." });
|
||||
}
|
||||
|
||||
if (user.isEmailVerified) {
|
||||
return res.status(400).json({ message: "Ce compte est déjà vérifié." });
|
||||
}
|
||||
|
||||
if (!user.emailVerifyToken || user.emailVerifyToken !== String(code)) {
|
||||
return res.status(400).json({ message: "Code invalide." });
|
||||
}
|
||||
|
||||
if (new Date() > user.emailVerifyExpires) {
|
||||
return res.status(400).json({ message: "Code expiré. Veuillez vous réinscrire." });
|
||||
}
|
||||
|
||||
await prisma.user.update({
|
||||
where: { id: user.id },
|
||||
data: { isEmailVerified: true, emailVerifyToken: null, emailVerifyExpires: null },
|
||||
});
|
||||
|
||||
const token = jwt.sign(
|
||||
{ id: user.id, role: user.role },
|
||||
process.env.JWT_SECRET,
|
||||
{ expiresIn: "24h" }
|
||||
);
|
||||
|
||||
return res.json({
|
||||
message: "Compte vérifié avec succès.",
|
||||
token,
|
||||
user: {
|
||||
id: user.id,
|
||||
firstname: user.firstname,
|
||||
lastname: user.lastname,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Erreur verifyCode:", error);
|
||||
return res.status(500).json({ message: "Erreur serveur lors de la vérification." });
|
||||
}
|
||||
};
|
||||
|
||||
const me = async (req, res) => {
|
||||
return res.json({
|
||||
user: req.user,
|
||||
});
|
||||
};
|
||||
|
||||
const deleteAccount = async (req, res) => {
|
||||
try {
|
||||
const userId = req.user.id;
|
||||
|
||||
await prisma.$transaction(async (tx) => {
|
||||
// 1. Supprimer le grand gagnant si c'est lui
|
||||
await tx.grandPrizeWinner.deleteMany({ where: { userId } });
|
||||
|
||||
// 2. Récupérer les participations pour supprimer leurs claims
|
||||
const participations = await tx.participation.findMany({
|
||||
where: { userId },
|
||||
select: { id: true },
|
||||
});
|
||||
const participationIds = participations.map((p) => p.id);
|
||||
|
||||
// 3. Supprimer les claims
|
||||
if (participationIds.length > 0) {
|
||||
await tx.claim.deleteMany({ where: { participationId: { in: participationIds } } });
|
||||
}
|
||||
|
||||
// 4. Supprimer les participations
|
||||
await tx.participation.deleteMany({ where: { userId } });
|
||||
|
||||
// 5. Libérer les tickets utilisés par ce user
|
||||
await tx.ticket.updateMany({
|
||||
where: { userId },
|
||||
data: { userId: null, isUsed: false, usedAt: null },
|
||||
});
|
||||
|
||||
// 6. Supprimer l'utilisateur
|
||||
await tx.user.delete({ where: { id: userId } });
|
||||
});
|
||||
|
||||
return res.json({ message: "Compte supprimé avec succès." });
|
||||
} catch (error) {
|
||||
console.error("Erreur deleteAccount:", error);
|
||||
return res.status(500).json({ message: "Erreur serveur lors de la suppression du compte." });
|
||||
}
|
||||
};
|
||||
|
||||
const changePassword = async (req, res) => {
|
||||
try {
|
||||
const { currentPassword, newPassword } = req.body;
|
||||
@@ -339,7 +435,9 @@ module.exports = {
|
||||
login,
|
||||
me,
|
||||
verifyEmail,
|
||||
verifyCode,
|
||||
resetPassword,
|
||||
forgotPassword,
|
||||
changePassword,
|
||||
deleteAccount,
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
const express = require("express");
|
||||
const { register, login, verifyEmail, forgotPassword, resetPassword, me, changePassword } = require("../controllers/auth.controller");
|
||||
const { register, login, verifyEmail, verifyCode, forgotPassword, resetPassword, me, changePassword, deleteAccount } = require("../controllers/auth.controller");
|
||||
const authMiddleware = require("../middlewares/auth.middleware");
|
||||
const validate = require("../middlewares/validate.middleware");
|
||||
const { registerSchema, loginSchema } = require("../validations/auth.validation");
|
||||
@@ -157,6 +157,8 @@ router.post("/forgot-password", forgotPassword);
|
||||
*/
|
||||
router.post("/reset-password/:token", resetPassword);
|
||||
|
||||
router.post("/verify-code", verifyCode);
|
||||
router.patch("/change-password", authMiddleware, changePassword);
|
||||
router.delete("/account", authMiddleware, deleteAccount);
|
||||
|
||||
module.exports = router;
|
||||
@@ -6,8 +6,13 @@ async function createAdmin() {
|
||||
const password = 'Admin@TipTop2026!'
|
||||
|
||||
const existing = await prisma.user.findUnique({ where: { email } })
|
||||
|
||||
if (existing) {
|
||||
console.log('Admin déjà existant :', email)
|
||||
await prisma.user.update({
|
||||
where: { email },
|
||||
data: { isEmailVerified: true, role: 'ADMIN' },
|
||||
})
|
||||
console.log('Admin mis à jour :', email)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -20,12 +25,13 @@ async function createAdmin() {
|
||||
email,
|
||||
password: hashed,
|
||||
role: 'ADMIN',
|
||||
isEmailVerified: true,
|
||||
},
|
||||
})
|
||||
|
||||
console.log(' Admin créé avec succès')
|
||||
console.log(' Email :', email)
|
||||
console.log(' Mot de passe :', password)
|
||||
console.log('Admin créé avec succès')
|
||||
console.log(' Email :', email)
|
||||
console.log(' Mot de passe:', password)
|
||||
}
|
||||
|
||||
createAdmin()
|
||||
|
||||
Reference in New Issue
Block a user