| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react'
- export interface User {
- id: string
- username: string
- email?: string
- real_name?: string
- roles: string[]
- is_active: boolean
- }
- interface AuthState {
- user: User | null
- token: string | null
- refreshToken: string | null
- isAuthenticated: boolean
- login: (token: string, refreshToken: string, user: User) => void
- logout: () => Promise<void>
- }
- const AuthContext = createContext<AuthState | null>(null)
- export function AuthProvider({ children }: { children: ReactNode }) {
- const [user, setUser] = useState<User | null>(null)
- const [token, setToken] = useState<string | null>(null)
- const [refreshToken, setRefreshToken] = useState<string | null>(null)
- useEffect(() => {
- const stored = localStorage.getItem('token')
- const storedRt = localStorage.getItem('refresh_token')
- const storedUser = localStorage.getItem('user')
- if (stored && storedUser) {
- setToken(stored)
- setRefreshToken(storedRt)
- setUser(JSON.parse(storedUser))
- }
- }, [])
- const login = useCallback((t: string, rt: string, u: User) => {
- setToken(t)
- setRefreshToken(rt)
- setUser(u)
- localStorage.setItem('token', t)
- localStorage.setItem('refresh_token', rt)
- localStorage.setItem('user', JSON.stringify(u))
- }, [])
- const logout = useCallback(async () => {
- const currentToken = localStorage.getItem('token')
- const currentRt = localStorage.getItem('refresh_token')
- if (currentToken && currentRt) {
- try {
- const res = await fetch('/api/v1/auth/logout', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${currentToken}`,
- },
- body: JSON.stringify({ token: currentToken, refresh_token: currentRt }),
- })
- const data = await res.json()
- if (data.data?.sso_logout_url) {
- clearAuth()
- window.location.href = data.data.sso_logout_url
- return
- }
- } catch {
- // ignore network errors during logout
- }
- }
- clearAuth()
- window.location.href = '/login'
- }, [])
- const clearAuth = useCallback(() => {
- setToken(null)
- setRefreshToken(null)
- setUser(null)
- localStorage.removeItem('token')
- localStorage.removeItem('refresh_token')
- localStorage.removeItem('user')
- }, [])
- return (
- <AuthContext.Provider
- value={{ user, token, refreshToken, isAuthenticated: !!token, login, logout }}
- >
- {children}
- </AuthContext.Provider>
- )
- }
- export function useAuth() {
- const ctx = useContext(AuthContext)
- if (!ctx) throw new Error('useAuth must be used inside AuthProvider')
- return ctx
- }
|