Skip to content

Commit c337b67

Browse files
committed
fix: magic links + legals
1 parent 4ecaea9 commit c337b67

File tree

11 files changed

+239
-106
lines changed

11 files changed

+239
-106
lines changed

api/src/auth/auth.controller.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import { Body, Controller, Delete, Get, Headers, HttpCode, HttpStatus, Post } from '@nestjs/common';
1+
import {
2+
Body,
3+
Controller,
4+
Delete,
5+
Get,
6+
Headers,
7+
HttpCode,
8+
HttpStatus,
9+
Post,
10+
Query,
11+
Request as Req,
12+
} from '@nestjs/common';
213
import { AuthService } from './auth.service';
314
import AuthSignInReqDto from './dto/req/auth-sign-in-req.dto';
415
import { IsPublic } from './decorator';
@@ -10,6 +21,7 @@ import { ApiAppErrorResponse } from '../app.dto';
1021
import { ConfigModule } from '../config/config.module';
1122
import AuthCreateMagicDto from './dto/req/auth-create-magic.dto';
1223
import AuthDeleteMagicDto from './dto/req/auth-delete-magic.dto';
24+
import { Request } from 'express';
1325

1426
@Controller('auth')
1527
@ApiTags('Authentication')
@@ -87,15 +99,19 @@ export class AuthController {
8799
};
88100
}
89101

