Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
DATABASE_URL=postgresql://admin:password@localhost:5432/integration-dev
OUTSIDE_DATABASE_URL=postgresql://admin:password@localhost:5432/integration-dev

POSTGRES_PASSWORD=password
POSTGRES_USER=admin
POSTGRES_DB=integration-dev
POSTGRES_HOST=localhost
POSTGRES_PORT=5432

SERVER_PORT=4001
SERVICE_URL=http://localhost:4001/

SHOTGUN_PASSWORD=vodka

CAS_VALIDATE_URL=
CAS_LOGIN_URL=

EMAIL_HOST=
EMAIL_USER=
EMAIL_PASSWORD=
EMAIL_FROM=

AUTOMATION_TOKEN=
10 changes: 10 additions & 0 deletions backend/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 4,
"arrowParens": "always",
"endOfLine": "lf",
"bracketSameLine": true
}
4 changes: 4 additions & 0 deletions backend/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import { initUser } from './src/database/initdb/initUser';
import { initEvent } from './src/database/initdb/initevent';
import { initRoles } from './src/database/initdb/initrole';
import { authenticateUser } from './src/middlewares/auth.middleware';
import { authenticateAutomation } from './src/middlewares/automation.middleware';
import authRoutes from './src/routes/auth.routes';
import automationRoutes from './src/routes/automation.routes';
import busRoutes from './src/routes/bus.routes';
import challengeRoutes from './src/routes/challenge.routes';
import defaultRoute from './src/routes/default.routes';
Expand Down Expand Up @@ -48,6 +50,7 @@ async function startServer() {
// Utilisation des routes d'authentification
app.use('/api', defaultRoute)
app.use('/api/auth', authRoutes);
app.use('/api/automation', authenticateAutomation, automationRoutes);
app.use('/api/authadmin', authenticateUser, authRoutes);
app.use('/api/role', authenticateUser, roleRoutes);
app.use('/api/user', authenticateUser, userRoutes);
Expand All @@ -63,6 +66,7 @@ async function startServer() {
app.use('/api/tent', authenticateUser, tentRoutes);
app.use('/api/bus', authenticateUser, busRoutes);
app.use("/api/uploads/news", express.static(path.join(__dirname, "/uploads/news")));
app.use("/api/uploads/notebooks", express.static(path.join(__dirname, "/uploads/notebooks")));
app.use("/api/uploads/foodmenu", express.static(path.join(__dirname, "/uploads/foodmenu")));
app.use("/api/uploads/plannings", express.static(path.join(__dirname, "/uploads/plannings")));
app.use("/api/exports/bus", express.static(path.join(__dirname, "/exports/bus")));
Expand Down
110 changes: 54 additions & 56 deletions backend/src/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
import bigInt from 'big-integer';
import { type Request, type Response } from 'express';
import { sign, verify } from 'jsonwebtoken';
import type { EmailOptions } from '../../types/email';
import { templateResetPassword } from '../email/email.registry';
import { compileTemplate } from '../email/email.renderer';
import * as auth_service from '../services/auth.service';
import * as email_service from '../services/email.service';
import * as registration_service from '../services/registration.service';
import * as role_service from '../services/role.service';
import * as user_service from '../services/user.service';
import * as template from '../utils/emailtemplates';
import { Error, Ok, Unauthorized } from '../utils/responses';
import { jwtSecret, service_url } from '../utils/secret';
import { email_from, jwtSecret, service_url } from '../utils/secret';
import { decodeToken } from '../utils/token';
import { type EmailOptions } from './email.controller';

// Fonction de connexion
export const login = async (req: Request, res: Response) => {
Expand Down Expand Up @@ -40,7 +41,6 @@
}
};


export const handlecasticket = async (req: Request, res: Response) => {
try {
const ticket = req.query.ticket as string;
Expand All @@ -52,14 +52,25 @@
// Assurez-vous que user.email est un string
let user = await user_service.getUserByEmail(CASuser.email.toLowerCase());
if (!user) {
const password = bigInt.randBetween(bigInt(2).pow(255), bigInt(2).pow(256).minus(1)).toString()
await user_service.createUser(CASuser.givenName, CASuser.sn, CASuser.email, true, "Student", " ", password)
user = await user_service.getUserByEmail(CASuser.email.toLowerCase())
const password = bigInt.randBetween(bigInt(2).pow(255), bigInt(2).pow(256).minus(1)).toString();
await user_service.createUser(
CASuser.givenName,
CASuser.sn,
CASuser.email,
true,
'Student',
' ',
password,
);
user = await user_service.getUserByEmail(CASuser.email.toLowerCase());
}

const id = user?.id
const id = user?.id;

if (!id) { Error(res, { msg: "Pas d'id" }); return; }
if (!id) {
Error(res, { msg: "Pas d'id" });
return;
}

await user_service.updateUserStudent(CASuser.givenName, CASuser.sn, CASuser.email);

Expand All @@ -74,10 +85,7 @@

const token = auth_service.generateToken(enrichedUser);


Ok(res, { data: { token } })


Ok(res, { data: { token } });
} else {
Unauthorized(res, { msg: 'Unauthorized: Invalid user email' });
}
Expand All @@ -87,75 +95,67 @@
} catch {
Unauthorized(res, { msg: 'Unauthorized: Invalid token' });
}
}

};

