From ccfc71075385bded7e4ecd5a97d6fd88f6a10377 Mon Sep 17 00:00:00 2001 From: Ryan Kegel Date: Thu, 5 Mar 2026 09:52:19 -0500 Subject: [PATCH] feat: implement force logout event and update navigation redirects --- backend/api/auth_api.py | 7 +++++++ backend/events/types/event_types.py | 2 ++ frontend/vue-app/src/common/api.ts | 2 +- .../src/components/BackendEventsListener.vue | 20 +++++++++++++++++-- .../src/components/landing/LandingPage.vue | 7 ++++++- .../src/components/profile/UserProfile.vue | 2 +- .../src/components/shared/LoginButton.vue | 2 +- frontend/vue-app/src/layout/AuthLayout.vue | 6 ++---- 8 files changed, 38 insertions(+), 10 deletions(-) diff --git a/backend/api/auth_api.py b/backend/api/auth_api.py index 07066b0..a728096 100644 --- a/backend/api/auth_api.py +++ b/backend/api/auth_api.py @@ -14,6 +14,10 @@ from werkzeug.security import generate_password_hash, check_password_hash from api.utils import sanitize_email from config.paths import get_user_image_dir +from events.sse import send_event_to_user +from events.types.event import Event +from events.types.event_types import EventType +from events.types.payload import Payload from api.error_codes import ( MISSING_FIELDS, EMAIL_EXISTS, MISSING_TOKEN, INVALID_TOKEN, TOKEN_TIMESTAMP_MISSING, @@ -359,6 +363,9 @@ def reset_password(): # Invalidate ALL refresh tokens for this user refresh_tokens_db.remove(TokenQuery.user_id == user.id) + # Notify all active sessions (other tabs/devices) to sign out immediately + send_event_to_user(user.id, Event(EventType.FORCE_LOGOUT.value, Payload({}))) + resp = jsonify({'message': 'Password has been reset'}) _clear_auth_cookies(resp) return resp, 200 diff --git a/backend/events/types/event_types.py b/backend/events/types/event_types.py index f66a87f..ebf5d5a 100644 --- a/backend/events/types/event_types.py +++ b/backend/events/types/event_types.py @@ -27,3 +27,5 @@ class EventType(Enum): CHORE_SCHEDULE_MODIFIED = "chore_schedule_modified" CHORE_TIME_EXTENDED = "chore_time_extended" CHILD_CHORE_CONFIRMATION = "child_chore_confirmation" + + FORCE_LOGOUT = "force_logout" diff --git a/frontend/vue-app/src/common/api.ts b/frontend/vue-app/src/common/api.ts index a4c3c43..70bb877 100644 --- a/frontend/vue-app/src/common/api.ts +++ b/frontend/vue-app/src/common/api.ts @@ -28,7 +28,7 @@ function handleUnauthorizedResponse(): void { unauthorizedRedirectHandler() return } - window.location.assign('/auth') + window.location.assign('/') } /** diff --git a/frontend/vue-app/src/components/BackendEventsListener.vue b/frontend/vue-app/src/components/BackendEventsListener.vue index e102aaa..d2d1839 100644 --- a/frontend/vue-app/src/components/BackendEventsListener.vue +++ b/frontend/vue-app/src/components/BackendEventsListener.vue @@ -1,9 +1,12 @@