added permission for teacher routes.

coté backend doit etre fait
This commit is contained in:
MathieuSevignyLavallee 2024-10-16 22:12:26 -04:00
parent 8770726873
commit deaaa8bc9b
8 changed files with 87 additions and 34 deletions

View file

@ -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",

View file

@ -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",

View file

@ -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 */}
<Route
path="/teacher/dashboard"
element={isAuthenticated ? <Dashboard /> : <Navigate to="/login" />}
element={isTeacherAuthenticated ? <Dashboard /> : <Navigate to="/login" />}
/>
<Route
path="/teacher/share/:id"
element={isAuthenticated ? <Share /> : <Navigate to="/login" />}
element={isTeacherAuthenticated ? <Share /> : <Navigate to="/login" />}
/>
<Route
path="/teacher/editor-quiz/:id"
element={isAuthenticated ? <QuizForm /> : <Navigate to="/login" />}
element={isTeacherAuthenticated ? <QuizForm /> : <Navigate to="/login" />}
/>
<Route
path="/teacher/manage-room/:id"
element={isAuthenticated ? <ManageRoom /> : <Navigate to="/login" />}
element={isTeacherAuthenticated ? <ManageRoom /> : <Navigate to="/login" />}
/>
{/* Pages espace étudiant */}

View file

@ -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 {

View file

@ -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<string>('');
const [isConnecting] = useState<boolean>(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 (
<LoginContainer
title='Créer un compte'
error={connectionError}>
title="Créer un compte"
error={connectionError}
>
<TextField
label="Email"
variant="outlined"
@ -63,6 +60,20 @@ const Register: React.FC = () => {
fullWidth
/>
<Box sx={{ display: 'flex', alignItems: 'center', marginBottom: '1rem' }}>
<FormLabel component="legend" sx={{ marginRight: '1rem' }}>Choisir votre rôle</FormLabel>
<RadioGroup
row
aria-label="role"
name="role"
value={role}
onChange={(e) => setRole(e.target.value)}
>
<FormControlLabel value="etudiant" control={<Radio />} label="Étudiant" />
<FormControlLabel value="professeur" control={<Radio />} label="Professeur" />
</RadioGroup>
</Box>
<LoadingButton
loading={isConnecting}
onClick={register}
@ -72,9 +83,7 @@ const Register: React.FC = () => {
>
S'inscrire
</LoadingButton>
</LoginContainer>
);
};

View file

@ -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);

View file

@ -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<any> {
public async register(email: string, password: string, role: string): Promise<any> {
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;

View file

@ -4,7 +4,7 @@ services:
frontend:
build:
context: ./server
context: ./client
dockerfile: Dockerfile
container_name: frontend
ports: