mirror of
https://github.com/woodchen-ink/Q58Connect.git
synced 2025-07-19 06:21:55 +08:00
refactor: Simplify Discourse OAuth callback with CallbackHandler component
This commit is contained in:
parent
d7c837ff25
commit
ee0efb325e
@ -1,12 +1,10 @@
|
|||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
import { redirect } from "next/navigation";
|
|
||||||
import { signIn } from "@/auth";
|
|
||||||
|
|
||||||
import { discourseCallbackVerify } from "@/lib/discourse/verify";
|
import { discourseCallbackVerify } from "@/lib/discourse/verify";
|
||||||
import { findAuthorization } from "@/lib/dto/authorization";
|
import { findAuthorization } from "@/lib/dto/authorization";
|
||||||
import { getClientByClientId } from "@/lib/dto/client";
|
import { getClientByClientId } from "@/lib/dto/client";
|
||||||
import { getAuthorizeUrl } from "@/lib/oauth/authorize-url";
|
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> {
|
export interface DiscourseCallbackParams extends Record<string, string> {
|
||||||
sig: string;
|
sig: string;
|
||||||
@ -34,32 +32,25 @@ export default async function DiscourseCallbackPage({
|
|||||||
searchParams.sig,
|
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
|
// check authorization
|
||||||
const authorization = await findAuthorization(user.id, client.id);
|
const authorization = await findAuthorization(user.id, client.id);
|
||||||
|
let redirectUrl: string | undefined;
|
||||||
|
|
||||||
if (authorization) {
|
if (authorization) {
|
||||||
const redirectUrl = await getAuthorizeUrl(oauthParams);
|
redirectUrl = await getAuthorizeUrl(oauthParams);
|
||||||
return redirect(redirectUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="flex min-h-screen flex-col items-center justify-center">
|
<main className="flex min-h-screen flex-col items-center justify-center">
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center">
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<AuthorizationCard client={client} oauthParams={searchParams.oauth} />
|
<CallbackHandler
|
||||||
|
client={client}
|
||||||
|
user={user}
|
||||||
|
oauthParams={searchParams.oauth}
|
||||||
|
hasAuthorization={!!authorization}
|
||||||
|
redirectUrl={redirectUrl}
|
||||||
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
76
src/components/auth/callback-handler.tsx
Normal file
76
src/components/auth/callback-handler.tsx
Normal 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} />;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user