From a5c1bab201d4ab6a4d88745ab20ddd84aa9437bf Mon Sep 17 00:00:00 2001 From: acazares Date: Wed, 12 Nov 2025 09:46:59 -0600 Subject: [PATCH] Refactor authentication handling and API calls in dashboard routes - Centralized API URL configuration and token management in $lib/server/api.ts. - Replaced direct token access with a centralized method for retrieving tokens. - Updated all dashboard reference data routes to use authenticatedFetch for API calls, improving token refresh handling. - Simplified login route by utilizing centralized token management functions. - Added a new layout file for the dashboard to pass user and company data to the client. --- .../components/sidebar/team-switcher.svelte | 7 +- frontend/src/lib/server/api.ts | 270 ++++++++++++++++++ frontend/src/lib/stores/company.svelte.ts | 46 ++- frontend/src/routes/+page.server.ts | 33 +-- .../src/routes/dashboard/+layout.server.ts | 116 ++------ frontend/src/routes/dashboard/+layout.svelte | 10 +- frontend/src/routes/dashboard/+layout.ts | 10 + .../dashboard/pedimentos/+page.server.ts | 58 ++-- .../pedimentos/edit/[id]/+page.server.ts | 31 +- .../code_pedimento_regimens/+page.server.ts | 30 +- .../reference_data/containers/+page.server.ts | 30 +- .../reference_data/countries/+page.server.ts | 30 +- .../currency_types/+page.server.ts | 30 +- .../customs_sections/+page.server.ts | 30 +- .../customs_warehouses/+page.server.ts | 30 +- .../reference_data/incoterms/+page.server.ts | 30 +- .../invoice_types/+page.server.ts | 30 +- .../material_types/+page.server.ts | 30 +- .../payment_methods/+page.server.ts | 30 +- .../pedimento_codes/+page.server.ts | 30 +- .../pedimento_regimens/+page.server.ts | 30 +- .../reference_data/sectors/+page.server.ts | 30 +- .../reference_data/states/+page.server.ts | 30 +- .../transport_modes/+page.server.ts | 30 +- .../transport_types/+page.server.ts | 30 +- .../valuation_methods/+page.server.ts | 30 +- frontend/src/routes/login/+page.server.ts | 31 +- 27 files changed, 549 insertions(+), 573 deletions(-) create mode 100644 frontend/src/lib/server/api.ts create mode 100644 frontend/src/routes/dashboard/+layout.ts diff --git a/frontend/src/lib/components/sidebar/team-switcher.svelte b/frontend/src/lib/components/sidebar/team-switcher.svelte index ae5870d7..6d85e6c5 100644 --- a/frontend/src/lib/components/sidebar/team-switcher.svelte +++ b/frontend/src/lib/components/sidebar/team-switcher.svelte @@ -9,12 +9,7 @@ const sidebar = useSidebar(); - // Inicializar el store cuando se monta el componente - $effect(() => { - if (companyStore.companies.length === 0) { - companyStore.initialize(); - } - }); + // Ya no es necesario inicializar aquí, se inicializa en +layout.svelte con datos SSR diff --git a/frontend/src/lib/server/api.ts b/frontend/src/lib/server/api.ts new file mode 100644 index 00000000..4c607d15 --- /dev/null +++ b/frontend/src/lib/server/api.ts @@ -0,0 +1,270 @@ +/** + * Utilidades para llamadas a la API desde el servidor (SSR) + * Centraliza la lógica de configuración de URL, autenticación y manejo de tokens + */ + +import { redirect, type Cookies } from '@sveltejs/kit'; + +/** + * Obtiene y normaliza la URL base de la API para llamadas desde el servidor + * Automáticamente reemplaza localhost/127.0.0.1 con 'backend' para Docker + */ +export function getServerApiUrl(): string { + let apiUrl = process.env.INTERNAL_API_URL; + + if (!apiUrl) { + apiUrl = import.meta.env.VITE_API_URL; + // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) + apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); + } + + // Normalizar la URL: asegurar que termine con '/' + return apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; +} + +/** + * Obtiene los tokens de autenticación de las cookies + */ +export function getAuthTokens(cookies: Cookies) { + return { + accessToken: cookies.get('access_token'), + refreshToken: cookies.get('refresh_token') + }; +} + +/** + * Establece los tokens de autenticación en las cookies + */ +export function setAuthTokens( + cookies: Cookies, + accessToken: string, + refreshToken?: string +) { + cookies.set('access_token', accessToken, { + path: '/', + httpOnly: false, + sameSite: 'lax', + secure: process.env.NODE_ENV === 'production', + maxAge: 60 * 60 * 24 * 7 // 7 días + }); + + if (refreshToken) { + cookies.set('refresh_token', refreshToken, { + path: '/', + httpOnly: false, + sameSite: 'lax', + secure: process.env.NODE_ENV === 'production', + maxAge: 60 * 60 * 24 * 30 // 30 días + }); + } +} + +/** + * Limpia todos los tokens de autenticación de las cookies + */ +export function clearAuthTokens(cookies: Cookies) { + cookies.delete('access_token', { path: '/' }); + cookies.delete('refresh_token', { path: '/' }); + cookies.delete('active_company_id', { path: '/' }); +} + +/** + * Crea headers de autorización con el token Bearer + */ +export function createAuthHeaders(token: string, additionalHeaders?: Record) { + return { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json', + ...additionalHeaders + }; +} + +/** + * Intenta refrescar el token de acceso usando el refresh token + * @returns El nuevo access token o null si falla + */ +export async function refreshAccessToken( + cookies: Cookies, + fetch: typeof globalThis.fetch +): Promise { + const { refreshToken } = getAuthTokens(cookies); + + if (!refreshToken) { + return null; + } + + try { + const baseUrl = getServerApiUrl(); + const response = await fetch(`${baseUrl}v1/auth/refresh`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ refresh_token: refreshToken }) + }); + + if (!response.ok) { + return null; + } + + const data = await response.json(); + + // Actualizar las cookies con los nuevos tokens + setAuthTokens(cookies, data.access_token, data.refresh_token); + + return data.access_token; + } catch (error) { + console.error('🔄 [API] Error al refrescar token:', error); + return null; + } +} + +/** + * Realiza una petición autenticada a la API con manejo automático de refresh + * @param endpoint - Endpoint relativo (ej: 'v1/auth/me') + * @param options - Opciones de fetch + * @param cookies - Objeto de cookies de SvelteKit + * @param fetch - Función fetch de SvelteKit + * @param redirectUrl - URL a la que redirigir si falla la autenticación (opcional) + */ +export async function authenticatedFetch( + endpoint: string, + options: RequestInit = {}, + cookies: Cookies, + fetch: typeof globalThis.fetch, + redirectUrl?: string +): Promise { + const baseUrl = getServerApiUrl(); + let { accessToken } = getAuthTokens(cookies); + + // Si no hay token, redirigir o lanzar error + if (!accessToken) { + if (redirectUrl) { + throw redirect(303, redirectUrl); + } + throw new Error('No access token available'); + } + + // Construir URL completa + const url = endpoint.startsWith('http') ? endpoint : `${baseUrl}${endpoint}`; + + // Realizar la petición inicial + const headers = createAuthHeaders(accessToken, options.headers as Record); + let response = await fetch(url, { + ...options, + headers + }); + + // Si es 401, intentar refrescar el token + if (response.status === 401) { + const newToken = await refreshAccessToken(cookies, fetch); + + if (newToken) { + // Reintentar la petición con el nuevo token + const newHeaders = createAuthHeaders(newToken, options.headers as Record); + response = await fetch(url, { + ...options, + headers: newHeaders + }); + } else { + // No se pudo refrescar, limpiar y redirigir + clearAuthTokens(cookies); + if (redirectUrl) { + throw redirect(303, redirectUrl); + } + } + } + + return response; +} + +/** + * Valida que el usuario esté autenticado y obtiene sus datos + * @returns Los datos del usuario o null si no está autenticado + */ +export async function validateAuth( + cookies: Cookies, + fetch: typeof globalThis.fetch, + redirectOnFail?: string +): Promise { + try { + const response = await authenticatedFetch( + 'v1/auth/me', + {}, + cookies, + fetch, + redirectOnFail + ); + + if (!response.ok) { + if (redirectOnFail) { + clearAuthTokens(cookies); + throw redirect(303, redirectOnFail); + } + return null; + } + + return await response.json(); + } catch (error) { + // Si es un redirect, re-lanzarlo + if (error && typeof error === 'object' && 'status' in error && 'location' in error) { + throw error; + } + + console.error('🔐 [API] Error validando autenticación:', error); + + if (redirectOnFail) { + clearAuthTokens(cookies); + throw redirect(303, redirectOnFail); + } + + return null; + } +} + +/** + * Obtiene las compañías del usuario autenticado + */ +export async function getUserCompanies( + cookies: Cookies, + fetch: typeof globalThis.fetch +): Promise { + try { + const response = await authenticatedFetch( + 'v1/a76/company/my-companies', + {}, + cookies, + fetch + ); + + if (!response.ok) { + console.error('🏢 [API] Error cargando compañías:', response.status); + return []; + } + + return await response.json(); + } catch (error) { + console.error('🏢 [API] Error cargando compañías:', error); + return []; + } +} + +/** + * Obtiene el ID de la compañía activa, o la primera disponible si no hay ninguna seleccionada + */ +export async function getActiveCompanyId( + cookies: Cookies, + fetch: typeof globalThis.fetch +): Promise { + let companyId = cookies.get('active_company_id'); + + // Si no hay companyId en cookie, obtener las compañías del usuario y usar la primera + if (!companyId) { + const companies = await getUserCompanies(cookies, fetch); + if (companies.length > 0) { + companyId = companies[0].id.toString(); + } + } + + return companyId || null; +} diff --git a/frontend/src/lib/stores/company.svelte.ts b/frontend/src/lib/stores/company.svelte.ts index 174c3ebf..54cfb71b 100644 --- a/frontend/src/lib/stores/company.svelte.ts +++ b/frontend/src/lib/stores/company.svelte.ts @@ -31,8 +31,42 @@ class CompanyStore { /** * Carga las compañías del tenant del usuario desde el backend + * @param preloadedCompanies - Compañías pre-cargadas desde el servidor (SSR) */ - async loadCompanies() { + async loadCompanies(preloadedCompanies?: Company[]) { + // Si tenemos compañías pre-cargadas, usarlas directamente + if (preloadedCompanies && preloadedCompanies.length > 0) { + // Detectar si el tenant ha cambiado + const newTenantId = preloadedCompanies[0].tenant_id; + + // Si el tenant cambió, limpiar el store primero + if (this._currentTenantId !== null && this._currentTenantId !== newTenantId) { + this.clear(); + } + + this._currentTenantId = newTenantId; + this._companies = preloadedCompanies; + + // Si hay compañías y no hay una activa, seleccionar la primera o la guardada + if (this._companies.length > 0 && !this._activeCompany) { + // Intentar restaurar la compañía guardada + if (typeof window !== 'undefined') { + const savedId = localStorage.getItem('activeCompanyId'); + if (savedId) { + const company = this._companies.find(c => c.id === parseInt(savedId)); + if (company) { + this.setActiveCompany(company); + return; + } + } + } + // Si no hay guardada, seleccionar la primera + this.setActiveCompany(this._companies[0]); + } + return; + } + + // Si no hay datos pre-cargados, hacer fetch (fallback) this._loading = true; try { const response = await fetch('/api/company/my-companies'); @@ -133,10 +167,14 @@ class CompanyStore { /** * Inicializa el store cargando las compañías + * @param preloadedCompanies - Compañías pre-cargadas desde el servidor (SSR) */ - async initialize() { - await this.loadCompanies(); - this.restoreActiveCompany(); + async initialize(preloadedCompanies?: Company[]) { + await this.loadCompanies(preloadedCompanies); + // Si no hay compañías pre-cargadas, intentar restaurar de localStorage + if (!preloadedCompanies) { + this.restoreActiveCompany(); + } } } diff --git a/frontend/src/routes/+page.server.ts b/frontend/src/routes/+page.server.ts index 915d6671..36adcfa4 100644 --- a/frontend/src/routes/+page.server.ts +++ b/frontend/src/routes/+page.server.ts @@ -1,35 +1,27 @@ import { redirect } from '@sveltejs/kit'; import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch, clearAuthTokens } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch }) => { - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); // Si hay token, validar que sea válido antes de redirigir - if (token) { + if (accessToken) { try { - // Configurar la URL de la API - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - // Verificar si el token es válido - const response = await fetch(`${baseUrl}v1/auth/me`, { - headers: { - 'Authorization': `Bearer ${token}` - } - }); + // Verificar si el token es válido usando authenticatedFetch + const response = await authenticatedFetch( + 'v1/auth/me', + {}, + cookies, + fetch + ); // Solo redirigir al dashboard si el token es válido if (response.ok) { throw redirect(303, '/dashboard'); } else { // Token inválido, limpiar cookies y mostrar la página pública - cookies.delete('access_token', { path: '/' }); - cookies.delete('refresh_token', { path: '/' }); + clearAuthTokens(cookies); } } catch (error) { // Si es un redirect, re-lanzarlo @@ -37,8 +29,7 @@ export const load: PageServerLoad = async ({ cookies, fetch }) => { throw error; } // Para otros errores, limpiar cookies y continuar - cookies.delete('access_token', { path: '/' }); - cookies.delete('refresh_token', { path: '/' }); + clearAuthTokens(cookies); } } diff --git a/frontend/src/routes/dashboard/+layout.server.ts b/frontend/src/routes/dashboard/+layout.server.ts index 8c562d3d..33475637 100644 --- a/frontend/src/routes/dashboard/+layout.server.ts +++ b/frontend/src/routes/dashboard/+layout.server.ts @@ -1,109 +1,36 @@ import { redirect } from '@sveltejs/kit'; import type { LayoutServerLoad } from './$types'; +import { + validateAuth, + getUserCompanies, + getAuthTokens, + clearAuthTokens +} from '$lib/server/api'; export const load: LayoutServerLoad = async ({ cookies, url, fetch }) => { // Verificar si existe el token en las cookies - let token = cookies.get('access_token'); - const refreshToken = cookies.get('refresh_token'); + const { accessToken } = getAuthTokens(cookies); // Si no hay token, redirigir al login - if (!token) { - // Guardar la URL a la que intentaba acceder para redirigir después del login - throw redirect(303, `/login?redirect=${encodeURIComponent(url.pathname)}`); + if (!accessToken) { + const redirectUrl = `/login?redirect=${encodeURIComponent(url.pathname)}`; + throw redirect(303, redirectUrl); } - // Configurar la URL de la API - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } + // Validar el token con el backend y obtener datos del usuario + // La función validateAuth maneja automáticamente el refresh de tokens + const redirectOnFail = `/login?redirect=${encodeURIComponent(url.pathname)}`; - // Normalizar la URL: asegurar que termine con '/' - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - // Validar el token con el backend para asegurar que sea válido - try { - const response = await fetch(`${baseUrl}v1/auth/me`, { - headers: { - 'Authorization': `Bearer ${token}` - } - }); + try { + const userData = await validateAuth(cookies, fetch, redirectOnFail); - // Si el token está expirado (401) y tenemos refresh token, intentar refrescar - if (response.status === 401 && refreshToken) { - try { - const refreshResponse = await fetch(`${baseUrl}v1/auth/refresh`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ refresh_token: refreshToken }) - }); - - if (refreshResponse.ok) { - const refreshData = await refreshResponse.json(); - - // Actualizar las cookies con los nuevos tokens - cookies.set('access_token', refreshData.access_token, { - path: '/', - httpOnly: false, - sameSite: 'lax', - secure: process.env.NODE_ENV === 'production', - maxAge: 60 * 60 * 24 * 7 // 7 días - }); - - if (refreshData.refresh_token) { - cookies.set('refresh_token', refreshData.refresh_token, { - path: '/', - httpOnly: false, - sameSite: 'lax', - secure: process.env.NODE_ENV === 'production', - maxAge: 60 * 60 * 24 * 30 // 30 días - }); - } - - // Usar el nuevo token para obtener la info del usuario - token = refreshData.access_token; - - // Reintentar la validación con el nuevo token - const retryResponse = await fetch(`${baseUrl}v1/auth/me`, { - headers: { - 'Authorization': `Bearer ${token}` - } - }); - - if (retryResponse.ok) { - const userData = await retryResponse.json(); - return { - authenticated: true, - user: userData - }; - } - } - } catch (refreshError) { - console.error('🔐 [Dashboard] Error al refrescar token:', refreshError); - } - - // Si llegamos aquí, el refresh falló - cookies.delete('access_token', { path: '/' }); - cookies.delete('refresh_token', { path: '/' }); - throw redirect(303, `/login?redirect=${encodeURIComponent(url.pathname)}`); - } - - if (!response.ok) { - // Token inválido y no se pudo refrescar, limpiar y redirigir - cookies.delete('access_token', { path: '/' }); - cookies.delete('refresh_token', { path: '/' }); - throw redirect(303, `/login?redirect=${encodeURIComponent(url.pathname)}`); - } - - const userData = await response.json(); + // Cargar las compañías del usuario en el servidor (SSR) + const companies = await getUserCompanies(cookies, fetch); return { authenticated: true, - user: userData + user: userData, + companies // Pasar las compañías al cliente }; } catch (error) { // Si es un redirect, re-lanzarlo sin tocar las cookies @@ -113,8 +40,7 @@ export const load: LayoutServerLoad = async ({ cookies, url, fetch }) => { // Para cualquier otro error (conexión, etc), limpiar token y redirigir console.error('🔐 [Dashboard] Error validando token:', error); - cookies.delete('access_token', { path: '/' }); - cookies.delete('refresh_token', { path: '/' }); - throw redirect(303, `/login?redirect=${encodeURIComponent(url.pathname)}`); + clearAuthTokens(cookies); + throw redirect(303, redirectOnFail); } }; diff --git a/frontend/src/routes/dashboard/+layout.svelte b/frontend/src/routes/dashboard/+layout.svelte index 9f9d5e79..350c00e5 100644 --- a/frontend/src/routes/dashboard/+layout.svelte +++ b/frontend/src/routes/dashboard/+layout.svelte @@ -1,15 +1,23 @@ diff --git a/frontend/src/routes/dashboard/+layout.ts b/frontend/src/routes/dashboard/+layout.ts new file mode 100644 index 00000000..daa0c25c --- /dev/null +++ b/frontend/src/routes/dashboard/+layout.ts @@ -0,0 +1,10 @@ +import type { LayoutLoad } from './$types'; + +export const load: LayoutLoad = async ({ data }) => { + // Pasar los datos del servidor al cliente + return { + user: data.user, + companies: data.companies, + authenticated: data.authenticated + }; +}; diff --git a/frontend/src/routes/dashboard/pedimentos/+page.server.ts b/frontend/src/routes/dashboard/pedimentos/+page.server.ts index 1d50c83f..0cc853a8 100644 --- a/frontend/src/routes/dashboard/pedimentos/+page.server.ts +++ b/frontend/src/routes/dashboard/pedimentos/+page.server.ts @@ -1,46 +1,22 @@ import type { PageServerLoad } from './$types'; import { redirect } from '@sveltejs/kit'; +import { + getAuthTokens, + getActiveCompanyId, + authenticatedFetch +} from '$lib/server/api'; export const load: PageServerLoad = async ({ fetch, cookies }) => { // Verificar autenticación - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { throw redirect(302, '/login'); } try { - // Cargar datos iniciales de pedimentos - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - // Obtener el company_id de la cookie o usar la primera disponible - let companyId = cookies.get('active_company_id'); - - // Si no hay companyId en cookie, obtener las compañías del usuario y usar la primera - if (!companyId) { - const companiesResponse = await fetch(`${baseUrl}v1/a76/company/my-companies`, { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - }); - - if (companiesResponse.ok) { - const companies = await companiesResponse.json(); - if (companies.length > 0) { - companyId = companies[0].id.toString(); - } - } - } + const companyId = await getActiveCompanyId(cookies, fetch); // Si aún no hay companyId, mostrar error if (!companyId) { @@ -53,18 +29,16 @@ export const load: PageServerLoad = async ({ fetch, cookies }) => { }; } - const response = await fetch(`${baseUrl}v1/a76/pedimentos?company_id=${companyId}&page=1&page_size=50`, { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - }); + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/a76/pedimentos?company_id=${companyId}&page=1&page_size=50`, + {}, + cookies, + fetch, + '/login' + ); if (!response.ok) { - if (response.status === 401 || response.status === 403) { - throw redirect(302, '/login'); - } - return { items: [], total: 0, diff --git a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts index 1a815c21..42c4e91f 100644 --- a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts +++ b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts @@ -1,8 +1,9 @@ import type { PageServerLoad } from './$types'; import { error, redirect } from '@sveltejs/kit'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; -export const load: PageServerLoad = async ({ params, cookies }) => { - const accessToken = cookies.get('access_token'); +export const load: PageServerLoad = async ({ params, cookies, fetch }) => { + const { accessToken } = getAuthTokens(cookies); if (!accessToken) { throw redirect(302, '/login'); @@ -23,26 +24,12 @@ export const load: PageServerLoad = async ({ params, cookies }) => { } try { - - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - // Cargar el pedimento desde el backend - const response = await fetch( - `${baseUrl}v1/a76/pedimentos/${pedimentoId}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - 'Content-Type': 'application/json' - } - } + // Cargar el pedimento desde el backend usando authenticatedFetch + const response = await authenticatedFetch( + `v1/a76/pedimentos/${pedimentoId}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.server.ts b/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.server.ts index 2ac8d182..6ae74b92 100644 --- a/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/code-pedimento-regimens?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/code-pedimento-regimens?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/containers/+page.server.ts b/frontend/src/routes/dashboard/reference_data/containers/+page.server.ts index 3210dc37..8ab88102 100644 --- a/frontend/src/routes/dashboard/reference_data/containers/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/containers/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/containers?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/containers?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/countries/+page.server.ts b/frontend/src/routes/dashboard/reference_data/countries/+page.server.ts index f2a7631b..439c6b29 100644 --- a/frontend/src/routes/dashboard/reference_data/countries/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/countries/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/countries?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/countries?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/currency_types/+page.server.ts b/frontend/src/routes/dashboard/reference_data/currency_types/+page.server.ts index a8a17651..5a37e04a 100644 --- a/frontend/src/routes/dashboard/reference_data/currency_types/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/currency_types/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/currency-types?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/currency-types?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/customs_sections/+page.server.ts b/frontend/src/routes/dashboard/reference_data/customs_sections/+page.server.ts index d0d6683a..894436d6 100644 --- a/frontend/src/routes/dashboard/reference_data/customs_sections/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/customs_sections/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/customs-sections?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/customs-sections?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.server.ts b/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.server.ts index a7a11917..95563d56 100644 --- a/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/customs-warehouses?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/customs-warehouses?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/incoterms/+page.server.ts b/frontend/src/routes/dashboard/reference_data/incoterms/+page.server.ts index 347e8ac8..8a20072d 100644 --- a/frontend/src/routes/dashboard/reference_data/incoterms/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/incoterms/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/incoterms?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/incoterms?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/invoice_types/+page.server.ts b/frontend/src/routes/dashboard/reference_data/invoice_types/+page.server.ts index 1ddd9026..714def83 100644 --- a/frontend/src/routes/dashboard/reference_data/invoice_types/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/invoice_types/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/invoice-types?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/invoice-types?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/material_types/+page.server.ts b/frontend/src/routes/dashboard/reference_data/material_types/+page.server.ts index fbf97e7e..71722001 100644 --- a/frontend/src/routes/dashboard/reference_data/material_types/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/material_types/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/material-types?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/material-types?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/payment_methods/+page.server.ts b/frontend/src/routes/dashboard/reference_data/payment_methods/+page.server.ts index f197fd6a..3a69dba5 100644 --- a/frontend/src/routes/dashboard/reference_data/payment_methods/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/payment_methods/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/payment-methods?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/payment-methods?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.server.ts b/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.server.ts index 4cd1e31b..93032444 100644 --- a/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/pedimento-codes?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/pedimento-codes?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.server.ts b/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.server.ts index aa169764..2d87af9e 100644 --- a/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/pedimento-regimens?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/pedimento-regimens?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/sectors/+page.server.ts b/frontend/src/routes/dashboard/reference_data/sectors/+page.server.ts index 21eef54e..9f30c5d4 100644 --- a/frontend/src/routes/dashboard/reference_data/sectors/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/sectors/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/sectors?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/sectors?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/states/+page.server.ts b/frontend/src/routes/dashboard/reference_data/states/+page.server.ts index c50ce29e..696a1940 100644 --- a/frontend/src/routes/dashboard/reference_data/states/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/states/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/states?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/states?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/transport_modes/+page.server.ts b/frontend/src/routes/dashboard/reference_data/transport_modes/+page.server.ts index 8a7a6969..005af3f5 100644 --- a/frontend/src/routes/dashboard/reference_data/transport_modes/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/transport_modes/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/transport-modes?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/transport-modes?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/transport_types/+page.server.ts b/frontend/src/routes/dashboard/reference_data/transport_types/+page.server.ts index 0742b526..1de57dd4 100644 --- a/frontend/src/routes/dashboard/reference_data/transport_types/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/transport_types/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/transport-types?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/transport-types?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.server.ts b/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.server.ts index 40ffc4bb..9f9201e0 100644 --- a/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.server.ts +++ b/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.server.ts @@ -1,12 +1,13 @@ import type { PageServerLoad } from './$types'; +import { getAuthTokens, authenticatedFetch } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { // Esperar a que el layout padre valide/refresque el token await parent(); - const token = cookies.get('access_token'); + const { accessToken } = getAuthTokens(cookies); - if (!token) { + if (!accessToken) { return { error: 'No authenticated', items: [], @@ -21,25 +22,12 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { const page = parseInt(url.searchParams.get('page') || '1'); const pageSize = parseInt(url.searchParams.get('page_size') || '50'); - // Configurar la URL de la API para SSR - let apiUrl = process.env.INTERNAL_API_URL; - if (!apiUrl) { - apiUrl = import.meta.env.VITE_API_URL; - // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - // Normalizar la URL - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; - - const response = await fetch( - `${baseUrl}v1/public/refrence_data/valuation-methods?page=${page}&page_size=${pageSize}`, - { - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json' - } - } + // Usar authenticatedFetch para manejar automáticamente el refresh de tokens + const response = await authenticatedFetch( + `v1/public/refrence_data/valuation-methods?page=${page}&page_size=${pageSize}`, + {}, + cookies, + fetch ); if (!response.ok) { diff --git a/frontend/src/routes/login/+page.server.ts b/frontend/src/routes/login/+page.server.ts index ec187222..38cfebc8 100644 --- a/frontend/src/routes/login/+page.server.ts +++ b/frontend/src/routes/login/+page.server.ts @@ -1,20 +1,17 @@ import { redirect, fail } from '@sveltejs/kit'; import type { Actions, PageServerLoad } from './$types'; +import { clearAuthTokens, setAuthTokens, getServerApiUrl } from '$lib/server/api'; export const load: PageServerLoad = async ({ cookies, url }) => { // Si hay un parámetro 'logout' en la URL, limpiar las cookies if (url.searchParams.has('logout')) { - cookies.delete('access_token', { path: '/' }); - cookies.delete('refresh_token', { path: '/' }); - cookies.delete('active_company_id', { path: '/' }); + clearAuthTokens(cookies); return {}; } // Limpiar siempre las cookies de sesión anterior al cargar login // Esto evita que se queden datos del tenant anterior - cookies.delete('access_token', { path: '/' }); - cookies.delete('refresh_token', { path: '/' }); - cookies.delete('active_company_id', { path: '/' }); + clearAuthTokens(cookies); // Permitir acceso al login sin redirigir automáticamente // Esto evita bucles de redirección cuando el token existe pero puede estar expirado @@ -33,17 +30,7 @@ export const actions = { } try { - // En Docker, el servidor debe usar el nombre del servicio 'backend' en lugar de 'localhost' - // Intentar primero con INTERNAL_API_URL, luego VITE_API_URL modificado - let apiUrl = process.env.INTERNAL_API_URL; - - if (!apiUrl) { - // Si no hay INTERNAL_API_URL, modificar VITE_API_URL para Docker - apiUrl = import.meta.env.VITE_API_URL; - apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); - } - - const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; + const baseUrl = getServerApiUrl(); const loginUrl = `${baseUrl}v1/auth/login`; const requestBody = { @@ -71,14 +58,8 @@ export const actions = { } if (result.access_token) { - // Establecer cookie en el servidor - cookies.set('access_token', result.access_token, { - path: '/', - httpOnly: false, // Permitir acceso desde JavaScript - secure: process.env.NODE_ENV === 'production', - sameSite: 'lax', - maxAge: 60 * 60 * 24 * 7 // 7 días - }); + // Establecer tokens usando la función centralizada + setAuthTokens(cookies, result.access_token, result.refresh_token); // Redirigir al dashboard o a la URL original const redirectUrl = url.searchParams.get('redirect') || '/dashboard';