Новый сервис pcp-tgu-ui-service: ТГУ-фронт на headless-auth nstart + платформенный CI/деплой
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user