feat: integrate Better Auth and enhance authentication flow
- Added Better Auth integration to the web application, allowing for dual login support with both custom and Better Auth systems. - Updated authentication client configuration to dynamically set the base URL based on the environment. - Enhanced chat components to utilize user authentication status, improving user experience and security. - Refactored various components to support Better Auth, including error handling and user identity management. - Improved notification handling and user feedback mechanisms during authentication processes.
This commit is contained in:
@@ -3,16 +3,115 @@
|
||||
import Sidebar from "$lib/components/Sidebar.svelte";
|
||||
import { PUBLIC_CONVEX_URL } from "$env/static/public";
|
||||
import { setupConvex } from "convex-svelte";
|
||||
// import { createSvelteAuthClient } from "@mmailaender/convex-better-auth-svelte/svelte";
|
||||
// import { authClient } from "$lib/auth";
|
||||
import { authStore } from "$lib/stores/auth.svelte";
|
||||
import { browser } from "$app/environment";
|
||||
import { createSvelteAuthClient } from "@mmailaender/convex-better-auth-svelte/svelte";
|
||||
import { authClient } from "$lib/auth";
|
||||
|
||||
const { children } = $props();
|
||||
|
||||
// Configurar Convex para usar o backend local
|
||||
// Interfaces TypeScript devem estar no nível superior
|
||||
interface ConvexHttpClientPrototype {
|
||||
_authPatched?: boolean;
|
||||
mutation?: (...args: unknown[]) => Promise<unknown>;
|
||||
query?: (...args: unknown[]) => Promise<unknown>;
|
||||
setAuth?: (token: string) => void;
|
||||
}
|
||||
|
||||
interface WindowWithConvexClients extends Window {
|
||||
__convexClients?: Array<{ setAuth?: (token: string) => void }>;
|
||||
}
|
||||
|
||||
// Configurar Convex
|
||||
setupConvex(PUBLIC_CONVEX_URL);
|
||||
|
||||
// Configurar cliente de autenticação
|
||||
// createSvelteAuthClient({ authClient });
|
||||
// CORREÇÃO CRÍTICA: Configurar token no cliente Convex após setup
|
||||
// O convex-svelte usa WebSocket, então precisamos configurar via setAuth
|
||||
if (browser) {
|
||||
// Aguardar setupConvex inicializar e então configurar token
|
||||
$effect(() => {
|
||||
const token = authStore.token;
|
||||
|
||||
if (!token) return;
|
||||
|
||||
// Aguardar um pouco para garantir que setupConvex inicializou
|
||||
setTimeout(() => {
|
||||
// Tentar acessar o cliente Convex interno do convex-svelte
|
||||
// O convex-svelte pode usar uma instância interna, então vamos tentar várias abordagens
|
||||
|
||||
// Abordagem 1: Interceptar WebSocket para adicionar token como query param
|
||||
const originalWebSocket = window.WebSocket;
|
||||
if (!(window as { _convexWsPatched?: boolean })._convexWsPatched) {
|
||||
window.WebSocket = class extends originalWebSocket {
|
||||
constructor(url: string | URL, protocols?: string | string[]) {
|
||||
const wsUrl = typeof url === 'string' ? url : url.href;
|
||||
|
||||
// Se for conexão Convex e tivermos token, adicionar como query param
|
||||
if ((wsUrl.includes(PUBLIC_CONVEX_URL) || wsUrl.includes('convex.cloud')) && token) {
|
||||
try {
|
||||
const urlObj = new URL(wsUrl);
|
||||
if (!urlObj.searchParams.has('authToken')) {
|
||||
urlObj.searchParams.set('authToken', token);
|
||||
super(urlObj.href, protocols);
|
||||
if (import.meta.env.DEV) {
|
||||
console.log("✅ [Convex Auth] Token adicionado ao WebSocket:", token.substring(0, 20) + "...");
|
||||
}
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// Se falhar, usar URL original
|
||||
}
|
||||
}
|
||||
|
||||
super(url, protocols);
|
||||
}
|
||||
} as typeof WebSocket;
|
||||
|
||||
(window as { _convexWsPatched?: boolean })._convexWsPatched = true;
|
||||
console.log("✅ [Convex Auth] Interceptador WebSocket configurado");
|
||||
}
|
||||
|
||||
// Abordagem 2: Interceptar fetch para requisições HTTP (fallback)
|
||||
const originalFetch = window.fetch;
|
||||
if (!(window as { _convexFetchPatched?: boolean })._convexFetchPatched) {
|
||||
window.fetch = function(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
|
||||
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
||||
const currentToken = authStore.token;
|
||||
|
||||
if (currentToken && (url.includes(PUBLIC_CONVEX_URL) || url.includes('convex.cloud'))) {
|
||||
const headers = new Headers(init?.headers);
|
||||
if (!headers.has('authorization')) {
|
||||
headers.set('authorization', `Bearer ${currentToken}`);
|
||||
}
|
||||
|
||||
return originalFetch(input, {
|
||||
...init,
|
||||
headers: headers,
|
||||
});
|
||||
}
|
||||
|
||||
return originalFetch(input, init);
|
||||
};
|
||||
|
||||
(window as { _convexFetchPatched?: boolean })._convexFetchPatched = true;
|
||||
console.log("✅ [Convex Auth] Interceptador Fetch configurado");
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
// FASE 4: Integração Better Auth com Convex
|
||||
// Better Auth agora está configurado e ativo
|
||||
// Usar $effect para garantir que seja executado apenas no cliente
|
||||
if (browser) {
|
||||
$effect(() => {
|
||||
try {
|
||||
createSvelteAuthClient({ authClient });
|
||||
} catch (error) {
|
||||
console.warn("⚠️ [Better Auth] Erro ao inicializar cliente:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user