const BASE = (process.env.REACT_APP_API_URL || 'http://localhost:3001') + '/api'; export function getToken() { return localStorage.getItem('dns_token'); } export function setToken(token) { if (token) localStorage.setItem('dns_token', token); else localStorage.removeItem('dns_token'); } function authHeaders() { const token = getToken(); return token ? { Authorization: `Bearer ${token}` } : {}; } async function handleResponse(res) { if (res.status === 401) { setToken(null); window.dispatchEvent(new Event('auth:logout')); throw new Error('Session expired — please log in again'); } if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(body.error || `HTTP ${res.status} ${res.statusText}`); } return res.json(); } // ─── Auth ───────────────────────────────────────────────────────────────────── export async function login(username, password) { const res = await fetch(`${BASE}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); return handleResponse(res); } export async function getMe() { return handleResponse(await fetch(`${BASE}/auth/me`, { headers: authHeaders() })); } export async function changePassword(currentPassword, newPassword) { return handleResponse(await fetch(`${BASE}/auth/change-password`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify({ currentPassword, newPassword }), })); } // ─── Users ──────────────────────────────────────────────────────────────────── export async function getUsers() { return handleResponse(await fetch(`${BASE}/users`, { headers: authHeaders() })); } export async function createUser(username, password) { return handleResponse(await fetch(`${BASE}/users`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify({ username, password }), })); } export async function deleteUser(id) { return handleResponse(await fetch(`${BASE}/users/${id}`, { method: 'DELETE', headers: authHeaders(), })); } export async function resetUserPassword(id, newPassword) { return handleResponse(await fetch(`${BASE}/users/${id}/password`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify({ newPassword }), })); } // ─── IPAM ───────────────────────────────────────────────────────────────────── export async function getIpam() { return handleResponse(await fetch(`${BASE}/ipam`, { headers: authHeaders() })); } export async function createIpEntry(data) { return handleResponse(await fetch(`${BASE}/ipam`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(data), })); } export async function updateIpEntry(id, data) { return handleResponse(await fetch(`${BASE}/ipam/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(data), })); } export async function deleteIpEntry(id) { return handleResponse(await fetch(`${BASE}/ipam/${id}`, { method: 'DELETE', headers: authHeaders(), })); } // ─── Secrets ────────────────────────────────────────────────────────────────── export async function getSecrets() { return handleResponse(await fetch(`${BASE}/secrets`, { headers: authHeaders() })); } export async function createSecret(data) { return handleResponse(await fetch(`${BASE}/secrets`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(data), })); } export async function updateSecret(id, data) { return handleResponse(await fetch(`${BASE}/secrets/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(data), })); } export async function deleteSecret(id) { return handleResponse(await fetch(`${BASE}/secrets/${id}`, { method: 'DELETE', headers: authHeaders(), })); } export async function getAuditLog({ limit, offset, user, action, provider, category } = {}) { const qs = new URLSearchParams(); if (limit) qs.set('limit', limit); if (offset) qs.set('offset', offset); if (user) qs.set('user', user); if (action) qs.set('action', action); if (provider) qs.set('provider', provider); if (category) qs.set('category', category); return handleResponse(await fetch(`${BASE}/audit?${qs}`, { headers: authHeaders() })); } export async function getProviderHealth() { return handleResponse(await fetch(`${BASE}/health/providers`, { headers: authHeaders() })); } export async function getProviders() { return handleResponse(await fetch(`${BASE}/providers`, { headers: authHeaders() })); } export async function getStats() { return handleResponse(await fetch(`${BASE}/stats`, { headers: authHeaders() })); } export async function getAllDomains() { return handleResponse(await fetch(`${BASE}/domains`, { headers: authHeaders() })); } export async function getSettings() { return handleResponse(await fetch(`${BASE}/settings`, { headers: authHeaders() })); } export async function saveSettings(settings) { return handleResponse(await fetch(`${BASE}/settings`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(settings), })); } export async function clearCache() { return handleResponse(await fetch(`${BASE}/settings/clear-cache`, { method: 'POST', headers: authHeaders() })); } export async function testNotification(gotify) { return handleResponse(await fetch(`${BASE}/settings/test-notification`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(gotify), })); } export async function getSyncStatus(provider) { return handleResponse(await fetch(`${BASE}/sync-status/${provider}`, { headers: authHeaders() })); } export async function getZones(provider) { return handleResponse(await fetch(`${BASE}/zones/${provider}`, { headers: authHeaders() })); } export async function getRecords(provider, zoneId) { return handleResponse(await fetch(`${BASE}/records/${provider}/${encodeURIComponent(zoneId)}`, { headers: authHeaders() })); } export async function syncRecords(provider, zoneId, zoneName) { return handleResponse(await fetch(`${BASE}/records/sync/${provider}/${encodeURIComponent(zoneId)}`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify({ zoneName }), })); } export async function addRecord(provider, zoneId, record) { return handleResponse(await fetch(`${BASE}/records/${provider}/${encodeURIComponent(zoneId)}`, { method: 'POST', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(record), })); } export async function updateRecord(provider, zoneId, recordId, record) { return handleResponse(await fetch(`${BASE}/records/${provider}/${encodeURIComponent(zoneId)}/${encodeURIComponent(recordId)}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', ...authHeaders() }, body: JSON.stringify(record), })); } export async function deleteRecord(provider, zoneId, recordId) { return handleResponse(await fetch(`${BASE}/records/${provider}/${encodeURIComponent(zoneId)}/${encodeURIComponent(recordId)}`, { method: 'DELETE', headers: authHeaders(), })); }