feat(07.1): session revocation on privilege change — CR-01/CR-02/CR-03
- revoke_all_refresh_tokens: add skip_token_hash optional param (exclude
current session while revoking others)
- change_password, enable_totp, disable_totp: call revoke with skip hash
derived from refresh cookie; return sessions_revoked in response and
write to audit log metadata_
- 3 new tests: test_{change_password,enable_totp,disable_totp}_revokes_other_sessions
— all PASSED; 373 total passing, 0 regressions
- Frontend toasts: SettingsAccountTab + TotpEnrollment show
"Other sessions have been terminated." when sessions_revoked > 0
- Companion fixes: rate_limiting get_client_ip refactor, deps/auth.py
request.state.current_user, locustfile refresh-token task removal
- Version bump: 0.1.0 → 0.1.1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
8d060a5da4
commit
c38c6b1c01
+26
@@ -0,0 +1,26 @@
|
||||
# Plan 07.1-01 Summary — Session revocation on privilege change (backend)
|
||||
|
||||
**Status:** Complete
|
||||
**Wave:** 1
|
||||
|
||||
## What was done
|
||||
|
||||
### services/auth.py
|
||||
- Extended `revoke_all_refresh_tokens` signature: added `skip_token_hash: Optional[str] = None`
|
||||
- When `skip_token_hash` is set, the WHERE clause excludes that token (`RefreshToken.token_hash != skip_token_hash`), so the calling session stays alive
|
||||
- Backwards-compatible: all existing callers that pass no third argument behave identically
|
||||
|
||||
### api/auth.py
|
||||
- `change_password`: derives skip hash from refresh cookie → calls `revoke_all_refresh_tokens` with skip → extends audit log `metadata_` with `sessions_revoked` → returns `{"message": "Password updated", "sessions_revoked": revoked}`
|
||||
- `enable_totp`: same pattern → returns `{"backup_codes": plain_codes, "sessions_revoked": revoked}`
|
||||
- `disable_totp`: same pattern → returns `{"message": "TOTP disabled", "sessions_revoked": revoked}`
|
||||
- `logout_all` handler: unchanged (intentionally revokes all sessions without skip)
|
||||
|
||||
## Verification
|
||||
|
||||
```
|
||||
grep -c "skip_token_hash" services/auth.py → 4
|
||||
grep -c "sessions_revoked" api/auth.py → 7
|
||||
grep -c "skip_token_hash" api/auth.py → 6
|
||||
python3 -c "import api.auth; import services.auth" → exits 0
|
||||
```
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# Plan 07.1-02 Summary — Tests + frontend toasts
|
||||
|
||||
**Status:** Complete
|
||||
**Wave:** 2
|
||||
|
||||
## What was done
|
||||
|
||||
### backend/tests/test_auth_api.py
|
||||
- Added `RefreshToken` to imports from `db.models`
|
||||
- Appended 3 new `@pytest.mark.asyncio` tests:
|
||||
- `test_change_password_revokes_other_sessions`: inserts a second RefreshToken, calls change-password, asserts `sessions_revoked >= 1` and the row is revoked
|
||||
- `test_enable_totp_revokes_other_sessions`: same pattern for totp/enable (mocks `verify_totp` and `store_backup_codes`)
|
||||
- `test_disable_totp_revokes_other_sessions`: same pattern for DELETE /api/auth/totp
|
||||
|
||||
### frontend/src/components/settings/SettingsAccountTab.vue
|
||||
- Added `sessionRevokedToast = ref(false)`
|
||||
- Added a fixed top-right toast (same visual pattern as SettingsView OAuth toast)
|
||||
- `changePassword()`: captures API response, shows toast for 5s when `sessions_revoked > 0`
|
||||
- `disableTotp()`: captures API response, shows toast for 5s when `sessions_revoked > 0`
|
||||
|
||||
### frontend/src/components/auth/TotpEnrollment.vue
|
||||
- Added `sessionRevokedToast = ref(false)`
|
||||
- Added an inline (non-fixed) alert block at the top of the component template
|
||||
- `confirmEnrollment()`: checks `data.sessions_revoked > 0` and shows the inline alert for 5s
|
||||
|
||||
## Verification
|
||||
|
||||
```
|
||||
pytest tests/test_auth_api.py -k "revokes_other_sessions" -v → 3 PASSED
|
||||
pytest -q --ignore=tests/test_extractor.py → 373 passed, 0 failed
|
||||
npm run build (frontend) → exits 0
|
||||
grep -c "sessions_revoked" SettingsAccountTab.vue → 2
|
||||
grep -c "sessions_revoked" TotpEnrollment.vue → 1
|
||||
```
|
||||
Reference in New Issue
Block a user