feat: Securisation du Backend

This commit is contained in:
Luc SORIGNET
2026-02-27 10:45:36 +01:00
parent 2fef6d61a4
commit fa843097ba
55 changed files with 2898 additions and 910 deletions

View File

@ -1,4 +1,15 @@
import logger from '@/utils/logger';
import { signOut } from 'next-auth/react';
let isSigningOut = false;
export const triggerSignOut = async () => {
if (isSigningOut || typeof window === 'undefined') return;
isSigningOut = true;
logger.warn('Session expirée, déconnexion en cours...');
await signOut({ callbackUrl: '/users/login' });
};
/**
*
* @param {*} response
@ -6,6 +17,18 @@ import logger from '@/utils/logger';
*/
export const requestResponseHandler = async (response) => {
try {
if (response.status === 401) {
// On lève une erreur plutôt que de déclencher un signOut automatique.
// Plusieurs requêtes concurrent pourraient déclencher des signOut en cascade.
// Le signOut est géré proprement via RefreshTokenError dans getAuthToken.
const body = await response.json().catch(() => ({}));
const error = new Error(
body?.detail || body?.errorMessage || 'Session expirée'
);
error.status = 401;
throw error;
}
const body = await response?.json();
if (response.ok) {
return body;

View File

@ -1,5 +1,6 @@
import { signOut, signIn } from 'next-auth/react';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth } from '@/utils/fetchWithAuth';
import {
BE_AUTH_LOGIN_URL,
BE_AUTH_REFRESH_JWT_URL,
@ -73,92 +74,49 @@ export const fetchProfileRoles = (
if (page !== '' && pageSize !== '') {
url = `${BE_AUTH_PROFILES_ROLES_URL}?filter=${filter}&establishment_id=${establishment}&page=${page}`;
}
return fetch(url, {
headers: {
'Content-Type': 'application/json',
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
export const updateProfileRoles = (id, data, csrfToken) => {
const request = new Request(`${BE_AUTH_PROFILES_ROLES_URL}/${id}`, {
return fetchWithAuth(`${BE_AUTH_PROFILES_ROLES_URL}/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
};
export const deleteProfileRoles = async (id, csrfToken) => {
const response = await fetch(`${BE_AUTH_PROFILES_ROLES_URL}/${id}`, {
export const deleteProfileRoles = (id, csrfToken) => {
return fetchWithAuth(`${BE_AUTH_PROFILES_ROLES_URL}/${id}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
});
if (!response.ok) {
// Extraire le message d'erreur du backend
const errorData = await response.json();
const errorMessage =
errorData?.error ||
'Une erreur est survenue lors de la suppression du profil.';
// Jeter une erreur avec le message spécifique
throw new Error(errorMessage);
}
return response.json();
};
export const fetchProfiles = () => {
return fetch(`${BE_AUTH_PROFILES_URL}`)
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(`${BE_AUTH_PROFILES_URL}`);
};
export const createProfile = (data, csrfToken) => {
const request = new Request(`${BE_AUTH_PROFILES_URL}`, {
return fetchWithAuth(`${BE_AUTH_PROFILES_URL}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
};
export const deleteProfile = (id, csrfToken) => {
const request = new Request(`${BE_AUTH_PROFILES_URL}/${id}`, {
return fetchWithAuth(`${BE_AUTH_PROFILES_URL}/${id}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
};
export const updateProfile = (id, data, csrfToken) => {
const request = new Request(`${BE_AUTH_PROFILES_URL}/${id}`, {
return fetchWithAuth(`${BE_AUTH_PROFILES_URL}/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
};
export const sendNewPassword = (data, csrfToken) => {

View File

@ -2,33 +2,20 @@ import {
BE_GESTIONEMAIL_SEARCH_RECIPIENTS_URL,
BE_GESTIONEMAIL_SEND_EMAIL_URL,
} from '@/utils/Url';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth } from '@/utils/fetchWithAuth';
import { getCsrfToken } from '@/utils/getCsrfToken';
// Recherche de destinataires pour email
export const searchRecipients = (establishmentId, query) => {
const url = `${BE_GESTIONEMAIL_SEARCH_RECIPIENTS_URL}/?establishment_id=${establishmentId}&q=${encodeURIComponent(query)}`;
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
// Envoyer un email
export const sendEmail = async (messageData) => {
const csrfToken = getCsrfToken();
return fetch(BE_GESTIONEMAIL_SEND_EMAIL_URL, {
return fetchWithAuth(BE_GESTIONEMAIL_SEND_EMAIL_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(messageData),
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};

View File

@ -7,23 +7,9 @@ import {
BE_GESTIONMESSAGERIE_UPLOAD_FILE_URL,
BE_GESTIONMESSAGERIE_DELETE_CONVERSATION_URL,
} from '@/utils/Url';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth, getAuthToken } from '@/utils/fetchWithAuth';
import logger from '@/utils/logger';
// Helper pour construire les en-têtes avec CSRF
const buildHeaders = (csrfToken) => {
const headers = {
'Content-Type': 'application/json',
};
// Ajouter le token CSRF
if (csrfToken) {
headers['X-CSRFToken'] = csrfToken;
}
return headers;
};
/**
* Récupère les conversations d'un utilisateur
*/
@ -31,15 +17,12 @@ export const fetchConversations = async (userId, csrfToken) => {
try {
// Utiliser la nouvelle route avec user_id en paramètre d'URL
const url = `${BE_GESTIONMESSAGERIE_CONVERSATIONS_URL}/user/${userId}/`;
const response = await fetch(url, {
method: 'GET',
headers: buildHeaders(csrfToken),
credentials: 'include',
return await fetchWithAuth(url, {
headers: { 'X-CSRFToken': csrfToken },
});
return await requestResponseHandler(response);
} catch (error) {
logger.error('Erreur lors de la récupération des conversations:', error);
return errorHandler(error);
throw error;
}
};
@ -62,15 +45,12 @@ export const fetchMessages = async (
url += `&user_id=${userId}`;
}
const response = await fetch(url, {
method: 'GET',
headers: buildHeaders(csrfToken),
credentials: 'include',
return await fetchWithAuth(url, {
headers: { 'X-CSRFToken': csrfToken },
});
return await requestResponseHandler(response);
} catch (error) {
logger.error('Erreur lors de la récupération des messages:', error);
return errorHandler(error);
throw error;
}
};
@ -79,16 +59,14 @@ export const fetchMessages = async (
*/
export const sendMessage = async (messageData, csrfToken) => {
try {
const response = await fetch(BE_GESTIONMESSAGERIE_SEND_MESSAGE_URL, {
return await fetchWithAuth(BE_GESTIONMESSAGERIE_SEND_MESSAGE_URL, {
method: 'POST',
headers: buildHeaders(csrfToken),
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(messageData),
});
return await requestResponseHandler(response);
} catch (error) {
logger.error("Erreur lors de l'envoi du message:", error);
return errorHandler(error);
throw error;
}
};
@ -103,17 +81,14 @@ export const createConversation = async (participantIds, csrfToken) => {
name: '', // Le nom sera généré côté backend
};
const response = await fetch(BE_GESTIONMESSAGERIE_CREATE_CONVERSATION_URL, {
return await fetchWithAuth(BE_GESTIONMESSAGERIE_CREATE_CONVERSATION_URL, {
method: 'POST',
headers: buildHeaders(csrfToken),
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(requestBody),
});
return await requestResponseHandler(response);
} catch (error) {
logger.error('Erreur lors de la création de la conversation:', error);
return errorHandler(error);
throw error;
}
};
@ -132,16 +107,12 @@ export const searchMessagerieRecipients = async (
const url = `${baseUrl}?establishment_id=${establishmentId}&q=${encodeURIComponent(query)}`;
const response = await fetch(url, {
method: 'GET',
headers: buildHeaders(csrfToken),
credentials: 'include',
return await fetchWithAuth(url, {
headers: { 'X-CSRFToken': csrfToken },
});
return await requestResponseHandler(response);
} catch (error) {
logger.error('Erreur lors de la recherche des destinataires:', error);
return errorHandler(error);
throw error;
}
};
@ -150,19 +121,17 @@ export const searchMessagerieRecipients = async (
*/
export const markAsRead = async (conversationId, userId, csrfToken) => {
try {
const response = await fetch(BE_GESTIONMESSAGERIE_MARK_AS_READ_URL, {
return await fetchWithAuth(BE_GESTIONMESSAGERIE_MARK_AS_READ_URL, {
method: 'POST',
headers: buildHeaders(csrfToken),
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify({
conversation_id: conversationId,
user_id: userId,
}),
});
return await requestResponseHandler(response);
} catch (error) {
logger.error('Erreur lors du marquage des messages comme lus:', error);
return errorHandler(error);
throw error;
}
};
@ -181,6 +150,7 @@ export const uploadFile = async (
formData.append('conversation_id', conversationId);
formData.append('sender_id', senderId);
const token = await getAuthToken();
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
@ -223,7 +193,10 @@ export const uploadFile = async (
xhr.withCredentials = true;
xhr.timeout = 30000;
// Ajouter le header CSRF pour XMLHttpRequest
// Ajouter les headers d'authentification pour XMLHttpRequest
if (token) {
xhr.setRequestHeader('Authorization', `Bearer ${token}`);
}
if (csrfToken) {
xhr.setRequestHeader('X-CSRFToken', csrfToken);
}
@ -238,14 +211,12 @@ export const uploadFile = async (
export const deleteConversation = async (conversationId, csrfToken) => {
try {
const url = `${BE_GESTIONMESSAGERIE_DELETE_CONVERSATION_URL}/${conversationId}/`;
const response = await fetch(url, {
return await fetchWithAuth(url, {
method: 'DELETE',
headers: buildHeaders(csrfToken),
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
});
return await requestResponseHandler(response);
} catch (error) {
logger.error('Erreur lors de la suppression de la conversation:', error);
return errorHandler(error);
throw error;
}
};

View File

@ -1,49 +1,31 @@
import { BE_PLANNING_PLANNINGS_URL, BE_PLANNING_EVENTS_URL } from '@/utils/Url';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth } from '@/utils/fetchWithAuth';
const getData = (url) => {
return fetch(`${url}`).then(requestResponseHandler).catch(errorHandler);
return fetchWithAuth(url);
};
const createDatas = (url, newData, csrfToken) => {
return fetch(url, {
return fetchWithAuth(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(newData),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
const updateDatas = (url, updatedData, csrfToken) => {
return fetch(`${url}`, {
return fetchWithAuth(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(updatedData),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
const removeDatas = (url, csrfToken) => {
return fetch(`${url}`, {
return fetchWithAuth(url, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
headers: { 'X-CSRFToken': csrfToken },
});
};
export const fetchPlannings = (

View File

@ -5,213 +5,113 @@ import {
BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL,
BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL
} from '@/utils/Url';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth, fetchWithAuthRaw } from '@/utils/fetchWithAuth';
// FETCH requests
export async function fetchRegistrationFileGroups(establishment) {
const response = await fetch(
`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}?establishment_id=${establishment}`,
{
credentials: 'include',
headers: {
Accept: 'application/json',
},
}
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}?establishment_id=${establishment}`
);
if (!response.ok) {
throw new Error('Failed to fetch file groups');
}
return response.json();
}
export const fetchRegistrationFileFromGroup = async (groupId) => {
const response = await fetch(
`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}/school_file_templates`,
{
credentials: 'include',
headers: {
Accept: 'application/json',
},
}
export const fetchRegistrationFileFromGroup = (groupId) => {
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}/school_file_templates`
);
if (!response.ok) {
throw new Error(
'Erreur lors de la récupération des fichiers associés au groupe'
);
}
return response.json();
};
export const fetchRegistrationSchoolFileMasters = (establishment) => {
let url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}?establishment_id=${establishment}`;
const request = new Request(`${url}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
const url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}?establishment_id=${establishment}`;
return fetchWithAuth(url);
};
export const fetchRegistrationParentFileMasters = (establishment) => {
let url = `${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}?establishment_id=${establishment}`;
const request = new Request(`${url}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
const url = `${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}?establishment_id=${establishment}`;
return fetchWithAuth(url);
};
export const fetchRegistrationSchoolFileTemplates = (establishment) => {
let url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}?establishment_id=${establishment}`;
const request = new Request(`${url}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
const url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}?establishment_id=${establishment}`;
return fetchWithAuth(url);
};
// CREATE requests
export async function createRegistrationFileGroup(groupData, csrfToken) {
const response = await fetch(
`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
body: JSON.stringify(groupData),
credentials: 'include',
}
);
if (!response.ok) {
throw new Error('Failed to create file group');
}
return response.json();
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}`, {
method: 'POST',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(groupData),
});
}
export const createRegistrationSchoolFileMaster = (data, csrfToken) => {
// Toujours FormData, jamais JSON
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}`, {
method: 'POST',
headers: { 'X-CSRFToken': csrfToken },
body: data,
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const createRegistrationParentFileMaster = (data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}`, {
method: 'POST',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const createRegistrationSchoolFileTemplate = (data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}`, {
method: 'POST',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const createRegistrationParentFileTemplate = (data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL}`, {
method: 'POST',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
// EDIT requests
export const editRegistrationFileGroup = async (
groupId,
groupData,
csrfToken
) => {
const response = await fetch(
export const editRegistrationFileGroup = (groupId, groupData, csrfToken) => {
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(groupData),
}
);
if (!response.ok) {
throw new Error('Erreur lors de la modification du groupe');
}
return response.json();
};
export const editRegistrationSchoolFileMaster = (fileId, data, csrfToken) => {
return fetch(
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}/${fileId}`,
{
method: 'PUT',
headers: { 'X-CSRFToken': csrfToken },
body: data,
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
}
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const editRegistrationParentFileMaster = (id, data, csrfToken) => {
return fetch(
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}/${id}`,
{
method: 'PUT',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
}
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const editRegistrationSchoolFileTemplates = (
@ -219,19 +119,14 @@ export const editRegistrationSchoolFileTemplates = (
data,
csrfToken
) => {
return fetch(
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${fileId}`,
{
method: 'PUT',
headers: { 'X-CSRFToken': csrfToken },
body: data,
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
}
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const editRegistrationParentFileTemplates = (
@ -239,86 +134,64 @@ export const editRegistrationParentFileTemplates = (
data,
csrfToken
) => {
return fetch(
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL}/${fileId}`,
{
method: 'PUT',
headers: { 'X-CSRFToken': csrfToken },
body: data,
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
}
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
// DELETE requests
export async function deleteRegistrationFileGroup(groupId, csrfToken) {
const response = await fetch(
return fetchWithAuthRaw(
`${BE_SUBSCRIPTION_REGISTRATIONFILE_GROUPS_URL}/${groupId}`,
{
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
}
);
return response;
}
export const deleteRegistrationSchoolFileMaster = (fileId, csrfToken) => {
return fetch(
return fetchWithAuthRaw(
`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}/${fileId}`,
{
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
}
);
};
export const deleteRegistrationParentFileMaster = (id, csrfToken) => {
return fetch(
return fetchWithAuthRaw(
`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_MASTERS_URL}/${id}`,
{
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
}
);
};
export const deleteRegistrationSchoolFileTemplates = (fileId, csrfToken) => {
return fetch(
return fetchWithAuthRaw(
`${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${fileId}`,
{
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
}
);
};
export const deleteRegistrationParentFileTemplate = (id, csrfToken) => {
return fetch(
return fetchWithAuthRaw(
`${BE_SUBSCRIPTION_REGISTRATION_PARENT_FILE_TEMPLATES_URL}/${id}`,
{
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
}
);
};

View File

@ -10,185 +10,125 @@ import {
BE_SCHOOL_ESTABLISHMENT_URL,
BE_SCHOOL_ESTABLISHMENT_COMPETENCIES_URL,
} from '@/utils/Url';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth } from '@/utils/fetchWithAuth';
export const deleteEstablishmentCompetencies = (ids, csrfToken) => {
return fetch(BE_SCHOOL_ESTABLISHMENT_COMPETENCIES_URL, {
return fetchWithAuth(BE_SCHOOL_ESTABLISHMENT_COMPETENCIES_URL, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify({ ids }),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const createEstablishmentCompetencies = (newData, csrfToken) => {
return fetch(BE_SCHOOL_ESTABLISHMENT_COMPETENCIES_URL, {
return fetchWithAuth(BE_SCHOOL_ESTABLISHMENT_COMPETENCIES_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(newData),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const fetchEstablishmentCompetencies = (establishment, cycle = 1) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_ESTABLISHMENT_COMPETENCIES_URL}?establishment_id=${establishment}&cycle=${cycle}`
)
.then(requestResponseHandler)
.catch(errorHandler);
};
export const fetchSpecialities = (establishment) => {
return fetch(
`${BE_SCHOOL_SPECIALITIES_URL}?establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
};
export const fetchTeachers = (establishment) => {
return fetch(`${BE_SCHOOL_TEACHERS_URL}?establishment_id=${establishment}`)
.then(requestResponseHandler)
.catch(errorHandler);
};
export const fetchClasses = (establishment) => {
return fetch(
`${BE_SCHOOL_SCHOOLCLASSES_URL}?establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
};
export const fetchClasse = (id) => {
return fetch(`${BE_SCHOOL_SCHOOLCLASSES_URL}/${id}`).then(
requestResponseHandler
);
};
export const fetchSpecialities = (establishment) => {
return fetchWithAuth(
`${BE_SCHOOL_SPECIALITIES_URL}?establishment_id=${establishment}`
);
};
export const fetchTeachers = (establishment) => {
return fetchWithAuth(`${BE_SCHOOL_TEACHERS_URL}?establishment_id=${establishment}`);
};
export const fetchClasses = (establishment) => {
return fetchWithAuth(
`${BE_SCHOOL_SCHOOLCLASSES_URL}?establishment_id=${establishment}`
);
};
export const fetchClasse = (id) => {
return fetchWithAuth(`${BE_SCHOOL_SCHOOLCLASSES_URL}/${id}`);
};
export const fetchSchedules = () => {
return fetch(`${BE_SCHOOL_PLANNINGS_URL}`)
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(`${BE_SCHOOL_PLANNINGS_URL}`);
};
export const fetchRegistrationDiscounts = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_DISCOUNTS_URL}?filter=registration&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchTuitionDiscounts = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_DISCOUNTS_URL}?filter=tuition&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchRegistrationFees = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_FEES_URL}?filter=registration&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchTuitionFees = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_FEES_URL}?filter=tuition&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchRegistrationPaymentPlans = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_PAYMENT_PLANS_URL}?filter=registration&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchTuitionPaymentPlans = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_PAYMENT_PLANS_URL}?filter=tuition&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchRegistrationPaymentModes = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_PAYMENT_MODES_URL}?filter=registration&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchTuitionPaymentModes = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SCHOOL_PAYMENT_MODES_URL}?filter=tuition&establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const fetchEstablishment = (establishment) => {
return fetch(`${BE_SCHOOL_ESTABLISHMENT_URL}/${establishment}`)
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(`${BE_SCHOOL_ESTABLISHMENT_URL}/${establishment}`);
};
export const createDatas = (url, newData, csrfToken) => {
return fetch(url, {
return fetchWithAuth(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(newData),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const updateDatas = (url, id, updatedData, csrfToken) => {
return fetch(`${url}/${id}`, {
return fetchWithAuth(`${url}/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(updatedData),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const removeDatas = (url, id, csrfToken) => {
return fetch(`${url}/${id}`, {
return fetchWithAuth(`${url}/${id}`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
headers: { 'X-CSRFToken': csrfToken },
});
};

View File

@ -1,5 +1,5 @@
import { BE_SETTINGS_SMTP_URL } from '@/utils/Url';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth } from '@/utils/fetchWithAuth';
export const PENDING = 'pending';
export const SUBSCRIBED = 'subscribed';
@ -10,26 +10,15 @@ export const fetchSmtpSettings = (csrfToken, establishment_id = null) => {
if (establishment_id) {
url += `?establishment_id=${establishment_id}`;
}
return fetch(`${url}`, {
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url, {
headers: { 'X-CSRFToken': csrfToken },
});
};
export const editSmtpSettings = (data, csrfToken) => {
return fetch(`${BE_SETTINGS_SMTP_URL}/`, {
return fetchWithAuth(`${BE_SETTINGS_SMTP_URL}/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};

View File

@ -11,20 +11,15 @@ import {
} from '@/utils/Url';
import { CURRENT_YEAR_FILTER } from '@/utils/constants';
import { errorHandler, requestResponseHandler } from './actionsHandlers';
import { fetchWithAuth, fetchWithAuthRaw } from '@/utils/fetchWithAuth';
import logger from '@/utils/logger';
export const editStudentCompetencies = (data, csrfToken) => {
const request = new Request(`${BE_SUBSCRIPTION_STUDENT_COMPETENCIES_URL}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_STUDENT_COMPETENCIES_URL}`, {
method: 'PUT',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
};
export const fetchStudentCompetencies = (id, period) => {
@ -33,13 +28,7 @@ export const fetchStudentCompetencies = (id, period) => {
? `${BE_SUBSCRIPTION_STUDENT_COMPETENCIES_URL}?student_id=${id}&period=${period}`
: `${BE_SUBSCRIPTION_STUDENT_COMPETENCIES_URL}?student_id=${id}`;
const request = new Request(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
return fetchWithAuth(url);
};
export const fetchRegisterForms = (
@ -53,37 +42,22 @@ export const fetchRegisterForms = (
if (page !== '' && pageSize !== '') {
url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}?filter=${filter}&establishment_id=${establishment}&page=${page}&search=${search}`;
}
return fetch(url, {
headers: {
'Content-Type': 'application/json',
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
export const fetchRegisterForm = (id) => {
return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`) // Utilisation de studentId au lieu de codeDI
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`); // Utilisation de studentId au lieu de codeDI
};
export const fetchLastGuardian = () => {
return fetch(`${BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL}`)
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(`${BE_SUBSCRIPTION_LAST_GUARDIAN_ID_URL}`);
};
export const editRegisterForm = (id, data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`, {
method: 'PUT',
headers: {
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: data,
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const autoSaveRegisterForm = async (id, data, csrfToken) => {
@ -106,15 +80,12 @@ export const autoSaveRegisterForm = async (id, data, csrfToken) => {
}
autoSaveData.append('auto_save', 'true');
return fetch(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}`, {
method: 'PATCH', // Utiliser PATCH pour les mises à jour partielles
headers: {
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: autoSaveData,
credentials: 'include',
})
.then(requestResponseHandler)
.then(() => {})
.catch(() => {
// Silent fail pour l'auto-save
logger.debug('Auto-save failed silently');
@ -127,62 +98,30 @@ export const autoSaveRegisterForm = async (id, data, csrfToken) => {
export const createRegisterForm = (data, csrfToken) => {
const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}`;
return fetch(url, {
return fetchWithAuth(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const sendRegisterForm = (id) => {
const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/send`;
return fetch(url, {
headers: {
'Content-Type': 'application/json',
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
export const resendRegisterForm = (id) => {
const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/resend`;
return fetch(url, {
headers: {
'Content-Type': 'application/json',
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
export const archiveRegisterForm = (id) => {
const url = `${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/archive`;
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
export const searchStudents = (establishmentId, query) => {
const url = `${BE_SUBSCRIPTION_SEARCH_STUDENTS_URL}/?establishment_id=${establishmentId}&q=${encodeURIComponent(query)}`;
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
export const fetchStudents = (establishment, id = null, status = null) => {
@ -195,153 +134,68 @@ export const fetchStudents = (establishment, id = null, status = null) => {
url += `&status=${status}`;
}
}
const request = new Request(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
return fetch(request).then(requestResponseHandler).catch(errorHandler);
return fetchWithAuth(url);
};
export const fetchChildren = (id, establishment) => {
const request = new Request(
`${BE_SUBSCRIPTION_CHILDRENS_URL}/${id}?establishment_id=${establishment}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}
return fetchWithAuth(
`${BE_SUBSCRIPTION_CHILDRENS_URL}/${id}?establishment_id=${establishment}`
);
return fetch(request).then(requestResponseHandler).catch(errorHandler);
};
export async function getRegisterFormFileTemplate(fileId) {
const response = await fetch(
`${BE_SUBSCRIPTION_REGISTERFORM_FILE_TEMPLATE_URL}/${fileId}`,
{
credentials: 'include',
headers: {
Accept: 'application/json',
},
}
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTERFORM_FILE_TEMPLATE_URL}/${fileId}`
);
if (!response.ok) {
throw new Error('Failed to fetch file template');
}
return response.json();
}
export const fetchSchoolFileTemplatesFromRegistrationFiles = async (id) => {
const response = await fetch(
`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/school_file_templates`,
{
credentials: 'include',
headers: {
Accept: 'application/json',
},
}
export const fetchSchoolFileTemplatesFromRegistrationFiles = (id) => {
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/school_file_templates`
);
if (!response.ok) {
throw new Error(
'Erreur lors de la récupération des fichiers associés au groupe'
);
}
return response.json();
};
export const fetchParentFileTemplatesFromRegistrationFiles = async (id) => {
const response = await fetch(
`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/parent_file_templates`,
{
credentials: 'include',
headers: {
Accept: 'application/json',
},
}
export const fetchParentFileTemplatesFromRegistrationFiles = (id) => {
return fetchWithAuth(
`${BE_SUBSCRIPTION_REGISTERFORMS_URL}/${id}/parent_file_templates`
);
if (!response.ok) {
throw new Error(
'Erreur lors de la récupération des fichiers associés au groupe'
);
}
return response.json();
};
export const dissociateGuardian = async (studentId, guardianId) => {
const response = await fetch(
export const dissociateGuardian = (studentId, guardianId) => {
return fetchWithAuth(
`${BE_SUBSCRIPTION_STUDENTS_URL}/${studentId}/guardians/${guardianId}/dissociate`,
{
credentials: 'include',
method: 'PUT',
headers: {
Accept: 'application/json',
},
}
);
if (!response.ok) {
// Extraire le message d'erreur du backend
const errorData = await response.json();
const errorMessage =
errorData?.error || 'Une erreur est survenue lors de la dissociation.';
// Jeter une erreur avec le message spécifique
throw new Error(errorMessage);
}
return response.json();
};
export const fetchAbsences = (establishment) => {
return fetch(
return fetchWithAuth(
`${BE_SUBSCRIPTION_ABSENCES_URL}?establishment_id=${establishment}`
)
.then(requestResponseHandler)
.catch(errorHandler);
);
};
export const createAbsences = (data, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_ABSENCES_URL}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_ABSENCES_URL}`, {
method: 'POST',
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(data),
headers: {
'X-CSRFToken': csrfToken,
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
export const editAbsences = (absenceId, payload, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_ABSENCES_URL}/${absenceId}`, {
return fetchWithAuth(`${BE_SUBSCRIPTION_ABSENCES_URL}/${absenceId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
body: JSON.stringify(payload), // Sérialisez les données en JSON
credentials: 'include',
}).then((response) => {
if (!response.ok) {
return response.json().then((error) => {
throw new Error(error);
});
}
return response.json();
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(payload),
});
};
export const deleteAbsences = (id, csrfToken) => {
return fetch(`${BE_SUBSCRIPTION_ABSENCES_URL}/${id}`, {
return fetchWithAuthRaw(`${BE_SUBSCRIPTION_ABSENCES_URL}/${id}`, {
method: 'DELETE',
headers: {
'X-CSRFToken': csrfToken,
},
credentials: 'include',
headers: { 'X-CSRFToken': csrfToken },
});
};
@ -352,16 +206,7 @@ export const deleteAbsences = (id, csrfToken) => {
*/
export const fetchRegistrationSchoolFileMasters = (establishmentId) => {
const url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_MASTERS_URL}?establishment_id=${establishmentId}`;
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};
/**
@ -373,22 +218,14 @@ export const fetchRegistrationSchoolFileMasters = (establishmentId) => {
*/
export const saveFormResponses = (templateId, formTemplateData, csrfToken) => {
const url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${templateId}`;
const payload = {
formTemplateData: formTemplateData,
};
return fetch(url, {
return fetchWithAuth(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
headers: { 'X-CSRFToken': csrfToken },
body: JSON.stringify(payload),
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
});
};
/**
@ -398,14 +235,5 @@ export const saveFormResponses = (templateId, formTemplateData, csrfToken) => {
*/
export const fetchFormResponses = (templateId) => {
const url = `${BE_SUBSCRIPTION_REGISTRATION_SCHOOL_FILE_TEMPLATES_URL}/${templateId}`;
return fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
})
.then(requestResponseHandler)
.catch(errorHandler);
return fetchWithAuth(url);
};