demo: add impersonation stop button and admin user configuration

This commit is contained in:
Bereket Engida
2025-03-04 14:33:04 +03:00
parent b5177bcfb8
commit c1216a988d
3 changed files with 57 additions and 28 deletions

View File

@@ -36,6 +36,7 @@ import {
QrCode, QrCode,
ShieldCheck, ShieldCheck,
ShieldOff, ShieldOff,
StopCircle,
Trash, Trash,
X, X,
} from "lucide-react"; } from "lucide-react";
@@ -447,33 +448,59 @@ export default function UserCard(props: {
</CardContent> </CardContent>
<CardFooter className="gap-2 justify-between items-center"> <CardFooter className="gap-2 justify-between items-center">
<ChangePassword /> <ChangePassword />
<Button {session?.session.impersonatedBy ? (
className="gap-2 z-10" <Button
variant="secondary" className="gap-2 z-10"
onClick={async () => { variant="secondary"
setIsSignOut(true); onClick={async () => {
await signOut({ setIsSignOut(true);
fetchOptions: { await client.admin.stopImpersonating();
onSuccess() { setIsSignOut(false);
router.push("/"); toast.info("Impersonation stopped successfully");
router.push("/admin");
}}
disabled={isSignOut}
>
<span className="text-sm">
{isSignOut ? (
<Loader2 size={15} className="animate-spin" />
) : (
<div className="flex items-center gap-2">
<StopCircle size={16} color="red" />
Stop Impersonation
</div>
)}
</span>
</Button>
) : (
<Button
className="gap-2 z-10"
variant="secondary"
onClick={async () => {
setIsSignOut(true);
await signOut({
fetchOptions: {
onSuccess() {
router.push("/");
},
}, },
}, });
}); setIsSignOut(false);
setIsSignOut(false); }}
}} disabled={isSignOut}
disabled={isSignOut} >
> <span className="text-sm">
<span className="text-sm"> {isSignOut ? (
{isSignOut ? ( <Loader2 size={15} className="animate-spin" />
<Loader2 size={15} className="animate-spin" /> ) : (
) : ( <div className="flex items-center gap-2">
<div className="flex items-center gap-2"> <LogOut size={16} />
<LogOut size={16} /> Sign Out
Sign Out </div>
</div> )}
)} </span>
</span> </Button>
</Button> )}
</CardFooter> </CardFooter>
</Card> </Card>
); );

View File

@@ -153,7 +153,9 @@ export const auth = betterAuth({
passkey(), passkey(),
openAPI(), openAPI(),
bearer(), bearer(),
admin(), admin({
adminUserIds: ["EXD5zjob2SD6CBWcEQ6OpLRHcyoUbnaB"],
}),
multiSession(), multiSession(),
oAuthProxy(), oAuthProxy(),
nextCookies(), nextCookies(),

View File

@@ -105,7 +105,7 @@ export const admin = <O extends AdminOptions>(options?: O) => {
const session = await getSessionFromCtx(ctx); const session = await getSessionFromCtx(ctx);
if ( if (
(!session?.session || !opts.adminRoles.includes(session.user.role)) && (!session?.session || !opts.adminRoles.includes(session.user.role)) &&
!opts.adminUserIds?.includes(session?.session?.user.id) !opts.adminUserIds?.includes(session?.user.id || "")
) { ) {
throw new APIError("UNAUTHORIZED"); throw new APIError("UNAUTHORIZED");
} }