From deaaa8bc9b393993720b1e0abb03454da30ce2dc Mon Sep 17 00:00:00 2001
From: MathieuSevignyLavallee
<89943988+MathieuSevignyLavallee@users.noreply.github.com>
Date: Wed, 16 Oct 2024 22:12:26 -0400
Subject: [PATCH] added permission for teacher routes.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
coté backend doit etre fait
---
client/package-lock.json | 9 +++++
client/package.json | 1 +
client/src/App.tsx | 25 ++++++------
.../AuthManager/callback/AuthCallback.tsx | 5 +++
.../providers/SimpleLogin/Register.tsx | 39 ++++++++++++-------
.../src/pages/Teacher/Register/Register.tsx | 2 +-
client/src/services/ApiService.tsx | 38 +++++++++++++++---
docker-compose.yaml | 2 +-
8 files changed, 87 insertions(+), 34 deletions(-)
diff --git a/client/package-lock.json b/client/package-lock.json
index be0ca9d..666c61e 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -22,6 +22,7 @@
"esbuild": "^0.23.1",
"gift-pegjs": "^1.0.2",
"jest-environment-jsdom": "^29.7.0",
+ "jwt-decode": "^4.0.0",
"katex": "^0.16.11",
"marked": "^14.1.2",
"nanoid": "^5.0.2",
@@ -9417,6 +9418,14 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/jwt-decode": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
+ "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/katex": {
"version": "0.16.11",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.11.tgz",
diff --git a/client/package.json b/client/package.json
index 6a7de25..8f2a8ad 100644
--- a/client/package.json
+++ b/client/package.json
@@ -26,6 +26,7 @@
"esbuild": "^0.23.1",
"gift-pegjs": "^1.0.2",
"jest-environment-jsdom": "^29.7.0",
+ "jwt-decode": "^4.0.0",
"katex": "^0.16.11",
"marked": "^14.1.2",
"nanoid": "^5.0.2",
diff --git a/client/src/App.tsx b/client/src/App.tsx
index fd0ee1a..5199afa 100644
--- a/client/src/App.tsx
+++ b/client/src/App.tsx
@@ -26,23 +26,24 @@ import ApiService from './services/ApiService';
import OAuthCallback from './pages/AuthManager/callback/AuthCallback';
const App: React.FC = () => {
- const [isAuthenticated, setIsAuthenticated] = useState(ApiService.isLoggedIn()); // Initial check
- const location = useLocation(); // Hook to detect route changes
+ const [isAuthenticated, setIsAuthenticated] = useState(ApiService.isLoggedIn());
+ const [isTeacherAuthenticated, setIsTeacherAuthenticated] = useState(ApiService.isLoggedInTeacher());
+ const location = useLocation();
// Check login status every time the route changes
useEffect(() => {
const checkLoginStatus = () => {
- const loggedIn = ApiService.isLoggedIn();
- setIsAuthenticated(loggedIn); // Update state if login status changes
- console.log('App.tsx - Login status:', loggedIn);
+ setIsAuthenticated(ApiService.isLoggedIn());
+ setIsTeacherAuthenticated(ApiService.isLoggedInTeacher());
};
- checkLoginStatus(); // Check login status whenever the route changes
- }, [location]); // Re-run when the location (route) changes
+ checkLoginStatus();
+ }, [location]);
const handleLogout = () => {
ApiService.logout();
- setIsAuthenticated(false); // Ensure we log out the user in the state as well
+ setIsAuthenticated(false);
+ setIsTeacherAuthenticated(false);
};
return (
@@ -57,19 +58,19 @@ const App: React.FC = () => {
{/* Pages espace enseignant */}
: }
+ element={isTeacherAuthenticated ? : }
/>
: }
+ element={isTeacherAuthenticated ? : }
/>
: }
+ element={isTeacherAuthenticated ? : }
/>
: }
+ element={isTeacherAuthenticated ? : }
/>
{/* Pages espace étudiant */}
diff --git a/client/src/pages/AuthManager/callback/AuthCallback.tsx b/client/src/pages/AuthManager/callback/AuthCallback.tsx
index a5a4138..c9b4997 100644
--- a/client/src/pages/AuthManager/callback/AuthCallback.tsx
+++ b/client/src/pages/AuthManager/callback/AuthCallback.tsx
@@ -1,6 +1,7 @@
import { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import apiService from '../../../services/ApiService';
+import { jwtDecode } from 'jwt-decode';
const OAuthCallback: React.FC = () => {
const navigate = useNavigate();
@@ -15,6 +16,10 @@ const OAuthCallback: React.FC = () => {
console.log(user);
apiService.saveToken(user);
+ const decodedToken = jwtDecode(user);
+ const { email } = decodedToken as { email: string;};
+ console.log(email + " connected!");
+
// Navigate to the dashboard or another page
navigate('/');
} else {
diff --git a/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx b/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx
index 5683e6d..305b5ab 100644
--- a/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx
+++ b/client/src/pages/AuthManager/providers/SimpleLogin/Register.tsx
@@ -1,13 +1,12 @@
-
import { useNavigate } from 'react-router-dom';
// JoinRoom.tsx
import React, { useEffect, useState } from 'react';
-import { TextField } from '@mui/material';
+import { TextField, FormLabel, RadioGroup, FormControlLabel, Radio, Box } from '@mui/material';
import LoadingButton from '@mui/lab/LoadingButton';
-import LoginContainer from '../../../../components/LoginContainer/LoginContainer'
+import LoginContainer from '../../../../components/LoginContainer/LoginContainer';
import ApiService from '../../../../services/ApiService';
const Register: React.FC = () => {
@@ -15,33 +14,31 @@ const Register: React.FC = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
+ const [role, setRole] = useState('etudiant');
const [connectionError, setConnectionError] = useState('');
const [isConnecting] = useState(false);
useEffect(() => {
- return () => {
-
- };
+ return () => { };
}, []);
const register = async () => {
- const result = await ApiService.register(email, password);
+ const result = await ApiService.register(email, password, role);
- if (result != true) {
+ if (result !== true) {
setConnectionError(result);
return;
}
- navigate("/login")
+ navigate("/login");
};
-
return (
-
+ title="Créer un compte"
+ error={connectionError}
+ >
{
fullWidth
/>
+
+ Choisir votre rôle
+ setRole(e.target.value)}
+ >
+ } label="Étudiant" />
+ } label="Professeur" />
+
+
+
{
>
S'inscrire
-
-
);
};
diff --git a/client/src/pages/Teacher/Register/Register.tsx b/client/src/pages/Teacher/Register/Register.tsx
index 29d5f2b..2dd1f3c 100644
--- a/client/src/pages/Teacher/Register/Register.tsx
+++ b/client/src/pages/Teacher/Register/Register.tsx
@@ -26,7 +26,7 @@ const Register: React.FC = () => {
}, []);
const register = async () => {
- const result = await ApiService.register(email, password);
+ const result = await ApiService.register(email, password, "temp"); // "temp", car ce fichier n'est plus utilisé. il est déplacer dans /AuthManager
if (result != true) {
setConnectionError(result);
diff --git a/client/src/services/ApiService.tsx b/client/src/services/ApiService.tsx
index ab667b2..5b1ba7b 100644
--- a/client/src/services/ApiService.tsx
+++ b/client/src/services/ApiService.tsx
@@ -1,4 +1,5 @@
import axios, { AxiosError, AxiosResponse } from 'axios';
+import {jwtDecode} from 'jwt-decode';
import { ENV_VARIABLES } from '../constants';
import { QuizType } from '../Types/QuizType';
@@ -66,8 +67,6 @@ class ApiService {
public isLoggedIn(): boolean {
const token = this.getToken()
- console.log("Check if loggedIn : " + token);
-
if (token == null) {
return false;
}
@@ -78,6 +77,35 @@ class ApiService {
return true;
}
+ public isLoggedInTeacher(): boolean {
+ const token = this.getToken();
+
+ console.log("Check if loggedIn : " + token);
+
+ if (token == null) {
+ return false;
+ }
+
+ try {
+ const decodedToken = jwtDecode(token) as { role: string };
+
+ const userRole = decodedToken.role;
+ const requiredRole = 'professeur';
+
+ if (userRole !== requiredRole) {
+ return false;
+ }
+
+ // Update token expiry
+ this.saveToken(token);
+
+ return true;
+ } catch (error) {
+ console.error("Error decoding token:", error);
+ return false;
+ }
+ }
+
public logout(): void {
return localStorage.removeItem("jwt");
}
@@ -88,7 +116,7 @@ class ApiService {
* @returns true if successful
* @returns A error string if unsuccessful,
*/
- public async register(email: string, password: string): Promise {
+ public async register(email: string, password: string, role: string): Promise {
try {
if (!email || !password) {
@@ -97,7 +125,7 @@ class ApiService {
const url: string = this.constructRequestUrl(`/user/register`);
const headers = this.constructRequestHeaders();
- const body = { email, password };
+ const body = { email, password, role };
const result: AxiosResponse = await axios.post(url, body, { headers: headers });
@@ -881,4 +909,4 @@ class ApiService {
}
const apiService = new ApiService();
-export default apiService;
+export default apiService;
\ No newline at end of file
diff --git a/docker-compose.yaml b/docker-compose.yaml
index b116e82..898a78a 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -4,7 +4,7 @@ services:
frontend:
build:
- context: ./server
+ context: ./client
dockerfile: Dockerfile
container_name: frontend
ports: