Session sistemi = Kullanıcının kim olduğunu takip etme
Device limit = Aynı anda kaç cihazda müzik dinleyebileceğini kontrol etme
LIFO (Last In First Out) = Yeni giriş yapan, eski girişi atar
TTL: 10080 dakika (7 gün)
Key format: 40 karakter alphanumeric
user_active_sessions tablosu
Tablo: tenant_muzibu_1528d0.user_active_sessions
Kullanım: Device limit kontrolü
Cookie adı: tuufi_session
Şifreleme: Laravel encrypt
Key: AKmX6ilTCPbot7IukdA8H3NblqBNmXp4qfJfcPKN
Value: {
"_token": "csrf_token_here",
"_previous": {"url": "https://muzibu.com"},
"login_web_...": 1, // User ID
"password_hash_web_...": "hash"
}
Kullanıcı otomatik logout olur. Sayfa yenileyince login sayfasına yönlendirilir.
Ama user_active_sessions tablosundaki kayıt kalır (stale data).
Bu nedenle 60 dakika sonra temizlenir.
| Kolon | Tip | Açıklama |
|---|---|---|
| id | bigint | Primary key |
| user_id | bigint | Kullanıcı ID (FK → users) |
| session_id | varchar(255) | Redis session ID (unique) |
| ip_address | varchar(45) | Kullanıcı IP |
| device_type | varchar(20) | desktop / mobile / tablet |
| device_name | varchar(100) | OS X - Chrome |
| last_activity | timestamp | Son aktivite (30 sn'de güncellenir) |
Frontend her 30 saniyede /api/auth/check-session çağırıyor.
Session DB'de yoksa → "session_terminated" döner → Kullanıcı logout olur.
Ama Redis'te session hala var! Bu durumda Laravel "giriş yapmış" sanır,
ama DeviceService "session yok" der. Sonuç: Çelişki ve logout.
Email + Password → POST /api/auth/login
Şifre doğrulanır, session regenerate edilir, yeni session ID oluşur
$request->session()->regenerate();
Session driver redis olduğu için otomatik yazılır
Redis KEY: AKmX6ilTCPbot7IukdA8... TTL: 10080 dakika (7 gün)
Session ID + cihaz bilgisi → user_active_sessions tablosuna
DB::table('user_active_sessions')->insert([
'user_id' => $user->id,
'session_id' => session()->getId(),
'device_name' => 'OS X - Chrome',
...
]);
Device limit aşıldıysa en eski session silinir
// enforceDeviceLimit() // Limit: 1 → 2. cihaz giriş yapınca 1. cihaz silinir // Limit: 2 → 3. cihaz giriş yapınca 1. cihaz silinir
Session ID şifrelenerek cookie'ye yazılır
Set-Cookie: tuufi_session=eyJpdiI6...; HttpOnly; Secure; SameSite=Lax
POST /api/auth/logout çağrılırDeviceService.unregisterSession() → DB'den silerAuth::logout() → Laravel logoutsession()->invalidate() → Redis'ten silerenforceDeviceLimit() çalışırcheck-session çağırır⚠️ Redis session hala var ama DB'de yok → Çelişki
users.device_limit
plans.device_limit
auth_device_limit
// DeviceService::getDeviceLimit()
1. User override: $user->device_limit (null değilse)
2. Subscription Plan: $user->subscriptions->plan->device_limit
3. Tenant setting: setting('auth_device_limit') → Default: 1
| Zaman | İşlem | Sonuç |
|---|---|---|
| 09:00 | Bilgisayardan login | Session A aktif |
| 10:00 | Telefondan login | Session B aktif, Session A siliniyor... |
| 10:00:30 | Bilgisayar check-session | Session A yok → Logout! |
| 10:01 | Bilgisayar login sayfasına | "Başka cihazdan giriş yapıldı" |
-- Belirli kullanıcının tüm sessionlarını sil DELETE FROM user_active_sessions WHERE user_id = 1; -- Sonuç: 30 saniye içinde logout olur
Frontend polling "session yok" alır → Logout
# Session ID'yi bul SELECT session_id FROM user_active_sessions WHERE user_id = 1; # Redis'ten sil redis-cli DEL "AKmX6ilTCPbot7IukdA8..." # Sonuç: ANINDA logout
Laravel session yok → Anında unauthorized
// Admin panelden
DeviceService::terminateSession($sessionId);
// Veya API endpoint (ileride)
POST /api/admin/users/{id}/logout
php artisan tinker
>>> tenancy()->initialize(\App\Models\Tenant::find(1001));
>>> DB::table('user_active_sessions')
... ->where('user_id', 1)
... ->delete();
Sadece DB'den silmek yetmez! Redis'te session hala var olabilir.
Kullanıcı logout olduktan sonra bile cookie ile request atabilir.
En güvenli: Hem DB hem Redis'ten sil.
GET /api/songs/{id}/stream
Auth kontrolü: auth('web')->user()
Giriş yapmamış → 30 sn preview
Session DB'de var mı?
DB::table('user_active_sessions')
->where('session_id', session()->getId())
->exists();
Session yoksa → 401 session_terminated
Session varsa → Device limit kontrolü
Premium kontrolü: $user->isPremiumOrTrial()
Premium değil → 30 sn preview
✅ Signed URL döndür → Şarkı çalar
MP3/HLS dosyasına erişim için geçici şifrelenmiş URL.
30 dakika sonra expire olur, tekrar stream isteği gerekir.
Bu sayede direkt link paylaşılsa bile çalışmaz.
localStorage'dan önceki state yükleniyor.
Eğer preview mode'da kaldıysa, isPreviewBlocked = true oluyor.
Play butonuna basınca "Premium'a geçin" toast çıkıyor.
State restore sırasında isPreviewBlocked flag'ini sıfırla.
Veya login olduktan sonra flag'i temizle.
loadState() fonksiyonu önceki queue'yu yüklüyor.
Sonra playSongFromQueue() çağrılıyor (autoplay=false bile olsa).
Stream API çağrısı yapılıyor, URL alınıyor.
State restore sırasında sadece UI güncellemesi yap.
Şarkıyı yükleme, stream isteği atma.
Kullanıcı play'e basınca yükle.
Redis session 7 gün yaşar.
DB session 60 dakika inaktifse silinir.
İkisi arasında senkronizasyon yok.
DB cleanup TTL'ini Redis ile eşitle.
Veya logout sırasında her ikisini de sil.