export const isTokenValid = async (req: Request, res: Response) => {
try {
const authHeader = req.headers["authorization"];
if (!authHeader || !authHeader.startsWith("Bearer ")) {
const authHeader = req.headers['authorization'];
if (!authHeader || !authHeader.startsWith('Bearer ')) {
Unauthorized(res, {
msg: "Unauthorized: Missing or malformed token",
msg: 'Unauthorized: Missing or malformed token',
data: false,
});
return;
}

const token = authHeader.split(" ")[1];
const token = authHeader.split(' ')[1];

// Décoder et valider le token
const decodedToken = decodeToken(token);
if (!decodedToken) {
Unauthorized(res, {
msg: "Unauthorized: Token has expired or is invalid",
msg: 'Unauthorized: Token has expired or is invalid',
data: false,
});
return
return;
}


// Vérifier que l'email est bien présent dans le token
if (!decodedToken.userEmail) {
Unauthorized(res, {
msg: "Unauthorized: Invalid token content",
msg: 'Unauthorized: Invalid token content',
data: false,
});
return
return;
}

// Répondre une seule fois
Ok(res, { data: true });
return
return;
} catch {
Error(res, { msg: "Unauthorized: Token validation failed" });
return
Error(res, { msg: 'Unauthorized: Token validation failed' });
return;
}
};


export const completeRegistration = async (req: Request, res: Response) => {

const { token, password } = req.body;

try {

await auth_service.completeRegistration(token, password)
Ok(res, { msg: "Inscription complétée avec succès.", data: true })

await auth_service.completeRegistration(token, password);
Ok(res, { msg: 'Inscription complétée avec succès.', data: true });
} catch (error) {
Error(res, { msg: error.message || "Une erreur est survenue." });
Error(res, { msg: error.message || 'Une erreur est survenue.' });
}

}
};

export const requestPasswordUser = async (req: Request, res: Response) => {

const { user_email } = req.body
const { user_email } = req.body;
const user = await user_service.getUserByEmail(user_email);

if (!user) {
Error(res, { msg: 'User not found' });
return
return;
}

// Générer un token JWT
Expand All @@ -164,18 +164,17 @@
// Créer le lien de réinitialisation
const resetLink = `${service_url}ResetPassword?token=${token}`;


// Générer le contenu HTML du mail
const htmlEmail = template.compileTemplate({ resetLink: resetLink }, template.templateResetPassword);
const htmlEmail = compileTemplate({ resetLink: resetLink }, templateResetPassword);

if (!htmlEmail) {
Error(res, { msg: "Nom de template invalide" });
Error(res, { msg: 'Nom de template invalide' });
return;
}

// Préparer les options d'email
const emailOptions: EmailOptions = {
from: "integration@utt.fr",
from: email_from,
to: [user_email],
cc: [],
bcc: [],
Expand All @@ -186,28 +185,26 @@
try {
// Envoyer l'e-mail
await email_service.sendEmail(emailOptions);
Ok(res, { msg: 'Email for password reste sent !' })
return
Ok(res, { msg: 'Email for password reste sent !' });
return;
} catch {
Error(res, { msg: 'Error when reseting password' });
return
return;
}

}
};

