feat: Add admin redirect and refactor authentication layout and components

This commit is contained in:
wood chen 2025-02-21 22:28:02 +08:00
parent 01ce107b70
commit 1050a8f6af
6 changed files with 74 additions and 82 deletions

View File

@ -1,6 +0,0 @@
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Auth Q58论坛",
description: "Sign in to your account",
};

View File

@ -1,11 +1,20 @@
"use client"; import { Suspense } from "react";
import { Metadata } from "next";
import Link from "next/link"; import Link from "next/link";
import { MessageCircleCode } from "lucide-react"; import { MessageCircleCode } from "lucide-react";
import { UserAuthForm } from "@/components/auth/user-auth-form"; import { UserAuthorize } from "@/components/auth/user-authorize";
export default function AuthPage() { type Props = {
searchParams: { [key: string]: string | string[] | undefined };
};
export const metadata: Metadata = {
title: `Auth  Q58论坛`,
description: "Sign in to your account",
};
export default function AuthPage({ searchParams }: Props) {
return ( return (
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]"> <div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="flex flex-col space-y-2 text-center"> <div className="flex flex-col space-y-2 text-center">
@ -15,7 +24,11 @@ export default function AuthPage() {
<span style={{ fontFamily: "Bahamas Bold" }}>Q58论坛</span> <span style={{ fontFamily: "Bahamas Bold" }}>Q58论坛</span>
</div> </div>
</div> </div>
<UserAuthForm /> <div>
<Suspense>
<UserAuthorize data={searchParams} />
</Suspense>
</div>
<p className="px-8 text-center text-sm text-muted-foreground"> <p className="px-8 text-center text-sm text-muted-foreground">
By clicking continue, you agree to our{" "} By clicking continue, you agree to our{" "}
<Link <Link

View File

@ -10,6 +10,7 @@ export default async function AuthLayout({
const user = await getCurrentUser(); const user = await getCurrentUser();
if (user) { if (user) {
if (user.role === "ADMIN") redirect("/admin");
redirect("/dashboard"); redirect("/dashboard");
} }

View File

@ -1,6 +0,0 @@
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Login",
description: "Login to your account",
};

View File

@ -8,6 +8,10 @@ import { cn } from "@/lib/utils";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { buttonVariants } from "@/components/ui/button"; import { buttonVariants } from "@/components/ui/button";
interface DiscourseData {
sso_url: string;
}
export function UserAuthForm({ export function UserAuthForm({
className, className,
...props ...props
@ -16,39 +20,32 @@ export function UserAuthForm({
const router = useRouter(); const router = useRouter();
const { toast } = useToast(); const { toast } = useToast();
async function handleSignIn() { const signIn = () => {
try { React.startTransition(async () => {
setIsLoading(true); const response = await fetch("/api/auth/q58", { method: "POST" });
const response = await fetch("/api/auth/q58", { if (!response.ok || response.status !== 200) {
method: "POST", setIsLoading(false);
headers: { toast({
"Content-Type": "application/json", variant: "destructive",
}, title: "内部服务异常",
}); description: response.statusText,
});
if (!response.ok) { } else {
throw new Error("登录请求失败"); let data: DiscourseData = await response.json();
router.push(data.sso_url);
} }
});
const data = await response.json(); };
window.location.href = data.sso_url;
} catch (error) {
console.error("登录错误:", error);
toast({
title: "登录失败",
description: "登录过程中发生错误,请稍后重试",
variant: "destructive",
});
setIsLoading(false);
}
}
return ( return (
<div className={cn("grid gap-3", className)} {...props}> <div className={cn("grid gap-3", className)} {...props}>
<button <button
type="button" type="button"
className={cn(buttonVariants({ variant: "outline" }))} className={cn(buttonVariants({ variant: "outline" }))}
onClick={handleSignIn} onClick={() => {
setIsLoading(true);
signIn();
}}
disabled={isLoading} disabled={isLoading}
> >
{isLoading ? ( {isLoading ? (

View File

@ -23,57 +23,50 @@ export function UserAuthorize({
} }
setIsLoading(true); setIsLoading(true);
try { try {
await signIn(data); await signIn({ ...data, redirectTo: "/dashboard" });
setIsLoading(false); setIsLoading(false);
} catch (error) { } catch (error) {
console.error("登录过程出错:", error);
setError(error); setError(error);
setIsLoading(false); setIsLoading(false);
} }
}, [data, isLoading]); }, []);
useEffect(() => { useEffect(() => {
const timer = setTimeout(signInCallback, 5); const timer = setTimeout(signInCallback, 5);
return () => { return () => {
clearTimeout(timer); clearTimeout(timer);
}; };
}, [signInCallback]); }, []);
if (error) {
return (
<Card className="w-full">
<CardHeader className="space-y-4 text-center">
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-red-100">
<div className="h-8 w-8 text-red-600"></div>
</div>
<CardTitle className="text-2xl font-semibold text-red-600">
</CardTitle>
</CardHeader>
<CardContent>
<p className="text-center text-gray-500">
{error instanceof Error
? error.message
: "登录异常,授权失败!请稍后重试。"}
</p>
</CardContent>
</Card>
);
}
return ( return (
<Card className="w-full"> <>
<CardHeader className="space-y-4 text-center"> {error ? (
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-blue-100"> <Card className="w-full">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-blue-600 border-t-transparent"></div> <CardHeader className="space-y-4 text-center">
</div> <div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-red-100">
<CardTitle className="text-2xl font-semibold"></CardTitle> <div className="h-8 w-8 text-red-600"></div>
</CardHeader> </div>
<CardContent> <CardTitle className="text-2xl font-semibold text-red-600">
<p className="text-center text-gray-500">
{isLoading ? "请稍候,我们正在处理您的授权请求" : "正在跳转..."} </CardTitle>
</p> </CardHeader>
</CardContent> <CardContent>
</Card> <p className="text-center text-gray-500"></p>
</CardContent>
</Card>
) : (
<Card className="w-full">
<CardHeader className="space-y-4 text-center">
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-blue-100">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-blue-600 border-t-transparent"></div>
</div>
<CardTitle className="text-2xl font-semibold">
</CardTitle>
</CardHeader>
<CardContent>...</CardContent>
</Card>
)}
</>
); );
} }