mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
chore: WIP uilisant d'un CSRF global à l'appli
This commit is contained in:
@ -11,11 +11,8 @@ urlpatterns = [
|
|||||||
re_path(r'^subscribe$', SubscribeView.as_view(), name='subscribe'),
|
re_path(r'^subscribe$', SubscribeView.as_view(), name='subscribe'),
|
||||||
re_path(r'^newPassword$', NewPasswordView.as_view(), name='newPassword'),
|
re_path(r'^newPassword$', NewPasswordView.as_view(), name='newPassword'),
|
||||||
re_path(r'^resetPassword/(?P<code>[a-zA-Z]+)$', ResetPasswordView.as_view(), name='resetPassword'),
|
re_path(r'^resetPassword/(?P<code>[a-zA-Z]+)$', ResetPasswordView.as_view(), name='resetPassword'),
|
||||||
re_path(r'^infoSession$', Auth.views.infoSession, name='infoSession'),
|
re_path(r'^infoSession$', SessionView.as_view(), name='infoSession'),
|
||||||
|
|
||||||
re_path(r'^profiles$', ProfileView.as_view(), name="profile"),
|
re_path(r'^profiles$', ProfileView.as_view(), name="profile"),
|
||||||
re_path(r'^profiles/(?P<id>[0-9]+)$', ProfileSimpleView.as_view(), name="profile"),
|
re_path(r'^profiles/(?P<id>[0-9]+)$', ProfileSimpleView.as_view(), name="profile"),
|
||||||
|
|
||||||
# Test SESSION VIEW
|
|
||||||
re_path(r'^session$', SessionView.as_view(), name="session"),
|
|
||||||
]
|
]
|
||||||
@ -29,6 +29,8 @@ import Subscriptions.util as util
|
|||||||
|
|
||||||
from N3wtSchool import bdd, error
|
from N3wtSchool import bdd, error
|
||||||
|
|
||||||
|
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||||||
|
|
||||||
|
|
||||||
@swagger_auto_schema(
|
@swagger_auto_schema(
|
||||||
method='get',
|
method='get',
|
||||||
@ -57,7 +59,7 @@ class SessionView(APIView):
|
|||||||
401: openapi.Response('Session invalide')
|
401: openapi.Response('Session invalide')
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
def post(self, request):
|
def get(self, request):
|
||||||
token = request.META.get('HTTP_AUTHORIZATION', '').split('Bearer ')[-1]
|
token = request.META.get('HTTP_AUTHORIZATION', '').split('Bearer ')[-1]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -146,27 +148,6 @@ class ProfileSimpleView(APIView):
|
|||||||
def delete(self, request, id):
|
def delete(self, request, id):
|
||||||
return bdd.delete_object(Profile, id)
|
return bdd.delete_object(Profile, id)
|
||||||
|
|
||||||
|
|
||||||
@swagger_auto_schema(
|
|
||||||
method='get',
|
|
||||||
operation_description="Obtenir les informations de session",
|
|
||||||
responses={200: openapi.Response('Informations de session', schema=openapi.Schema(
|
|
||||||
type=openapi.TYPE_OBJECT,
|
|
||||||
properties={
|
|
||||||
'cacheSession': openapi.Schema(type=openapi.TYPE_BOOLEAN),
|
|
||||||
'typeProfil': openapi.Schema(type=openapi.TYPE_STRING),
|
|
||||||
'username': openapi.Schema(type=openapi.TYPE_STRING)
|
|
||||||
}
|
|
||||||
))}
|
|
||||||
)
|
|
||||||
@api_view(['GET'])
|
|
||||||
def infoSession(request):
|
|
||||||
profilCache = cache.get('session_cache')
|
|
||||||
if profilCache:
|
|
||||||
return JsonResponse({"cacheSession":True,"typeProfil":profilCache.droit, "username":profilCache.email}, safe=False)
|
|
||||||
else:
|
|
||||||
return JsonResponse({"cacheSession":False,"typeProfil":Profile.Droits.PROFIL_UNDEFINED, "username":""}, safe=False)
|
|
||||||
|
|
||||||
@method_decorator(csrf_protect, name='dispatch')
|
@method_decorator(csrf_protect, name='dispatch')
|
||||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||||
class LoginView(APIView):
|
class LoginView(APIView):
|
||||||
@ -195,7 +176,7 @@ class LoginView(APIView):
|
|||||||
def post(self, request):
|
def post(self, request):
|
||||||
data=JSONParser().parse(request)
|
data=JSONParser().parse(request)
|
||||||
validatorAuthentication = validator.ValidatorAuthentication(data=data)
|
validatorAuthentication = validator.ValidatorAuthentication(data=data)
|
||||||
retour = error.returnMessage[error.WRONGid]
|
retour = error.returnMessage[error.WRONG_ID]
|
||||||
validationOk, errorFields = validatorAuthentication.validate()
|
validationOk, errorFields = validatorAuthentication.validate()
|
||||||
user = None
|
user = None
|
||||||
if validationOk:
|
if validationOk:
|
||||||
@ -212,15 +193,8 @@ class LoginView(APIView):
|
|||||||
retour = ''
|
retour = ''
|
||||||
else:
|
else:
|
||||||
retour = error.returnMessage[error.PROFIL_INACTIVE]
|
retour = error.returnMessage[error.PROFIL_INACTIVE]
|
||||||
|
|
||||||
# Génération du token JWT
|
|
||||||
# jwt_token = jwt.encode({
|
|
||||||
# 'id': user.id,
|
|
||||||
# 'email': user.email,
|
|
||||||
# 'role': "admin"
|
|
||||||
# }, settings.SECRET_KEY, algorithm='HS256')
|
|
||||||
else:
|
else:
|
||||||
retour = error.returnMessage[error.WRONGid]
|
retour = error.returnMessage[error.WRONG_ID]
|
||||||
|
|
||||||
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
|
|||||||
@ -13,6 +13,7 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
@ -53,6 +54,7 @@ INSTALLED_APPS = [
|
|||||||
'django_celery_beat',
|
'django_celery_beat',
|
||||||
'N3wtSchool',
|
'N3wtSchool',
|
||||||
'drf_yasg',
|
'drf_yasg',
|
||||||
|
'rest_framework_simplejwt'
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
@ -250,10 +252,19 @@ CORS_ALLOW_ALL_HEADERS = True
|
|||||||
CORS_ALLOW_CREDENTIALS = True
|
CORS_ALLOW_CREDENTIALS = True
|
||||||
|
|
||||||
CORS_ALLOWED_ORIGINS = [
|
CORS_ALLOWED_ORIGINS = [
|
||||||
os.getenv('CORS_ALLOWED_ORIGINS', 'http://localhost:3000')
|
'http://localhost:3000'
|
||||||
]
|
]
|
||||||
|
|
||||||
CSRF_TRUSTED_ORIGINS = os.getenv('CSRF_TRUSTED_ORIGINS', 'http://localhost:3000,http://localhost:8080').split(',')
|
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_COOKIE_HTTPONLY = False
|
CSRF_COOKIE_HTTPONLY = False
|
||||||
CSRF_COOKIE_SECURE = False
|
CSRF_COOKIE_SECURE = False
|
||||||
@ -289,7 +300,10 @@ NB_MAX_PAGE = 100
|
|||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PAGINATION_CLASS': 'Subscriptions.pagination.CustomPagination',
|
'DEFAULT_PAGINATION_CLASS': 'Subscriptions.pagination.CustomPagination',
|
||||||
'PAGE_SIZE': NB_RESULT_PER_PAGE
|
'PAGE_SIZE': NB_RESULT_PER_PAGE,
|
||||||
|
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||||
|
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
CELERY_BROKER_URL = 'redis://redis:6379/0'
|
CELERY_BROKER_URL = 'redis://redis:6379/0'
|
||||||
@ -308,3 +322,18 @@ REDIS_DB = 0
|
|||||||
REDIS_PASSWORD = None
|
REDIS_PASSWORD = None
|
||||||
|
|
||||||
SECRET_KEY = 'QWQ8bYlCz1NpQ9G0vR5kxMnvWszfH2y3'
|
SECRET_KEY = 'QWQ8bYlCz1NpQ9G0vR5kxMnvWszfH2y3'
|
||||||
|
SIMPLE_JWT = {
|
||||||
|
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
|
||||||
|
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
|
||||||
|
'ROTATE_REFRESH_TOKENS': False,
|
||||||
|
'BLACKLIST_AFTER_ROTATION': True,
|
||||||
|
'ALGORITHM': 'HS256',
|
||||||
|
'SIGNING_KEY': SECRET_KEY,
|
||||||
|
'VERIFYING_KEY': None,
|
||||||
|
'AUTH_HEADER_TYPES': ('Bearer',),
|
||||||
|
'USER_ID_FIELD': 'id',
|
||||||
|
'USER_ID_CLAIM': 'user_id',
|
||||||
|
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
|
||||||
|
'TOKEN_TYPE_CLAIM': 'token_type',
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
252
Front-End/package-lock.json
generated
252
Front-End/package-lock.json
generated
@ -13,9 +13,11 @@
|
|||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"framer-motion": "^11.11.11",
|
"framer-motion": "^11.11.11",
|
||||||
"ics": "^3.8.1",
|
"ics": "^3.8.1",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.453.0",
|
"lucide-react": "^0.453.0",
|
||||||
"next": "14.2.11",
|
"next": "14.2.11",
|
||||||
|
"next-auth": "^4.24.11",
|
||||||
"next-intl": "^3.24.0",
|
"next-intl": "^3.24.0",
|
||||||
"next-logger": "^5.0.1",
|
"next-logger": "^5.0.1",
|
||||||
"pino": "^9.6.0",
|
"pino": "^9.6.0",
|
||||||
@ -616,6 +618,15 @@
|
|||||||
"node": ">=12.4.0"
|
"node": ">=12.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@panva/hkdf": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/panva"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@pkgjs/parseargs": {
|
"node_modules/@pkgjs/parseargs": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -1651,6 +1662,12 @@
|
|||||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-equal-constant-time": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/busboy": {
|
"node_modules/busboy": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -2092,6 +2109,15 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/ecdsa-sig-formatter": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.47",
|
"version": "1.5.47",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz",
|
||||||
@ -3715,6 +3741,15 @@
|
|||||||
"jiti": "bin/jiti.js"
|
"jiti": "bin/jiti.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jose": {
|
||||||
|
"version": "4.15.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
|
||||||
|
"integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/panva"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
@ -3768,6 +3803,28 @@
|
|||||||
"json5": "lib/cli.js"
|
"json5": "lib/cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsonwebtoken": {
|
||||||
|
"version": "9.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||||
|
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jws": "^3.2.2",
|
||||||
|
"lodash.includes": "^4.3.0",
|
||||||
|
"lodash.isboolean": "^3.0.3",
|
||||||
|
"lodash.isinteger": "^4.0.4",
|
||||||
|
"lodash.isnumber": "^3.0.3",
|
||||||
|
"lodash.isplainobject": "^4.0.6",
|
||||||
|
"lodash.isstring": "^4.0.1",
|
||||||
|
"lodash.once": "^4.0.0",
|
||||||
|
"ms": "^2.1.1",
|
||||||
|
"semver": "^7.5.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12",
|
||||||
|
"npm": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jsx-ast-utils": {
|
"node_modules/jsx-ast-utils": {
|
||||||
"version": "3.3.5",
|
"version": "3.3.5",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@ -3782,6 +3839,27 @@
|
|||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jwa": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-equal-constant-time": "1.0.1",
|
||||||
|
"ecdsa-sig-formatter": "1.0.11",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jws": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jwa": "^1.4.1",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/keyv": {
|
"node_modules/keyv": {
|
||||||
"version": "4.5.4",
|
"version": "4.5.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@ -3863,11 +3941,53 @@
|
|||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.includes": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isboolean": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isinteger": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isnumber": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isplainobject": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isstring": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.once": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/logform": {
|
"node_modules/logform": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
|
||||||
@ -3963,7 +4083,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"devOptional": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/mz": {
|
"node_modules/mz": {
|
||||||
@ -4045,6 +4164,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/next-auth": {
|
||||||
|
"version": "4.24.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.11.tgz",
|
||||||
|
"integrity": "sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.20.13",
|
||||||
|
"@panva/hkdf": "^1.0.2",
|
||||||
|
"cookie": "^0.7.0",
|
||||||
|
"jose": "^4.15.5",
|
||||||
|
"oauth": "^0.9.15",
|
||||||
|
"openid-client": "^5.4.0",
|
||||||
|
"preact": "^10.6.3",
|
||||||
|
"preact-render-to-string": "^5.1.19",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@auth/core": "0.34.2",
|
||||||
|
"next": "^12.2.5 || ^13 || ^14 || ^15",
|
||||||
|
"nodemailer": "^6.6.5",
|
||||||
|
"react": "^17.0.2 || ^18 || ^19",
|
||||||
|
"react-dom": "^17.0.2 || ^18 || ^19"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@auth/core": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"nodemailer": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/next-intl": {
|
"node_modules/next-intl": {
|
||||||
"version": "3.24.0",
|
"version": "3.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-3.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-3.24.0.tgz",
|
||||||
@ -4157,6 +4308,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/oauth": {
|
||||||
|
"version": "0.9.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
|
||||||
|
"integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -4282,6 +4439,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/oidc-token-hash": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^10.13.0 || >=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/on-exit-leak-free": {
|
"node_modules/on-exit-leak-free": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
|
||||||
@ -4308,6 +4474,42 @@
|
|||||||
"fn.name": "1.x.x"
|
"fn.name": "1.x.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/openid-client": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jose": "^4.15.9",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"object-hash": "^2.2.0",
|
||||||
|
"oidc-token-hash": "^5.0.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/panva"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/openid-client/node_modules/lru-cache": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/openid-client/node_modules/object-hash": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@ -4631,6 +4833,28 @@
|
|||||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/preact": {
|
||||||
|
"version": "10.25.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.25.4.tgz",
|
||||||
|
"integrity": "sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/preact"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/preact-render-to-string": {
|
||||||
|
"version": "5.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz",
|
||||||
|
"integrity": "sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"pretty-format": "^3.8.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"preact": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@ -4639,6 +4863,12 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pretty-format": {
|
||||||
|
"version": "3.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz",
|
||||||
|
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/process-warning": {
|
"node_modules/process-warning": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz",
|
||||||
@ -5101,9 +5331,7 @@
|
|||||||
"type": "consulting",
|
"type": "consulting",
|
||||||
"url": "https://feross.org/support"
|
"url": "https://feross.org/support"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"optional": true,
|
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/safe-regex-test": {
|
"node_modules/safe-regex-test": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
@ -5138,7 +5366,6 @@
|
|||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.6.3",
|
"version": "7.6.3",
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
@ -5917,6 +6144,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
@ -6136,6 +6372,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/yaml": {
|
"node_modules/yaml": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
|
||||||
|
|||||||
@ -15,9 +15,11 @@
|
|||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"framer-motion": "^11.11.11",
|
"framer-motion": "^11.11.11",
|
||||||
"ics": "^3.8.1",
|
"ics": "^3.8.1",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.453.0",
|
"lucide-react": "^0.453.0",
|
||||||
"next": "14.2.11",
|
"next": "14.2.11",
|
||||||
|
"next-auth": "^4.24.11",
|
||||||
"next-intl": "^3.24.0",
|
"next-intl": "^3.24.0",
|
||||||
"next-logger": "^5.0.1",
|
"next-logger": "^5.0.1",
|
||||||
"pino": "^9.6.0",
|
"pino": "^9.6.0",
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState } from 'react'
|
||||||
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
|
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
|
||||||
|
|
||||||
import Logo from '@/components/Logo';
|
import Logo from '@/components/Logo';
|
||||||
import { useSearchParams, useRouter } from 'next/navigation'
|
import { useSearchParams, useRouter } from 'next/navigation'
|
||||||
import InputTextIcon from '@/components/InputTextIcon';
|
import InputTextIcon from '@/components/InputTextIcon';
|
||||||
@ -9,13 +8,11 @@ import Loader from '@/components/Loader'; // Importez le composant Loader
|
|||||||
import Button from '@/components/Button'; // Importez le composant Button
|
import Button from '@/components/Button'; // Importez le composant Button
|
||||||
import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
|
import { User, KeySquare } from 'lucide-react'; // Importez directement les icônes nécessaires
|
||||||
import {
|
import {
|
||||||
FE_ADMIN_SUBSCRIPTIONS_EDIT_URL,
|
FE_USERS_NEW_PASSWORD_URL,
|
||||||
FE_ADMIN_SUBSCRIPTIONS_URL,
|
BE_AUTH_INFO_SESSION } from '@/utils/Url';
|
||||||
FE_PARENTS_HOME_URL,
|
|
||||||
FE_USERS_NEW_PASSWORD_URL } from '@/utils/Url';
|
|
||||||
import useLocalStorage from '@/hooks/useLocalStorage';
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import useCsrfToken from '@/hooks/useCsrfToken';
|
import { signIn } from 'next-auth/react';
|
||||||
import { login } from '@/app/lib/authAction';
|
import { useCsrfToken } from '@/context/CsrfContext'; // Importez le hook useCsrfToken
|
||||||
|
|
||||||
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
|
const useFakeData = process.env.NEXT_PUBLIC_USE_FAKE_DATA === 'true';
|
||||||
|
|
||||||
@ -30,78 +27,39 @@ export default function Page() {
|
|||||||
const [userId, setUserId] = useLocalStorage("userId", '') ;
|
const [userId, setUserId] = useLocalStorage("userId", '') ;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const csrfToken = useCsrfToken();
|
const csrfToken = useCsrfToken(); // Utilisez le hook useCsrfToken
|
||||||
|
|
||||||
|
|
||||||
function isOK(data) {
|
function isOK(data) {
|
||||||
return data.errorMessage === ""
|
return data.errorMessage === ""
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFormLogin(formData) {
|
function handleFormLogin(formData) {
|
||||||
if (useFakeData) {
|
setIsLoading(true);
|
||||||
// Simuler une réponse réussie
|
console.log('Form Data', Object.fromEntries(formData.entries())); // Affichez les entrées du FormData
|
||||||
const data = {
|
console.log('csrf passé ', csrfToken); // Affichez le token CSRF
|
||||||
errorFields: {},
|
|
||||||
errorMessage: "",
|
signIn('credentials', {
|
||||||
profil: "fakeProfileId"
|
redirect: false,
|
||||||
};
|
|
||||||
setUserFieldError("")
|
|
||||||
setPasswordFieldError("")
|
|
||||||
setErrorMessage("")
|
|
||||||
if(isOK(data)){
|
|
||||||
localStorage.setItem('userId', data.profil); // Stocker l'identifiant de l'utilisateur
|
|
||||||
router.push(`${FE_ADMIN_SUBSCRIPTIONS_EDIT_URL}?id=${data.profil}`);
|
|
||||||
} else {
|
|
||||||
if(data.errorFields){
|
|
||||||
setUserFieldError(data.errorFields.email)
|
|
||||||
setPasswordFieldError(data.errorFields.password);
|
|
||||||
}
|
|
||||||
if(data.errorMessage){
|
|
||||||
setErrorMessage(data.errorMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const data = {
|
|
||||||
email: formData.get('login'),
|
email: formData.get('login'),
|
||||||
password: formData.get('password'),
|
password: formData.get('password'),
|
||||||
}
|
csrfToken: csrfToken // Utilisez le token CSRF récupéré par le hook
|
||||||
login(data,csrfToken)
|
})
|
||||||
.then(data => {
|
.then(result => {
|
||||||
console.log('Success:', data);
|
console.log('Sign In Result', result);
|
||||||
setUserFieldError("")
|
setIsLoading(false);
|
||||||
setPasswordFieldError("")
|
|
||||||
setErrorMessage("")
|
|
||||||
if(isOK(data)){
|
|
||||||
localStorage.setItem('userId', data.profil); // Stocker l'identifiant de l'utilisateur
|
|
||||||
if (data.droit == 0) {
|
|
||||||
// Vue ECOLE
|
|
||||||
} else if (data.droit == 1) {
|
|
||||||
// Vue ADMIN
|
|
||||||
router.push(`${FE_ADMIN_SUBSCRIPTIONS_URL}`);
|
|
||||||
} else if (data.droit == 2) {
|
|
||||||
// Vue PARENT
|
|
||||||
router.push(`${FE_PARENTS_HOME_URL}`);
|
|
||||||
} else {
|
|
||||||
// Cas anormal
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
setErrorMessage(result.error);
|
||||||
} else {
|
} else {
|
||||||
if(data.errorFields){
|
router.push(result.url);
|
||||||
setUserFieldError(data.errorFields.email)
|
|
||||||
setPasswordFieldError(data.errorFields.password);
|
|
||||||
}
|
|
||||||
if(data.errorMessage){
|
|
||||||
setErrorMessage(data.errorMessage)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Error fetching data:', error);
|
console.error('Error during sign in:', error);
|
||||||
error = error.message;
|
setIsLoading(false);
|
||||||
console.log(error);
|
setErrorMessage('An error occurred during sign in.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (isLoading === true) {
|
if (isLoading === true) {
|
||||||
return <Loader /> // Affichez le composant Loader
|
return <Loader /> // Affichez le composant Loader
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { NextIntlClientProvider } from 'next-intl';
|
import { NextIntlClientProvider } from 'next-intl';
|
||||||
|
import { CsrfProvider } from '@/context/CsrfContext'; // Importez le CsrfProvider
|
||||||
|
|
||||||
import { getMessages } from 'next-intl/server';
|
import { getMessages } from 'next-intl/server';
|
||||||
import "@/css/tailwind.css";
|
import "@/css/tailwind.css";
|
||||||
@ -27,9 +28,11 @@ export default async function RootLayout({ children, params: { locale } }) {
|
|||||||
return (
|
return (
|
||||||
<html lang={locale}>
|
<html lang={locale}>
|
||||||
<body>
|
<body>
|
||||||
|
<CsrfProvider> {/* Enveloppez votre application avec le CsrfProvider */}
|
||||||
<NextIntlClientProvider messages={messages}>
|
<NextIntlClientProvider messages={messages}>
|
||||||
{children}
|
{children}
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
|
</CsrfProvider>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,8 +25,8 @@ const requestResponseHandler = async (response) => {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const login = (data, csrfToken) => {
|
export const login = (data, csrfToken) => {
|
||||||
|
console.log('data', data);
|
||||||
const request = new Request(
|
const request = new Request(
|
||||||
`${BE_AUTH_LOGIN_URL}`,
|
`${BE_AUTH_LOGIN_URL}`,
|
||||||
{
|
{
|
||||||
|
|||||||
39
Front-End/src/context/CsrfContext.js
Normal file
39
Front-End/src/context/CsrfContext.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
'use client'; // Ajoutez cette ligne pour marquer ce fichier comme un composant client
|
||||||
|
|
||||||
|
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||||
|
import { BE_AUTH_CSRF_URL } from '@/utils/Url';
|
||||||
|
import { setCsrfToken } from '@/utils/getCsrfToken';
|
||||||
|
|
||||||
|
const CsrfContext = createContext();
|
||||||
|
|
||||||
|
export const CsrfProvider = ({ children }) => {
|
||||||
|
const [csrfToken, setCsrfTokenState] = 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 && data.csrfToken) {
|
||||||
|
setCsrfTokenState(data.csrfToken);
|
||||||
|
setCsrfToken(data.csrfToken); // Définir le token CSRF global
|
||||||
|
console.log('CSRF Token reçu:', data.csrfToken);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error fetching CSRF token:', error);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CsrfContext.Provider value={csrfToken}>
|
||||||
|
{children}
|
||||||
|
</CsrfContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCsrfToken = () => {
|
||||||
|
return useContext(CsrfContext);
|
||||||
|
};
|
||||||
12
Front-End/src/csrfMiddleware.js
Normal file
12
Front-End/src/csrfMiddleware.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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);
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -1,29 +1,29 @@
|
|||||||
import { useEffect, useState } from 'react';
|
// import { useEffect, useState } from 'react';
|
||||||
import { BE_AUTH_CSRF_URL } from '@/utils/Url';
|
// import { BE_AUTH_CSRF_URL } from '@/utils/Url';
|
||||||
|
|
||||||
const useCsrfToken = () => {
|
// const useCsrfToken = () => {
|
||||||
const [token, setToken] = useState('');
|
// const [token, setToken] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
fetch(`${BE_AUTH_CSRF_URL}`, {
|
// fetch(`${BE_AUTH_CSRF_URL}`, {
|
||||||
method: 'GET',
|
// method: 'GET',
|
||||||
credentials: 'include' // Inclut les cookies dans la requête
|
// credentials: 'include' // Inclut les cookies dans la requête
|
||||||
})
|
// })
|
||||||
.then(response => response.json())
|
// .then(response => response.json())
|
||||||
.then(data => {
|
// .then(data => {
|
||||||
if (data) {
|
// if (data) {
|
||||||
if(data.csrfToken != token) {
|
// if(data.csrfToken != token) {
|
||||||
setToken(data.csrfToken);
|
// setToken(data.csrfToken);
|
||||||
// console.log('------------> CSRF Token reçu:', data.csrfToken);
|
// console.log('------------> CSRF Token reçu:', data.csrfToken);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
.catch(error => {
|
// .catch(error => {
|
||||||
console.error('Error fetching CSRF token:', error);
|
// console.error('Error fetching CSRF token:', error);
|
||||||
});
|
// });
|
||||||
}, []);
|
// }, []);
|
||||||
|
|
||||||
return token;
|
// return token;
|
||||||
};
|
// };
|
||||||
|
|
||||||
export default useCsrfToken;
|
// export default useCsrfToken;
|
||||||
|
|||||||
79
Front-End/src/pages/api/auth/[...nextauth].js
Normal file
79
Front-End/src/pages/api/auth/[...nextauth].js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import NextAuth from 'next-auth';
|
||||||
|
import CredentialsProvider from 'next-auth/providers/credentials';
|
||||||
|
import jwt from 'jsonwebtoken';
|
||||||
|
import { csrfMiddleware } from '@/csrfMiddleware'; // Importez le middleware csrfMiddleware
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
providers: [
|
||||||
|
CredentialsProvider({
|
||||||
|
name: 'Credentials',
|
||||||
|
credentials: {
|
||||||
|
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`, {
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
session: {
|
||||||
|
jwt: true
|
||||||
|
},
|
||||||
|
callbacks: {
|
||||||
|
async jwt(token, user) {
|
||||||
|
if (user) {
|
||||||
|
token.id = user.id;
|
||||||
|
token.email = user.email;
|
||||||
|
token.role = user.role;
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
},
|
||||||
|
async session(session, token) {
|
||||||
|
session.user.id = token.id;
|
||||||
|
session.user.email = token.email;
|
||||||
|
session.user.role = token.role;
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pages: {
|
||||||
|
signIn: '/[locale]/users/login'
|
||||||
|
},
|
||||||
|
csrf: false // Désactiver la gestion CSRF de NextAuth.js
|
||||||
|
};
|
||||||
|
|
||||||
|
export default csrfMiddleware((req, res) => NextAuth(req, res, options));
|
||||||
22
Front-End/src/pages/api/auth/signin.js
Normal file
22
Front-End/src/pages/api/auth/signin.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { getCsrfToken } from 'next-auth/react';
|
||||||
|
import useCsrfToken from '@/hooks/useCsrfToken';
|
||||||
|
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
|
||||||
|
|
||||||
|
export default function SignIn({ csrfToken }) {
|
||||||
|
|
||||||
|
const csrfToken = useCsrfToken();
|
||||||
|
return (
|
||||||
|
<form method="post" action="/api/auth/callback/credentials">
|
||||||
|
<DjangoCSRFToken csrfToken={csrfToken} />
|
||||||
|
<label>
|
||||||
|
Email
|
||||||
|
<input name="email" type="email" />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Password
|
||||||
|
<input name="password" type="password" />
|
||||||
|
</label>
|
||||||
|
<button type="submit">Sign in</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
9
Front-End/src/pages/api/auth/signout.js
Normal file
9
Front-End/src/pages/api/auth/signout.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { signOut } from 'next-auth/client';
|
||||||
|
|
||||||
|
export default function SignOut() {
|
||||||
|
return (
|
||||||
|
<button onClick={() => signOut({ callbackUrl: '/' })}>
|
||||||
|
Sign out
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
42
Front-End/src/pages/protected-page.js
Normal file
42
Front-End/src/pages/protected-page.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
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 <p>Loading...</p>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Protected Page</h1>
|
||||||
|
<p>Welcome, {session.user.email}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getServerSideProps(context) {
|
||||||
|
const session = await getSession(context);
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: '/auth/signin',
|
||||||
|
permanent: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: { session }
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@ export const BE_AUTH_LOGIN_URL = `${BASE_URL}/Auth/login`
|
|||||||
export const BE_AUTH_LOGOUT_URL = `${BASE_URL}/Auth/logout`
|
export const BE_AUTH_LOGOUT_URL = `${BASE_URL}/Auth/logout`
|
||||||
export const BE_AUTH_PROFILES_URL = `${BASE_URL}/Auth/profiles`
|
export const BE_AUTH_PROFILES_URL = `${BASE_URL}/Auth/profiles`
|
||||||
export const BE_AUTH_CSRF_URL = `${BASE_URL}/Auth/csrf`
|
export const BE_AUTH_CSRF_URL = `${BASE_URL}/Auth/csrf`
|
||||||
|
export const BE_AUTH_INFO_SESSION = `${BASE_URL}/Auth/infoSession`
|
||||||
|
|
||||||
// GESTION INSCRIPTION
|
// GESTION INSCRIPTION
|
||||||
export const BE_SUBSCRIPTION_STUDENTS_URL = `${BASE_URL}/Subscriptions/students` // Récupère la liste des élèves inscrits ou en cours d'inscriptions
|
export const BE_SUBSCRIPTION_STUDENTS_URL = `${BASE_URL}/Subscriptions/students` // Récupère la liste des élèves inscrits ou en cours d'inscriptions
|
||||||
|
|||||||
9
Front-End/src/utils/getCsrfToken.js
Normal file
9
Front-End/src/utils/getCsrfToken.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
let csrfToken = '';
|
||||||
|
|
||||||
|
export const setCsrfToken = (token) => {
|
||||||
|
csrfToken = token;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCsrfToken = () => {
|
||||||
|
return csrfToken;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user