Se soluciono autenticacion
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
const API_URL = import.meta.env.VITE_EFC_API_URL;
|
||||
|
||||
// Variable para controlar si ya hay una renovación de token en proceso
|
||||
let isRefreshing = false;
|
||||
let failedQueue = [];
|
||||
|
||||
// Función para procesar la cola de peticiones fallidas después de renovar el token
|
||||
const processQueue = (error, token = null) => {
|
||||
failedQueue.forEach(prom => {
|
||||
if (error) {
|
||||
prom.reject(error);
|
||||
} else {
|
||||
prom.resolve(token);
|
||||
}
|
||||
});
|
||||
|
||||
failedQueue = [];
|
||||
};
|
||||
|
||||
// Función para renovar el token usando el refresh token
|
||||
const refreshToken = async () => {
|
||||
try {
|
||||
const refresh = localStorage.getItem('refresh');
|
||||
if (!refresh) {
|
||||
throw new Error('No refresh token available');
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_URL}/auth/token/refresh/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
refresh: refresh
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to refresh token');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Guardar el nuevo access token
|
||||
localStorage.setItem('access', data.access);
|
||||
|
||||
// Si viene un nuevo refresh token, guardarlo también
|
||||
if (data.refresh) {
|
||||
localStorage.setItem('refresh', data.refresh);
|
||||
}
|
||||
|
||||
return data.access;
|
||||
} catch (error) {
|
||||
// Si falla la renovación, limpiar tokens y redirigir al login
|
||||
localStorage.removeItem('access');
|
||||
localStorage.removeItem('refresh');
|
||||
localStorage.removeItem('user_id');
|
||||
localStorage.removeItem('user_is_importador');
|
||||
|
||||
// Redirigir al login después de un pequeño delay
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
}, 1000);
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Función principal para hacer peticiones con manejo automático de tokens
|
||||
export const fetchWithAuth = async (url, options = {}) => {
|
||||
// Obtener el token actual
|
||||
let token = localStorage.getItem('access');
|
||||
|
||||
// Configurar headers por defecto
|
||||
const defaultHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
...(token && { 'Authorization': `Bearer ${token}` })
|
||||
};
|
||||
|
||||
// Combinar headers
|
||||
const finalOptions = {
|
||||
...options,
|
||||
headers: {
|
||||
...defaultHeaders,
|
||||
...options.headers
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
// Hacer la petición inicial
|
||||
let response = await fetch(url, finalOptions);
|
||||
|
||||
// Si la respuesta es 401 (Unauthorized), intentar renovar el token
|
||||
if (response.status === 401 && !isRefreshing) {
|
||||
isRefreshing = true;
|
||||
|
||||
try {
|
||||
// Renovar el token
|
||||
const newToken = await refreshToken();
|
||||
|
||||
// Procesar la cola de peticiones pendientes
|
||||
processQueue(null, newToken);
|
||||
|
||||
// Actualizar el header de autorización y reintentar la petición original
|
||||
finalOptions.headers['Authorization'] = `Bearer ${newToken}`;
|
||||
response = await fetch(url, finalOptions);
|
||||
|
||||
} catch (refreshError) {
|
||||
// Si falla la renovación, procesar la cola con error
|
||||
processQueue(refreshError, null);
|
||||
throw refreshError;
|
||||
} finally {
|
||||
isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Si todavía hay un 401 después del intento de renovación, redirigir al login
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('access');
|
||||
localStorage.removeItem('refresh');
|
||||
localStorage.removeItem('user_id');
|
||||
localStorage.removeItem('user_is_importador');
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
}, 1000);
|
||||
|
||||
throw new Error('Session expired');
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
// Si hay un error de red o cualquier otro error, propagarlo
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Función auxiliar para hacer peticiones GET con manejo de tokens
|
||||
export const getWithAuth = async (url) => {
|
||||
return fetchWithAuth(url, { method: 'GET' });
|
||||
};
|
||||
|
||||
// Función auxiliar para hacer peticiones POST con manejo de tokens
|
||||
export const postWithAuth = async (url, data) => {
|
||||
return fetchWithAuth(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
};
|
||||
|
||||
// Función auxiliar para hacer peticiones PUT con manejo de tokens
|
||||
export const putWithAuth = async (url, data) => {
|
||||
return fetchWithAuth(url, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
};
|
||||
|
||||
// Función auxiliar para hacer peticiones PATCH con manejo de tokens
|
||||
export const patchWithAuth = async (url, data) => {
|
||||
return fetchWithAuth(url, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
};
|
||||
|
||||
// Función auxiliar para hacer peticiones DELETE con manejo de tokens
|
||||
export const deleteWithAuth = async (url) => {
|
||||
return fetchWithAuth(url, { method: 'DELETE' });
|
||||
};
|
||||
|
||||
// Función para hacer peticiones con FormData (para archivos)
|
||||
export const postFormDataWithAuth = async (url, formData) => {
|
||||
let token = localStorage.getItem('access');
|
||||
|
||||
const options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...(token && { 'Authorization': `Bearer ${token}` })
|
||||
},
|
||||
body: formData
|
||||
};
|
||||
|
||||
try {
|
||||
let response = await fetch(url, options);
|
||||
|
||||
if (response.status === 401 && !isRefreshing) {
|
||||
isRefreshing = true;
|
||||
|
||||
try {
|
||||
const newToken = await refreshToken();
|
||||
processQueue(null, newToken);
|
||||
|
||||
options.headers['Authorization'] = `Bearer ${newToken}`;
|
||||
response = await fetch(url, options);
|
||||
|
||||
} catch (refreshError) {
|
||||
processQueue(refreshError, null);
|
||||
throw refreshError;
|
||||
} finally {
|
||||
isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('access');
|
||||
localStorage.removeItem('refresh');
|
||||
localStorage.removeItem('user_id');
|
||||
localStorage.removeItem('user_is_importador');
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/login';
|
||||
}, 1000);
|
||||
|
||||
throw new Error('Session expired');
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export default fetchWithAuth;
|
||||
|
||||
Reference in New Issue
Block a user