Files

75 lines
2.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createAppAuth, type DefaultAuthUser } from '@nstart/auth'
import { createContext, type ReactNode, useContext, useEffect } from 'react'
import { setApiAuthToken } from '../api/apiFetch'
import { env } from '../config/env'
export type AppUser = DefaultAuthUser
// Состояние, совместимое с AuthState из @nstart/auth (headless-ядро). Используем
// ТОЛЬКО headless-слой пакета: createAppAuth/useAppAuth дают токен, login, logout,
// loading и коды ошибок — без единого компонента @nstart/ui (их UI: ProfilePage/
// UserPanel — намеренно не подключаем).
interface AppAuthState {
user: AppUser | null
token: string | null
loading: boolean
errorCode: 'notAuthenticated' | 'initFailed' | null
errorDetails: string | null
login: () => void
logout: () => void
}
// Anonymous-режим: фейковый контекст, чтобы useAppAuth() работал везде в коде
// без условий. Токен null → apiFetch не добавляет Authorization, поведение как у
// исходного сервиса (открывается сразу, без Keycloak).
const ANONYMOUS_STATE: AppAuthState = {
user: null,
token: null,
loading: false,
errorCode: null,
errorDetails: null,
login: () => undefined,
logout: () => undefined,
}
const AnonymousAuthContext = createContext<AppAuthState>(ANONYMOUS_STATE)
function AnonymousAuthProvider({ children }: { children: ReactNode }) {
return (
<AnonymousAuthContext.Provider value={ANONYMOUS_STATE}>
{children}
</AnonymousAuthContext.Provider>
)
}
function useAnonymousAuth(): AppAuthState {
return useContext(AnonymousAuthContext)
}
const newStartIdAuth = createAppAuth({
url: env.newStartIdUrl,
realm: env.newStartIdRealm,
clientId: env.newStartIdClientId,
loginMode: 'redirect',
})
export const { AppAuthProvider, useAppAuth } =
env.authMode === 'new-start-id'
? newStartIdAuth
: { AppAuthProvider: AnonymousAuthProvider, useAppAuth: useAnonymousAuth }
/**
* Прокидывает токен из useAppAuth() в сетевой слой (держатель apiFetch). Ничего
* не рендерит; монтируется внутри AppAuthProvider. В режиме anonymous token === null,
* поэтому заголовок Authorization не выставляется и поведение запросов не меняется.
*
* @returns Ничего не отображает (null).
*/
export function AuthTokenBridge(): null {
const { token } = useAppAuth()
useEffect(() => {
setApiAuthToken(token ?? null)
}, [token])
return null
}