casualroom/apps/fenghuo/web/app/[locale]/test/page.tsx

295 lines
14 KiB
TypeScript
Raw Normal View History

2025-07-28 07:50:50 +08:00
"use client";
import { client } from "@/lib/auth-client";
import { Button } from "@nice/ui/components/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@nice/ui/components/card";
import { Input } from "@nice/ui/components/input";
import { Label } from "@nice/ui/components/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@nice/ui/components/tabs";
import { toast } from "@nice/ui/components/sonner";
import { useState } from "react";
export default function BetterAuthDemo() {
const [currentUser, setCurrentUser] = useState<any>(null);
const [testCredentials, setTestCredentials] = useState({
email: "test@example.com",
password: "Test123456",
name: "Test User"
});
const [discoveryInfo, setDiscoveryInfo] = useState<any>(null);
// 获取 OIDC Discovery 信息
const handleGetDiscoveryInfo = async () => {
try {
const response = await fetch('http://localhost:3001/api/auth/.well-known/openid-configuration');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const info = await response.json();
setDiscoveryInfo(info);
toast.success("获取 Discovery 信息成功!");
} catch (error: any) {
console.error("获取 Discovery 信息失败:", error);
toast.error(`获取 Discovery 信息失败: ${error.message || "未知错误"}`);
}
};
// 测试 Generic OAuth 配置
const handleTestGenericOAuthConfig = async () => {
try {
const result = await client.signIn.oauth2({
providerId: "fenghuo-oidc",
callbackURL: "http://localhost:3000/auth/better-auth-callback",
});
if (result.data) {
toast.success("OAuth 配置测试成功!");
} else if (result.error) {
console.error("OAuth 错误详情:", result.error);
toast.error(`OAuth 配置测试失败: ${result.error.message}`);
}
} catch (error: any) {
console.error("OAuth 配置测试失败:", error);
toast.error(`OAuth 配置测试失败: ${error.message || "未知错误"}`);
}
};
// 检查当前会话
const handleCheckSession = async () => {
try {
const session = await client.getSession();
console.log("当前会话:", session);
setCurrentUser(session.data);
toast.success(session.data ? `会话存在: ${session.data.user.email}` : "无活跃会话");
return session.data;
} catch (error: any) {
console.error("检查会话失败:", error);
toast.error(`检查会话失败: ${error.message}`);
return null;
}
};
// 创建测试用户
const handleCreateTestUser = async () => {
try {
const result = await client.signUp.email({
email: testCredentials.email,
password: testCredentials.password,
name: testCredentials.name,
});
if (result.data) {
toast.success("测试用户创建成功!");
setCurrentUser(result.data);
} else if (result.error) {
console.error("创建用户失败:", result.error);
toast.error(`创建用户失败: ${result.error.message}`);
}
} catch (error: any) {
console.error("创建用户失败:", error);
toast.error(`创建用户失败: ${error.message || "未知错误"}`);
}
};
// 用邮箱密码登录
const handleEmailSignIn = async () => {
try {
const result = await client.signIn.email({
email: testCredentials.email,
password: testCredentials.password,
});
if (result.data) {
toast.success("邮箱登录成功!");
setCurrentUser(result.data);
} else if (result.error) {
console.error("邮箱登录失败:", result.error);
toast.error(`邮箱登录失败: ${result.error.message}`);
}
} catch (error: any) {
console.error("邮箱登录失败:", error);
toast.error(`邮箱登录失败: ${error.message || "未知错误"}`);
}
};
// 登出
const handleSignOut = async () => {
try {
await client.signOut();
setCurrentUser(null);
toast.success("已登出");
} catch (error: any) {
console.error("登出失败:", error);
toast.error(`登出失败: ${error.message}`);
}
};
return (
<div className="container mx-auto p-6 space-y-6">
<div className="text-center">
<h1 className="text-3xl font-bold mb-2">Better Auth </h1>
<p className="text-muted-foreground"></p>
</div>
<Tabs defaultValue="account" className="space-y-6">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="account"></TabsTrigger>
<TabsTrigger value="discovery">OIDC </TabsTrigger>
<TabsTrigger value="oauth">OAuth </TabsTrigger>
</TabsList>
{/* 账户管理 Tab */}
<TabsContent value="account" className="space-y-6">
<Card>
<CardHeader>
<CardTitle></CardTitle>
<CardDescription>
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex gap-4 mb-4">
<Button onClick={handleCheckSession} variant="outline">
</Button>
{currentUser && (
<Button onClick={handleSignOut} variant="destructive">
</Button>
)}
</div>
{currentUser ? (
<div className="space-y-2">
<h4 className="font-semibold">:</h4>
<div className="bg-green-50 dark:bg-green-900/20 p-4 rounded-md">
<div className="text-sm space-y-1">
<div><strong>Email:</strong> {currentUser.user?.email}</div>
<div><strong>Name:</strong> {currentUser.user?.name}</div>
<div><strong>ID:</strong> {currentUser.user?.id}</div>
</div>
</div>
</div>
) : (
<div className="bg-yellow-50 dark:bg-yellow-900/20 p-4 rounded-md">
<div className="text-sm text-yellow-800 dark:text-yellow-200">
</div>
</div>
)}
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle></CardTitle>
<CardDescription>
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="space-y-2">
<Label htmlFor="testEmail"></Label>
<Input
id="testEmail"
type="email"
value={testCredentials.email}
onChange={(e) => setTestCredentials({ ...testCredentials, email: e.target.value })}
/>
</div>
<div className="space-y-2">
<Label htmlFor="testPassword"></Label>
<Input
id="testPassword"
type="password"
value={testCredentials.password}
onChange={(e) => setTestCredentials({ ...testCredentials, password: e.target.value })}
/>
</div>
<div className="space-y-2">
<Label htmlFor="testName"></Label>
<Input
id="testName"
value={testCredentials.name}
onChange={(e) => setTestCredentials({ ...testCredentials, name: e.target.value })}
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<Button onClick={handleCreateTestUser} className="w-full">
</Button>
<Button onClick={handleEmailSignIn} variant="outline" className="w-full">
</Button>
</div>
</CardContent>
</Card>
</TabsContent>
{/* OIDC 信息 Tab */}
<TabsContent value="discovery" className="space-y-6">
<Card>
<CardHeader>
<CardTitle>OIDC Discovery </CardTitle>
<CardDescription>
OIDC Provider
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Button onClick={handleGetDiscoveryInfo} className="w-full">
Discovery
</Button>
{discoveryInfo && (
<div className="space-y-2">
<h4 className="font-semibold">Discovery :</h4>
<pre className="bg-muted p-4 rounded-md overflow-x-auto text-xs">
{JSON.stringify(discoveryInfo, null, 2)}
</pre>
</div>
)}
</CardContent>
</Card>
</TabsContent>
{/* OAuth 测试 Tab */}
<TabsContent value="oauth" className="space-y-6">
<Card>
<CardHeader>
<CardTitle>OAuth2 </CardTitle>
<CardDescription>
OAuth2
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="text-sm text-muted-foreground mb-4">
<p><strong> </strong> "account_not_linked" "账户管理"</p>
</div>
<Button onClick={handleTestGenericOAuthConfig} className="w-full">
OAuth2
</Button>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle></CardTitle>
<CardDescription>
OAuth
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-2 text-sm">
<div><strong>Provider ID:</strong> <code>fenghuo-oidc</code></div>
<div><strong>Discovery URL:</strong> <code>http://localhost:3001/api/auth/.well-known/openid-configuration</code></div>
<div><strong> URL:</strong> <code>http://localhost:3000/auth/better-auth-callback</code></div>
</div>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
);
}