import { useState, useCallback, type ReactNode } from 'react'; import Cookies from 'js-cookie'; import { AuthContext } from './AuthContext'; import { sha512 } from '../utils/crypto'; import type { AuthResponse } from '../types/auth'; const TOKEN_KEY = 'ktty_shared_token'; // 1. DYNAMICZNE USTALANIE DOMENY const getCookieConfig = () => { const hostname = window.location.hostname; // Jeśli testujesz na localhost, nie ustawiamy atrybutu 'domain' if (hostname === 'localhost' || hostname === '127.0.0.1') { return { domain: undefined, secure: false }; } // Na produkcji używamy domeny nadrzędnej z kropką // To pozwoli s.ktty.is i ktty.is widzieć to samo ciasteczko return { domain: '.ktty.is', secure: true }; }; const getSubdomain = (): string | null => { const hostname = window.location.hostname; const parts = hostname.split('.'); if (parts.length <= 2) return null; return parts[0]; }; export function AuthProvider({ children }: { children: ReactNode }) { const config = getCookieConfig(); const subdomain = getSubdomain(); // Inicjalizacja stanu bezpośrednio z ciasteczka const [token, setToken] = useState(() => Cookies.get(TOKEN_KEY) || null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const authRequest = useCallback(async (endpoint: 'signUp' | 'signIn', name: string, pass: string) => { setLoading(true); setError(null); try { const hashedPassword = await sha512(pass); const fullUrl = `/api/v1/user/${endpoint}`; const response = await fetch(fullUrl, { method: 'POST', headers: { 'accept': 'application/json', 'Content-Type': 'application/json', 'X-Subdomain': subdomain || '', }, body: JSON.stringify({ name, password: hashedPassword, ttl: 86400 }), }); const data: AuthResponse = await response.json(); if (!response.ok) { throw new Error(data?.error || data?.message || 'Błąd logowania'); } if (data?.token) { // 2. ZAPIS Z DYNAMICZNĄ KONFIGURACJĄ Cookies.set(TOKEN_KEY, data.token, { domain: config.domain, expires: 7, // wydłużamy do 7 dni dla wygody secure: config.secure, sameSite: 'lax' }); setToken(data.token); } return data; } catch (err: unknown) { let errorMessage = 'Wystąpił nieoczekiwany błąd'; if (err instanceof Error) errorMessage = err.message; setError(errorMessage); return null; } finally { setLoading(false); } }, [subdomain, config]); const logout = useCallback(() => { // 3. USUNIĘCIE MUSI MIEĆ TĘ SAMĄ DOMENĘ CO ZAPIS Cookies.remove(TOKEN_KEY, { domain: config.domain }); setToken(null); }, [config]); return ( authRequest('signIn', n, p), signUp: (n, p) => authRequest('signUp', n, p), logout }}> {children} ); }