This commit is contained in:
IGNY8 VPS (Salman)
2025-12-17 00:27:53 +00:00
parent 8f97666522
commit 69c0fd8b69
8 changed files with 262 additions and 174 deletions

View File

@@ -0,0 +1,345 @@
# Logout Tracking System - Testing Checklist
**Purpose:** Verify the logout tracking system works correctly for all scenarios
---
## Pre-Testing Setup
- [ ] Backend container restarted
- [ ] Frontend container restarted
- [ ] Browser DevTools console open
- [ ] Backend logs accessible (`docker logs -f igny8_backend`)
---
## Test 1: Manual Logout
**Steps:**
1. Login to the app
2. Navigate to any page (e.g., `/dashboard`)
3. Click the logout button
**Expected Results:**
- [ ] Console shows: `🚪 LOGOUT - User Action:`
- [ ] Redirected to `/signin`
- [ ] Yellow alert box appears on signin page
- [ ] Alert shows: "User manually logged out"
- [ ] Original page shown in alert: `/dashboard`
- [ ] Click icon shows technical details
- [ ] Technical details show:
- Code: `MANUAL_LOGOUT`
- Source: `manual_user_action`
- Path: `/dashboard` (or whatever page you were on)
- User email in context
- Timestamp
- [ ] After refresh, alert is gone (single display)
---
## Test 2: Token Expiration (401)
**Steps:**
1. Login to the app
2. Get the access token from localStorage
3. In browser console, manually expire it:
```javascript
localStorage.setItem('access_token', 'invalid_token')
```
4. Navigate to a protected page or make an API call
**Expected Results:**
- [ ] Console shows: `🚨 LOGOUT TRIGGERED - Token Refresh Failed` or `🚨 LOGOUT TRIGGERED - No Refresh Token`
- [ ] Redirected to `/signin`
- [ ] Yellow alert box appears
- [ ] Alert shows token-related message
- [ ] Original page shown in alert
- [ ] Technical details show correct error code
---
## Test 3: Session Contamination (Account Mismatch)
**Steps:**
1. Login with a user account
2. In Django admin or shell, create session contamination:
```python
# Get a session and modify _account_id to wrong value
from django.contrib.sessions.models import Session
session = Session.objects.first()
data = session.get_decoded()
data['_account_id'] = 99999 # Non-existent account
session.session_data = session.encode(data)
session.save()
```
3. Refresh the app or make an API call
**Expected Results:**
- [ ] Backend logs show: `[AUTO-LOGOUT] SESSION_ACCOUNT_MISMATCH`
- [ ] Console shows: `🚨 LOGOUT TRIGGERED - Backend Validation Failed`
- [ ] Redirected to `/signin`
- [ ] Yellow alert shows: "Session contamination: account ID mismatch"
- [ ] Technical details show:
- Code: `SESSION_ACCOUNT_MISMATCH`
- Source: `backend_middleware`
- Context: stored vs current account IDs
- [ ] Backend logs include IP, path, user ID, timestamp
---
## Test 4: Missing Account
**Steps:**
1. In Django admin, remove account from a user:
```python
user = User.objects.get(email='test@example.com')
user.account = None
user.save()
```
2. Try to login with that user
**Expected Results:**
- [ ] Backend logs show: `[AUTO-LOGOUT] ACCOUNT_MISSING`
- [ ] Console shows: `🚨 LOGOUT TRIGGERED`
- [ ] Alert shows: "Account not configured for this user"
- [ ] Technical details show:
- Code: `ACCOUNT_MISSING`
- Source: `backend_middleware` or `refresh_user_validation`
---
## Test 5: Inactive Plan
**Steps:**
1. In Django admin, deactivate user's plan:
```python
plan = Plan.objects.get(slug='starter')
plan.is_active = False
plan.save()
```
2. User makes an API call or refreshes page
**Expected Results:**
- [ ] Backend logs show: `[AUTO-LOGOUT] PLAN_INACTIVE`
- [ ] Console shows: `🚨 LOGOUT TRIGGERED`
- [ ] Alert shows: "Subscription plan is inactive"
- [ ] Technical details show:
- Code: `PLAN_INACTIVE`
- HTTP status 402 in context
---
## Test 6: Suspended Account
**Steps:**
1. In Django admin, suspend an account:
```python
account = Account.objects.get(id=1)
account.status = 'suspended'
account.save()
```
2. User tries to access protected page
**Expected Results:**
- [ ] Backend logs show: `[AUTO-LOGOUT] ACCOUNT_SUSPENDED`
- [ ] Alert shows: "Account is suspended"
- [ ] Technical details show:
- Code: `ACCOUNT_SUSPENDED`
- HTTP status 403
---
## Test 7: 403 Auth Credentials Error
**Steps:**
1. Login to the app
2. In browser console, corrupt the token:
```javascript
localStorage.setItem('access_token', 'Bearer corrupted')
```
3. Make an API call
**Expected Results:**
- [ ] Console shows: `🚨 LOGOUT TRIGGERED - Authentication Credentials Missing`
- [ ] Alert shows authentication credentials error
- [ ] Technical details show:
- Code: `AUTH_CREDENTIALS_MISSING`
- Source: `api_403_auth_error`
---
## Test 8: Page Path Accuracy
**Steps:**
1. Login and navigate through multiple pages
2. Trigger logout from different pages:
- From `/dashboard` → Check logout shows `/dashboard`
- From `/planner/keywords` → Check logout shows `/planner/keywords`
- From `/writer/articles` → Check logout shows `/writer/articles`
**Expected Results:**
- [ ] Every logout shows **exact page** where logout occurred
- [ ] **Never** shows `/signin` as logout path
- [ ] Path captured BEFORE redirect
---
## Test 9: Console Logging Format
**Expected in Browser Console:**
- [ ] 🚨 emoji for automatic logouts
- [ ] 🚪 emoji for manual logout
- [ ] Grouped logs with expandable details
- [ ] Full JSON context logged
- [ ] Timestamps present
- [ ] Error codes visible
**Expected in Backend Logs:**
```bash
[AUTO-LOGOUT] ERROR_CODE: Message. User=123, Account=456, Path=/page, IP=..., Timestamp=...
```
- [ ] `[AUTO-LOGOUT]` prefix present
- [ ] Error code included
- [ ] All context fields present
- [ ] Grep-friendly format
---
## Test 10: Alert Box UI
**Visual Checks:**
- [ ] Yellow background (not red)
- [ ] Clear heading: "Session Ended"
- [ ] User-friendly message displayed
- [ ] Original page path shown (if not /signin)
- [ ] Info icon () present
- [ ] Click info icon expands technical details
- [ ] Technical details show:
- Error code
- Source
- Timestamp (formatted)
- Context JSON (formatted with indentation)
- [ ] Click info icon again collapses details
- [ ] Alert disappears after page refresh
---
## Test 11: Multiple Logouts
**Steps:**
1. Trigger logout (any method)
2. See alert on signin page
3. Login again
4. Trigger different logout (different error)
5. Return to signin page
**Expected Results:**
- [ ] First logout reason cleared after first display
- [ ] Second logout shows new reason (not old one)
- [ ] No accumulation of old logout reasons
- [ ] Each logout tracked separately
---
## Test 12: Edge Cases
### No Logout Reason
**Steps:** Navigate directly to `/signin` without logout
**Expected:**
- [ ] No alert box shown
- [ ] No console errors
- [ ] No localStorage pollution
### localStorage Disabled
**Steps:** Disable localStorage in browser, trigger logout
**Expected:**
- [ ] Console warning about failed storage
- [ ] App still functions
- [ ] No crash
### Malformed Logout Reason
**Steps:** Manually corrupt logout_reason in localStorage
```javascript
localStorage.setItem('logout_reason', 'invalid json')
```
**Expected:**
- [ ] Console warning about parsing failure
- [ ] No alert shown
- [ ] No crash
---
## Test 13: Cross-Browser Testing
Test in multiple browsers:
- [ ] Chrome
- [ ] Firefox
- [ ] Safari
- [ ] Edge
**All features should work identically**
---
## Test 14: Mobile Responsiveness
Test on mobile devices/emulator:
- [ ] Alert box displays correctly
- [ ] Technical details expand/collapse works
- [ ] Text is readable
- [ ] No horizontal scroll
---
## Success Criteria
✅ **All tests pass**
✅ **Every logout has visible reason**
✅ **Exact page tracking works**
✅ **Console logs are clear**
✅ **Backend logs are searchable**
✅ **User sees helpful message**
✅ **Developers can debug easily**
---
## Troubleshooting
### Alert not showing
- Check browser console for logout reason object
- Check if localStorage.getItem('logout_reason') returns data
- Verify SignInForm component mounted
### Wrong page shown
- Verify `window.location.pathname` captured BEFORE redirect
- Check logout trigger happens before navigation
- Ensure logout_reason stored BEFORE logout() call
### Backend logs missing
- Check logger level is WARNING or INFO
- Verify logger name: 'auth.middleware'
- Check LOGGING config in settings.py
### Console logs missing
- Check browser console filters (show all levels)
- Verify emoji not filtered out
- Check if code throwing before log statement
---
## Maintenance
**When adding new logout causes:**
1. Add error code to `LOGOUT_REASONS` dict
2. Update logout trigger to create structured reason
3. Store in localStorage before logout
4. Log to console with 🚨
5. Update this testing checklist
6. Update LOGOUT-CAUSES-COMPLETE-REFERENCE.md
**Keep documentation in sync with implementation!**