Session Silme Mesajları

Yanlış Logout Mesajı Sorunu - Analiz ve Çözüm

📅 20 Aralık 2025 🏢 Muzibu.com.tr 🔧 Session Management

📝 Basit Anlatım (Herkes İçin)

❌ Sorun Neydi?

Kullanıcılar müzik dinlerken oturumları kapanıyor ve "Başka bir cihazdan giriş yapıldı" mesajı görüyorlardı. Ama kimse başka cihazdan giriş yapmamıştı! Mesaj tamamen yanlıştı.

🔍 Gerçek Neden Neydi?

Sistem 4 farklı sebepten oturumu kapatabiliyordu:

  • Gerçekten başka cihazdan giriş - Bu durumda mesaj doğru
  • 60 dakika hiç kullanılmamış - Otomatik temizlik, ama mesaj yanlış!
  • Kullanıcı çıkış yaptı - Manuel logout, ama mesaj yanlış!
  • Yönetici sonlandırdı - Admin işlemi, ama mesaj yanlış!

Yani 4 sebepten sadece 1'inde mesaj doğruydu, diğer 3'ünde kullanıcı yanıltılıyordu!

💡 Nasıl Çözüldü?

Sistem artık oturumu kapatırken "neden kapattığını" hatırlıyor. Kullanıcı geri geldiğinde gerçek sebebi gösteriyor:

🔒 "Başka bir cihazdan giriş yapıldı." (Gerçekten başka cihaz varsa)
"Oturumunuz 60 dakika inaktif kaldığı için otomatik olarak kapatıldı."
👋 "Oturumunuz kapatıldı." (Kendiniz çıkış yaptıysanız)
👮 "Oturumunuz yönetici tarafından sonlandırıldı."

🎯 Sonuç

Artık kullanıcılar neden logout olduklarını tam olarak biliyorlar. Yanlış "başka cihazdan giriş" uyarısı görmeyecekler.

🔧 Teknik Detaylar (Geliştiriciler İçin)

❌ Sorun Analizi

Kod Lokasyonu:

app/Http/Controllers/Api/Auth/AuthController.php:210

Eski Kod (Hatalı):

if (!$deviceService->sessionExists($user)) {
    return response()->json([
        'valid' => false,
        'reason' => 'session_terminated',
        'message' => 'Başka bir cihazdan giriş yapıldı.', // ❌ HER ZAMAN AYNI!
    ]);
}

Asıl Sorun:

Sistem sadece session'ın DB'de olup olmadığını kontrol ediyordu. Session yoksa → "LIFO kicked" olduğunu varsayıyordu. Ama 4 farklı sebep vardı!

Session Silinme Senaryoları:

1. LIFO (Last In First Out)
DeviceService.php:525-542
Yeni cihaz login → Eski session siliniyor
✅ Mesaj DOĞRU olmalı
2. 60 Dakika Cleanup
DeviceService.php:392-412
60dk inaktif → Otomatik cleanup
❌ Mesaj YANLIŞTI
3. Manuel Logout
DeviceService.php:108-120
User logout butonu → Session siliniyor
❌ Mesaj YANLIŞTI
4. Admin Terminated
DeviceService.php:560-567
Admin terminateSession() → Session siliniyor
❌ Mesaj YANLIŞTI

✅ Çözüm Mimarisi

Yaklaşım: Cache-Based Reason Tracking

Session silinirken nedeni cache'e kaydediyoruz, kullanıcı polling yaptığında cache'den okuyup doğru mesajı gösteriyoruz.

1
Session Silinecek
📍 DeviceService.php
🔑 Cache Key:
session_deleted_reason:{user_id}:{login_token}
💾 Value: 'lifo' | '60min_cleanup' | 'manual_logout' | 'admin_terminated'
⏰ TTL: 300 saniye (5 dakika)
2
Polling Geldi
📍 AuthController.php:checkSession()
🔍 Cache'den reason oku
📝 match() ile mesaj belirle
📤 Response döndür
🗑️ Cache'i temizle (tek kullanımlık)
⚡ Neden Cache?
  • ✅ Session silinmiş olsa bile reason okunabilir
  • ✅ DB'ye `deleted_reason` field eklemek gerekmez
  • ✅ 5 dakika TTL yeterli (polling 5 saniyede bir)
  • ✅ Tek kullanımlık (okuyan ilk polling temizliyor)

📝 Kod Değişiklikleri

📁 DeviceService.php - Cache'e Reason Kaydetme

