'use server' import { revalidatePath } from 'next/cache' import { redirect } from 'next/navigation' import { getAccessToken, refreshAccessToken } from '@/app/auth/actions' const API_BASE = process.env.API_BASE_URL ?? 'http://localhost:8080' async function getToken(): Promise { const token = await getAccessToken() if (token) return token const fresh = await refreshAccessToken() if (fresh) return fresh redirect('/auth/login?from=/admin/users') } /** API'nin döndürdüğü hata yanıtından okunabilir bir mesaj çıkarır. */ function extractError(data: Record, fallback: string): string { if (typeof data?.error === 'string' && data.error) return data.error if (typeof data?.message === 'string' && data.message) return data.message if (typeof data?.detail === 'string' && data.detail) return data.detail if (data?.errors && typeof data.errors === 'object') { const msgs = Object.values(data.errors as Record).filter(Boolean) if (msgs.length > 0) return msgs.join(', ') } console.error('[API Error]', JSON.stringify(data)) return fallback } export type User = { id: number username: string email: string email_verified: boolean is_active: boolean is_admin: boolean created_at: string updated_at: string } export type UsersResponse = { items: User[] meta: { page: number; limit: number; total: number } } export type UserFormState = { error?: string success?: boolean user?: User deletedId?: number } export async function getUsers(page = 1, limit = 10): Promise { let token = await getToken() const url = `${API_BASE}/api/v1/admin/users?page=${page}&limit=${limit}` const doFetch = () => fetch(url, { headers: { Authorization: `Bearer ${token}` }, cache: 'no-store' }) let res: Response try { res = await doFetch() } catch (error) { console.error('[getUsers] fetch failed', error) throw new Error('API sunucusuna bağlanılamadı. Backend çalışıyor mu kontrol edin.') } // Token süresi dolmuşsa yenile ve bir kez daha dene if (res.status === 401) { const fresh = await refreshAccessToken() if (!fresh) throw new Error('Oturum süresi doldu') token = fresh try { res = await doFetch() } catch (error) { console.error('[getUsers] fetch failed after refresh', error) throw new Error('API sunucusuna bağlanılamadı. Backend çalışıyor mu kontrol edin.') } } // Rate limit aşıldıysa kısa aralıkla sınırlı sayıda tekrar dene if (res.status === 429) { for (const waitMs of [500, 1000, 1500]) { await new Promise((r) => setTimeout(r, waitMs)) res = await doFetch() if (res.ok) break if (res.status !== 429) break } } if (!res.ok) { console.error(`[getUsers] API error: ${res.status} ${res.statusText}`) if (res.status === 429) { throw new Error('Çok fazla istek gönderildi, lütfen birkaç saniye sonra tekrar deneyin (429)') } throw new Error(`Kullanıcılar alınamadı (${res.status})`) } return res.json() } export async function createUser( _prev: UserFormState, formData: FormData ): Promise { 'use server' try { const token = await getToken() const body = { username: formData.get('username') as string, email: formData.get('email') as string, password: formData.get('password') as string, confirm_password: formData.get('confirm_password') as string, is_active: formData.get('is_active') === 'true', is_admin: formData.get('is_admin') === 'true', } const res = await fetch(`${API_BASE}/api/v1/admin/users`, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(body), }) if (!res.ok) { const data = await res.json().catch(() => ({})) return { error: extractError(data, 'Kullanıcı oluşturulamadı') } } revalidatePath('/admin/users') const created = (await res.json()) as User return { success: true, user: created } } catch (e) { console.error('[createUser]', e) return { error: 'Sunucu hatası' } } } export async function updateUser( id: number, _prev: UserFormState, formData: FormData ): Promise { 'use server' try { const token = await getToken() const body = { username: formData.get('username') as string, email: formData.get('email') as string, password: formData.get('password') as string, confirm_password: formData.get('confirm_password') as string, is_active: formData.get('is_active') === 'true', is_admin: formData.get('is_admin') === 'true', } const res = await fetch(`${API_BASE}/api/v1/admin/users/${id}`, { method: 'PUT', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(body), }) if (!res.ok) { const data = await res.json().catch(() => ({})) return { error: extractError(data, 'Kullanıcı güncellenemedi') } } revalidatePath('/admin/users') const updated = (await res.json()) as User return { success: true, user: updated } } catch (e) { console.error('[updateUser]', e) return { error: 'Sunucu hatası' } } } export async function deleteUser( _prev: UserFormState, formData: FormData ): Promise { 'use server' try { const token = await getToken() const id = formData.get('id') as string const res = await fetch(`${API_BASE}/api/v1/admin/users/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }) if (!res.ok) { const data = await res.json().catch(() => ({})) return { error: extractError(data, 'Kullanıcı silinemedi') } } revalidatePath('/admin/users') return { success: true, deletedId: Number(id) } } catch (e) { console.error('[deleteUser]', e) return { error: 'Sunucu hatası' } } } export async function changeUserStatus( id: number, isActive: boolean ): Promise { 'use server' try { const token = await getToken() const res = await fetch(`${API_BASE}/api/v1/admin/users/${id}/status`, { method: 'PATCH', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ is_active: isActive }), }) if (!res.ok) { const data = await res.json().catch(() => ({})) return { error: extractError(data, 'Durum güncellenemedi') } } revalidatePath('/admin/users') const updated = (await res.json()) as User return { success: true, user: updated } } catch (e) { console.error('[changeUserStatus]', e) return { error: 'Sunucu hatası' } } }