From a49ab4a02ae10205918b345e4c23086bfbcfb9fd Mon Sep 17 00:00:00 2001 From: Kan-A-Pesh Date: Sat, 24 Feb 2024 20:15:26 +0100 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=9A=A8=20Update=20ESLint=20configurat?= =?UTF-8?q?ion=20and=20package.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.eslintrc.cjs | 28 +++++++++-------------- frontend/package.json | 52 +++++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs index d6c9537..da4b84e 100644 --- a/frontend/.eslintrc.cjs +++ b/frontend/.eslintrc.cjs @@ -1,18 +1,12 @@ module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], - rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, -} + root: true, + env: { browser: true, es2020: true }, + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:react-hooks/recommended"], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], + rules: { + "react-refresh/only-export-components": ["warn", { allowConstantExport: true }], + "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], + }, +}; diff --git a/frontend/package.json b/frontend/package.json index 1a0721b..98eb63c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,28 +1,28 @@ { - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" - }, - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@typescript-eslint/eslint-plugin": "^6.14.0", - "@typescript-eslint/parser": "^6.14.0", - "@vitejs/plugin-react-swc": "^3.5.0", - "eslint": "^8.55.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", - "typescript": "^5.2.2", - "vite": "^5.0.8" - } + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react-swc": "^3.5.0", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } } From 1a2c65a9cd86100f41fa75698532bbcb28372100 Mon Sep 17 00:00:00 2001 From: Alexi Reyes Date: Mon, 26 Feb 2024 20:07:39 +0100 Subject: [PATCH 2/4] added ban-unban --- backend/controllers/Account.ts | 168 +++++++++++++++++++++++++++++---- backend/package-lock.json | 1 - 2 files changed, 152 insertions(+), 17 deletions(-) diff --git a/backend/controllers/Account.ts b/backend/controllers/Account.ts index 9d79db4..274f0c5 100644 --- a/backend/controllers/Account.ts +++ b/backend/controllers/Account.ts @@ -1,4 +1,13 @@ -import type express from "express"; +import type SocketIO from "socket.io"; +import express from "express"; +import nodemailer from "nodemailer"; +import { + generateAuthenticationToken, + generateAuthorizationToken, + verifyAuthorizationToken, +} from "../auth/tokenUtils"; +import { PrismaClient } from "@prisma/client"; +const prisma = new PrismaClient(); class AccountController { /** @@ -8,12 +17,16 @@ class AccountController { * @param req The Express request object * @param res The Express response object */ - public static async sendMagicLink(req: express.Request, res: express.Response) { + public static async sendMagicLink( + req: express.Request, + res: express.Response + ) { // TODO: Send a magic link containing the AUTHORIZATION token to the user's email /** * VALIDATION * * Validate the user email (must be a Devinci email) * + * PROCESS * * Generate an AUTHORIZATION token * * Send the magic link to the user's email @@ -22,6 +35,44 @@ class AccountController { * * Send a success message * * Send an error message if the email is invalid */ + const { email } = req.body; + + const isDevinciEmail = (email: string): boolean => { + const expression: RegExp = /^[a-zA-Z0-9._-]+@edu\.devinci.fr$/; + + return expression.test(email); + }; + + if (isDevinciEmail(email) == true) { + const token: string = generateAuthorizationToken(email); + const link: string = `url/login?token=${token}`; + + const transporter = nodemailer.createTransport({ + host: "your_host", + port: 587, + secure: true, + auth: { + user: "your_email_address", + pass: "your_email_password", + }, + }); + + const message = { + from: "your_email", + to: email, + subject: "Lien pour se connecter", + html: `Clique pour te connecter: ${link}`, + }; + + try { + await transporter.sendMail(message); + res.status(200).send("Lien envoyé. Regarder vos mails."); + } catch (error) { + res.status(500).send("Une erreur s'est produite."); + } + } else { + res.send("Email non valide"); + } } /** @@ -32,19 +83,30 @@ class AccountController { * @param res The Express response object */ public static async login(req: express.Request, res: express.Response) { - // TODO: Log the user - /** - * VALIDATION - * * Validate AUTHORIZATION token - * - * PROCESS - * * Generate an AUTHENTICATION token - * - * RESPONSE - * * Send the AUTHENTICATION token - * * Send an error message if the AUTHORIZATION token is invalid - * * Send an error message if the AUTHORIZATION token is expired - */ + const { token, email } = req.body; + if (!verifyAuthorizationToken(token, email)) { + return res.status(401).send("Invalid token"); + } + + try { + const user = await prisma.account.findFirst({ + where: { + devinciEmail: email, + }, + }); + + if (!user) { + await prisma.account.create({ + data: { + devinciEmail: email, + }, + }); + } + } catch (error) { + return res.status(500).send("Unable to connect to the database"); + } + + return res.status(200).send(generateAuthenticationToken(email)); } // Admin routes @@ -92,7 +154,81 @@ class AccountController { * * Send a success message * * Send an error message if the user ID is invalid */ + const { user, target } = req.body; + + const isUserAdmin = (id: number): boolean => { + try { + const user = prisma.account.findUnique({ + where: { id: id }, + select: { isAdmin: true } + }); + + return user?.isAdmin ?? false; + } catch (error) { + return false; + } + } + + const isUserBanned = (id: number): boolean => { + try { + const user = prisma.account.findUnique({ + where: { id: id }, + select: { isBanned: true } + }); + + return user?.isAdmin ?? false; + } catch (error) { + console.log(error); + return false; + } + } + + if (isUserAdmin(user.id) == false) { + res.send("User is not an admin"); + return; + } + + + try { + if (isUserBanned(target.id) == true) { + await prisma.account.update({ + where: { id: target.id }, + data: { isBanned: false } + }); + + res.send("User unbanned successfully"); + } else if (isUserBanned(target.id) == false) { + await prisma.account.update({ + where: { id: target.id }, + data: { isBanned: true } + }); + + res.send("User banned successfully"); + } + } catch (error) { + console.error(error); + res.status(500).send("Error banning/unbanning user"); + return; + } + } + + /** + * Auth a websocket client + * @server WebSocket + * + * @param socket The client socket + * @param data The payload + */ + public static async authSocket(socket: SocketIO.Socket, [token, email]: [string, string]) { + if (verifyAuthenticationToken(token, email)) { + socket.data.token = token; + socket.data.email = email; + + socket.emit("auth-callback", true); + } else { + socket.emit("auth-callback", false); + } } } -export default AccountController; +export default AccountController; \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index 0a5e97e..586cf3b 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -19,7 +19,6 @@ }, "devDependencies": { "@types/express": "^4.17.21", - "@types/node": "^20.11.17", "@types/jsonwebtoken": "^9.0.5", "@types/node": "^20.11.16", "@typescript-eslint/eslint-plugin": "^6.21.0", From 55f5b7b5c3f7763f4cc79c41cd9514e7c836d421 Mon Sep 17 00:00:00 2001 From: "Michel Moccand-J." Date: Thu, 29 Feb 2024 18:36:24 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20account=20c?= =?UTF-8?q?ontroller=20and=20update=20package.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controllers/Account.ts | 37 ++-------------------------------- frontend/package.json | 8 -------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/backend/controllers/Account.ts b/backend/controllers/Account.ts index 1dbb8ed..50dc8b7 100644 --- a/backend/controllers/Account.ts +++ b/backend/controllers/Account.ts @@ -169,27 +169,12 @@ class AccountController { * * Send a success message * * Send an error message if the user ID is invalid */ - const { userId, command } = req.body; - - - try { - await prisma.account.findUnique({ - where: { - id: userId, - isAdmin: false - } - }); - - res.status(200).send("User is not admin"); - } catch (error) { - res.status(500).send("User is admin"); - return; - } + const { userId, isBanned } = req.body; try { await prisma.account.update({ where: { id: userId }, - data: { isBanned: command } + data: { isBanned: isBanned } }); res.status(200).send("Successful"); @@ -216,24 +201,6 @@ class AccountController { socket.emit("auth-callback", false); } } - - /** - * Auth a websocket client - * @server WebSocket - * - * @param socket The client socket - * @param data The payload - */ - public static async authSocket(socket: SocketIO.Socket, [token, email]: [string, string]) { - if (verifyAuthenticationToken(token, email)) { - socket.data.token = token; - socket.data.email = email; - - socket.emit("auth-callback", true); - } else { - socket.emit("auth-callback", false); - } - } } export default AccountController; \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 2ec32aa..7a7a69d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,21 +6,13 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", -<<<<<<< HEAD - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", -======= "lint": "eslint . --ext ts,tsx", ->>>>>>> 926e6b100cac117e69372d97fbd55ef49d927d12 "preview": "vite preview" }, "dependencies": { "react": "^18.2.0", -<<<<<<< HEAD - "react-dom": "^18.2.0" -======= "react-dom": "^18.2.0", "socket.io-client": "^4.7.4" ->>>>>>> 926e6b100cac117e69372d97fbd55ef49d927d12 }, "devDependencies": { "@types/react": "^18.2.43", From 78fee6d49f080053f0fd67276b2f5e9b6f79d1ea Mon Sep 17 00:00:00 2001 From: "Michel Moccand-J." Date: Thu, 29 Feb 2024 18:37:11 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A5=20Remove=20TODO=20comments=20i?= =?UTF-8?q?n=20AccountController?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/controllers/Account.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/backend/controllers/Account.ts b/backend/controllers/Account.ts index 50dc8b7..55c2767 100644 --- a/backend/controllers/Account.ts +++ b/backend/controllers/Account.ts @@ -156,19 +156,6 @@ class AccountController { * @param res The Express response object */ public static async banUser(req: express.Request, res: express.Response) { - // TODO: Ban/unban a user - /** - * VALIDATION - * * Check if the user is an admin - * * Validate the user ID - * - * PROCESS - * * Ban/unban the user - * - * RESPONSE - * * Send a success message - * * Send an error message if the user ID is invalid - */ const { userId, isBanned } = req.body; try {