86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import { redirect, fail } from '@sveltejs/kit';
|
|
import type { PageServerLoad, Actions } from './$types';
|
|
import { getServerApiUrl, getAuthTokens } from '$lib/server/api';
|
|
import { redirectToKeycloakLogin } from '$lib/server/workspace-auth';
|
|
|
|
export const load: PageServerLoad = async ({ url, cookies, fetch }) => {
|
|
const code = url.searchParams.get('code')?.toUpperCase().trim() ?? '';
|
|
const step = url.searchParams.get('step') ?? '';
|
|
|
|
// Paso 3: usuario volvió de Keycloak, consumir el código
|
|
if (code && step === 'consume') {
|
|
const { accessToken } = getAuthTokens(cookies);
|
|
|
|
if (!accessToken) {
|
|
// Sesión KC expiró entre redirecciones — volver a auth
|
|
redirectToKeycloakLogin(url.origin, `/join?code=${code}&step=consume`);
|
|
}
|
|
|
|
const apiUrl = getServerApiUrl();
|
|
|
|
// Consumir el código
|
|
const consumeRes = await fetch(`${apiUrl}v1/core/invite-codes/consume/${code}`, {
|
|
method: 'POST',
|
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
});
|
|
|
|
if (!consumeRes.ok) {
|
|
const body = await consumeRes.json().catch(() => ({}));
|
|
return {
|
|
step: 'preview',
|
|
code,
|
|
codeInfo: null,
|
|
error: body?.detail ?? 'No se pudo canjear el código. Intenta de nuevo.'
|
|
};
|
|
}
|
|
|
|
const result = await consumeRes.json();
|
|
return { step: 'success', code, result, error: null, codeInfo: null };
|
|
}
|
|
|
|
// Paso 2: hay código en la URL (viene de validar), mostrar preview
|
|
if (code) {
|
|
const apiUrl = getServerApiUrl();
|
|
const validateRes = await fetch(`${apiUrl}v1/core/invite-codes/validate/${code}`);
|
|
|
|
if (!validateRes.ok) {
|
|
return { step: 'input', code: '', error: 'Código inválido, expirado o agotado.', codeInfo: null };
|
|
}
|
|
|
|
const codeInfo = await validateRes.json();
|
|
return { step: 'preview', code, codeInfo, error: null };
|
|
}
|
|
|
|
return { step: 'input', code: '', error: null, codeInfo: null };
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
// Valida el código y redirige a la URL con ?code=XXX para el preview
|
|
validate: async ({ request }) => {
|
|
const data = await request.formData();
|
|
const code = (data.get('code') as string ?? '').toUpperCase().trim();
|
|
|
|
if (!code) return fail(422, { error: 'Ingresa un código de invitación.' });
|
|
|
|
redirect(303, `/join?code=${code}`);
|
|
},
|
|
|
|
// Inicia el join: si hay sesión, consume; si no, va a KC login
|
|
join: async ({ request, cookies, url, fetch }) => {
|
|
const data = await request.formData();
|
|
const code = (data.get('code') as string ?? '').toUpperCase().trim();
|
|
|
|
if (!code) return fail(422, { error: 'Código inválido.' });
|
|
|
|
const { accessToken } = getAuthTokens(cookies);
|
|
|
|
if (!accessToken) {
|
|
// Redirigir a Keycloak; al volver, el callback irá a /join?code=XXX&step=consume
|
|
redirectToKeycloakLogin(url.origin, `/join?code=${code}&step=consume`);
|
|
}
|
|
|
|
// Si ya hay sesión, consumir directamente vía redirect a step=consume
|
|
redirect(303, `/join?code=${code}&step=consume`);
|
|
}
|
|
};
|