auth querying consolidation

This commit is contained in:
Michael Freno
2026-01-06 23:26:51 -05:00
parent 08a9ad35af
commit 445ab6d7de
10 changed files with 224 additions and 91 deletions

81
src/lib/auth-query.ts Normal file
View File

@@ -0,0 +1,81 @@
/**
* Shared Auth Query
* Single source of truth for authentication state across the app
*
* Security Model:
* - Server query reads from httpOnly cookies (secure)
* - Client context syncs from this query (UI convenience)
* - Server endpoints always validate independently (never trust client)
*/
import { query, revalidate as revalidateKey } from "@solidjs/router";
import { getRequestEvent } from "solid-js/web";
export interface UserState {
isAuthenticated: boolean;
userId: string | null;
email: string | null;
displayName: string | null;
emailVerified: boolean;
privilegeLevel: "admin" | "user" | "anonymous";
}
/**
* Global auth state query - single source of truth
* Called on server during SSR, cached by SolidStart router
*/
export const getUserState = query(async (): Promise<UserState> => {
"use server";
const { getPrivilegeLevel, getUserID, ConnectionFactory } =
await import("~/server/utils");
const event = getRequestEvent()!;
const privilegeLevel = await getPrivilegeLevel(event.nativeEvent);
const userId = await getUserID(event.nativeEvent);
if (!userId) {
return {
isAuthenticated: false,
userId: null,
email: null,
displayName: null,
emailVerified: false,
privilegeLevel: "anonymous"
};
}
const conn = ConnectionFactory();
const res = await conn.execute({
sql: "SELECT email, display_name, email_verified FROM User WHERE id = ?",
args: [userId]
});
if (res.rows.length === 0) {
return {
isAuthenticated: false,
userId: null,
email: null,
displayName: null,
emailVerified: false,
privilegeLevel: "anonymous"
};
}
const user = res.rows[0] as any;
return {
isAuthenticated: true,
userId,
email: user.email ?? null,
displayName: user.display_name ?? null,
emailVerified: user.email_verified === 1,
privilegeLevel
};
}, "global-auth-state");
/**
* Revalidate auth state globally
* Call this after login, logout, token refresh, email verification
*/
export function revalidateAuth() {
revalidateKey(getUserState.key);
}

View File

@@ -6,6 +6,7 @@
import { api } from "~/lib/api";
import { getClientCookie } from "~/lib/cookies.client";
import { getTimeUntilExpiry } from "~/lib/client-utils";
import { revalidateAuth } from "~/lib/auth-query";
class TokenRefreshManager {
private refreshTimer: ReturnType<typeof setTimeout> | null = null;
@@ -108,6 +109,7 @@ class TokenRefreshManager {
if (result.success) {
console.log("[Token Refresh] Token refreshed successfully");
revalidateAuth(); // Refresh auth state after token refresh
this.scheduleNextRefresh(); // Schedule next refresh
return true;
} else {