ファイル
btrc-hub/frontend/src/lib/users.ts
T
2026-10-20 20:44:14 +09:00

72 行
1.6 KiB
TypeScript

import { apiGet, apiPost, isApiError } from '@/lib/api'
import type { User, UserRole } from '@/types'
const CONTENT_EDITOR_ROLES: readonly UserRole[] = ['admin', 'member']
let pendingSession: Promise<User> | null = null
const storedUserCode = (): string | null => {
try
{
return localStorage.getItem ('user_code')
}
catch
{
return null
}
}
export const rememberUserCode = (code: string): void => {
try
{
localStorage.setItem ('user_code', code)
}
catch
{
// A missing recovery copy must not invalidate the authenticated Cookie.
}
}
const restoreUserSession = async (): Promise<User> => {
try
{
return await apiGet<User> ('/users/me')
}
catch (error)
{
if (!isApiError (error) || error.response?.status !== 401)
throw error
}
const code = storedUserCode ()
if (code)
{
const data = await apiPost<{ valid: boolean; user: User }> (
'/users/verify', { code, restore: true })
if (data.valid)
return data.user
}
const data = await apiPost<{ code: string; user: User }> ('/users')
return data.user
}
export const initialiseUserSession = (): Promise<User> => {
if (typeof window === 'undefined')
throw new Error ('Browser session initialisation is client-only')
pendingSession ??= restoreUserSession ().then (user => {
rememberUserCode (user.inheritanceCode)
return user
}).finally (() => {
pendingSession = null
})
return pendingSession
}
export const canEditContent = (
user: Pick<User, 'role'> | null | undefined): boolean => user != null && CONTENT_EDITOR_ROLES.includes (user.role)