Fix impersonation: hard navigation + stop impersonating banner

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-25 13:12:47 +05:00
parent 808bcadfca
commit dd198349fb
3 changed files with 46 additions and 3 deletions
+4
View File
@@ -4,6 +4,7 @@ import { redirect } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
import { LogoutButton } from "@/components/layout/logout-button"; import { LogoutButton } from "@/components/layout/logout-button";
import { getSetting } from "@/lib/settings"; import { getSetting } from "@/lib/settings";
import { StopImpersonateBanner } from "@/components/admin/stop-impersonate-banner";
export default async function StudentLayout({ children }: { children: React.ReactNode }) { export default async function StudentLayout({ children }: { children: React.ReactNode }) {
const session = await auth.api.getSession({ headers: await headers() }); const session = await auth.api.getSession({ headers: await headers() });
@@ -15,8 +16,11 @@ export default async function StudentLayout({ children }: { children: React.Reac
if (maintenance === "true") redirect("/maintenance"); if (maintenance === "true") redirect("/maintenance");
} }
const isImpersonating = !!(session.session as { impersonatedBy?: string }).impersonatedBy;
return ( return (
<div className="min-h-screen flex flex-col" style={{ backgroundColor: "var(--background)" }}> <div className="min-h-screen flex flex-col" style={{ backgroundColor: "var(--background)" }}>
{isImpersonating && <StopImpersonateBanner userName={session.user.name} />}
<header <header
className="sticky top-0 z-10 flex items-center justify-between px-6 py-3" className="sticky top-0 z-10 flex items-center justify-between px-6 py-3"
style={{ borderBottom: "2px solid var(--border)", backgroundColor: "var(--background)" }} style={{ borderBottom: "2px solid var(--border)", backgroundColor: "var(--background)" }}
@@ -0,0 +1,40 @@
"use client";
import { useState } from "react";
import { authClient } from "@/lib/auth-client";
export function StopImpersonateBanner({ userName }: { userName: string }) {
const [loading, setLoading] = useState(false);
async function handleStop() {
setLoading(true);
try {
await authClient.admin.stopImpersonating();
window.location.href = "/admin/users";
} catch {
setLoading(false);
}
}
return (
<div
className="flex items-center justify-between px-6 py-2 text-sm"
style={{
backgroundColor: "var(--color-highlight)",
borderBottom: "2px solid var(--foreground)",
}}
>
<span>
Вы просматриваете платформу как <strong>{userName}</strong>
</span>
<button
type="button"
onClick={handleStop}
disabled={loading}
className="btn-aubade text-xs px-3 py-1"
>
{loading ? "..." : "← Вернуться в админку"}
</button>
</div>
);
}
+2 -3
View File
@@ -100,9 +100,8 @@ function ImpersonateButton({ userId }: { userId: string }) {
setLoading(true); setLoading(true);
try { try {
await authClient.admin.impersonateUser({ userId }); await authClient.admin.impersonateUser({ userId });
router.push("/dashboard"); window.location.href = "/dashboard";
router.refresh(); } catch {
} finally {
setLoading(false); setLoading(false);
} }
} }