export const resetPasswordUser = async (req: Request, res: Response) => {
const { token, password } = req.body;


try {
// Vérifiez et décodez le token
const decoded: any = verify(token, jwtSecret);

Check warning on line 201 in backend/src/controllers/auth.controller.ts

View workflow job for this annotation

GitHub Actions / lint-api

Unexpected any. Specify a different type

// Trouvez l'utilisateur par ID
const user = await user_service.getUserById(decoded.userId);
if (!user) {
Error(res, { msg: 'Utilisateur non trouvé' });
return
return;
}

// Hash du nouveau mot de passe
Expand All @@ -216,29 +213,30 @@
// Mettez à jour le mot de passe de l'utilisateur
await user_service.updateUserPassword(Number(user.userId), hashedPassword);
Ok(res, { msg: 'Mot de passe réinitialisé avec succès' });
return
return;
} catch (error) {
console.log(error);
Error(res, { msg: 'Token invalid or expire' });
return
return;
}
}
};

export const renewToken = async (req: Request, res: Response) => {
const { userId } = req.body;

try {

const userToken = await registration_service.getRegistrationByUserId(userId);

if (userToken) {
await auth_service.deleteUserRegistrationToken(userId);
}

const newToken = await auth_service.createRegistrationToken(userId)
const newToken = await auth_service.createRegistrationToken(userId);

Ok(res, {
msg: 'Token renouvelé, vous pouvez renvoyer un email de bienvenu avec ce lien : https://integration.utt.fr/Register?token=' + newToken,
msg:
'Token renouvelé, vous pouvez renvoyer un email de bienvenu avec ce lien : https://integration.utt.fr/Register?token=' +
newToken,
});
} catch (err) {
Error(res, { msg: err.message });
Expand Down
29 changes: 15 additions & 14 deletions backend/src/controllers/bus.controller.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type Request, type Response } from "express";
import * as bus_service from "../services/bus.service";
import { sendEmail } from "../services/email.service";
import { Error, Ok } from "../utils/responses";
import { generateEmailHtml } from "./email.controller";
import { type Request, type Response } from 'express';
import * as bus_service from '../services/bus.service';
import { generateEmailHtml, sendEmail } from '../services/email.service';
import { Error, Ok } from '../utils/responses';
import { email_from } from '../utils/secret';

interface MulterRequest extends Request {
file?: Express.Multer.File;
Expand All @@ -13,23 +13,24 @@ export const sendBusAttributionEmails = async (req: Request, res: Response) => {
const attributions = await bus_service.getAllBusAttributions();

if (!attributions.length) {
Error(res, { msg: "Aucune attribution de bus trouvée." });
Error(res, { msg: 'Aucune attribution de bus trouvée.' });
return;
}

for (const attr of attributions) {
const htmlEmail = generateEmailHtml("templateAttributionBus", {
bus: attr.bus, time: attr.departure_time
const htmlEmail = generateEmailHtml('templateAttributionBus', {
bus: attr.bus,
time: attr.departure_time,
});

const emailOptions = {
from: "integration@utt.fr",
from: email_from,
to: [attr.email],
cc: [],
bcc: [],
subject: `Attribution Bus - ${attr.firstName ?? ""} ${attr.lastName ?? ""}`,
subject: `Attribution Bus - ${attr.firstName ?? ''} ${attr.lastName ?? ''}`,
text: `Votre bus attribué est le numéro ${attr.bus}`,
html: htmlEmail || "",
html: htmlEmail || '',
};

await sendEmail(emailOptions);
Expand All @@ -46,13 +47,13 @@ export const uploadbusCSV = async (req: MulterRequest, res: Response) => {
try {
const file = req.file;
if (!file) {
Error(res, { msg: "Fichier CSV manquant." });
Error(res, { msg: 'Fichier CSV manquant.' });
}

await bus_service.importBusFromCSV(file.path);
Ok(res, { msg: "Importation réalisée avec succès." });
Ok(res, { msg: 'Importation réalisée avec succès.' });
} catch (error) {
console.error("Erreur import CSV :", error);
console.error('Erreur import CSV :', error);
Error(res, { msg: "Échec de l'importation." });
}
};
Loading
Loading