mirror of
https://github.com/woodchen-ink/Q58Connect.git
synced 2025-07-18 14:01:55 +08:00
refactor: Simplify OAuth authorization page and component with direct SSO handling
This commit is contained in:
parent
a3e43bf9e1
commit
a05bce4e38
@ -32,7 +32,7 @@ export default function LoginPage() {
|
|||||||
<MessageCircleCode className="mx-auto size-12" />
|
<MessageCircleCode className="mx-auto size-12" />
|
||||||
<div className="text-2xl font-semibold tracking-tight">
|
<div className="text-2xl font-semibold tracking-tight">
|
||||||
<span>Welcome to</span>{" "}
|
<span>Welcome to</span>{" "}
|
||||||
<span style={{ fontFamily: "Bahamas Bold" }}>Q58论坛 Connect</span>
|
<span style={{ fontFamily: "Bahamas Bold" }}>Q58 Connect</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
|
@ -6,18 +6,19 @@ import { Authorizing } from "@/components/auth/authorizing";
|
|||||||
import { ErrorCard } from "@/components/auth/error-card";
|
import { ErrorCard } from "@/components/auth/error-card";
|
||||||
|
|
||||||
export interface AuthorizeParams {
|
export interface AuthorizeParams {
|
||||||
|
scope?: string;
|
||||||
response_type: string;
|
response_type: string;
|
||||||
client_id: string;
|
client_id: string;
|
||||||
redirect_uri: string;
|
redirect_uri: string;
|
||||||
scope?: string;
|
|
||||||
state?: string;
|
state?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function AuthorizePage({
|
export default async function OAuthAuthorization({
|
||||||
searchParams,
|
searchParams,
|
||||||
}: {
|
}: {
|
||||||
searchParams: AuthorizeParams;
|
searchParams: AuthorizeParams;
|
||||||
}) {
|
}) {
|
||||||
|
// 检查用户是否已登录
|
||||||
const user = await getCurrentUser();
|
const user = await getCurrentUser();
|
||||||
if (!user?.id) {
|
if (!user?.id) {
|
||||||
redirect("/sign-in");
|
redirect("/sign-in");
|
||||||
@ -57,6 +58,7 @@ export default async function AuthorizePage({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 验证客户端
|
||||||
const client = await getClientByClientId(searchParams.client_id);
|
const client = await getClientByClientId(searchParams.client_id);
|
||||||
if (!client) {
|
if (!client) {
|
||||||
return (
|
return (
|
||||||
@ -102,25 +104,10 @@ export default async function AuthorizePage({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建 OAuth 参数
|
// 使用原始的 Authorizing 组件处理授权流程
|
||||||
const oauthParams = new URLSearchParams();
|
|
||||||
oauthParams.set("response_type", searchParams.response_type);
|
|
||||||
oauthParams.set("client_id", searchParams.client_id);
|
|
||||||
oauthParams.set("redirect_uri", searchParams.redirect_uri);
|
|
||||||
if (searchParams.scope) oauthParams.set("scope", searchParams.scope);
|
|
||||||
if (searchParams.state) oauthParams.set("state", searchParams.state);
|
|
||||||
|
|
||||||
// 转换参数格式
|
|
||||||
const authorizeParams = {
|
|
||||||
oauth: btoa(oauthParams.toString()),
|
|
||||||
clientId: client.id,
|
|
||||||
scope: searchParams.scope || "read_profile",
|
|
||||||
redirectUri: searchParams.redirect_uri,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-center justify-center p-4">
|
<div className="flex min-h-screen items-center justify-center bg-gray-50 p-4">
|
||||||
<Authorizing {...authorizeParams} />
|
<Authorizing />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,60 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import { handleAuthorizeAction } from "@/actions/authorizing";
|
import { getDiscourseSSOUrl } from "@/actions/discourse-sso-url";
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { ErrorCard } from "@/components/auth/error-card";
|
import { ErrorCard } from "@/components/auth/error-card";
|
||||||
|
|
||||||
interface AuthorizingProps {
|
export function Authorizing() {
|
||||||
oauth: string;
|
const router = useRouter();
|
||||||
clientId: string;
|
const searchParams = useSearchParams();
|
||||||
scope: string;
|
const [error, setError] = useState<unknown | null>(null);
|
||||||
redirectUri: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Authorizing({
|
|
||||||
oauth,
|
|
||||||
clientId,
|
|
||||||
scope,
|
|
||||||
redirectUri,
|
|
||||||
}: AuthorizingProps) {
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
const signInCallback = useCallback(async () => {
|
||||||
const authorize = async () => {
|
|
||||||
try {
|
try {
|
||||||
const result = await handleAuthorizeAction(oauth, clientId, scope);
|
const url = await getDiscourseSSOUrl(searchParams.toString());
|
||||||
if (result.error) {
|
router.push(url);
|
||||||
setError(result.error);
|
} catch (error) {
|
||||||
} else if (result.redirectUrl) {
|
setError(error);
|
||||||
const url = await result.redirectUrl;
|
|
||||||
window.location.href = url;
|
|
||||||
} else {
|
|
||||||
setError("授权响应无效");
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("授权过程出错:", err);
|
|
||||||
setError(err instanceof Error ? err.message : "授权过程发生未知错误");
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
}, [router, searchParams]);
|
||||||
|
|
||||||
authorize();
|
useEffect(() => {
|
||||||
}, [oauth, clientId, scope]);
|
// Delay 3s get sso url go to ...
|
||||||
|
const timer = setTimeout(signInCallback, 3);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
};
|
||||||
|
}, [signInCallback]);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-center justify-center p-4">
|
<Card className="w-full">
|
||||||
<ErrorCard
|
<CardHeader className="space-y-4 text-center">
|
||||||
title="授权失败"
|
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-red-100">
|
||||||
description={error}
|
<div className="h-8 w-8 text-red-600">❌</div>
|
||||||
redirectUri={redirectUri}
|
|
||||||
error="access_denied"
|
|
||||||
errorDescription={error}
|
|
||||||
/>
|
|
||||||
</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 max-w-md">
|
<Card className="w-full">
|
||||||
<CardHeader className="space-y-4 text-center">
|
<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="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 className="h-8 w-8 animate-spin rounded-full border-4 border-blue-600 border-t-transparent"></div>
|
||||||
|
@ -62,7 +62,7 @@ export function UserAuthForm({
|
|||||||
) : (
|
) : (
|
||||||
<MessageCircleCode className="mr-2 size-4" />
|
<MessageCircleCode className="mr-2 size-4" />
|
||||||
)}{" "}
|
)}{" "}
|
||||||
Q58
|
Q58论坛
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user