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

295 lines
14 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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>
);
}