90-
@HttpCode(HttpStatus.OK)
102+
@HttpCode(HttpStatus.NO_CONTENT)
91103
@IsPublic()
92104
@Post('magic')
93105
@ApiOperation({
94106
description: 'Generates a magic link for the user. This link should be sent to the user by email.',
95107
})
96108
@ApiBody({ type: AuthCreateMagicDto })
97-
async generateMagicLink(@Body() dto: AuthCreateMagicDto, @Headers() { 'X-Forwarded-for': ip }): Promise<void> {
98-
const linkData = await this.authService.generateMagicLink(dto.login, ip);
109+
async generateMagicLink(
110+
@Body() dto: AuthCreateMagicDto,
111+
@Headers() { 'X-Forwarded-for': ip },
112+
@Req() res: Request,
113+
): Promise<void> {
114+
const linkData = await this.authService.generateMagicLink(dto.login, ip || res.socket.remoteAddress);
99115
if (!linkData) throw new AppException(ERROR_CODE.INVALID_CREDENTIALS);
100116
await this.authService.sendMagicLink(dto.login, linkData.code, linkData.name);
101117
}
@@ -107,8 +123,11 @@ export class AuthController {
107123
description: 'Consumes/Deletes the magic link.',
108124
})
109125
@ApiBody({ type: AuthDeleteMagicDto })
110-
async consumeMagicLink(@Body() dto: AuthDeleteMagicDto): Promise<AccessTokenResponse> {
111-
const { token, id } = (await this.authService.consumeMagicLink(dto.spell)) ?? {};
126+
async consumeMagicLink(@Query() dto: AuthDeleteMagicDto): Promise<AccessTokenResponse> {
127+
const { token, id } =
128+
(await this.authService.consumeMagicLink(
129+
dto.spell.replaceAll(/(?<=^.{8}|^.{12}|^.{16}|^.{20})/g, '-').toLocaleLowerCase(),
130+
)) ?? {};
112131
if (!token) throw new AppException(ERROR_CODE.INVALID_CREDENTIALS);
113132
const user = id ? await this.authService.getUser(id) : undefined;
114133
return {

api/src/auth/auth.service.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -110,35 +110,45 @@ export class AuthService {
110110
}
111111

112112
async sendMagicLink(email: string, token: string, name: string): Promise<void> {
113-
return this.mail.sendGeneric({
114-
recipient: email,
115-
title: 'Accès à ton compte BuckUTT',
116-
content: `<h2>Bonjour ${name},</h2><p>Voici le lien pour accéder à ton compte BuckUTT : <a href="${this.config.FRONT_URL}/magic?spell=${token}">${this.config.FRONT_URL}/magic?spell=${token}</a></p><p>Le lien est valide pendant ${this.config.MAGIC_LINK_VALIDITY / 60000} minutes. Si tu n'as pas demandé ce lien, ignore ce message.</p><p>À bientôt !</p>`,
117-
});
113+
try {
114+
return this.mail.sendGeneric({
115+
recipient: email,
116+
title: 'Accès à ton compte BuckUTT',
117+
content: `<h2>Bonjour ${name},</h2><p>Voici le lien pour accéder à ton compte BuckUTT : <a href="${this.config.FRONT_URL}/magic?spell=${token}">${this.config.FRONT_URL}/magic?spell=${token}</a></p><p>Le lien est valide pendant ${this.config.MAGIC_LINK_VALIDITY / 60000} minutes. Si tu n'as pas demandé ce lien, ignore ce message.</p><p>À bientôt !</p>`,
118+
});
119+
} catch (e) {
120+
console.warn(e);
121+
// The student mail does not exist anymore, contact bde
122+
return null;
123+
}
118124
}
119125

120126
async consumeMagicLink(token: string): Promise<{ token: string; id: string } | null> {
121-
const link = await this.prisma.magicLink.update({
122-
data: {
123-
usedAt: new Date(),
124-
},
125-
where: {
126-
usedAt: null,
127-
token,
128-
createdAt: {
129-
gte: new Date(Date.now() - this.config.MAGIC_LINK_VALIDITY),
127+
try {
128+
const link = await this.prisma.magicLink.update({
129+
data: {
130+
usedAt: new Date(),
130131
},
131-
},
132-
select: {
133-
user: {
134-
select: {
135-
id: true,
136-
email: true,
132+
where: {
133+
usedAt: null,
134+
token,
135+
createdAt: {
136+
gte: new Date(Date.now() - this.config.MAGIC_LINK_VALIDITY),
137137
},
138138
},
139-
},
140-
});
141-
if (!link) return null;
142-
return { token: await this.signToken(link.user.id, link.user.email), id: link.user.id };
139+
select: {
140+
user: {
141+
select: {
142+
id: true,
143+
email: true,
144+
},
145+
},
146+
},
147+
});
148+
return { token: await this.signToken(link.user.id, link.user.email), id: link.user.id };
149+
} catch {
150+
// Link is not valid
151+
return null;
152+
}
143153
}
144154
}

api/src/mails/mail.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class MailService {
4545
if (!match) throw new Error('No title found in the email template');
4646
const derivedSubject = match[1];
4747
const mailOptions = {
48-
from: this.config.SMTP_FROM,
48+
from: `${this.config.SMTP_FROM} <${this.config.SMTP_USER}>`,
4949
to: recipient,
5050
subject: derivedSubject,
5151
html: content,

front/public/locales/fr/common.json.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ export default {
88
'login.explanation.line1': 'Connecte toi avec tes anciens',
99
'login.explanation.line2': 'identifiants BuckUTT',
1010
'login.loading': 'Chargement',
11+
'login.loading.2': 'Merci de patienter quelques instants...',
12+
'login.magic': 'Mot de passe oublié',
13+
'login.magic.undo': 'En fait je me souviens de mon mot de passe 🤭',
14+
'login.magic.generate': 'Se connecter avec un email',
15+
'login.magic.sent': 'Email envoyé',
16+
'login.magic.sent.2': 'Utilise le mail que tu as reçu pour te connecter',
17+
'login.magic.success': 'Tu est connecté !',
18+
'login.magic.success.2': 'Redirection en cours...',
19+
'login.magic.error': 'Une erreur est survenue...',
20+
'login.magic.error.2': 'Merci de réessayer plus tard',
1121
'login.fail.creds': 'Identifiants incorrects',
1222
'login.fail.other': 'Impossible de se connecter',
1323
'magic_link.placeholder': 'Adresse email',

front/src/app/legal/page.tsx

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ export default function LegalPage() {
1414
const ASSOCIATION_EMAIL = 'ung@utt.fr';
1515

1616
// Data Protection Officer
17-
const DPO_NAME = 'Guillaume Etheve';
17+
const DPO_NAME = 'Camille Moussou';
1818
const DPO_EMAIL = 'ung@utt.fr';
1919

2020
// Updates
21-
const LAST_TERMS_UPDATE = '15/09/2024';
22-
const LAST_PRIVACY_POLICY_UPDATE = '15/09/2024';
21+
const LAST_TERMS_UPDATE = '03/04/2025';
22+
const LAST_PRIVACY_POLICY_UPDATE = '03/04/2025';
2323

2424
return (
2525
<div id="legal" className={styles.legal}>
@@ -41,31 +41,6 @@ export default function LegalPage() {
4141
<a href={`mailto:${ASSOCIATION_EMAIL}`}>{ASSOCIATION_EMAIL}</a>
4242
</p>
4343
<h1>Conditions Générales d'Utilisation (CGU)</h1>
44-
{/* <h2 className={styles.articleTitle}>Collecte des données</h2>
45-
<p>
46-
Le site collecte certaines données personnelles renseignées par l’Utilisateur sur le site telles que le nom et
47-
le prénom. Ces données ne seront en aucun cas échangées, distribuées ou vendues à un tiers sans l'accord
48-
explicite de l'Utilisateur. L'Utilisateur peut, à tout moment, accorder ou révoquer son accord pour partager
49-
ses données avec les autres utilisateurs du site.
50-
<br />
51-
En vertu de la loi Informatique et Libertés, en date du 6 janvier 1978, l'Utilisateur dispose d'un droit
52-
d'accès, de rectification, de suppression et d'opposition de ses données personnelles. L'Utilisateur peut
53-
exercer ce droit directement en effectuant une demande par mail à l’adresse{' '}
54-
<a href="mailto:ung@utt.fr">ung@utt.fr</a>.
55-
<br />
56-
Le responsable du traitement des données est Guillaume ETHEVE.
57-
<br />
58-
L’équipe technique, les administrateurs, et les modérateurs du site pourront accéder aux données personnelles
59-
de l'Utilisateur, sans nécessiter l'autorisation de l'utilisateur de partager ses données personnelles avec
60-
les autres utilisateurs du site.
61-
<br />
62-
Les modérateurs du site sont désignés par l'UNG. L'UNG ne peut être tenu responsable des actions des
63-
modérateurs du site. L'UNG doit cependant s'assurer, dans les limites du raisonnable, que les modérateurs sont
64-
des personnes de confiance et respecteront la vie privée des utilisateurs.
65-
<br />
66-
Ces données seront conservées jusqu'à ce que l'Utilisateur décide de les supprimer, ou qu'il ait terminé ses
67-
études à l'Université de Technologie de Troyes et n'ait pas demandé la conservation de son compte.
68-
</p> */}
6944
<h2 className={styles.articleTitle}>Propriété intellectuelle</h2>
7045
<p>
7146
Le contenu du site internet reste la propriété de l'association ASS UTT NET GROUP, seul titulaire des droits
@@ -162,41 +137,54 @@ export default function LegalPage() {
162137
<h2 className={styles.articleTitle}>
163138
3. Données à caractère personnel collectées et traitées dans le cadre de la navigation sur le site
164139
</h2>
165-
{/* <p>
166-
Les données à caractère personnel collectées sur le site sont les suivantes :
140+
<h3 className={styles.subArticleTitle}>3.1. Données collectées</h3>
141+
<p>
142+
Les données collectés par ce site sont de trois types distincts :
167143
<ul>
168-
<li>Les données de connexion (adresse IP, logs) ;</li>
169-
<li>Les données de navigation (type de navigateur, durée de la visite, pages visitées) ;</li>
170-
<li>Les données de localisation.</li>
144+
<li>
145+
<b>les données préexistantes :</b> Certaines données (nom, prénom, adresse mail, mot de passe, solde
146+
buckutt) sont issues des informations des anciens comptes buckutt. Elles ne peuvent en aucun cas être
147+
issues d'un autre service.
148+
</li>
149+
<li>
150+
<b>les données renseignées :</b> L'utilisateur est incité à fournir certaines données dans le cadre du
151+
fonctionnement du service (IBAN, BIC). Ces données sont modifiables jusqu'à émission du remboursement par
152+
l'association BDE UTT.
153+
</li>
154+
<li>
155+
<b>les données de services :</b> Afin d'assurer le bon fonctionnement du service, certaines données
156+
(adresse ip, logs, horodatages) sont collectées. Elles permettent de vérifier la légitimité des actions
157+
menées sur la plateforme et de pouvoir enquêter sur les évènements anormaux.
158+
</li>
171159
</ul>
172-
<br />
173160
</p>
174-
161+
<h3 className={styles.subArticleTitle}>3.2. Mode de collecte des données</h3>
175162
<p>
176-
En cas de création d'un compte utilisateur, sont également collectées les données suivantes :
163+
Les données sont collectées de différentes manières :
177164
<ul>
178-
<li>Nom et prénom ;</li>
179-
<li>Adresse email ;</li>
180-
<li>Numéro de téléphone ;</li>
181-
<li>Adresse postale.</li>
165+
<li>Les données préexistantes sont extraites de vos anciennes données BuckUTT.</li>
166+
<li>
167+
Les données renseignées sont fournies par l'utilisateur (vous). Vous pouvez décider ne pas les fournir
168+
mais le service ne pourra pas fonctionner correctement.
169+
</li>
170+
<li>Les données de service sont collectées par le serveur lors de l'utilisation du site internet.</li>
182171
</ul>
172+
</p>
173+
<h3 className={styles.subArticleTitle}>3.3. Transmissions des données à un tier</h3>
174+
<p>
175+
Certaines informations de l'utilisateur sont transmises à l'association BDE UTT pour permettre le service
176+
fournit par l'application. Tout utilisateur ne renseignant pas son IBAN ne verra pas ses données transmises à
177+
BDE UTT.
183178
<br />
184-
185-
186-
La collecte et le traitement de ces données répond aux finalités suivantes :
187-
179+
<br />
180+
Les informations suivantes sont transmises de manière chiffrée à BDE UTT dans le cadre de l'utilisation du
181+
service :
188182
<ul>
189-
<li>Statistiques et amélioration du site ;</li>
190-
<li>Envoi de newsletters ;</li>
191-
<li>Fonctionnement des fonctionnalités internes au site telles que le trombinoscope et le cumul d'emploi du temps ;</li>
183+
<li>Nom, Prénom</li>
184+
<li>Solde BuckUTT</li>
185+
<li>Informations bancaires : IBAN, BIC</li>
192186
</ul>
193-
</p> */}
194-
<h3 className={styles.subArticleTitle}>3.1. Données collectées</h3>
195-
<p>{/** TODO: Add Data collected */}</p>
196-
<h3 className={styles.subArticleTitle}>3.2. Mode de collecte des données</h3>
197-
<p>{/** TODO: Add Data Collection Mode */}</p>
198-
<h3 className={styles.subArticleTitle}>3.3. Transmissions des données à un tier</h3>
199-
<p>{/** TODO: Add Matomo and Sentry here */}</p>
187+
</p>
200188
<h3 className={styles.subArticleTitle}>3.4. Informations relatives aux cookies</h3>
201189
<p>
202190
Nous utilisons des cookies afin d'obtenir des statistiques sur notre site web. Ces informations ne seront en

0 commit comments

Comments
 (0)