70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
import { create } from 'zustand'
|
|
import { persist, createJSONStorage } from 'zustand/middleware'
|
|
import axios from 'axios'
|
|
|
|
interface User {
|
|
id: number
|
|
username: string
|
|
role: string
|
|
gatekeeper_groups?: string[]
|
|
}
|
|
|
|
interface AuthState {
|
|
token: string | null
|
|
user: User | null
|
|
login: (username: string, password: string) => Promise<void>
|
|
logout: () => void
|
|
clearAuth: () => void
|
|
}
|
|
|
|
const API_URL = (import.meta as any).env?.VITE_API_URL || '/api/v1'
|
|
|
|
export const useAuthStore = create<AuthState>()(
|
|
persist(
|
|
(set) => ({
|
|
token: null,
|
|
user: null,
|
|
|
|
async login(username: string, password: string) {
|
|
const formData = new URLSearchParams()
|
|
formData.append('username', username)
|
|
formData.append('password', password)
|
|
|
|
const response = await axios.post(`${API_URL}/auth/login`, formData, {
|
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
})
|
|
|
|
const { access_token, user } = response.data
|
|
set({ token: access_token, user })
|
|
axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`
|
|
console.log('[Auth] Logged in, token:', access_token.substring(0, 30) + '...')
|
|
},
|
|
|
|
logout() {
|
|
console.log('[Auth] Logging out...')
|
|
set({ token: null, user: null })
|
|
delete axios.defaults.headers.common['Authorization']
|
|
},
|
|
|
|
clearAuth() {
|
|
console.log('[Auth] Clearing all auth data...')
|
|
set({ token: null, user: null })
|
|
localStorage.removeItem('auth-storage')
|
|
delete axios.defaults.headers.common['Authorization']
|
|
},
|
|
}),
|
|
{
|
|
name: 'auth-storage',
|
|
storage: createJSONStorage(() => localStorage),
|
|
}
|
|
)
|
|
)
|
|
|
|
axios.interceptors.request.use((config) => {
|
|
const token = useAuthStore.getState().token
|
|
if (token) {
|
|
config.headers.Authorization = `Bearer ${token}`
|
|
}
|
|
return config
|
|
})
|