Import Eklendi:
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
1️⃣ LIFO (enforceDeviceLimit - Satır 529-536):
if ($old->login_token) {
    Cache::put(
        "session_deleted_reason:{$user->id}:{$old->login_token}",
        'lifo',
        300
    );
}
2️⃣ 60dk Cleanup (getActiveDevices - Satır 397-406):
foreach ($staleSessions as $staleSession) {
    if ($staleSession->login_token) {
        Cache::put(
            "session_deleted_reason:{$user->id}:{$staleSession->login_token}",
            '60min_cleanup',
            300
        );
    }
}
3️⃣ Manuel Logout (unregisterSession - Satır 113-119):
if ($session && $session->login_token) {
    Cache::put(
        "session_deleted_reason:{$user->id}:{$session->login_token}",
        'manual_logout',
        300
    );
}
4️⃣ Admin Terminate (terminateSession - Satır 560-566):
if ($session && $session->login_token) {
    Cache::put(
        "session_deleted_reason:{$session->user_id}:{$session->login_token}",
        'admin_terminated',
        300
    );
}

📁 AuthController.php - Cache'den Reason Okuma

Import Eklendi:
use Illuminate\Support\Facades\Cache;
checkSession() Güncellendi (Satır 196-217):
if (!$deviceService->sessionExists($user)) {
    // Cache'den silinme nedenini oku
    $cookieToken = $request->cookie('mzb_login_token');
    $deletedReason = null;

    if ($cookieToken) {
        $cacheKey = "session_deleted_reason:{$user->id}:{$cookieToken}";
        $deletedReason = Cache::get($cacheKey);

        // Cache'den okuduktan sonra sil (tek kullanımlık)
        if ($deletedReason) {
            Cache::forget($cacheKey);
        }
    }

    // Reason'a göre mesaj belirle
    $message = match($deletedReason) {
        'lifo' => 'Başka bir cihazdan giriş yapıldı.',
        '60min_cleanup' => 'Oturumunuz 60 dakika inaktif kaldığı için otomatik olarak kapatıldı.',
        'manual_logout' => 'Oturumunuz kapatıldı.',
        'admin_terminated' => 'Oturumunuz yönetici tarafından sonlandırıldı.',
        default => 'Oturumunuz sonlandırıldı. Lütfen tekrar giriş yapın.',
    };

    return response()->json([
        'valid' => false,
        'reason' => 'session_terminated',
        'message' => $message, // ✅ DOĞRU MESAJ!
    ]);
}

🧪 Test Sonuçları

✅ Tüm Senaryolar Test Edildi

TEST 1: 60 Dakika Cleanup ✅ BAŞARILI
Cache Reason: 60min_cleanup
📝 "Oturumunuz 60 dakika inaktif kaldığı için otomatik olarak kapatıldı."
TEST 2: Manuel Logout ✅ BAŞARILI
Cache Reason: manual_logout
📝 "Oturumunuz kapatıldı."
TEST 3: LIFO (Başka Cihaz) ✅ BAŞARILI
Cache Reason: lifo
📝 "Başka bir cihazdan giriş yapıldı."
TEST 4: Admin Terminated ✅ BAŞARILI
Cache Reason: admin_terminated
📝 "Oturumunuz yönetici tarafından sonlandırıldı."
TEST 5: Unknown Reason ✅ BAŞARILI
Cache Reason: null
📝 "Oturumunuz sonlandırıldı. Lütfen tekrar giriş yapın."

⏱️ Sorun Çözüm Timeline

1

Sorun Keşfi (19 Aralık)

User 2 yanlış "başka cihazdan giriş" mesajı aldı. Log analizi başladı.

2

Kök Sebep Bulundu (20 Aralık, 21:41)

60 dakika cleanup sisteminin yanlış mesaj gösterdiği tespit edildi.

3

Çözüm Tasarımı (20 Aralık)

Cache-based reason tracking yaklaşımı tasarlandı.

4

Kod Yazımı (20 Aralık)

DeviceService.php ve AuthController.php güncellendi.

5

Test & Deploy (20 Aralık)

5 senaryo test edildi, tüm mesajlar doğru çalışıyor. Sisteme deploy edildi.

🎯 Özet

❌ Önceden:

  • ✗ 4 sebep → 1 mesaj
  • ✗ Kullanıcı her zaman "başka cihazdan giriş" görüyordu
  • ✗ 60dk timeout → Yanlış mesaj
  • ✗ Manuel logout → Yanlış mesaj
  • ✗ Admin silme → Yanlış mesaj

✅ Şimdi:

  • ✓ 4 sebep → 4 farklı mesaj
  • ✓ Her sebep için özel mesaj
  • ✓ 60dk timeout → "60 dakika inaktif" mesajı
  • ✓ Manuel logout → "Oturumunuz kapatıldı" mesajı
  • ✓ Admin silme → "Yönetici sonlandırdı" mesajı

🎉 Kullanıcılar artık neden logout olduklarını kesin olarak biliyorlar!