From acd7cd7329085c419f767aa703c885040f9c85de Mon Sep 17 00:00:00 2001 From: Antoine Date: Sun, 30 Aug 2026 22:06:31 +0200 Subject: [PATCH 1/6] fix: consider timezone in perm notifications --- backend/src/services/permanence.service.ts | 43 ++++++++++++++-------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/backend/src/services/permanence.service.ts b/backend/src/services/permanence.service.ts index 6f182db..d576c91 100644 --- a/backend/src/services/permanence.service.ts +++ b/backend/src/services/permanence.service.ts @@ -25,6 +25,17 @@ import { respoPermanenceSchema, userPermanenceSchema } from '../schemas/Relation import { email_from } from '../shared/secrets/secrets'; import { generateEmailHtml, sendEmail } from './email.service'; +const PARIS_TIMEZONE = 'Europe/Paris'; + +const formatParisDate = (date: Date | null | undefined, options: Intl.DateTimeFormatOptions) => { + if (!date) return ''; + + return new Intl.DateTimeFormat('fr-FR', { + ...options, + timeZone: PARIS_TIMEZONE, + }).format(new Date(date)); +}; + export const getPermanenceById = async (permId: number) => { const permanence = await db.query.permanenceSchema.findFirst({ where: eq(permanenceSchema.id, permId), @@ -429,8 +440,8 @@ export const claimMember = async (userId: number, permId: number, claimed: boole export const getDailyNotifications = async (): Promise => { const permanences = await db.query.permanenceSchema.findMany({ where: sql` - ${permanenceSchema.start_at} >= CURRENT_DATE + INTERVAL '1 day' - AND ${permanenceSchema.start_at} < CURRENT_DATE + INTERVAL '2 day' + (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') >= (timezone('Europe/Paris', now()) + interval '1 day') + AND (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') < (timezone('Europe/Paris', now()) + interval '2 day') `, orderBy: permanenceSchema.start_at, }); @@ -441,8 +452,8 @@ export const getDailyNotifications = async (): Promise => { export const getHourlyNotifications = async (): Promise => { const permanences = await db.query.permanenceSchema.findMany({ where: sql` - ${permanenceSchema.start_at} >= now() + interval '1 hour' - AND ${permanenceSchema.start_at} < now() + interval '1 hour 5 minutes' + (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') >= (timezone('Europe/Paris', now()) + interval '1 hour') + AND (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') < (timezone('Europe/Paris', now()) + interval '1 hour 5 minutes') `, orderBy: permanenceSchema.start_at, }); @@ -649,22 +660,22 @@ export const sendNotifications = async (notifications: Notification[]) => { for (const notification of notifications) { const permanenceEmailData: PermanenceEmailData = { permName: notification.permanence.name, - permBeginDate: new Intl.DateTimeFormat('fr-FR', { + permBeginDate: formatParisDate(notification.permanence.start_at, { day: '2-digit', month: 'long', - }).format(notification.permanence.start_at), - permBeginHour: new Intl.DateTimeFormat('fr-FR', { + }), + permBeginHour: formatParisDate(notification.permanence.start_at, { hour: '2-digit', minute: '2-digit', - }).format(notification.permanence.start_at), - permEndDate: new Intl.DateTimeFormat('fr-FR', { + }), + permEndDate: formatParisDate(notification.permanence.end_at, { day: '2-digit', month: 'long', - }).format(notification.permanence.end_at), - permEndHour: new Intl.DateTimeFormat('fr-FR', { + }), + permEndHour: formatParisDate(notification.permanence.end_at, { hour: '2-digit', minute: '2-digit', - }).format(notification.permanence.end_at), + }), permLocation: notification.permanence.location, permDescription: notification.permanence.description, }; @@ -696,18 +707,18 @@ export const sendConcurrentPermanenceNotifications = async (notifications: Concu const permanenceEmailData: ConcurrentPermanencesEmailData = { permanences: notification.permanences.map((permanence) => ({ name: permanence.name, - startAt: new Intl.DateTimeFormat('fr-FR', { + startAt: formatParisDate(permanence.start_at, { day: '2-digit', month: 'long', hour: '2-digit', minute: '2-digit', - }).format(permanence.start_at), - endAt: new Intl.DateTimeFormat('fr-FR', { + }), + endAt: formatParisDate(permanence.end_at, { day: '2-digit', month: 'long', hour: '2-digit', minute: '2-digit', - }).format(permanence.end_at), + }), location: permanence.location, })), }; From 8c7182489b4e6048f686374f1416f06d1d9e302f Mon Sep 17 00:00:00 2001 From: Antoine Date: Mon, 31 Aug 2026 23:41:41 +0200 Subject: [PATCH 2/6] Revert "fix: consider timezone in perm notifications" This reverts commit acd7cd7329085c419f767aa703c885040f9c85de. --- backend/src/services/permanence.service.ts | 43 ++++++++-------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/backend/src/services/permanence.service.ts b/backend/src/services/permanence.service.ts index d576c91..6f182db 100644 --- a/backend/src/services/permanence.service.ts +++ b/backend/src/services/permanence.service.ts @@ -25,17 +25,6 @@ import { respoPermanenceSchema, userPermanenceSchema } from '../schemas/Relation import { email_from } from '../shared/secrets/secrets'; import { generateEmailHtml, sendEmail } from './email.service'; -const PARIS_TIMEZONE = 'Europe/Paris'; - -const formatParisDate = (date: Date | null | undefined, options: Intl.DateTimeFormatOptions) => { - if (!date) return ''; - - return new Intl.DateTimeFormat('fr-FR', { - ...options, - timeZone: PARIS_TIMEZONE, - }).format(new Date(date)); -}; - export const getPermanenceById = async (permId: number) => { const permanence = await db.query.permanenceSchema.findFirst({ where: eq(permanenceSchema.id, permId), @@ -440,8 +429,8 @@ export const claimMember = async (userId: number, permId: number, claimed: boole export const getDailyNotifications = async (): Promise => { const permanences = await db.query.permanenceSchema.findMany({ where: sql` - (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') >= (timezone('Europe/Paris', now()) + interval '1 day') - AND (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') < (timezone('Europe/Paris', now()) + interval '2 day') + ${permanenceSchema.start_at} >= CURRENT_DATE + INTERVAL '1 day' + AND ${permanenceSchema.start_at} < CURRENT_DATE + INTERVAL '2 day' `, orderBy: permanenceSchema.start_at, }); @@ -452,8 +441,8 @@ export const getDailyNotifications = async (): Promise => { export const getHourlyNotifications = async (): Promise => { const permanences = await db.query.permanenceSchema.findMany({ where: sql` - (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') >= (timezone('Europe/Paris', now()) + interval '1 hour') - AND (${permanenceSchema.start_at} AT TIME ZONE 'Europe/Paris') < (timezone('Europe/Paris', now()) + interval '1 hour 5 minutes') + ${permanenceSchema.start_at} >= now() + interval '1 hour' + AND ${permanenceSchema.start_at} < now() + interval '1 hour 5 minutes' `, orderBy: permanenceSchema.start_at, }); @@ -660,22 +649,22 @@ export const sendNotifications = async (notifications: Notification[]) => { for (const notification of notifications) { const permanenceEmailData: PermanenceEmailData = { permName: notification.permanence.name, - permBeginDate: formatParisDate(notification.permanence.start_at, { + permBeginDate: new Intl.DateTimeFormat('fr-FR', { day: '2-digit', month: 'long', - }), - permBeginHour: formatParisDate(notification.permanence.start_at, { + }).format(notification.permanence.start_at), + permBeginHour: new Intl.DateTimeFormat('fr-FR', { hour: '2-digit', minute: '2-digit', - }), - permEndDate: formatParisDate(notification.permanence.end_at, { + }).format(notification.permanence.start_at), + permEndDate: new Intl.DateTimeFormat('fr-FR', { day: '2-digit', month: 'long', - }), - permEndHour: formatParisDate(notification.permanence.end_at, { + }).format(notification.permanence.end_at), + permEndHour: new Intl.DateTimeFormat('fr-FR', { hour: '2-digit', minute: '2-digit', - }), + }).format(notification.permanence.end_at), permLocation: notification.permanence.location, permDescription: notification.permanence.description, }; @@ -707,18 +696,18 @@ export const sendConcurrentPermanenceNotifications = async (notifications: Concu const permanenceEmailData: ConcurrentPermanencesEmailData = { permanences: notification.permanences.map((permanence) => ({ name: permanence.name, - startAt: formatParisDate(permanence.start_at, { + startAt: new Intl.DateTimeFormat('fr-FR', { day: '2-digit', month: 'long', hour: '2-digit', minute: '2-digit', - }), - endAt: formatParisDate(permanence.end_at, { + }).format(permanence.start_at), + endAt: new Intl.DateTimeFormat('fr-FR', { day: '2-digit', month: 'long', hour: '2-digit', minute: '2-digit', - }), + }).format(permanence.end_at), location: permanence.location, })), }; From 74ac30a44088b95ce66cc1ad789a36739d6e6d2d Mon Sep 17 00:00:00 2001 From: Antoine Date: Mon, 31 Aug 2026 23:55:49 +0200 Subject: [PATCH 3/6] fix: adjust notification times for timezone handling --- backend/src/services/permanence.service.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/src/services/permanence.service.ts b/backend/src/services/permanence.service.ts index 6f182db..d978367 100644 --- a/backend/src/services/permanence.service.ts +++ b/backend/src/services/permanence.service.ts @@ -441,8 +441,8 @@ export const getDailyNotifications = async (): Promise => { export const getHourlyNotifications = async (): Promise => { const permanences = await db.query.permanenceSchema.findMany({ where: sql` - ${permanenceSchema.start_at} >= now() + interval '1 hour' - AND ${permanenceSchema.start_at} < now() + interval '1 hour 5 minutes' + ${permanenceSchema.start_at} >= now() + interval '3 hour' -- 1 hour + 2 for timezone + AND ${permanenceSchema.start_at} < now() + interval '3 hour 5 minutes' -- 1 hour + 2 for timezone `, orderBy: permanenceSchema.start_at, }); @@ -652,19 +652,19 @@ export const sendNotifications = async (notifications: Notification[]) => { permBeginDate: new Intl.DateTimeFormat('fr-FR', { day: '2-digit', month: 'long', - }).format(notification.permanence.start_at), + }).format(new Date(notification.permanence.start_at.getTime() + 2 * 3600000)), permBeginHour: new Intl.DateTimeFormat('fr-FR', { hour: '2-digit', minute: '2-digit', - }).format(notification.permanence.start_at), + }).format(new Date(notification.permanence.start_at.getTime() + 2 * 3600000)), permEndDate: new Intl.DateTimeFormat('fr-FR', { day: '2-digit', month: 'long', - }).format(notification.permanence.end_at), + }).format(new Date(notification.permanence.end_at.getTime() + 2 * 3600000)), permEndHour: new Intl.DateTimeFormat('fr-FR', { hour: '2-digit', minute: '2-digit', - }).format(notification.permanence.end_at), + }).format(new Date(notification.permanence.end_at.getTime() + 2 * 3600000)), permLocation: notification.permanence.location, permDescription: notification.permanence.description, }; @@ -701,13 +701,13 @@ export const sendConcurrentPermanenceNotifications = async (notifications: Concu month: 'long', hour: '2-digit', minute: '2-digit', - }).format(permanence.start_at), + }).format(new Date(permanence.start_at.getTime() + 2 * 3600000)), endAt: new Intl.DateTimeFormat('fr-FR', { day: '2-digit', month: 'long', hour: '2-digit', minute: '2-digit', - }).format(permanence.end_at), + }).format(new Date(permanence.end_at.getTime() + 2 * 3600000)), location: permanence.location, })), }; From 448ef2aebb2ab8bf937f527fafa984b7dbf4d92c Mon Sep 17 00:00:00 2001 From: Antoine Date: Tue, 1 Sep 2026 00:05:54 +0200 Subject: [PATCH 4/6] fix: seems good for timezone --- backend/src/services/permanence.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/services/permanence.service.ts b/backend/src/services/permanence.service.ts index d978367..e60ac05 100644 --- a/backend/src/services/permanence.service.ts +++ b/backend/src/services/permanence.service.ts @@ -441,8 +441,8 @@ export const getDailyNotifications = async (): Promise => { export const getHourlyNotifications = async (): Promise => { const permanences = await db.query.permanenceSchema.findMany({ where: sql` - ${permanenceSchema.start_at} >= now() + interval '3 hour' -- 1 hour + 2 for timezone - AND ${permanenceSchema.start_at} < now() + interval '3 hour 5 minutes' -- 1 hour + 2 for timezone + ${permanenceSchema.start_at} >= now() + interval '1 hour' + AND ${permanenceSchema.start_at} < now() + interval '1 hour 5 minutes' `, orderBy: permanenceSchema.start_at, }); From e9962204c60c44ebbfb917684feb71f8b8166c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Poncin?= Date: Tue, 1 Sep 2026 10:37:01 +0200 Subject: [PATCH 5/6] fix: block CAS account creation (temporary) --- backend/src/controllers/auth.controller.ts | 47 +++++++++++----------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/backend/src/controllers/auth.controller.ts b/backend/src/controllers/auth.controller.ts index 924f21d..e8754c6 100644 --- a/backend/src/controllers/auth.controller.ts +++ b/backend/src/controllers/auth.controller.ts @@ -1,11 +1,11 @@ import bcrypt from 'bcryptjs'; -import bigInt from 'big-integer'; +//import bigInt from 'big-integer'; 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 banned_service from '../services/banned.service'; +//import * as banned_service from '../services/banned.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'; @@ -58,27 +58,28 @@ export const handlecasticket: AppRequestHandler = async const CASuser = await auth_service.validateCASTicket(ticket); if (CASuser && CASuser.email && CASuser.givenName && CASuser.sn) { - // Assurez-vous que user.email est un string - let user = await user_service.getUserByEmail(CASuser.email.toLowerCase()); - if (!user) { - const isBanned = await banned_service.getBannedByEmail(CASuser.email); - - if (isBanned) { - Unauthorized(res, { msg: 'Unauthorized: user email prohibited' }); - } - - 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()); - } + // TEMPORAIRE POUR BLOQUER LA CREATION DE COMPTES NOUVEAUX + // remettre user en let + const user = await user_service.getUserByEmail(CASuser.email.toLowerCase()); + // if (!user) { + // const isBanned = await banned_service.getBannedByEmail(CASuser.email); + // + // if (isBanned) { + // Unauthorized(res, { msg: 'Unauthorized: user email prohibited' }); + // } + // + // 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; From a6bb83420b3c94bc5c3de4d87c79bd4f0cfc1ac0 Mon Sep 17 00:00:00 2001 From: Arthur Dodin <52950784+tuturd@users.noreply.github.com> Date: Tue, 1 Sep 2026 10:39:20 +0200 Subject: [PATCH 6/6] Change iframe source for meal ticket display Updated iframe source URL for the meal ticket section. --- frontend/src/components/WEI_SDI_Food/foodSection.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/WEI_SDI_Food/foodSection.tsx b/frontend/src/components/WEI_SDI_Food/foodSection.tsx index f8aa861..33ed8ec 100644 --- a/frontend/src/components/WEI_SDI_Food/foodSection.tsx +++ b/frontend/src/components/WEI_SDI_Food/foodSection.tsx @@ -100,13 +100,13 @@ export const FoodSection = () => { ) : ( <> -
+ {/*