summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2025-08-13 16:49:09 +0100
committerdiogo464 <[email protected]>2025-08-13 16:49:09 +0100
commit0a588ec2d7417b12b53a8cc816a399a09d3a0814 (patch)
treeeab24526c00abeef411084b83059d6a480ab5853
parentfa13fa8db757946e34b515270456d9008627d61e (diff)
refactor: move auth components to server-side rendering
- Create server-side AuthButtons component that renders login/logout based on auth state - Add DriveHeader component for title and auth buttons (server-side) - Restructure DriveDirectoryClient to focus on breadcrumbs/actions/files only - Remove client-side auth state management from DriveDirectoryClient - Add /api/logout route handler for server-side logout flow - Update DriveDirectoryView to compose header and directory components - Preserve existing TinyAuth integration and dev mode bypass 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
-rw-r--r--frontend/app/api/logout/route.ts32
-rw-r--r--frontend/components/auth/AuthButtons.tsx30
-rw-r--r--frontend/components/drive/DriveDirectoryClient.tsx40
-rw-r--r--frontend/components/drive/DriveDirectoryView.tsx21
-rw-r--r--frontend/components/drive/DriveHeader.tsx15
5 files changed, 96 insertions, 42 deletions
diff --git a/frontend/app/api/logout/route.ts b/frontend/app/api/logout/route.ts
new file mode 100644
index 0000000..51de324
--- /dev/null
+++ b/frontend/app/api/logout/route.ts
@@ -0,0 +1,32 @@
1import { NextRequest } from 'next/server';
2import { redirect } from 'next/navigation';
3import { Auth_tinyauth_endpoint, Auth_tinyauth_public_endpoint } from '@/lib/auth_shared';
4
5export async function POST(request: NextRequest) {
6 try {
7 // Get the current session cookie
8 const cookies = request.cookies.getAll();
9 const sessionCookie = cookies.find(cookie => cookie.name.includes('tinyauth-session'));
10
11 if (sessionCookie) {
12 // Call tinyauth logout endpoint to invalidate the session
13 const logoutResponse = await fetch(`${Auth_tinyauth_endpoint()}/auth/logout`, {
14 method: 'POST',
15 headers: {
16 'Cookie': `${sessionCookie.name}=${sessionCookie.value}`
17 }
18 });
19
20 // Note: We don't need to check the response status as we'll redirect anyway
21 }
22
23 // Redirect to the public logout endpoint which should clear cookies client-side
24 const publicLogoutUrl = `${Auth_tinyauth_public_endpoint()}/auth/logout`;
25 return Response.redirect(publicLogoutUrl, 302);
26
27 } catch (error) {
28 console.error('Logout error:', error);
29 // Even if logout fails, redirect to home
30 return redirect('/');
31 }
32} \ No newline at end of file
diff --git a/frontend/components/auth/AuthButtons.tsx b/frontend/components/auth/AuthButtons.tsx
new file mode 100644
index 0000000..5b5053d
--- /dev/null
+++ b/frontend/components/auth/AuthButtons.tsx
@@ -0,0 +1,30 @@
1import { LogIn, LogOut } from "lucide-react"
2import { Button } from "@/components/ui/button"
3import { Auth_get_user } from "@/lib/auth"
4import { Auth_tinyauth_public_endpoint } from "@/lib/auth_shared"
5
6export async function AuthButtons() {
7 const user = await Auth_get_user()
8
9 if (user.isLoggedIn) {
10 return (
11 <form action="/api/logout" method="post">
12 <Button type="submit" variant="outline">
13 <LogOut className="mr-2 h-4 w-4" />
14 Logout
15 </Button>
16 </form>
17 )
18 }
19
20 const authUrl = `${Auth_tinyauth_public_endpoint()}/auth/google`
21
22 return (
23 <Button asChild>
24 <a href={authUrl}>
25 <LogIn className="mr-2 h-4 w-4" />
26 Login
27 </a>
28 </Button>
29 )
30} \ No newline at end of file
diff --git a/frontend/components/drive/DriveDirectoryClient.tsx b/frontend/components/drive/DriveDirectoryClient.tsx
index d48be61..3058a68 100644
--- a/frontend/components/drive/DriveDirectoryClient.tsx
+++ b/frontend/components/drive/DriveDirectoryClient.tsx
@@ -3,7 +3,6 @@
3import type React from "react" 3import type React from "react"
4import { useState, useRef } from "react" 4import { useState, useRef } from "react"
5import Link from "next/link" 5import Link from "next/link"
6import { Auth_tinyauth_public_endpoint } from "@/lib/auth_shared"
7import { 6import {
8 ChevronRight, 7 ChevronRight,
9 File, 8 File,
@@ -12,12 +11,9 @@ import {
12 Trash2, 11 Trash2,
13 Move, 12 Move,
14 MoreHorizontal, 13 MoreHorizontal,
15 HardDrive,
16 Edit, 14 Edit,
17 Link as LinkIcon, 15 Link as LinkIcon,
18 Info, 16 Info,
19 LogIn,
20 LogOut,
21 FolderPlus, 17 FolderPlus,
22} from "lucide-react" 18} from "lucide-react"
23import { Button } from "@/components/ui/button" 19import { Button } from "@/components/ui/button"
@@ -39,6 +35,7 @@ import { UPLOAD_MAX_FILE_SIZE, UPLOAD_MAX_FILES } from "@/lib/constants"
39import { DriveMoveDialog } from "./DriveMoveDialog" 35import { DriveMoveDialog } from "./DriveMoveDialog"
40import { StorageUsage } from "./StorageUsage" 36import { StorageUsage } from "./StorageUsage"
41import type { StorageData } from "@/lib/storage" 37import type { StorageData } from "@/lib/storage"
38import type { UserAuth } from "@/lib/auth_types"
42 39
43function formatFileSize(bytes: number): string { 40function formatFileSize(bytes: number): string {
44 if (bytes === 0) return "0 Bytes" 41 if (bytes === 0) return "0 Bytes"
@@ -75,9 +72,10 @@ interface DriveDirectoryClientProps {
75 files: DriveLsEntry[] 72 files: DriveLsEntry[]
76 breadcrumbs: Breadcrumb[] 73 breadcrumbs: Breadcrumb[]
77 storageData: StorageData 74 storageData: StorageData
75 user: UserAuth
78} 76}
79 77
80export function DriveDirectoryClient({ path, files, breadcrumbs, storageData }: DriveDirectoryClientProps) { 78export function DriveDirectoryClient({ path, files, breadcrumbs, storageData, user }: DriveDirectoryClientProps) {
81 const [selectedFiles, setSelectedFiles] = useState<Set<string>>(new Set()) 79 const [selectedFiles, setSelectedFiles] = useState<Set<string>>(new Set())
82 const [renameDialogOpen, setRenameDialogOpen] = useState(false) 80 const [renameDialogOpen, setRenameDialogOpen] = useState(false)
83 const [infoDialogOpen, setInfoDialogOpen] = useState(false) 81 const [infoDialogOpen, setInfoDialogOpen] = useState(false)
@@ -89,7 +87,6 @@ export function DriveDirectoryClient({ path, files, breadcrumbs, storageData }:
89 const fileInputRef = useRef<HTMLInputElement>(null) 87 const fileInputRef = useRef<HTMLInputElement>(null)
90 const [uploading, setUploading] = useState(false) 88 const [uploading, setUploading] = useState(false)
91 89
92 const [isLoggedIn, setIsLoggedIn] = useState(true) // Mock logged in state
93 90
94 const toggleFileSelection = (filePath: string) => { 91 const toggleFileSelection = (filePath: string) => {
95 const newSelected = new Set(selectedFiles) 92 const newSelected = new Set(selectedFiles)
@@ -311,17 +308,6 @@ export function DriveDirectoryClient({ path, files, breadcrumbs, storageData }:
311 } 308 }
312 } 309 }
313 310
314 const handleLogin = () => {
315 // Redirect to tinyauth Google OAuth endpoint
316 const authUrl = `${Auth_tinyauth_public_endpoint()}/auth/google`
317 window.location.href = authUrl
318 }
319
320 const handleLogout = () => {
321 // Handle logout (would typically clear tokens, etc.)
322 setIsLoggedIn(false)
323 // Could also redirect to logout endpoint
324 }
325 311
326 const handleMove = async (destinationPath: string) => { 312 const handleMove = async (destinationPath: string) => {
327 // TODO: Implement actual move API calls 313 // TODO: Implement actual move API calls
@@ -379,15 +365,10 @@ export function DriveDirectoryClient({ path, files, breadcrumbs, storageData }:
379 } 365 }
380 366
381 return ( 367 return (
382 <div className="container mx-auto p-6 space-y-6"> 368 <div className="space-y-6">
383 {/* Header with Breadcrumbs */} 369 {/* Navigation and Actions */}
384 <div className="flex items-center justify-between"> 370 <div className="flex items-center justify-between">
385 <div className="flex items-center gap-4"> 371 <div className="flex items-center gap-4">
386 <div className="flex items-center gap-2">
387 <HardDrive className="h-6 w-6" />
388 <h1 className="text-2xl font-bold">FCT Drive</h1>
389 </div>
390
391 {/* Breadcrumbs */} 372 {/* Breadcrumbs */}
392 <nav className="flex items-center gap-1 text-sm text-muted-foreground"> 373 <nav className="flex items-center gap-1 text-sm text-muted-foreground">
393 {breadcrumbs.map((crumb, index) => ( 374 {breadcrumbs.map((crumb, index) => (
@@ -423,17 +404,6 @@ export function DriveDirectoryClient({ path, files, breadcrumbs, storageData }:
423 <Upload className="mr-2 h-4 w-4" /> 404 <Upload className="mr-2 h-4 w-4" />
424 {uploading ? "Uploading..." : "Upload Files"} 405 {uploading ? "Uploading..." : "Upload Files"}
425 </Button> 406 </Button>
426 {isLoggedIn ? (
427 <Button variant="outline" onClick={handleLogout}>
428 <LogOut className="mr-2 h-4 w-4" />
429 Logout
430 </Button>
431 ) : (
432 <Button onClick={handleLogin}>
433 <LogIn className="mr-2 h-4 w-4" />
434 Login
435 </Button>
436 )}
437 </div> 407 </div>
438 </div> 408 </div>
439 409
diff --git a/frontend/components/drive/DriveDirectoryView.tsx b/frontend/components/drive/DriveDirectoryView.tsx
index 3558537..d2f30ee 100644
--- a/frontend/components/drive/DriveDirectoryView.tsx
+++ b/frontend/components/drive/DriveDirectoryView.tsx
@@ -1,6 +1,8 @@
1import { DriveLsEntry } from "@/lib/drive_types" 1import { DriveLsEntry } from "@/lib/drive_types"
2import { DriveDirectoryClient } from "./DriveDirectoryClient" 2import { DriveDirectoryClient } from "./DriveDirectoryClient"
3import { DriveHeader } from "./DriveHeader"
3import type { StorageData } from "@/lib/storage" 4import type { StorageData } from "@/lib/storage"
5import { Auth_get_user } from "@/lib/auth"
4 6
5interface DriveDirectoryViewProps { 7interface DriveDirectoryViewProps {
6 path: string 8 path: string
@@ -43,16 +45,21 @@ function sortFiles(files: DriveLsEntry[]): DriveLsEntry[] {
43 }); 45 });
44} 46}
45 47
46export function DriveDirectoryView({ path, files, storageData }: DriveDirectoryViewProps) { 48export async function DriveDirectoryView({ path, files, storageData }: DriveDirectoryViewProps) {
47 const sortedFiles = sortFiles(files) 49 const sortedFiles = sortFiles(files)
48 const breadcrumbs = generateBreadcrumbs(path) 50 const breadcrumbs = generateBreadcrumbs(path)
51 const user = await Auth_get_user()
49 52
50 return ( 53 return (
51 <DriveDirectoryClient 54 <div className="container mx-auto p-6 space-y-6">
52 path={path} 55 <DriveHeader />
53 files={sortedFiles} 56 <DriveDirectoryClient
54 breadcrumbs={breadcrumbs} 57 path={path}
55 storageData={storageData} 58 files={sortedFiles}
56 /> 59 breadcrumbs={breadcrumbs}
60 storageData={storageData}
61 user={user}
62 />
63 </div>
57 ) 64 )
58} \ No newline at end of file 65} \ No newline at end of file
diff --git a/frontend/components/drive/DriveHeader.tsx b/frontend/components/drive/DriveHeader.tsx
new file mode 100644
index 0000000..718d031
--- /dev/null
+++ b/frontend/components/drive/DriveHeader.tsx
@@ -0,0 +1,15 @@
1import { HardDrive } from "lucide-react"
2import { AuthButtons } from "@/components/auth/AuthButtons"
3
4export async function DriveHeader() {
5 return (
6 <div className="flex items-center justify-between">
7 <div className="flex items-center gap-2">
8 <HardDrive className="h-6 w-6" />
9 <h1 className="text-2xl font-bold">FCT Drive</h1>
10 </div>
11
12 <AuthButtons />
13 </div>
14 )
15} \ No newline at end of file