56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import { create } from 'zustand'
|
|
import { persist } from 'zustand/middleware'
|
|
import type { AdminUser, TokenGrant } from '@/api/types'
|
|
|
|
interface AuthState {
|
|
accessToken: string | null
|
|
refreshToken: string | null
|
|
user: AdminUser | null
|
|
roles: string[]
|
|
permissions: string[]
|
|
setTokens: (grant: TokenGrant) => void
|
|
setSession: (user: AdminUser, roles: string[], permissions: string[]) => void
|
|
clear: () => void
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>()(
|
|
persist(
|
|
(set) => ({
|
|
accessToken: null,
|
|
refreshToken: null,
|
|
user: null,
|
|
roles: [],
|
|
permissions: [],
|
|
setTokens: (grant) =>
|
|
set({
|
|
accessToken: grant.access_token,
|
|
refreshToken: grant.refresh_token ?? null,
|
|
}),
|
|
setSession: (user, roles, permissions) => set({ user, roles, permissions }),
|
|
clear: () =>
|
|
set({ accessToken: null, refreshToken: null, user: null, roles: [], permissions: [] }),
|
|
}),
|
|
{ name: 'gig-admin-auth' },
|
|
),
|
|
)
|
|
|
|
export function hasRole(role: string): boolean {
|
|
return useAuthStore.getState().roles.includes(role)
|
|
}
|
|
|
|
/** super-admin implicitly passes every permission check (mirrors backend seeding). */
|
|
export function can(permission: string): boolean {
|
|
const { roles, permissions } = useAuthStore.getState()
|
|
return roles.includes('super-admin') || permissions.includes(permission)
|
|
}
|
|
|
|
export function useCan(permission: string): boolean {
|
|
const roles = useAuthStore((s) => s.roles)
|
|
const permissions = useAuthStore((s) => s.permissions)
|
|
return roles.includes('super-admin') || permissions.includes(permission)
|
|
}
|
|
|
|
export function isAuthenticated(): boolean {
|
|
return Boolean(useAuthStore.getState().accessToken)
|
|
}
|