refactor: Simplify Discourse OAuth callback with CallbackHandler component

This commit is contained in:
wood chen 2025-02-23 05:41:23 +08:00
parent d7c837ff25
commit ee0efb325e
2 changed files with 86 additions and 19 deletions

View File

@ -1,12 +1,10 @@
import { Suspense } from "react";
import { redirect } from "next/navigation";
import { signIn } from "@/auth";
import { discourseCallbackVerify } from "@/lib/discourse/verify";
import { findAuthorization } from "@/lib/dto/authorization";
import { getClientByClientId } from "@/lib/dto/client";
import { getAuthorizeUrl } from "@/lib/oauth/authorize-url";
import { AuthorizationCard } from "@/components/auth/authorization-card";
import { CallbackHandler } from "@/components/auth/callback-handler";
export interface DiscourseCallbackParams extends Record<string, string> {
sig: string;
@ -34,32 +32,25 @@ export default async function DiscourseCallbackPage({
searchParams.sig,
);
// 设置用户会话
await signIn("credentials", {
id: user.id,
username: user.username,
email: user.email,
name: user.name,
avatarUrl: user.avatarUrl,
role: user.role,
moderator: user.moderator,
groups: JSON.stringify(user.groups),
redirect: false,
});
// check authorization
const authorization = await findAuthorization(user.id, client.id);
let redirectUrl: string | undefined;
if (authorization) {
const redirectUrl = await getAuthorizeUrl(oauthParams);
return redirect(redirectUrl);
redirectUrl = await getAuthorizeUrl(oauthParams);
}
return (
<main className="flex min-h-screen flex-col items-center justify-center">
<div className="flex items-center justify-center">
<Suspense>
<AuthorizationCard client={client} oauthParams={searchParams.oauth} />
<CallbackHandler
client={client}
user={user}
oauthParams={searchParams.oauth}
hasAuthorization={!!authorization}
redirectUrl={redirectUrl}
/>
</Suspense>
</div>
</main>

View File

@ -0,0 +1,76 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { signIn } from "@/auth";
import { Client } from "@prisma/client";
import { AuthorizationCard } from "./authorization-card";
interface CallbackHandlerProps {
client: Client;
user: any;
oauthParams: string;
hasAuthorization: boolean;
redirectUrl?: string;
}
export function CallbackHandler({
client,
user,
oauthParams,
hasAuthorization,
redirectUrl,
}: CallbackHandlerProps) {
const router = useRouter();
const [error, setError] = useState<string | null>(null);
const [isProcessing, setIsProcessing] = useState(true);
useEffect(() => {
async function handleAuth() {
try {
// 设置用户会话
await signIn("credentials", {
id: user.id,
username: user.username,
email: user.email,
name: user.name,
avatarUrl: user.avatarUrl,
role: user.role,
moderator: user.moderator,
groups: JSON.stringify(user.groups),
redirect: false,
});
// 如果已经授权过,直接重定向
if (hasAuthorization && redirectUrl) {
router.push(redirectUrl);
return;
}
setIsProcessing(false);
} catch (error) {
console.error("Auth error:", error);
setError("认证过程中发生错误");
setIsProcessing(false);
}
}
handleAuth();
}, []);
if (error) {
return <div className="text-red-500">{error}</div>;
}
if (isProcessing) {
return (
<div className="flex items-center justify-center">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent"></div>
<span className="ml-2">...</span>
</div>
);
}
return <AuthorizationCard client={client} oauthParams={oauthParams} />;
}