import { defineStore } from 'pinia' import { AUTH_TOKEN_KEY, api } from '../lib/api' import { ApiRequestError } from '../lib/http' import type { AuthSession, ChangePasswordPayload, DemoLoginPayload, LoginPayload, TeamLoginPayload, TwitchAuthorizePayload, } from '../types/awards' const adminAccessRoles = new Set(['member', 'reviewer', 'organization_team', 'content_admin', 'admin', 'owner', 'creator']) const contentManageRoles = new Set(['content_admin', 'admin', 'owner', 'creator']) const adminWorkspaceRoles = new Set(['admin', 'owner', 'creator']) const adminWorkspacePermissions = new Set([ 'dashboard', 'years', 'nominations', 'categories', 'candidates', 'clips', 'risk', 'audit', 'analytics', 'winners', ]) function readStoredToken() { if (typeof window === 'undefined') return null return window.localStorage.getItem(AUTH_TOKEN_KEY) } function writeStoredToken(token: string | null) { if (typeof window === 'undefined') return if (token) { window.localStorage.setItem(AUTH_TOKEN_KEY, token) } else { window.localStorage.removeItem(AUTH_TOKEN_KEY) } } export const useAuthStore = defineStore('auth', { state: () => ({ session: null as AuthSession | null, hydrated: false, loading: false, }), getters: { isLoggedIn: (state) => Boolean(state.session), isAdmin: (state) => adminAccessRoles.has(state.session?.role ?? ''), canAccessAdmin: (state) => adminAccessRoles.has(state.session?.role ?? ''), canManageContent: (state) => contentManageRoles.has(state.session?.role ?? '') || (state.session?.permissionKeys ?? []).includes('content'), canManageAdminWorkspace: (state) => adminWorkspaceRoles.has(state.session?.role ?? '') || (state.session?.permissionKeys ?? []).some((key) => adminWorkspacePermissions.has(key)), canManageOperationalSettings: (state) => state.session?.role === 'owner' || state.session?.role === 'creator', canManageTeam: (state) => (state.session?.permissionKeys ?? []).includes('team'), hasPermission: (state) => (permissionKey: string) => (state.session?.permissionKeys ?? []).includes(permissionKey), isOwner: (state) => state.session?.role === 'owner', isCreator: (state) => state.session?.role === 'creator', isOwnerOrCreator: (state) => state.session?.role === 'owner' || state.session?.role === 'creator', isTeamSession: (state) => Boolean(state.session?.teamLogin), }, actions: { clearSession() { this.session = null writeStoredToken(null) }, async hydrate() { if (!readStoredToken()) { this.session = null this.hydrated = true return } try { this.session = await api.getSession() } catch (error) { if (error instanceof ApiRequestError && (error.status === 401 || error.status === 403)) { this.clearSession() } } finally { this.hydrated = true } }, async login(payload: LoginPayload) { this.loading = true try { const session = await api.login(payload) this.session = session writeStoredToken(session.sessionToken) } finally { this.loading = false } }, async demoLogin(payload: DemoLoginPayload) { this.loading = true try { const session = await api.demoLogin(payload) this.session = session writeStoredToken(session.sessionToken) } finally { this.loading = false } }, async teamLogin(payload: TeamLoginPayload) { this.loading = true try { const session = await api.teamLogin(payload) this.session = session writeStoredToken(session.sessionToken) } finally { this.loading = false } }, async changePassword(payload: ChangePasswordPayload) { this.loading = true try { const session = await api.changePassword(payload) this.session = session writeStoredToken(session.sessionToken) } finally { this.loading = false } }, async startTwitchAuthorization(payload: Omit) { this.loading = true try { const response = await api.startTwitchAuthorization({ ...payload, frontendOrigin: window.location.origin, }) window.location.assign(response.authorizationUrl) } finally { this.loading = false } }, async disconnectTwitchBinding() { this.loading = true try { const response = await api.disconnectTwitchBinding() this.session = response.session writeStoredToken(response.session?.sessionToken ?? null) return response } finally { this.loading = false } }, async completeOAuthSession(sessionToken: string) { this.loading = true try { writeStoredToken(sessionToken) this.session = await api.getSession() this.hydrated = true } catch (error) { writeStoredToken(null) this.session = null throw error } finally { this.loading = false } }, async logout() { this.loading = true try { await api.logout() } finally { this.clearSession() this.loading = false } }, async deleteMyData() { this.loading = true try { const result = await api.deleteMyData() this.clearSession() return result } finally { this.loading = false } }, }, }) export type AuthStore = ReturnType