import { config } from '../config.js' const DEBUG_LOG = (location, message, data, hypothesisId) => { // #region agent log fetch('http://127.0.0.1:7281/ingest/30e8e71c-b377-4e72-84f9-593826c6d234', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '80bbfc' }, body: JSON.stringify({ sessionId: '80bbfc', location, message, data, hypothesisId, timestamp: Date.now(), }), }).catch(() => {}) // #endregion } function appwriteHeaders() { return { 'Content-Type': 'application/json', 'X-Appwrite-Project': config.appwrite.projectId, } } async function appwriteFetch(path, { method = 'GET', body } = {}) { const url = `${config.appwrite.endpoint}${path}` const response = await fetch(url, { method, headers: appwriteHeaders(), body: body ? JSON.stringify(body) : undefined, }) let data = null const text = await response.text() if (text) { try { data = JSON.parse(text) } catch { data = { message: text } } } if (!response.ok) { const error = new Error(data?.message || `Appwrite ${response.status}`) error.status = response.status error.code = data?.code error.type = data?.type if (response.status === 429 || data?.type === 'general_rate_limit_exceeded') { error.message = 'Zu viele Anmeldeversuche. Bitte warte einige Minuten, bevor du es erneut versuchst.' error.status = 429 } throw error } return data } /** * Login via Appwrite Auth REST. userId kommt aus der Session – kein users.read nötig. */ let appwriteLoginBlockedUntil = 0 const APPWRITE_LOGIN_COOLDOWN_MS = 5 * 60 * 1000 const APPWRITE_RATE_LIMIT_COOLDOWN_MS = 15 * 60 * 1000 export function getLoginCooldownRemainingSec() { const left = appwriteLoginBlockedUntil - Date.now() return left > 0 ? Math.ceil(left / 1000) : 0 } export function clearLoginCooldown() { appwriteLoginBlockedUntil = 0 } export async function loginWithAppwrite(email, password) { const now = Date.now() if (now < appwriteLoginBlockedUntil) { const waitSec = Math.ceil((appwriteLoginBlockedUntil - now) / 1000) DEBUG_LOG('appwriteClient.js:cooldown', 'login blocked locally', { waitSec }, 'H8') const error = new Error( `Zu viele Anmeldeversuche. Bitte warte noch ${waitSec} Sekunden.` ) error.status = 429 throw error } let session try { session = await appwriteFetch('/account/sessions/email', { method: 'POST', body: { email, password }, }) DEBUG_LOG('appwriteClient.js:session', 'createEmailPasswordSession ok', { hasUserId: Boolean(session?.userId), sessionId: session?.$id || null, }, 'H6') } catch (err) { DEBUG_LOG('appwriteClient.js:session', 'createEmailPasswordSession fail', { message: err?.message?.slice(0, 120), code: err?.code, }, 'H1') if (err.status === 429) { appwriteLoginBlockedUntil = Date.now() + APPWRITE_RATE_LIMIT_COOLDOWN_MS } const error = new Error(err.message || 'Anmeldung fehlgeschlagen') error.status = err.status || 401 throw error } if (!session?.userId) { const error = new Error('Appwrite-Session ohne userId.') error.status = 500 throw error } const user = { $id: session.userId, email, name: '' } DEBUG_LOG('appwriteClient.js:user', 'using session userId', { userId: user.$id }, 'H7') clearLoginCooldown() return user }