Files
gobeyhan/GEMINI.md
Beyhan Oğur f34e54c5a5 first commit
2026-04-26 21:43:40 +03:00

213 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Admin Panel — Giriş (Login) + Refresh Token Mantığı Prompt / İş Tanımı
Amaç:
- Var olan `admin-panel` Vue projesinde (Tailwind, reka-ui, Pinia, vue-auth3, lucide-vue-next, zod, vb.) Go backend API ile sadece "login" işlevi sunan admin arayüzü oluşturmak.
- Backend JWT access token + refresh token mekanizması destekliyor (refresh token mantığı kurulmalı).
- Backend base: `http://localhost:8080/api/v1` — login endpoint: `POST /auth/login` (dönen: access token + refresh token + user) — refresh endpoint olarak `POST /auth/refresh` (veya backend ile uyumlu başka path) bekleniyor.
- Hedef: güvenli, responsive login + refresh token tabanlı token yenileme, token saklama ve otomatik yenileme akışı ile korunan admin dashboard iskeleti.
Genel Tasarım Kararları (kritik)
- Access token (kısa ömürlü, örneğin 5-15 dk): uygulamada bellek/Pinia state veya memory-only saklama (localStorage'ta saklanması güvenlik riski taşıdığından önerilmez).
- Refresh token (uzun ömürlü, örneğin 7-30 gün): production için HttpOnly, Secure cookie ile saklanmalı — bu, XSS riskini azaltır. Eğer backend cookie ile set ediyorsa client sadece server çağrısıyla refresh yapar (cookie otomatik gönderilir).
- Eğer backend refresh token'ı client tarafında bekliyorsa (ör. JSON response ile gönderip client saklıyorsa), yalnızca sessionStorage (veya yine tercihen HttpOnly cookie) kullanılmalı; localStorage önerilmez.
- Refresh token rotation ve revocation: backend destekliyorsa rotasyonu kullan; logout veya refresh hatasında token'ı serverda iptal et.
Beklenen Endpoint'ler (uygulama tarafının kullanacağı)
- POST /api/v1/auth/login
- Body: { email, password }
- Response (örnek): { access_token, refresh_token (opsiyonel if cookie), user, expires_in }
- POST /api/v1/auth/refresh
- Use-case: access token yenileme. Eğer refresh token cookie ile saklanıyorsa body boş olabilir; aksi halde { refresh_token } gönderilebilir.
- Response: { access_token, refresh_token (rotated), expires_in }
- POST /api/v1/auth/logout
- Use-case: refresh token'ı server tarafında invalidasyon + client temizleme.
Refresh Token Akışı — Kabul Kriterleri ve Davranış
1. Login akışı
- Kullanıcı /login formunu doldurur.
- POST /auth/login çağrısı yapılır.
- Başarılıysa:
- Access token uygulama state'ine (Pinia memory) veya güvenli saklama yerine kısa süreli tutulacak şekilde konur.
- Refresh token:
- Tercih A (öncelikli, tavsiye): backend Set-Cookie ile HttpOnly, Secure cookie olarak gönderir. Client hiçbir şekilde refresh token'ı JS üzerinden okumaz veya yazmaz.
- Tercih B (fallback): backend refresh token'ı JSON içinde dönerse client token'ı sessionStorage'e veya (remember me seçeneği varsa) localStorage'e koyar ve riskler README'de belirtilir.
- Kullanıcı /admin'e yönlendirilir.
2. Otomatik yenileme (interceptor + single-refresh lock)
- Tüm korumalı isteklerde Authorization: Bearer <access_token> header kullanılır.
- Bir istek 401 dönerse ve hata sebebi token expiration ise:
- HTTP client (axios/fetch wrapper) bir *refresh attempt* başlatır:
- Eğer başka bir refresh devam ediyorsa yeni istek bekletilir (queue) — bu, aynı anda birden çok refresh çağrısının yapılmasını engeller.
- Refresh başarılı ise yeni access token (ve varsa yeni refresh token) saklanır; bekleyen istekler yeniden denenir (replay).
- Refresh başarısız ise (refresh expired veya invalid) -> authStore.logout() çağrılır ve kullanıcı /login'e yönlendirilir.
- İstek interceptor'ı 401'lerde doğrudan logout yerine önce refresh denemeli; refresh'in başarısız olması durumunda logout yapılmalı.
3. Proaktif yenileme (optional, önerilen UX)
- Access token expiry (exp) okunarak (token JWT ise), expiry zamanından örn. 60-120s önce otomatik yenileme tetiklenebilir.
- Bu, kullanıcı etkileşimi sırasında beklenmedik logout'ları azaltır.
- Proaktif yenileme, aynı queue/lock mekanizmasını kullanarak aynı anda birden fazla refresh'i engeller.
4. Logout / revocation
- logout() çağrıldığında client:
- Eğer refresh cookie ise: POST /auth/logout çağrısı yaparak server tarafında refresh token iptal edilir ve server cookie'yi temizler.
- Client state'teki access token ve user bilgileri temizlenir; local/session storage temizlenir.
- Kullanıcı /login'e yönlendirilir.
5. Refresh token rotation & güvenlik
- Eğer backend rotation destekliyorsa (refresh token her yenilemede değişiyorsa), client her refresh response'unda yeni refresh token'ı saklamalı (ve/veya server Set-Cookie ile güncelleyip JS erişim izni vermemeli).
- Tek kullanımlık (one-time) refresh token kullanımı varsa backend başarısız veya yeniden kullanım durumunda tüm oturumları iptal etmeli.
- HTTP cookie attributeleri (production):
- HttpOnly
- Secure
- SameSite=Lax (veya Strict, ihtiyaçlara göre)
- Path=/api/v1/auth/refresh (gerekirse) veya Path=/
- Domain ihtiyaca göre ayarlanmalı
Client tarafında uygulama tasarımı (yapılacaklar — geliştiriciye talimat)
- Auth store (Pinia) içinde:
- state: accessToken (memory), user, loading, refreshPromise / refreshLock (internal)
- getters: isAuthenticated
- actions: login(), logout(), setAccessToken(), tryRefresh()
- tryRefresh(): refresh endpoint'ine istek atar; başarılıysa accessToken güncellenir; başarısızsa reject -> logout.
- HTTP client wrapper:
- baseURL: VITE_API_BASE_URL
- request interceptor: access token mevcutsa Authorization header ekle
- response interceptor:
- 401 alındığında:
- Eğer hata tipi token expired ise tryRefresh() çağrılır.
- tryRefresh() başarılı ise orijinal istek yeniden gönderilir.
- Eğer tryRefresh() başarısızsa logout() ve /login yönlendirme.
- Her isteğin retry mekanizması maksimum 1 refresh attempt ile sınırlı olmalı (sonsuz döngü olmaması için).
- Concurrent refresh yönetimi: single refresh promise pattern (ilk refresh çağrısı bir Promise döndürür; diğer istekler bu promise'i await eder).
- Proaktif yenileme (opsiyonel ama önerilen):
- Access token decode edilerek exp timestamp alınır.
- exp - now <= threshold (örn. 60s) olduğunda tryRefresh() çağrılır.
- Bu mekanizma kullanıcı etkileşiminde veya route değişimlerinde tetiklenebilir.
- Storage politikası:
- access token: bellek (Pinia) veya short-lived storage
- refresh token: HttpOnly cookie (tercih) veya sessionStorage/secure storage fallback
- README'de hangi seçeneğin neden seçildiği açıkça dokümante edilecek.
Hata Yönetimi & UX
- Refresh başarısız olursa kullanıcıya basit, net bir mesaj göster: "Oturum süresi doldu, lütfen tekrar giriş yapın."
- Arka arkaya çalışan isteklerde refresh sırasında spinner veya global loading state kullanılabilir.
- Eğer backend 429 (rate limit) veya 5xx dönerse kullanıcı uygun uyarı almalı (tekrar dene vs).
Test Senaryoları (kritik)
1. Başarılı login:
- login -> access token alındı, refresh token cookie ile set edildi (veya sessionStorage'e kondu) -> /admin'e yönlendirme.
2. Access token expire iken istek:
- İlk korumalı istek 401 döner -> tryRefresh() tetiklenir -> refresh başarılı -> orijinal istek tekrar çalışır -> kullanıcı etkileşimi kesintisiz devam eder.
3. Refresh expired veya invalid:
- Refresh attempt başarısız -> logout -> /login ve uygun hata mesajı.
4. Concurrent istekler token expired durumda:
- Birden fazla istek gönderildiğinde yalnızca bir refresh çağrısı yapılmalı, diğerleri bekletilip ardından yeniden denenmeli.
5. Logout:
- logout çağrıldığında server /auth/logout çağrılır (varsa) ve client state & storageler temizlenir.
6. Proaktif yenileme:
- Token exp < threshold iken uygulama otomatik yenileme yapıyor ve kullanıcıyı kesintiye uğratmıyor.
Dokümantasyon ve README Notları
- .env örneği: VITE_API_BASE_URL=http://localhost:8080/api/v1
- Token saklama tercihleri ve güvenlik nedenleri (HttpOnly cookie vs localStorage) açıkça yazılmalı.
- Backend ile cookie tabanlı refresh kullanılıyorsa CORS ve credentials ayarlarııklanmalı (axios: withCredentials=true; server: Access-Control-Allow-Credentials: true).
- Güvenlik önerileri: refresh token'ların server-side revocation tablosunda saklanması, rotation kullanımı ve refresh token reuse detection.
Teslim Edilecekler (geliştiriciye verilecek)
- Güncellenmiş prompt (bu dosya) — refresh token mantığı, beklenen endpoint'ler, client davranışı ve test senaryolarıık.
- Uygulamada olması gerekenler:
- login sayfası
- Pinia auth store (refresh logic ile)
- HTTP client wrapper (interceptor + refresh queue/lock)
- Router guard (protected rotalar)
- Dashboard iskeleti ve en az bir örnek protected endpoint kullanımı
- README: environment, çalışma, güvenlik ve token saklama tercihleri
Notlar / Varsayımlar
- Backend, refresh endpoint ve/veya Set-Cookie davranışını destekliyor olmalıdır. Eğer backend cookie yerine JSON refresh token dönerse prompt'ta belirtilen fallback yöntem uygulanacak.
- Exact refresh endpoint path'ı backend ile netleştirilmeli (`/auth/refresh`, `/auth/refresh-token` veya benzeri).
- Backend CORS + cookie kullanımında `Access-Control-Allow-Credentials: true` ve client çağrılarında `withCredentials: true` gerekecektir.
---
## ✅ İMPLEMENTASYON TAMAMLANDI (12 Şubat 2026)
Yukarıdaki tüm gereksinimler başarıyla implement edildi. İşte teslim edilen bileşenler:
### Oluşturulan Dosyalar
#### Environment & Yapılandırma
- `.env` - Environment variables
- `.env.example` - Environment template
- `tsconfig.app.json` - TypeScript path alias yapılandırması
#### Core Infrastructure
- `src/lib/http-client.ts` - Axios wrapper + interceptors (401 handling, refresh logic, retry)
- `src/services/auth.service.ts` - Auth API endpoints (login, refresh, logout)
- `src/types/auth.types.ts` - TypeScript interfaces
#### State Management
- `src/stores/auth.ts` - Pinia auth store
- Login/logout actions
- Refresh token logic (single promise lock)
- Proaktif token yenileme (exp check)
- Concurrent refresh prevention
#### UI Components
- `src/components/ui/Button.vue` - Reusable button (variants, loading, sizes)
- `src/components/ui/Input.vue` - Reusable input (validation, error states)
#### Views
- `src/views/LoginView.vue` - Modern login sayfası (Zod validation, responsive, dark mode)
- `src/views/DashboardView.vue` - Admin dashboard (user info, stats, protected content)
#### Router & Navigation
- `src/router/index.ts` - Router configuration + navigation guards
- `/login` (public)
- `/admin` (protected, requires auth)
#### App Structure
- `src/App.vue` - Minimal layout (sadece RouterView)
#### Dokümantasyon
- `README.md` - Detaylı dokümantasyon
- Token saklama stratejisi
- CORS yapılandırması
- Auth akışı diagramları
- Backend endpoint gereksinimleri
- Güvenlik best practices
### Teknolojiler
- Vue 3 (Composition API)
- TypeScript
- Pinia (state management)
- Vue Router
- Axios
- Zod (validation)
- Tailwind CSS
- Lucide Icons
- SweetAlert2
- jwt-decode
### Güvenlik Özellikleri
✅ Access token bellek (Pinia) depolaması
✅ HttpOnly cookie desteği (refresh token)
✅ withCredentials: true (CORS)
✅ Single refresh promise lock (concurrent prevention)
✅ Proaktif token yenileme (60s threshold)
✅ Router guards (protected routes)
✅ Form validation (Zod)
✅ XSS koruması
### Test Senaryoları (Hazır)
1. ✅ Başarılı login akışı
2. ✅ Access token expiration & refresh
3. ✅ Refresh token invalid/expired handling
4. ✅ Concurrent requests (single refresh)
5. ✅ Logout flow
6. ✅ Protected route guards
7. ✅ Proaktif yenileme
**Backend Hazırlığı**: Frontend tamamlandı, backend endpoint'leri (`/auth/login`, `/auth/refresh`, `/auth/logout`) hazır olduğunda test edilebilir.
**Çalıştırma**: `npm run dev` komutu ile başlatılabilir.