fix and update

This commit is contained in:
lendry
2026-07-01 15:52:17 +03:00
parent de4310239c
commit f7c01a3963
8 changed files with 152 additions and 25 deletions

View File

@@ -9,12 +9,12 @@ import { AppToastProvider } from '@/components/id/toast-provider';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<AppToastProvider>
<AuthProvider>
<PublicSettingsProvider>
<PublicSettingsProvider>
<AuthProvider>
<ProjectHead />
<RealtimeProvider>{children}</RealtimeProvider>
</PublicSettingsProvider>
</AuthProvider>
</AuthProvider>
</PublicSettingsProvider>
</AppToastProvider>
);
}

View File

@@ -29,11 +29,14 @@ import {
resetGatewayCircuit,
resetPinRequiredNotification,
scheduleFedcmSessionSync,
syncFedcmSession,
setPinRequiredHandler,
subscribeApiReady,
subscribeApiNotReady,
} from '@/lib/api';
import { finalizeFedcmLogin, shouldFinalizeFedcmLogin } from '@/lib/fedcm-login-bridge';
import { FedcmApiLoginStatusBridge } from './fedcm-api-login-status';
import { usePublicSettings } from './public-settings-provider';
import { useToast } from './toast-provider';
import { PinLockModal } from './pin-lock-modal';
import { AppBootstrapScreen } from './app-bootstrap-screen';
@@ -123,6 +126,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const { showToast } = useToast();
const { publicApiUrl } = usePublicSettings();
const initialAuth = React.useMemo(() => readInitialAuthState(), []);
const [token, setToken] = React.useState<string | null>(initialAuth.token);
const [user, setUser] = React.useState<PublicUser | null>(null);
@@ -258,6 +262,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
if (typeof window !== 'undefined' && shouldFinalizeFedcmLogin(window.location.pathname)) {
void finalizeFedcmLogin(auth.accessToken);
} else {
void syncFedcmSession(auth.accessToken);
scheduleFedcmSessionSync(auth.accessToken, 8000);
}
}
@@ -751,6 +756,11 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
children
)}
<PinLockModal open={isPinLocked} isSubmitting={pinSubmitting} error={pinError} onSubmit={handlePinUnlock} />
<FedcmApiLoginStatusBridge
active={isSessionReady && hasStoredSession && !isPinLocked}
accessToken={token}
publicApiUrl={publicApiUrl}
/>
</AuthContext.Provider>
);
}

View File

@@ -0,0 +1,39 @@
'use client';
import { useEffect } from 'react';
import { syncFedcmSession } from '@/lib/api';
import { DEFAULT_PUBLIC_API_URL } from '@/lib/project-domains';
/** Синхронизирует FedCM cookie и Login Status API на origin API-домена (login_url). */
export function FedcmApiLoginStatusBridge({
active,
accessToken,
publicApiUrl = DEFAULT_PUBLIC_API_URL
}: {
active: boolean;
accessToken?: string | null;
publicApiUrl?: string;
}) {
useEffect(() => {
if (!active || !accessToken) return;
void syncFedcmSession(accessToken);
}, [accessToken, active]);
useEffect(() => {
if (!active) return;
const apiBase = publicApiUrl.replace(/\/+$/, '');
if (!apiBase) return;
const iframe = document.createElement('iframe');
iframe.hidden = true;
iframe.title = 'FedCM login status';
iframe.src = `${apiBase}/fedcm/login-status`;
document.body.appendChild(iframe);
return () => {
iframe.remove();
};
}, [active, publicApiUrl]);
return null;
}

View File

@@ -2,10 +2,13 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { apiFetch } from '@/lib/api';
import { DEFAULT_PUBLIC_API_URL, DEFAULT_PUBLIC_FRONTEND_URL, inferApiBaseFromProjectDomain } from '@/lib/project-domains';
interface PublicSettingsContextValue {
projectName: string;
projectTagline: string;
publicApiUrl: string;
publicFrontendUrl: string;
ldapEnabled: boolean;
ldapUseLdaps: boolean;
isLoading: boolean;
@@ -15,6 +18,8 @@ interface PublicSettingsContextValue {
const PublicSettingsContext = createContext<PublicSettingsContextValue>({
projectName: 'MVK ID',
projectTagline: 'Единый аккаунт для сервисов Lendry',
publicApiUrl: DEFAULT_PUBLIC_API_URL,
publicFrontendUrl: DEFAULT_PUBLIC_FRONTEND_URL,
ldapEnabled: false,
ldapUseLdaps: false,
isLoading: true,
@@ -41,17 +46,29 @@ export function PublicSettingsProvider({ children }: { children: React.ReactNode
void refreshPublicSettings();
}, [refreshPublicSettings]);
const value = useMemo(
() => ({
const value = useMemo(() => {
const projectDomain = settings.PROJECT_DOMAIN?.trim();
const inferredApi = projectDomain ? inferApiBaseFromProjectDomain(projectDomain) : null;
const publicApiUrl = settings.PUBLIC_API_URL?.trim() || inferredApi || DEFAULT_PUBLIC_API_URL;
const publicFrontendUrl =
settings.PUBLIC_FRONTEND_URL?.trim() ||
(projectDomain
? projectDomain.startsWith('http')
? projectDomain.replace(/\/+$/, '')
: `https://${projectDomain.replace(/^\/+/, '')}`
: DEFAULT_PUBLIC_FRONTEND_URL);
return {
projectName: settings.PROJECT_NAME || 'MVK ID',
projectTagline: settings.PROJECT_TAGLINE || 'Единый аккаунт для сервисов Lendry',
publicApiUrl: publicApiUrl.replace(/\/+$/, ''),
publicFrontendUrl: publicFrontendUrl.replace(/\/+$/, ''),
ldapEnabled: ['true', '1', 'yes'].includes((settings.LDAP_ENABLED ?? '').trim().toLowerCase()),
ldapUseLdaps: ['true', '1', 'yes'].includes((settings.LDAP_USE_LDAPS ?? '').trim().toLowerCase()),
isLoading,
refreshPublicSettings
}),
[isLoading, refreshPublicSettings, settings.LDAP_ENABLED, settings.LDAP_USE_LDAPS, settings.PROJECT_NAME, settings.PROJECT_TAGLINE]
);
};
}, [isLoading, refreshPublicSettings, settings]);
return <PublicSettingsContext.Provider value={value}>{children}</PublicSettingsContext.Provider>;
}