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 @@
diff --git a/frontend/vue-app/src/components/landing/LandingPage.vue b/frontend/vue-app/src/components/landing/LandingPage.vue
index 11cf071..ef0f699 100644
--- a/frontend/vue-app/src/components/landing/LandingPage.vue
+++ b/frontend/vue-app/src/components/landing/LandingPage.vue
@@ -3,7 +3,7 @@
@@ -34,6 +34,10 @@ function goToLogin() {
router.push({ name: 'Login' })
}
+function scrollToTop() {
+ window.scrollTo({ top: 0, behavior: 'smooth' })
+}
+
onMounted(() => {
window.addEventListener('scroll', onScroll, { passive: true })
})
@@ -82,6 +86,7 @@ onUnmounted(() => {
.nav-logo {
height: 34px;
filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35));
+ cursor: pointer;
}
.nav-signin {
diff --git a/frontend/vue-app/src/components/profile/UserProfile.vue b/frontend/vue-app/src/components/profile/UserProfile.vue
index 829e88d..208d6d9 100644
--- a/frontend/vue-app/src/components/profile/UserProfile.vue
+++ b/frontend/vue-app/src/components/profile/UserProfile.vue
@@ -341,7 +341,7 @@ function handleDeleteSuccess() {
}).finally(() => {
// Clear client-side auth and redirect, regardless of logout response
logoutUser()
- router.push('/auth/login')
+ router.push('/')
})
}
diff --git a/frontend/vue-app/src/components/shared/LoginButton.vue b/frontend/vue-app/src/components/shared/LoginButton.vue
index c421ab0..ed09bf9 100644
--- a/frontend/vue-app/src/components/shared/LoginButton.vue
+++ b/frontend/vue-app/src/components/shared/LoginButton.vue
@@ -225,7 +225,7 @@ async function signOut() {
try {
await fetch('/api/auth/logout', { method: 'POST' })
logoutUser()
- router.push('/auth')
+ router.push('/')
} catch {
// Optionally show error
}
diff --git a/frontend/vue-app/src/layout/AuthLayout.vue b/frontend/vue-app/src/layout/AuthLayout.vue
index 53870c6..025e874 100644
--- a/frontend/vue-app/src/layout/AuthLayout.vue
+++ b/frontend/vue-app/src/layout/AuthLayout.vue
@@ -21,10 +21,8 @@ const router = useRouter()
const route = useRoute()
const handleBack = () => {
- // route to the auth landing page instead of using browser history
- router.push({ name: 'AuthLanding' }).catch(() => {
- // fallback to a safe path if named route isn't available
- window.location.href = '/auth'
+ router.push({ name: 'LandingPage' }).catch(() => {
+ window.location.href = '/'
})
}