Refactor code structure and remove redundant sections for improved readability and maintainability
All checks were successful
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 1m48s

This commit is contained in:
2026-04-10 17:44:37 -04:00
parent 8080a59de1
commit 861b3dc9d4
19 changed files with 52 additions and 2811 deletions

View File

@@ -2,23 +2,23 @@
"cookies": [
{
"name": "refresh_token",
"value": "oQxjeMmAW3v4aoI_hBdjpMXThVDzKZTG_6bQGPJBokc",
"value": "pjakYk7dm_bGf-VXaBpRXFNNq08FH0csnh3nBhCqWGw",
"domain": "localhost",
"path": "/api/auth",
"expires": 1782271329.747941,
"expires": 1783633314.818346,
"httpOnly": true,
"secure": true,
"sameSite": "Strict"
},
{
"name": "access_token",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImUyZS1jY0B0ZXN0LmNvbSIsInVzZXJfaWQiOiIyYjQ1MmRiNi1lYTRmLTQyMDItODIzYi0zNjllN2E3YTQ5MjYiLCJ0b2tlbl92ZXJzaW9uIjowLCJleHAiOjE3NzQ0OTYyMjl9.docokOZYHgPtNNqirbfLSRABQHHsmTj-9_txuR8NHOM",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImUyZS1jY0B0ZXN0LmNvbSIsInVzZXJfaWQiOiI3NWQ3NGU4OC1jMjY0LTQ3MGMtOThiNC02ZTQ0YTBkYzkyOTMiLCJ0b2tlbl92ZXJzaW9uIjowLCJleHAiOjE3NzU4NTgyMTR9.lXWnj-O3MszrJ_GIwp6ViN0W5-5XEpSDVlAQIQSll-Q",
"domain": "localhost",
"path": "/",
"expires": -1,
"expires": 1775858214.818293,
"httpOnly": true,
"secure": true,
"sameSite": "Strict"
"sameSite": "Lax"
}
],
"origins": [
@@ -27,11 +27,11 @@
"localStorage": [
{
"name": "authSyncEvent",
"value": "{\"type\":\"logout\",\"at\":1774495329388}"
"value": "{\"type\":\"logout\",\"at\":1775857314645}"
},
{
"name": "parentAuth",
"value": "{\"expiresAt\":1774668130069}"
"value": "{\"expiresAt\":1776030114975}"
}
]
}

View File

@@ -2,23 +2,23 @@
"cookies": [
{
"name": "refresh_token",
"value": "PcQvgm3e7SXL3CHGNXYGXhRrU7erXomAQDbOzVAUrCQ",
"value": "sTFHvjZ5hJxJrlNHoxdWkNJ6vxdDzrZwTRFz55JxWKs",
"domain": "localhost",
"path": "/api/auth",
"expires": 1782271328.966396,
"expires": 1783633314.820088,
"httpOnly": true,
"secure": true,
"sameSite": "Strict"
},
{
"name": "access_token",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImUyZS1kZWxldGVAdGVzdC5jb20iLCJ1c2VyX2lkIjoiOWM4ODk0MWUtMjhiMy00YzFmLWJhNDctMDNkMTU0MTc2ODA5IiwidG9rZW5fdmVyc2lvbiI6MCwiZXhwIjoxNzc0NDk2MjI4fQ.xxzCNQEX6y07hFJzEdumbYbhm_52VWM90tHsTPDfSKs",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImUyZS1kZWxldGVAdGVzdC5jb20iLCJ1c2VyX2lkIjoiY2U4MmI2MzMtMDUwMy00MmMxLWFlNjMtZmEzNzcxMmMxODZiIiwidG9rZW5fdmVyc2lvbiI6MCwiZXhwIjoxNzc1ODU4MjE0fQ.meuVUYIk9NFuo66KDhLPZHoXgHRLWmRDGyR23doTLIw",
"domain": "localhost",
"path": "/",
"expires": -1,
"expires": 1775858214.820046,
"httpOnly": true,
"secure": true,
"sameSite": "Strict"
"sameSite": "Lax"
}
],
"origins": [
@@ -27,11 +27,11 @@
"localStorage": [
{
"name": "authSyncEvent",
"value": "{\"type\":\"logout\",\"at\":1774495328432}"
"value": "{\"type\":\"logout\",\"at\":1775857314657}"
},
{
"name": "parentAuth",
"value": "{\"expiresAt\":1774668129476}"
"value": "{\"expiresAt\":1776030114992}"
}
]
}

View File

