import {awaitWithAbort} from './abortable.js'; /** * Google ile Giriş — frontend istemcisi (GIS ID-token akışı). * Token localStorage'da 'ihaleist_token', kullanıcı 'ihaleist_user' altında saklanır. */ const TOKEN_KEY = 'ihaleist_token'; const USER_KEY = 'ihaleist_user'; export function getToken() { try { return localStorage.getItem(TOKEN_KEY); } catch { return null; } } export function getStoredUser() { try { return JSON.parse(localStorage.getItem(USER_KEY) || 'null'); } catch { return null; } } export function setSession(token, user) { try { localStorage.setItem(TOKEN_KEY, token); localStorage.setItem(USER_KEY, JSON.stringify(user)); } catch { /* yoksay */ } } export function clearSession() { try { localStorage.removeItem(TOKEN_KEY); localStorage.removeItem(USER_KEY); } catch { /* yoksay */ } } async function authRequest(url,options={}) { const {signal,...requestOptions}=options,controller=new AbortController(); const cancel=()=>controller.abort(signal.reason); if(signal?.aborted)cancel();else signal?.addEventListener('abort',cancel,{once:true}); let timeout=false; const timer=setTimeout(()=>{timeout=true;controller.abort();},30000); try{ controller.signal.throwIfAborted(); const res=await awaitWithAbort(fetch(url,{...requestOptions,signal:controller.signal}),controller.signal); const data=await awaitWithAbort(res.json().catch(error=>{if(res.ok)throw error;return null;}),controller.signal); controller.signal.throwIfAborted(); if(!res.ok){const error=new Error(data?.error || 'Giriş hizmetine ulaşılamadı. Yeniden deneyin.');error.status=res.status;throw error;} return data; }catch(error){if(timeout)throw new Error('Giriş hizmeti zamanında yanıt vermedi. Yeniden deneyin.');throw error;} finally{clearTimeout(timer);signal?.removeEventListener('abort',cancel);} } export async function getGoogleConfig({signal}={}) { const data=await authRequest('/api/auth/google/config',{signal}); if(!data || !Object.hasOwn(data,'clientId') || (data.clientId!==null&&typeof data.clientId!=='string'))throw new Error('Giriş yapılandırması doğrulanamadı. Yeniden deneyin.'); return data; } export async function loginWithGoogle(credential,{signal}={}) { const data=await authRequest('/api/auth/google',{method:'POST',signal,headers:{'Content-Type':'application/json'},body:JSON.stringify({credential})}); if(!data?.success)throw new Error(data?.error || 'Giriş başarısız'); if(typeof data.token!=='string'||!data.token||typeof data.user?.email!=='string'||!data.user.email)throw new Error('Giriş yanıtı doğrulanamadı.'); signal?.throwIfAborted(); setSession(data.token,data.user); if(getToken()!==data.token||getStoredUser()?.email!==data.user.email){clearSession();throw new Error('Tarayıcı oturumu saklayamadı. Site depolama iznini kontrol edip tekrar deneyin.');} return data.user; } // Geçici hizmet hatası oturumu silmez; yalnız açık yetki reddi sona erdirir. export async function restoreSession() { const token = getToken(); if (!token) return null; try { const data = await authRequest('/api/auth/me', { headers: { Authorization: `Bearer ${token}` } }); if (getToken() !== token) return getStoredUser(); if (data?.success && typeof data.user?.email === 'string' && data.user.email) { setSession(token, data.user); return data.user; } return getStoredUser(); } catch (error) { if (getToken() !== token) return getStoredUser(); if (error.status === 401 || error.status === 403) { clearSession(); return null; } return getStoredUser(); } }