diff --git a/Back-End/Auth/views.py b/Back-End/Auth/views.py index ccf9478..b66c904 100644 --- a/Back-End/Auth/views.py +++ b/Back-End/Auth/views.py @@ -236,7 +236,6 @@ def makeToken(user): "establishment__name": role.establishment.name, "establishment__evaluation_frequency": role.establishment.evaluation_frequency, "establishment__total_capacity": role.establishment.total_capacity, - "establishment__api_docuseal": role.establishment.api_docuseal, "establishment__logo": logo_url, }) diff --git a/Back-End/DocuSeal/urls.py b/Back-End/DocuSeal/urls.py deleted file mode 100644 index 06a434b..0000000 --- a/Back-End/DocuSeal/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.urls import path, re_path -from .views import generate_jwt_token, clone_template, remove_template, download_template - -urlpatterns = [ - re_path(r'generateToken$', generate_jwt_token, name='generate_jwt_token'), - re_path(r'cloneTemplate$', clone_template, name='clone_template'), - re_path(r'removeTemplate/(?P[0-9]+)$', remove_template, name='remove_template'), - re_path(r'downloadTemplate/(?P[\w-]+)$', download_template, name='download_template') -] diff --git a/Back-End/DocuSeal/views.py b/Back-End/DocuSeal/views.py deleted file mode 100644 index 9a21cb3..0000000 --- a/Back-End/DocuSeal/views.py +++ /dev/null @@ -1,200 +0,0 @@ -from django.conf import settings -from django.views.decorators.csrf import csrf_exempt -from rest_framework.decorators import api_view -from rest_framework.response import Response -from rest_framework import status -import jwt -import datetime -import requests -from Establishment.models import Establishment - -@csrf_exempt -@api_view(['POST']) -def generate_jwt_token(request): - # Récupérer l'établissement concerné (par ID ou autre info transmise) - establishment_id = request.data.get('establishment_id') - if not establishment_id: - return Response({'error': 'establishment_id requis'}, status=status.HTTP_400_BAD_REQUEST) - - try: - establishment = Establishment.objects.get(id=establishment_id) - except Establishment.DoesNotExist: - return Response({'error': "Établissement introuvable"}, status=status.HTTP_404_NOT_FOUND) - - # Vérifier la clé API reçue dans le header - api_key = request.headers.get('X-Auth-Token') - if not api_key or not establishment.api_docuseal or api_key != establishment.api_docuseal: - return Response({'error': 'Clé API invalide'}, status=status.HTTP_401_UNAUTHORIZED) - - # Récupérer les données de la requête - user_email = request.data.get('user_email') - documents_urls = request.data.get('documents_urls', []) - template_id = request.data.get('id') - - if not user_email: - return Response({'error': 'User email is required'}, status=status.HTTP_400_BAD_REQUEST) - - # Utiliser la clé API de l'établissement comme secret JWT - jwt_secret = establishment.api_docuseal - jwt_algorithm = settings.DOCUSEAL_JWT['ALGORITHM'] - expiration_delta = settings.DOCUSEAL_JWT['EXPIRATION_DELTA'] - - payload = { - 'user_email': user_email, - 'documents_urls': documents_urls, - 'template_id': template_id, - 'exp': datetime.datetime.utcnow() + expiration_delta - } - - token = jwt.encode(payload, jwt_secret, algorithm=jwt_algorithm) - return Response({'token': token}, status=status.HTTP_200_OK) - -@csrf_exempt -@api_view(['POST']) -def clone_template(request): - # Récupérer l'établissement concerné - establishment_id = request.data.get('establishment_id') - print(f"establishment_id : {establishment_id}") - if not establishment_id: - return Response({'error': 'establishment_id requis'}, status=status.HTTP_400_BAD_REQUEST) - - try: - establishment = Establishment.objects.get(id=establishment_id) - except Establishment.DoesNotExist: - return Response({'error': "Établissement introuvable"}, status=status.HTTP_404_NOT_FOUND) - - # Vérifier la clé API reçue dans le header - api_key = request.headers.get('X-Auth-Token') - if not api_key or not establishment.api_docuseal or api_key != establishment.api_docuseal: - return Response({'error': 'Clé API invalide'}, status=status.HTTP_401_UNAUTHORIZED) - - # Récupérer les données de la requête - document_id = request.data.get('templateId') - email = request.data.get('email') - is_required = request.data.get('is_required') - - # Vérifier les données requises - if not document_id: - return Response({'error': 'template ID is required'}, status=status.HTTP_400_BAD_REQUEST) - - # URL de l'API de DocuSeal pour cloner le template - clone_url = f'https://docuseal.com/api/templates/{document_id}/clone' - - # Faire la requête pour cloner le template - try: - response = requests.post(clone_url, headers={ - 'Content-Type': 'application/json', - 'X-Auth-Token': establishment.api_docuseal - }) - - if response.status_code != status.HTTP_200_OK: - return Response({'error': 'Failed to clone template'}, status=response.status_code) - - data = response.json() - - if is_required: - # URL de l'API de DocuSeal pour créer une submission - submission_url = f'https://docuseal.com/api/submissions' - - try: - clone_id = data['id'] - response = requests.post(submission_url, json={ - 'template_id': clone_id, - 'send_email': False, - 'submitters': [{'email': email}] - }, headers={ - 'Content-Type': 'application/json', - 'X-Auth-Token': establishment.api_docuseal - }) - - if response.status_code != status.HTTP_200_OK: - return Response({'error': 'Failed to create submission'}, status=response.status_code) - - data = response.json() - data[0]['id'] = clone_id - return Response(data[0], status=status.HTTP_200_OK) - - except requests.RequestException as e: - return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) - else: - print(f'NOT REQUIRED -> on ne crée pas de submission') - return Response(data, status=status.HTTP_200_OK) - - except requests.RequestException as e: - return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) - -@csrf_exempt -@api_view(['DELETE']) -def remove_template(request, id): - # Récupérer l'établissement concerné - establishment_id = request.GET.get('establishment_id') - if not establishment_id: - return Response({'error': 'establishment_id requis'}, status=status.HTTP_400_BAD_REQUEST) - - try: - establishment = Establishment.objects.get(id=establishment_id) - except Establishment.DoesNotExist: - return Response({'error': "Établissement introuvable"}, status=status.HTTP_404_NOT_FOUND) - - # Vérifier la clé API reçue dans le header - api_key = request.headers.get('X-Auth-Token') - if not api_key or not establishment.api_docuseal or api_key != establishment.api_docuseal: - return Response({'error': 'Clé API invalide'}, status=status.HTTP_401_UNAUTHORIZED) - - # URL de l'API de DocuSeal pour supprimer le template - - clone_url = f'https://docuseal.com/api/templates/{id}' - - try: - response = requests.delete(clone_url, headers={ - 'X-Auth-Token': establishment.api_docuseal - }) - - if response.status_code != status.HTTP_200_OK: - return Response({'error': 'Failed to remove template'}, status=response.status_code) - - data = response.json() - return Response(data, status=status.HTTP_200_OK) - - except requests.RequestException as e: - return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) - -@csrf_exempt -@api_view(['GET']) -def download_template(request, slug): - # Récupérer l'établissement concerné - establishment_id = request.GET.get('establishment_id') - if not establishment_id: - return Response({'error': 'establishment_id requis'}, status=status.HTTP_400_BAD_REQUEST) - - try: - establishment = Establishment.objects.get(id=establishment_id) - except Establishment.DoesNotExist: - return Response({'error': "Établissement introuvable"}, status=status.HTTP_404_NOT_FOUND) - - # Vérifier la clé API reçue dans le header - api_key = request.headers.get('X-Auth-Token') - if not api_key or not establishment.api_docuseal or api_key != establishment.api_docuseal: - return Response({'error': 'Clé API invalide'}, status=status.HTTP_401_UNAUTHORIZED) - - # Vérifier les données requises - if not slug: - return Response({'error': 'slug is required'}, status=status.HTTP_400_BAD_REQUEST) - - # URL de l'API de DocuSeal pour télécharger le template - download_url = f'https://docuseal.com/submitters/{slug}/download' - - try: - response = requests.get(download_url, headers={ - 'Content-Type': 'application/json', - 'X-Auth-Token': establishment.api_docuseal - }) - - if response.status_code != status.HTTP_200_OK: - return Response({'error': 'Failed to download template'}, status=response.status_code) - - data = response.json() - return Response(data, status=status.HTTP_200_OK) - - except requests.RequestException as e: - return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) diff --git a/Back-End/Establishment/models.py b/Back-End/Establishment/models.py index 27d6099..e79c292 100644 --- a/Back-End/Establishment/models.py +++ b/Back-End/Establishment/models.py @@ -27,7 +27,6 @@ class Establishment(models.Model): licence_code = models.CharField(max_length=100, blank=True) is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) - api_docuseal = models.CharField(max_length=255, blank=True, null=True) logo = models.FileField( upload_to=registration_logo_upload_to, null=True, diff --git a/Back-End/N3wtSchool/settings.py b/Back-End/N3wtSchool/settings.py index 5a7a8c6..8214b73 100644 --- a/Back-End/N3wtSchool/settings.py +++ b/Back-End/N3wtSchool/settings.py @@ -349,13 +349,6 @@ SIMPLE_JWT = { 'TOKEN_TYPE_CLAIM': 'token_type', } -# Configuration for DocuSeal JWT -DOCUSEAL_JWT = { - 'ALGORITHM': 'HS256', - 'SIGNING_KEY': SECRET_KEY, - 'EXPIRATION_DELTA': timedelta(hours=1) -} - # Django Channels Configuration ASGI_APPLICATION = 'N3wtSchool.asgi.application' diff --git a/Back-End/N3wtSchool/urls.py b/Back-End/N3wtSchool/urls.py index 458d0b2..8ebb2ff 100644 --- a/Back-End/N3wtSchool/urls.py +++ b/Back-End/N3wtSchool/urls.py @@ -46,7 +46,6 @@ urlpatterns = [ path("GestionEmail/", include(("GestionEmail.urls", 'GestionEmail'), namespace='GestionEmail')), path("GestionNotification/", include(("GestionNotification.urls", 'GestionNotification'), namespace='GestionNotification')), path("School/", include(("School.urls", 'School'), namespace='School')), - path("DocuSeal/", include(("DocuSeal.urls", 'DocuSeal'), namespace='DocuSeal')), path("Planning/", include(("Planning.urls", 'Planning'), namespace='Planning')), path("Establishment/", include(("Establishment.urls", 'Establishment'), namespace='Establishment')), path("Settings/", include(("Settings.urls", 'Settings'), namespace='Settings')), diff --git a/Back-End/Subscriptions/models.py b/Back-End/Subscriptions/models.py index 4334c88..b9abb78 100644 --- a/Back-End/Subscriptions/models.py +++ b/Back-End/Subscriptions/models.py @@ -294,12 +294,13 @@ class RegistrationForm(models.Model): ####################### MASTER FILES ######################## ############################################################# -####### DocuSeal masters (documents école, à signer ou pas) ####### +####### Formulaires masters (documents école, à signer ou pas) ####### class RegistrationSchoolFileMaster(models.Model): groups = models.ManyToManyField(RegistrationFileGroup, related_name='school_file_masters', blank=True) id = models.IntegerField(primary_key=True) name = models.CharField(max_length=255, default="") is_required = models.BooleanField(default=False) + formMasterData = models.JSONField(default=list, blank=True, null=True) def __str__(self): return f'{self.group.name} - {self.id}' @@ -321,7 +322,7 @@ def registration_school_file_upload_to(instance, filename): def registration_parent_file_upload_to(instance, filename): return f"registration_files/dossier_rf_{instance.registration_form.pk}/parent/{filename}" -####### DocuSeal templates (par dossier d'inscription) ####### +####### Formulaires templates (par dossier d'inscription) ####### class RegistrationSchoolFileTemplate(models.Model): master = models.ForeignKey(RegistrationSchoolFileMaster, on_delete=models.CASCADE, related_name='school_file_templates', blank=True) id = models.IntegerField(primary_key=True) @@ -329,6 +330,7 @@ class RegistrationSchoolFileTemplate(models.Model): name = models.CharField(max_length=255, default="") registration_form = models.ForeignKey(RegistrationForm, on_delete=models.CASCADE, related_name='school_file_templates', blank=True) file = models.FileField(null=True,blank=True, upload_to=registration_school_file_upload_to) + formTemplateData = models.JSONField(default=list, blank=True, null=True) def __str__(self): return self.name diff --git a/Back-End/requirements.txt b/Back-End/requirements.txt index 57e40e9..5d93dbd 100644 Binary files a/Back-End/requirements.txt and b/Back-End/requirements.txt differ