Files
SRCmail/app/(main)/[locale]/layout.tsx
T
shukiv 246df49c03 fix(impersonation): reconcile stale persisted account chip after handoff
After a master-user impersonation handoff (GET /api/auth/impersonate) the server
swaps the slot-0 session cookie but the client's persisted account registry
(account-registry / auth-storage in localStorage) still lists the previous
account, so the top-left account chip keeps showing the old mailbox until a
manual sign-out. Redirect impersonation to /?impersonated=1 and add a headless
ImpersonationReconciler that drops the stale persisted account/auth state (and
server-derived caches) then reloads to a clean URL, so the app rehydrates empty
and re-derives the single account from the fresh session. Cookies untouched, so
the just-granted session survives. Runs exactly once.

Reported downstream: shukiv/jabali-panel#646.
2026-07-27 05:20:53 +03:00

57 lines
2.1 KiB
TypeScript

import { notFound } from "next/navigation";
import { IntlProvider } from "@/components/providers/intl-provider";
import { ThemeProvider } from "@/components/providers/theme-provider";
import { CalendarAlertProvider } from "@/components/providers/calendar-alert-provider";
import { EmbeddedBridgeProvider } from "@/components/providers/embedded-bridge-provider";
import { RateLimitToastProvider } from "@/components/providers/rate-limit-toast-provider";
import { TourProvider } from "@/components/tour/tour-provider";
import { ProtocolLaunchHandlerProvider } from "@/components/protocol/protocol-launch-handler-provider";
import { ProInterfaceRedirect } from "@/components/pro/pro-interface-redirect";
import { ImpersonationReconciler } from "@/components/impersonation/impersonation-reconciler";
import { PluginDialogHost } from "@/components/plugins/plugin-dialog-host";
import { PluginConsentDialog } from "@/components/plugins/plugin-consent-dialog";
import { PWAInstallPrompt } from "@/components/pwa-install-prompt";
import { locales } from "@/i18n/routing";
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
if (!(locales as readonly string[]).includes(locale)) notFound();
let messages;
try {
messages = (await import(`@/locales/${locale}/common.json`)).default;
} catch {
notFound();
}
return (
<IntlProvider locale={locale} messages={messages}>
<ThemeProvider>
<CalendarAlertProvider>
<RateLimitToastProvider>
<EmbeddedBridgeProvider>
<TourProvider>
<ProtocolLaunchHandlerProvider>
<ProInterfaceRedirect />
<ImpersonationReconciler />
{children}
<PluginDialogHost />
<PluginConsentDialog />
<PWAInstallPrompt />
</ProtocolLaunchHandlerProvider>
</TourProvider>
</EmbeddedBridgeProvider>
</RateLimitToastProvider>
</CalendarAlertProvider>
</ThemeProvider>
</IntlProvider>
);
}