Skip to content

Commit 51bfcc2

Browse files
authored
Merge pull request #9 from ungdev/prod
Update dev
2 parents 84bccb6 + 407cfc7 commit 51bfcc2

21 files changed

+537
-158
lines changed

backend/package-lock.json

+234-45
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
"description": "",
2020
"dependencies": {
2121
"@electric-sql/pglite": "^0.2.17",
22+
"@types/multer": "^1.4.12",
2223
"axios": "^1.8.4",
2324
"bcryptjs": "^3.0.2",
2425
"big-integer": "^1.6.52",
2526
"cors": "^2.8.5",
26-
"crypto": "^1.0.1",
2727
"dotenv": "^16.5.0",
2828
"drizzle-kit": "^0.30.6",
2929
"drizzle-orm": "^0.41.0",
@@ -34,16 +34,20 @@
3434
"handlebars": "^4.7.8",
3535
"jsdom": "^26.1.0",
3636
"jsonwebtoken": "^9.0.2",
37+
"multer": "^1.4.5-lts.2",
3738
"nodemailer": "^6.10.1",
39+
"papaparse": "^5.5.2",
3840
"pg": "^8.14.1",
3941
"pg-promise": "^11.13.0",
4042
"postgres": "^3.4.5",
43+
"randombytes": "^2.1.0",
4144
"randomstring": "^1.3.1"
4245
},
4346
"devDependencies": {
4447
"@types/cors": "^2.8.17",
4548
"@types/express": "^5.0.1",
4649
"@types/node": "^22.14.1",
50+
"@types/papaparse": "^5.3.15",
4751
"@types/pg": "^8.11.12",
4852
"nodemon": "^3.1.9",
4953
"ts-node": "^10.9.2",

backend/src/controllers/permanence.controller.ts

+19
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { Request, Response } from "express";
22
import * as permanence_service from "../services/permanence.service";
33
import { Ok, Error } from "../utils/responses";
44

5+
interface MulterRequest extends Request {
6+
file?: Express.Multer.File;
7+
}
8+
59
// Validation des données de permanence
610
const validatePermanenceData = (start_at: string, end_at: string) => {
711
const startDate = new Date(start_at);
@@ -295,4 +299,19 @@ export const removeUserToPermanence = async (req: Request, res: Response) => {
295299
}
296300
};
297301

302+
export const uploadPermanencesCSV = async (req: MulterRequest, res: Response) => {
303+
try {
304+
const file = req.file;
305+
if (!file) {
306+
Error(res, { msg: "Fichier CSV manquant." });
307+
}
308+
309+
await permanence_service.importPermanencesFromCSV(file.path);
310+
Ok(res,{ msg: "Importation réalisée avec succès." });
311+
} catch (error) {
312+
console.error("Erreur import CSV :", error);
313+
Error(res, { msg: "Échec de l'importation." });
314+
}
315+
};
316+
298317

backend/src/controllers/team.controller.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const createNewTeam = async (req: Request, res: Response) => {
1919
Error(res, { msg: "Il n'y a pas assez de membre dans l'équipe." });
2020
return;
2121
}
22-
if(members.length >= 5){
22+
if(members.length > 5){
2323
Error(res, { msg: "Il y a trop de membre dans l'équipe." });
2424
return;
2525
}

backend/src/controllers/user.controller.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ export const getUsersByPermission = async (req: Request, res: Response) => {
3434

3535

3636
export const syncNewstudent = async (req: Request, res: Response) => {
37+
38+
const {date} = req.body;
39+
3740
try {
3841

3942
const token = await SIEP_Utils.getTokenUTTAPI();
40-
const newStudents = await SIEP_Utils.getNewStudentsFromUTTAPI(token);
43+
const newStudents = await SIEP_Utils.getNewStudentsFromUTTAPI(token, date);
4144
//const newStudentfiltered = newStudents.filter((student : any) => !noSyncEmails.includes(student.email));
4245

4346
newStudents.forEach( async (element: any) => {

backend/src/middlewares/user.middleware.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import { Request, Response, NextFunction } from 'express';
2-
import jwt from 'jsonwebtoken';
3-
import { jwtSecret } from '../utils/secret';
42
import { Unauthorized } from '../utils/responses';
53

64
// Middleware pour vérifier le rôle

backend/src/routes/permanences.routes.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import express from "express";
2+
import multer from "multer";
23
import * as permanenceController from "../controllers/permanence.controller";
34
import { checkRole } from "../middlewares/user.middleware";
45

56
const permanenceRouter = express.Router();
7+
const upload = multer({ dest: "uploads/" });
68

79
// Admin routes
810
permanenceRouter.post("/admin/permanence", checkRole("Admin"), permanenceController.createPermanence);
@@ -14,6 +16,7 @@ permanenceRouter.get("/admin/permanences", checkRole("Admin"), permanenceControl
1416
permanenceRouter.get("/admin/users", checkRole("Admin"), permanenceController.getUsersInPermanence);
1517
permanenceRouter.post("/admin/add", checkRole("Admin"), permanenceController.addUserToPermanence);
1618
permanenceRouter.post("/admin/remove", checkRole("Admin"), permanenceController.removeUserToPermanence);
19+
permanenceRouter.post("/admin/importpermanences", upload.single("file"), permanenceController.uploadPermanencesCSV);
1720

1821

1922
// Student routes

backend/src/services/auth.service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { db } from '../database/db'
22
import bcrypt from 'bcryptjs';
33
import jwt from 'jsonwebtoken';
4-
import crypto from "crypto";
4+
import rdmb from "randombytes";
55
import { JSDOM } from 'jsdom';
66
import { cas_validate_url, jwtSecret, service_url } from '../utils/secret';
77
import * as userservice from './user.service';
@@ -139,7 +139,7 @@ export const completeRegistration = async(token : string, password : string) =>
139139
}
140140

141141
export const createRegistrationToken = async(userId: number) => {
142-
const token = crypto.randomBytes(32).toString("hex"); // Jeton bien sécurisé
142+
const token = rdmb.randomBytes(32).toString("hex"); // Jeton bien sécurisé
143143
const expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24 * 90); // 90Jours
144144

145145
await db.insert(registrationSchema).values({

backend/src/services/permanence.service.ts

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1+
import fs from "fs";
2+
import Papa from "papaparse";
13
import { and, count, eq, sql } from "drizzle-orm";
24
import { userSchema } from "../schemas/Basic/user.schema";
35
import { permanenceSchema } from "../schemas/Basic/permanence.schema";
46
import { db } from "../database/db";
57
import { userPermanenceSchema } from "../schemas/Relational/userpermanences.schema";
68

9+
type CsvPermanence = {
10+
name: string;
11+
description: string;
12+
location: string;
13+
start_at: string; // ISO string
14+
end_at: string;
15+
capacity: string;
16+
is_open: string; // 'true' or 'false'
17+
};
18+
719
// Classes d'erreurs personnalisées
820
class UnauthorizedError extends Error {}
921
class AlreadyRegisteredError extends Error {}
@@ -250,4 +262,30 @@ export const getAllPermanencesWithUsers = async () => {
250262
);
251263

252264
return results;
253-
};
265+
};
266+
267+
export const importPermanencesFromCSV = async (filePath: string): Promise<void> => {
268+
const fileContent = fs.readFileSync(filePath, "utf8");
269+
270+
const { data, errors } = Papa.parse<CsvPermanence>(fileContent, {
271+
header: true,
272+
skipEmptyLines: true,
273+
});
274+
275+
if (errors.length > 0) {
276+
console.error("CSV parsing errors:", errors);
277+
throw new Error("Erreur lors du parsing du CSV.");
278+
}
279+
280+
const parsedData = data.map((r) => ({
281+
name: r.name,
282+
description: r.description,
283+
location: r.location,
284+
start_at: new Date(r.start_at),
285+
end_at: new Date(r.end_at),
286+
capacity: parseInt(r.capacity, 10),
287+
is_open: r.is_open?.toLowerCase() === "true",
288+
}));
289+
290+
await db.insert(permanenceSchema).values(parsedData);
291+
};

backend/src/utils/siep.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ export const getTokenUTTAPI = async() => {
1818
}
1919
}
2020

21-
export const getNewStudentsFromUTTAPI = async (token: string) => {
21+
export const getNewStudentsFromUTTAPI = async (token: string, date : string) => {
2222
const allNewStudents: any[] = [];
2323
let currentPage = 1;
2424
let hasNextPage = true;
2525

2626
try {
2727
while (hasNextPage) {
28-
const response = await axios.get(`${api_utt_admis_url_ismajor}?page=${currentPage}`, {
28+
const response = await axios.get(api_utt_admis_url_ismajor+date+"?page="+currentPage, {
2929
headers: {
3030
Authorization: `Bearer ${token}`,
3131
},

frontend/src/App.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const App: React.FC = () => {
4040
<Route path="/admin/teams" element={<AdminRoute><AdminPageTeam /></AdminRoute>} />
4141
<Route path="/admin/factions" element={<AdminRoute><AdminPageFaction /></AdminRoute>} />
4242
<Route path="/admin/shotgun" element={<AdminRoute><AdminPageShotgun /></AdminRoute>} />
43-
<Route path="/admin/export" element={<AdminRoute><AdminPageExport /></AdminRoute>} />
43+
<Route path="/admin/export-import" element={<AdminRoute><AdminPageExport /></AdminRoute>} />
4444
<Route path="/admin/permanences" element={<AdminRoute><AdminPagePerm /></AdminRoute>} />
4545
<Route path="/admin/challenge" element={<AdminRoute><AdminPageChall /></AdminRoute>} />
4646
<Route path="/admin/email" element={<AdminRoute><AdminPageEmail /></AdminRoute>} />

frontend/src/components/Admin/adminExport.tsx

-48
This file was deleted.

0 commit comments

Comments
 (0)