@@ -2,23 +2,23 @@
"cookies": [
{
"name": "refresh_token",
"value": "K9dRbu3607bZL23pmoMCD8qGM697tnpfY-dYVJ7qXPU",
"value": "nbOCYWuMXIGNyjN2uc6uohUFqkl-Bv1d01YjAOirGi8",
"domain": "localhost",
"path": "/api/auth",
"expires": 1782271324.066253,
"expires": 1783633312.982067,
"httpOnly": true,
"secure": true,
"sameSite": "Strict"
},
{
"name": "access_token",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImUyZUB0ZXN0LmNvbSIsInVzZXJfaWQiOiJiMGFhNDczMC05ZDI4LTQ3NzQtODE3NC1kZTZmZWJkMjZjMmIiLCJ0b2tlbl92ZXJzaW9uIjowLCJleHAiOjE3NzQ0OTYyMjR9.3RoSBnOU30YFn61lbfKo_ZMF2LQcsKb7qO31CK4AOl8",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImUyZUB0ZXN0LmNvbSIsInVzZXJfaWQiOiJlNjM1MjRiOS03NmIzLTRiMmQtODc1Ni05ZmNkNTk0MDRhYTkiLCJ0b2tlbl92ZXJzaW9uIjowLCJleHAiOjE3NzU4NTgyMTJ9.ztnqGJFbFDSze0GvK-2G37v5HaDdWRK392T7vsUpnhw",
"domain": "localhost",
"path": "/",
"expires": -1,
"expires": 1775858212.982022,
"httpOnly": true,
"secure": true,
"sameSite": "Strict"
"sameSite": "Lax"
}
],
"origins": [
@@ -27,11 +27,11 @@
"localStorage": [
{
"name": "authSyncEvent",
"value": "{\"type\":\"logout\",\"at\":1774495323817}"
"value": "{\"type\":\"logout\",\"at\":1775857312837}"
},
{
"name": "parentAuth",
"value": "{\"expiresAt\":1774668124255}"
"value": "{\"expiresAt\":1776030113109}"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -12,7 +12,6 @@ vi.mock('@/stores/auth', () => ({
isAuthReady: isAuthReadyMock,
isUserLoggedIn: isUserLoggedInMock,
isParentAuthenticated: isParentAuthenticatedMock,
logoutParent: vi.fn(),
enforceParentExpiry: vi.fn(),
}))

View File

@@ -28,7 +28,6 @@ import {
isUserLoggedIn,
isParentAuthenticated,
isAuthReady,
logoutParent,
enforceParentExpiry,
} from '../stores/auth'
import ParentPinSetup from '@/components/auth/ParentPinSetup.vue'
@@ -304,8 +303,6 @@ router.beforeEach(async (to, from, next) => {
if (isParentAuthenticated.value) {
return next('/parent')
} else {
// Ensure parent auth is fully cleared when redirecting away from /parent
logoutParent()
return next('/child')
}
})

View File

@@ -12,6 +12,31 @@ export const isParentAuthenticated = ref(false)
export const isParentPersistent = ref(false)
export const parentAuthExpiresAt = ref<number | null>(null)
// --- Background expiry watcher ---
// Declared before the init block so startParentExpiryWatcher is safe to call during restore.
let expiryWatcherIntervalId: ReturnType<typeof setInterval> | null = null
function runExpiryCheck() {
if (parentAuthExpiresAt.value !== null && Date.now() >= parentAuthExpiresAt.value) {
applyParentLoggedOutState()
if (typeof window !== 'undefined') {
window.location.href = '/child'
}
}
}
export function startParentExpiryWatcher() {
stopParentExpiryWatcher()
expiryWatcherIntervalId = setInterval(runExpiryCheck, 15_000)
}
export function stopParentExpiryWatcher() {
if (expiryWatcherIntervalId !== null) {
clearInterval(expiryWatcherIntervalId)
expiryWatcherIntervalId = null
}
}
// Restore persistent parent auth from localStorage on store init
if (hasLocalStorage) {
try {
@@ -38,30 +63,6 @@ export const currentUserId = ref('')
export const suppressForceLogout = ref(false)
let authSyncInitialized = false
// --- Background expiry watcher ---
let expiryWatcherIntervalId: ReturnType<typeof setInterval> | null = null
function runExpiryCheck() {
if (parentAuthExpiresAt.value !== null && Date.now() >= parentAuthExpiresAt.value) {
applyParentLoggedOutState()
if (typeof window !== 'undefined') {
window.location.href = '/child'
}
}
}
export function startParentExpiryWatcher() {
stopParentExpiryWatcher()
expiryWatcherIntervalId = setInterval(runExpiryCheck, 15_000)
}
export function stopParentExpiryWatcher() {
if (expiryWatcherIntervalId !== null) {
clearInterval(expiryWatcherIntervalId)
expiryWatcherIntervalId = null
}
}
/**
* Explicitly checks whether parent auth has expired and clears it if so.
* Called by the router guard before allowing /parent routes.
@@ -163,10 +164,12 @@ export async function checkAuth() {
currentUserId.value = data.id
isUserLoggedIn.value = true
} else {
logoutUser()
isUserLoggedIn.value = false
currentUserId.value = ''
}
} catch {
logoutUser()
isUserLoggedIn.value = false
currentUserId.value = ''
}
isAuthReady.value = true
}