diff --git a/Back-End/Auth/views.py b/Back-End/Auth/views.py
index 16c71dc..2eb71a5 100644
--- a/Back-End/Auth/views.py
+++ b/Back-End/Auth/views.py
@@ -148,8 +148,7 @@ class ProfileSimpleView(APIView):
def delete(self, request, id):
return bdd.delete_object(Profile, id)
-@method_decorator(csrf_protect, name='dispatch')
-@method_decorator(ensure_csrf_cookie, name='dispatch')
+@method_decorator(csrf_exempt, name='dispatch')
class LoginView(APIView):
@swagger_auto_schema(
operation_description="Connexion utilisateur",
@@ -168,13 +167,14 @@ class LoginView(APIView):
'errorFields': openapi.Schema(type=openapi.TYPE_OBJECT),
'errorMessage': openapi.Schema(type=openapi.TYPE_STRING),
'profil': openapi.Schema(type=openapi.TYPE_INTEGER),
- 'droit': openapi.Schema(type=openapi.TYPE_INTEGER)
+ 'droit': openapi.Schema(type=openapi.TYPE_INTEGER),
+ 'id': openapi.Schema(type=openapi.TYPE_INTEGER),
}
))
}
)
def post(self, request):
- data=JSONParser().parse(request)
+ data = JSONParser().parse(request)
validatorAuthentication = validator.ValidatorAuthentication(data=data)
retour = error.returnMessage[error.WRONG_ID]
validationOk, errorFields = validatorAuthentication.validate()
@@ -196,13 +196,12 @@ class LoginView(APIView):
else:
retour = error.returnMessage[error.WRONG_ID]
-
return JsonResponse({
- 'errorFields':errorFields,
- 'errorMessage':retour,
- 'profil':user.id if user else -1,
- 'droit':user.droit if user else -1,
- #'jwtToken':jwt_token if profil != -1 else ''
+ 'errorFields': errorFields,
+ 'errorMessage': retour,
+ 'profil': user.id if user else -1,
+ 'droit': user.droit if user else -1,
+ 'id': user.id if user else -1,
}, safe=False)
@method_decorator(csrf_protect, name='dispatch')
diff --git a/Back-End/N3wtSchool/settings.py b/Back-End/N3wtSchool/settings.py
index 1ce52b6..8f08fac 100644
--- a/Back-End/N3wtSchool/settings.py
+++ b/Back-End/N3wtSchool/settings.py
@@ -252,19 +252,10 @@ CORS_ALLOW_ALL_HEADERS = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
- 'http://localhost:3000'
+ os.getenv('CORS_ALLOWED_ORIGINS', 'http://localhost:3000')
]
-CSRF_TRUSTED_ORIGINS = [
- 'http://localhost:3000',
- 'http://localhost:8080'
-]
-
-# CORS_ALLOWED_ORIGINS = [
-# os.getenv('CORS_ALLOWED_ORIGINS', 'http://localhost:3000')
-# ]
-
-# CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', 'http://localhost:3000,http://localhost:8080').split(',')
+CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', 'http://localhost:3000,http://localhost:8080').split(',')
CSRF_COOKIE_HTTPONLY = False
CSRF_COOKIE_SECURE = False
diff --git a/Front-End/src/app/[locale]/admin/layout.js b/Front-End/src/app/[locale]/admin/layout.js
index 3f86c1c..223dc03 100644
--- a/Front-End/src/app/[locale]/admin/layout.js
+++ b/Front-End/src/app/[locale]/admin/layout.js
@@ -26,6 +26,8 @@ import {
import { disconnect } from '@/app/lib/authAction';
import { fetchEstablishment } from '@/app/lib/schoolAction';
+import ProtectedRoute from '@/components/ProtectedRoute';
+import { SessionProvider } from 'next-auth/react';
export default function Layout({
children,
@@ -73,6 +75,9 @@ export default function Layout({
return (
<>
+
+
+
{!isLoading && (
@@ -105,6 +110,9 @@ export default function Layout({
)}
+
+
+
>
);
}
diff --git a/Front-End/src/app/[locale]/admin/structure/page.js b/Front-End/src/app/[locale]/admin/structure/page.js
index dd1360c..b8de3f8 100644
--- a/Front-End/src/app/[locale]/admin/structure/page.js
+++ b/Front-End/src/app/[locale]/admin/structure/page.js
@@ -4,7 +4,7 @@ import StructureManagement from '@/components/Structure/Configuration/StructureM
import ScheduleManagement from '@/components/Structure/Planning/ScheduleManagement';
import FeesManagement from '@/components/Structure/Tarification/FeesManagement';
import DjangoCSRFToken from '@/components/DjangoCSRFToken';
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { ClassesProvider } from '@/context/ClassesContext';
import { createDatas,
updateDatas,
diff --git a/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js b/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js
index 510e121..2b95eb9 100644
--- a/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js
+++ b/Front-End/src/app/[locale]/admin/subscriptions/editInscription/page.js
@@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared';
import { FE_ADMIN_SUBSCRIPTIONS_URL } from '@/utils/Url';
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { mockStudent } from '@/data/mockStudent';
import { editRegisterForm, fetchRegisterForm } from '@/app/lib/subscriptionAction';
diff --git a/Front-End/src/app/[locale]/admin/subscriptions/page.js b/Front-End/src/app/[locale]/admin/subscriptions/page.js
index 9c09fca..9e0b486 100644
--- a/Front-End/src/app/[locale]/admin/subscriptions/page.js
+++ b/Front-End/src/app/[locale]/admin/subscriptions/page.js
@@ -42,7 +42,7 @@ import {
FE_ADMIN_SUBSCRIPTIONS_EDIT_URL } from '@/utils/Url';
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { fetchRegistrationFileGroups } from '@/app/lib/registerFileGroupAction';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
diff --git a/Front-End/src/app/[locale]/parents/editInscription/page.js b/Front-End/src/app/[locale]/parents/editInscription/page.js
index 9d44d3f..1de9938 100644
--- a/Front-End/src/app/[locale]/parents/editInscription/page.js
+++ b/Front-End/src/app/[locale]/parents/editInscription/page.js
@@ -2,7 +2,7 @@
import React, { useState } from 'react';
import InscriptionFormShared from '@/components/Inscription/InscriptionFormShared';
import { useSearchParams, useRouter } from 'next/navigation';
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { FE_PARENTS_HOME_URL} from '@/utils/Url';
import { editRegisterForm} from '@/app/lib/subscriptionAction';
diff --git a/Front-End/src/app/[locale]/users/login/page.js b/Front-End/src/app/[locale]/users/login/page.js
index f980710..64d31a5 100644
--- a/Front-End/src/app/[locale]/users/login/page.js
+++ b/Front-End/src/app/[locale]/users/login/page.js
@@ -9,9 +9,12 @@ import Button from '@/components/Button'; // Importez le composant Button
import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
import {
FE_USERS_NEW_PASSWORD_URL,
- BE_AUTH_INFO_SESSION } from '@/utils/Url';
+ BE_AUTH_INFO_SESSION,
+ FE_ADMIN_SUBSCRIPTIONS_URL,
+ FE_PARENTS_HOME_URL
+} from '@/utils/Url';
import useLocalStorage from '@/hooks/useLocalStorage';
-import { signIn } from 'next-auth/react';
+import { signIn, getSession } from 'next-auth/react';
import { useCsrfToken } from '@/context/CsrfContext'; // Importez le hook useCsrfToken
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
@@ -33,32 +36,46 @@ export default function Page() {
return data.errorMessage === ""
}
- function handleFormLogin(formData) {
+ async function handleFormLogin(formData) {
setIsLoading(true);
- console.log('Form Data', Object.fromEntries(formData.entries())); // Affichez les entrées du FormData
- console.log('csrf passé ', csrfToken); // Affichez le token CSRF
- signIn('credentials', {
- redirect: false,
- email: formData.get('login'),
- password: formData.get('password'),
- csrfToken: csrfToken // Utilisez le token CSRF récupéré par le hook
- })
- .then(result => {
+ try {
+ const result = await signIn('credentials', {
+ redirect: false,
+ email: formData.get('login'),
+ password: formData.get('password'),
+ });
+
console.log('Sign In Result', result);
setIsLoading(false);
if (result.error) {
setErrorMessage(result.error);
} else {
- router.push(result.url);
+ const session = await getSession();
+ if (!session || !session.user) {
+ throw new Error('Session not found');
+ }
+ const user = session.user;
+ console.log('User Session:', user);
+ localStorage.setItem('userId', user.id); // Stocker l'identifiant de l'utilisateur
+ if (user.droit === 0) {
+ // Vue ECOLE
+ } else if (user.droit === 1) {
+ // Vue ADMIN
+ router.push(FE_ADMIN_SUBSCRIPTIONS_URL);
+ } else if (user.droit === 2) {
+ // Vue PARENT
+ router.push(FE_PARENTS_HOME_URL);
+ } else {
+ // Cas anormal
+ }
}
- })
- .catch(error => {
+ } catch (error) {
console.error('Error during sign in:', error);
setIsLoading(false);
setErrorMessage('An error occurred during sign in.');
- });
+ }
}
if (isLoading === true) {
diff --git a/Front-End/src/app/[locale]/users/password/new/page.js b/Front-End/src/app/[locale]/users/password/new/page.js
index dcc108e..900e76d 100644
--- a/Front-End/src/app/[locale]/users/password/new/page.js
+++ b/Front-End/src/app/[locale]/users/password/new/page.js
@@ -10,7 +10,7 @@ import Button from '@/components/Button'; // Importez le composant Button
import Popup from '@/components/Popup'; // Importez le composant Popup
import { User } from 'lucide-react'; // Importez directement les icônes nécessaires
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { sendNewPassword } from '@/app/lib/authAction';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
diff --git a/Front-End/src/app/[locale]/users/password/reset/page.js b/Front-End/src/app/[locale]/users/password/reset/page.js
index cae7a16..427ad57 100644
--- a/Front-End/src/app/[locale]/users/password/reset/page.js
+++ b/Front-End/src/app/[locale]/users/password/reset/page.js
@@ -11,7 +11,7 @@ import Button from '@/components/Button'; // Importez le composant Button
import Popup from '@/components/Popup';
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
import { KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { getResetPassword, resetPassword } from '@/app/lib/authAction';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
diff --git a/Front-End/src/app/[locale]/users/subscribe/page.js b/Front-End/src/app/[locale]/users/subscribe/page.js
index 5ea51ca..768bfbc 100644
--- a/Front-End/src/app/[locale]/users/subscribe/page.js
+++ b/Front-End/src/app/[locale]/users/subscribe/page.js
@@ -11,7 +11,7 @@ import Button from '@/components/Button'; // Importez le composant Button
import Popup from '@/components/Popup'; // Importez le composant Popup
import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { subscribe } from '@/app/lib/authAction';
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
diff --git a/Front-End/src/app/layout.js b/Front-End/src/app/layout.js
index d953956..21e0d14 100644
--- a/Front-End/src/app/layout.js
+++ b/Front-End/src/app/layout.js
@@ -1,8 +1,7 @@
import React from 'react';
-import { NextIntlClientProvider } from 'next-intl';
-import { CsrfProvider } from '@/context/CsrfContext'; // Importez le CsrfProvider
-
import { getMessages } from 'next-intl/server';
+import { NextIntlClientProvider } from 'next-intl';
+import { CsrfProvider } from '@/context/CsrfContext';
import "@/css/tailwind.css";
export const metadata = {
@@ -22,14 +21,15 @@ export const metadata = {
},
};
-export default async function RootLayout({ children, params: { locale } }) {
- const messages = await getMessages();
+export default async function RootLayout({ children, params }) {
+ const { locale } = params;
+ const messages = await getMessages(locale); // Passez le locale ici
return (
- {/* Enveloppez votre application avec le CsrfProvider */}
-
+
+ {/* Passez le locale ici */}
{children}
diff --git a/Front-End/src/components/ProtectedRoute.js b/Front-End/src/components/ProtectedRoute.js
index 43f02c5..34cdd4c 100644
--- a/Front-End/src/components/ProtectedRoute.js
+++ b/Front-End/src/components/ProtectedRoute.js
@@ -1,24 +1,27 @@
import React, { useEffect } from 'react';
import { useRouter } from 'next/navigation';
-import useLocalStorage from '@/hooks/useLocalStorage';
+import { useSession } from 'next-auth/react';
+import Loader from '@/components/Loader'; // Importez le composant Loader
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
const ProtectedRoute = ({ children }) => {
+ const { data: session, status } = useSession();
const router = useRouter();
- const [userId] = useLocalStorage("userId", '');
useEffect(() => {
- if (!userId) {
+ if (status === 'loading') return; // Ne rien faire tant que le statut est "loading"
+ if (!session) {
// Rediriger vers la page de login si l'utilisateur n'est pas connecté
- router.push(FE_USERS_LOGIN_URL);
+ router.push(`${FE_USERS_LOGIN_URL}`);
}
- }, [userId, router]);
+ }, [session, status, router]);
- if (!userId) {
- return Loading...
;
+ if (status === 'loading' || !session) {
+ return ; // Affichez un loader pendant le chargement ou si l'utilisateur n'est pas connecté
}
+
// Afficher les enfants seulement si l'utilisateur est connecté
- return userId ? children : null;
+ return children;
};
export default ProtectedRoute;
\ No newline at end of file
diff --git a/Front-End/src/components/Structure/Configuration/TeachersSection.js b/Front-End/src/components/Structure/Configuration/TeachersSection.js
index 01d979c..f421b3d 100644
--- a/Front-End/src/components/Structure/Configuration/TeachersSection.js
+++ b/Front-End/src/components/Structure/Configuration/TeachersSection.js
@@ -4,7 +4,7 @@ import Table from '@/components/Table';
import Popup from '@/components/Popup';
import ToggleSwitch from '@/components/ToggleSwitch';
import { createProfile, updateProfile } from '@/app/lib/authAction';
-import useCsrfToken from '@/hooks/useCsrfToken';
+import { useCsrfToken } from '@/context/CsrfContext';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import InputText from '@/components/InputText';
diff --git a/Front-End/src/csrfMiddleware.js b/Front-End/src/csrfMiddleware.js
deleted file mode 100644
index 9638410..0000000
--- a/Front-End/src/csrfMiddleware.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { getCsrfToken } from '@/utils/getCsrfToken';
-
-export const csrfMiddleware = (handler) => {
- return async (req, res) => {
- const csrfToken = getCsrfToken();
- if (!csrfToken) {
- console.error('CSRF Token is undefined');
- }
- req.csrfToken = csrfToken;
- return handler(req, res);
- };
-};
\ No newline at end of file
diff --git a/Front-End/src/hooks/useCsrfToken.js b/Front-End/src/hooks/useCsrfToken.js
deleted file mode 100644
index a5b9ca8..0000000
--- a/Front-End/src/hooks/useCsrfToken.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// import { useEffect, useState } from 'react';
-// import { BE_AUTH_CSRF_URL } from '@/utils/Url';
-
-// const useCsrfToken = () => {
-// const [token, setToken] = useState('');
-
-// useEffect(() => {
-// fetch(`${BE_AUTH_CSRF_URL}`, {
-// method: 'GET',
-// credentials: 'include' // Inclut les cookies dans la requête
-// })
-// .then(response => response.json())
-// .then(data => {
-// if (data) {
-// if(data.csrfToken != token) {
-// setToken(data.csrfToken);
-// console.log('------------> CSRF Token reçu:', data.csrfToken);
-// }
-// }
-// })
-// .catch(error => {
-// console.error('Error fetching CSRF token:', error);
-// });
-// }, []);
-
-// return token;
-// };
-
-// export default useCsrfToken;
diff --git a/Front-End/src/pages/api/auth/[...nextauth].js b/Front-End/src/pages/api/auth/[...nextauth].js
index e08d741..51b604f 100644
--- a/Front-End/src/pages/api/auth/[...nextauth].js
+++ b/Front-End/src/pages/api/auth/[...nextauth].js
@@ -1,7 +1,6 @@
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
-import jwt from 'jsonwebtoken';
-import { csrfMiddleware } from '@/csrfMiddleware'; // Importez le middleware csrfMiddleware
+import { BE_AUTH_LOGIN_URL } from '@/utils/Url';
const options = {
providers: [
@@ -11,43 +10,32 @@ const options = {
email: { label: 'Email', type: 'email' },
password: { label: 'Password', type: 'password' }
},
- authorize: (credentials, req) => {
- console.log('Credentials:', credentials); // Vérifiez si ce log s'affiche
-
- // Utilisez le token CSRF injecté par le middleware
- const csrfToken = req.csrfToken;
- console.log("data to send : ", JSON.stringify({
- email: credentials.email,
- password: credentials.password
- }), "csrfToken : ", csrfToken);
-
- return fetch(`${process.env.NEXT_PUBLIC_API_URL}/Auth/login`, {
+ authorize: async (credentials, req) => {
+ const response = await fetch(`${BE_AUTH_LOGIN_URL}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
- 'X-CSRFToken': csrfToken // Utiliser le token CSRF ici
},
body: JSON.stringify({
email: credentials.email,
password: credentials.password
}),
credentials: 'include'
- })
- .then(response => response.text())
- .then(text => {
- console.log('Response Text:', text); // Loggez la réponse
- const user = JSON.parse(text); // Parsez la réponse en JSON
-
- if (response.ok && user) {
- return user;
- } else {
- throw new Error(user.errorMessage || 'Invalid credentials');
- }
- })
- .catch(error => {
- console.error('Error during authentication:', error);
- throw new Error('Authentication failed');
});
+
+ const user = await response.json();
+
+ console.log("API response:", user);
+ if (response.ok && user) {
+ const userData = {
+ id: user.id,
+ role: user.profil,
+ droit: user.droit
+ };
+ return userData;
+ } else {
+ throw new Error(user.errorMessage || 'Invalid credentials');
+ }
}
})
],
@@ -55,25 +43,35 @@ const options = {
jwt: true
},
callbacks: {
- async jwt(token, user) {
+ async jwt({ token, user }) {
+ console.log("JWT callback called", user);
if (user) {
token.id = user.id;
- token.email = user.email;
token.role = user.role;
+ token.droit = user.droit;
}
return token;
},
- async session(session, token) {
- session.user.id = token.id;
- session.user.email = token.email;
- session.user.role = token.role;
+ async session({ session, token }) {
+ console.log("Session callback called", token);
+ if (!token) {
+ throw new Error('Token not found');
+ }
+ session.user = {
+ id: token.id,
+ role: token.role,
+ droit: token.droit
+ };
return session;
}
},
pages: {
signIn: '/[locale]/users/login'
},
- csrf: false // Désactiver la gestion CSRF de NextAuth.js
+ csrf: true
};
-export default csrfMiddleware((req, res) => NextAuth(req, res, options));
\ No newline at end of file
+export default (req, res) => {
+ console.log("NextAuth handler called");
+ return NextAuth(req, res, options);
+};
\ No newline at end of file
diff --git a/Front-End/src/pages/protected-page.js b/Front-End/src/pages/protected-page.js
deleted file mode 100644
index 341959b..0000000
--- a/Front-End/src/pages/protected-page.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { useSession, getSession } from 'next-auth/react';
-import { useRouter } from 'next/router';
-import { useEffect } from 'react';
-
-export default function ProtectedPage() {
- const [session, loading] = useSession();
- const router = useRouter();
-
- useEffect(() => {
- if (!loading && !session) {
- router.push('/auth/signin');
- }
- }, [loading, session, router]);
-
- if (loading || !session) {
- return Loading...
;
- }
-
- return (
-
-
Protected Page
-
Welcome, {session.user.email}
-
- );
-}
-
-export async function getServerSideProps(context) {
- const session = await getSession(context);
-
- if (!session) {
- return {
- redirect: {
- destination: '/auth/signin',
- permanent: false
- }
- };
- }
-
- return {
- props: { session }
- };
-}
\ No newline at end of file