Files
gig-admin/src/auth/store.ts

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)
}