fix: resolve frontend build errors and enable credentials for options requests in backend
This commit is contained in:
@@ -1,109 +1,108 @@
|
||||
1|'use client'
|
||||
2|
|
||||
3|import React, { createContext, useContext, useEffect, useState, useCallback } from 'react'
|
||||
4|import { useRouter } from 'next/navigation'
|
||||
5|import apiRequest from '@/lib/api/client'
|
||||
6|import LoadingOverlay from '@/components/LoadingOverlay'
|
||||
7|import { logoutAction, getSessionAction } from '@/app/actions/auth'
|
||||
8|
|
||||
9|interface User {
|
||||
10| id: string
|
||||
11| email: string
|
||||
12| totp_enabled: boolean
|
||||
13|}
|
||||
14|
|
||||
15|interface AuthContextType {
|
||||
16| user: User | null
|
||||
17| loading: boolean
|
||||
18| login: (user: User) => void
|
||||
19| logout: () => void
|
||||
20| refresh: () => Promise<void>
|
||||
21| refreshSession: () => Promise<void>
|
||||
22|}
|
||||
23|
|
||||
24|const AuthContext = createContext<AuthContextType>({
|
||||
25| user: null,
|
||||
26| loading: true,
|
||||
27| login: () => {},
|
||||
28| logout: () => {},
|
||||
29| refresh: async () => {},
|
||||
30| refreshSession: async () => {},
|
||||
31|})
|
||||
32|
|
||||
33|export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
34| const [user, setUser] = useState<User | null>(null)
|
||||
35| const [loading, setLoading] = useState(true)
|
||||
36| const [isLoggingOut, setIsLoggingOut] = useState(false)
|
||||
37| const router = useRouter()
|
||||
38|
|
||||
39| const login = (userData: User) => {
|
||||
40| // * We still store user profile in localStorage for optimistic UI, but NOT the token
|
||||
41| localStorage.setItem('user', JSON.stringify(userData))
|
||||
42| setUser(userData)
|
||||
43| router.refresh()
|
||||
44| }
|
||||
45|
|
||||
46| const logout = useCallback(async () => {
|
||||
47| setIsLoggingOut(true)
|
||||
48| await logoutAction()
|
||||
49| localStorage.removeItem('user')
|
||||
50| // * Clear legacy tokens if they exist
|
||||
51| localStorage.removeItem('token')
|
||||
52| localStorage.removeItem('refreshToken')
|
||||
53|
|
||||
54| setTimeout(() => {
|
||||
55| window.location.href = '/'
|
||||
56| }, 500)
|
||||
57| }, [])
|
||||
58|
|
||||
59| const refresh = useCallback(async () => {
|
||||
60| try {
|
||||
61| const userData = await apiRequest<User>('/auth/user/me')
|
||||
62| setUser(userData)
|
||||
63| localStorage.setItem('user', JSON.stringify(userData))
|
||||
64| } catch (e) {
|
||||
65| console.error('Failed to refresh user data', e)
|
||||
66| }
|
||||
67| router.refresh()
|
||||
68| }, [router])
|
||||
69|
|
||||
70| const refreshSession = useCallback(async () => {
|
||||
71| await refresh()
|
||||
72| }, [refresh])
|
||||
73|
|
||||
74| // Initial load
|
||||
75| useEffect(() => {
|
||||
76| const init = async () => {
|
||||
77| // * 1. Check server-side session (cookies)
|
||||
78| const session = await getSessionAction()
|
||||
79|
|
||||
80| if (session) {
|
||||
81| setUser(session)
|
||||
82| localStorage.setItem('user', JSON.stringify(session))
|
||||
83| } else {
|
||||
84| // * Session invalid/expired
|
||||
85| localStorage.removeItem('user')
|
||||
86| setUser(null)
|
||||
87| }
|
||||
88|
|
||||
89| // * Clear legacy tokens if they exist (migration)
|
||||
90| if (localStorage.getItem('token')) {
|
||||
91| localStorage.removeItem('token')
|
||||
92| localStorage.removeItem('refreshToken')
|
||||
93| }
|
||||
94|
|
||||
95| setLoading(false)
|
||||
96| }
|
||||
97| init()
|
||||
98| }, [])
|
||||
99|
|
||||
100| return (
|
||||
101| <AuthContext.Provider value={{ user, loading, login, logout, refresh, refreshSession }}>
|
||||
102| {isLoggingOut && <LoadingOverlay logoSrc="/ciphera_icon_no_margins.png" title="Ciphera Analytics" />}
|
||||
103| {children}
|
||||
104| </AuthContext.Provider>
|
||||
105| )
|
||||
106|}
|
||||
107|
|
||||
108|export const useAuth = () => useContext(AuthContext)
|
||||
109|
|
||||
'use client'
|
||||
|
||||
import React, { createContext, useContext, useEffect, useState, useCallback } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import apiRequest from '@/lib/api/client'
|
||||
import LoadingOverlay from '@/components/LoadingOverlay'
|
||||
import { logoutAction, getSessionAction } from '@/app/actions/auth'
|
||||
|
||||
interface User {
|
||||
id: string
|
||||
email: string
|
||||
totp_enabled: boolean
|
||||
}
|
||||
|
||||
interface AuthContextType {
|
||||
user: User | null
|
||||
loading: boolean
|
||||
login: (user: User) => void
|
||||
logout: () => void
|
||||
refresh: () => Promise<void>
|
||||
refreshSession: () => Promise<void>
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType>({
|
||||
user: null,
|
||||
loading: true,
|
||||
login: () => {},
|
||||
logout: () => {},
|
||||
refresh: async () => {},
|
||||
refreshSession: async () => {},
|
||||
})
|
||||
|
||||
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [isLoggingOut, setIsLoggingOut] = useState(false)
|
||||
const router = useRouter()
|
||||
|
||||
const login = (userData: User) => {
|
||||
// * We still store user profile in localStorage for optimistic UI, but NOT the token
|
||||
localStorage.setItem('user', JSON.stringify(userData))
|
||||
setUser(userData)
|
||||
router.refresh()
|
||||
}
|
||||
|
||||
const logout = useCallback(async () => {
|
||||
setIsLoggingOut(true)
|
||||
await logoutAction()
|
||||
localStorage.removeItem('user')
|
||||
// * Clear legacy tokens if they exist
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refreshToken')
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = '/'
|
||||
}, 500)
|
||||
}, [])
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
try {
|
||||
const userData = await apiRequest<User>('/auth/user/me')
|
||||
setUser(userData)
|
||||
localStorage.setItem('user', JSON.stringify(userData))
|
||||
} catch (e) {
|
||||
console.error('Failed to refresh user data', e)
|
||||
}
|
||||
router.refresh()
|
||||
}, [router])
|
||||
|
||||
const refreshSession = useCallback(async () => {
|
||||
await refresh()
|
||||
}, [refresh])
|
||||
|
||||
// Initial load
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
// * 1. Check server-side session (cookies)
|
||||
const session = await getSessionAction()
|
||||
|
||||
if (session) {
|
||||
setUser(session)
|
||||
localStorage.setItem('user', JSON.stringify(session))
|
||||
} else {
|
||||
// * Session invalid/expired
|
||||
localStorage.removeItem('user')
|
||||
setUser(null)
|
||||
}
|
||||
|
||||
// * Clear legacy tokens if they exist (migration)
|
||||
if (localStorage.getItem('token')) {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('refreshToken')
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
}
|
||||
init()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, loading, login, logout, refresh, refreshSession }}>
|
||||
{isLoggingOut && <LoadingOverlay logoSrc="/ciphera_icon_no_margins.png" title="Ciphera Analytics" />}
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useAuth = () => useContext(AuthContext)
|
||||
|
||||
Reference in New Issue
Block a user