fix: integrate Better Auth session data instead of mock data
- Replace demo user data with actual Better Auth session data - Update session endpoint to use auth.api.getSession() for real user info - Fix UserProfile component to display actual user profile in header - Improve logout functionality with proper state cleanup - Add event listeners for OAuth state changes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,31 +1,27 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
import { auth } from "@/lib/auth";
|
||||||
// Mock session data for demo purposes
|
|
||||||
// In a real app, this would check the actual Better Auth session
|
|
||||||
const mockSession = {
|
|
||||||
user: {
|
|
||||||
id: "demo-user-123",
|
|
||||||
name: "Demo User",
|
|
||||||
email: "demo@example.com",
|
|
||||||
emailVerified: true,
|
|
||||||
image: "https://via.placeholder.com/40"
|
|
||||||
},
|
|
||||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString()
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
export async function GET(request: Request) {
|
||||||
try {
|
try {
|
||||||
// For demo purposes, we'll always return an authenticated user
|
// Use Better Auth to get the actual session
|
||||||
// This simulates a successful OAuth login scenario
|
const session = await auth.api.getSession({
|
||||||
|
headers: request.headers,
|
||||||
// In a real implementation, you would:
|
});
|
||||||
// 1. Check for valid session cookies/tokens
|
|
||||||
// 2. Validate the session with Better Auth
|
if (session?.user) {
|
||||||
// 3. Return the actual user data
|
return NextResponse.json({
|
||||||
|
session: {
|
||||||
|
user: session.user,
|
||||||
|
expires: session.session?.expiresAt
|
||||||
|
},
|
||||||
|
user: session.user
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no session found, return not authenticated
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
session: mockSession,
|
session: null,
|
||||||
user: mockSession.user
|
user: null
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Session check error:", error);
|
console.error("Session check error:", error);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useSession, signOut } from "@/lib/auth-client";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { SignInButton } from "./sign-in-button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@@ -12,29 +12,25 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
import { User, LogOut } from "lucide-react";
|
import { User, LogOut } from "lucide-react";
|
||||||
|
|
||||||
export function UserProfile() {
|
export function UserProfile() {
|
||||||
const { data: session, isPending } = useSession();
|
const { user, isAuthenticated, isLoading, login, logout } = useAuth();
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
if (isPending) {
|
if (isLoading) {
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session) {
|
if (!isAuthenticated || !user) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center gap-4 p-6">
|
<Button onClick={login} variant="outline">
|
||||||
<SignInButton />
|
Sign in
|
||||||
</div>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSignOut = async () => {
|
const handleSignOut = async () => {
|
||||||
await signOut();
|
await logout();
|
||||||
router.replace("/");
|
|
||||||
router.refresh();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -42,14 +38,14 @@ export function UserProfile() {
|
|||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Avatar className="size-8 cursor-pointer hover:opacity-80 transition-opacity">
|
<Avatar className="size-8 cursor-pointer hover:opacity-80 transition-opacity">
|
||||||
<AvatarImage
|
<AvatarImage
|
||||||
src={session.user?.image || ""}
|
src={user?.image || ""}
|
||||||
alt={session.user?.name || "User"}
|
alt={user?.name || "User"}
|
||||||
referrerPolicy="no-referrer"
|
referrerPolicy="no-referrer"
|
||||||
/>
|
/>
|
||||||
<AvatarFallback>
|
<AvatarFallback>
|
||||||
{(
|
{(
|
||||||
session.user?.name?.[0] ||
|
user?.name?.[0] ||
|
||||||
session.user?.email?.[0] ||
|
user?.email?.[0] ||
|
||||||
"U"
|
"U"
|
||||||
).toUpperCase()}
|
).toUpperCase()}
|
||||||
</AvatarFallback>
|
</AvatarFallback>
|
||||||
@@ -59,10 +55,10 @@ export function UserProfile() {
|
|||||||
<DropdownMenuLabel className="font-normal">
|
<DropdownMenuLabel className="font-normal">
|
||||||
<div className="flex flex-col space-y-1">
|
<div className="flex flex-col space-y-1">
|
||||||
<p className="text-sm font-medium leading-none">
|
<p className="text-sm font-medium leading-none">
|
||||||
{session.user?.name}
|
{user?.name}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs leading-none text-muted-foreground">
|
<p className="text-xs leading-none text-muted-foreground">
|
||||||
{session.user?.email}
|
{user?.email}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenuLabel>
|
</DropdownMenuLabel>
|
||||||
|
|||||||
@@ -82,6 +82,22 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
checkAuth();
|
checkAuth();
|
||||||
|
|
||||||
|
// Add a listener for auth state changes (for OAuth callbacks)
|
||||||
|
const handleAuthChange = () => {
|
||||||
|
checkAuth();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for storage changes (in case user logs in from another tab)
|
||||||
|
window.addEventListener('storage', handleAuthChange);
|
||||||
|
|
||||||
|
// Custom event for OAuth completion
|
||||||
|
window.addEventListener('auth-state-changed', handleAuthChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('storage', handleAuthChange);
|
||||||
|
window.removeEventListener('auth-state-changed', handleAuthChange);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const login = async () => {
|
const login = async () => {
|
||||||
@@ -117,11 +133,21 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
try {
|
try {
|
||||||
// Call server-side logout endpoint
|
// Call server-side logout endpoint
|
||||||
await fetch("/api/auth/logout", { method: "POST" });
|
await fetch("/api/auth/logout", { method: "POST" });
|
||||||
|
|
||||||
|
// Clear all auth-related data
|
||||||
setUser(null);
|
setUser(null);
|
||||||
localStorage.removeItem("moneymind-session");
|
localStorage.removeItem("moneymind-session");
|
||||||
window.location.href = "/";
|
sessionStorage.clear();
|
||||||
|
|
||||||
|
// Force reload to clear any cached state
|
||||||
|
window.location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Logout error:", error);
|
console.error("Logout error:", error);
|
||||||
|
// Even if server call fails, clear local state and reload
|
||||||
|
setUser(null);
|
||||||
|
localStorage.removeItem("moneymind-session");
|
||||||
|
sessionStorage.clear();
|
||||||
|
window.location.reload();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user