summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2025-08-12 16:40:00 +0100
committerdiogo464 <[email protected]>2025-08-12 16:40:00 +0100
commit4902a199b93fbdd9b265f9741c70e00eaf368939 (patch)
treed483bc5648a1625a2241cab17b09b17245a907e8
parentfcd70649f43a72dbbcbc79e524fbe3fe20261021 (diff)
Implement authenticated file/directory deletion
- Add /api/delete endpoint with authentication checks - Update DriveDirectoryClient to use actual delete API - Replace placeholder TODO with working delete functionality - Include proper error handling and user feedback 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
-rw-r--r--CLAUDE.md27
-rw-r--r--frontend/app/api/delete/route.ts67
-rw-r--r--frontend/components/drive/DriveDirectoryClient.tsx41
3 files changed, 99 insertions, 36 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 0eda37d..15e05da 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -46,30 +46,5 @@
46- **Updates**: Manual refresh only (no real-time) 46- **Updates**: Manual refresh only (no real-time)
47- the server is running at `127.0.0.1:3000` and you can use curl to test the page 47- the server is running at `127.0.0.1:3000` and you can use curl to test the page
48 48
49## API Endpoints 49## HTTP Testing
50
51### Tree Endpoint
52- `/api/tree` - GET filesystem tree with hierarchy
53
54### RESTful API - `/api/fs/[...path]`
55- **GET** `/api/fs/path/to/directory` - List directory contents
56- **POST** `/api/fs/path/to/directory` - Create directory
57- **PUT** `/api/fs/path/to/file.txt` - Upload/create file
58- **DELETE** `/api/fs/path/to/item` - Delete file or directory
59
60## API Testing
61- For testing authenticated endpoints in development, use header `AUTH: 1` 50- For testing authenticated endpoints in development, use header `AUTH: 1`
62- Examples:
63 ```bash
64 # List directory
65 curl "http://localhost:3000/api/fs/some/directory"
66
67 # Create directory
68 curl -X POST "http://localhost:3000/api/fs/new_directory" -H "AUTH: 1"
69
70 # Upload file
71 curl -X PUT "http://localhost:3000/api/fs/path/file.txt" -H "AUTH: 1" -H "Content-Type: multipart/form-data" -F "file=@local_file.txt"
72
73 # Delete file/directory
74 curl -X DELETE "http://localhost:3000/api/fs/path/to/delete" -H "AUTH: 1"
75 ``` \ No newline at end of file
diff --git a/frontend/app/api/delete/route.ts b/frontend/app/api/delete/route.ts
new file mode 100644
index 0000000..31af119
--- /dev/null
+++ b/frontend/app/api/delete/route.ts
@@ -0,0 +1,67 @@
1import { NextRequest, NextResponse } from 'next/server'
2import { Auth_get_user } from '@/lib/auth'
3import { Drive_remove } from '@/lib/drive_server'
4
5// DELETE /api/delete - Delete files/directories
6export async function DELETE(request: NextRequest) {
7 try {
8 // Check user authentication
9 const user = await Auth_get_user()
10 if (!user.isLoggedIn) {
11 return NextResponse.json({ error: 'User not authenticated' }, { status: 401 })
12 }
13
14 // Parse request body to get paths to delete
15 const body = await request.json()
16 const { paths } = body
17
18 if (!paths || !Array.isArray(paths) || paths.length === 0) {
19 return NextResponse.json({ error: 'No paths provided for deletion' }, { status: 400 })
20 }
21
22 // Validate paths (basic sanitation)
23 for (const path of paths) {
24 if (typeof path !== 'string' || path.trim() === '') {
25 return NextResponse.json({ error: 'Invalid path provided' }, { status: 400 })
26 }
27 }
28
29 const results = []
30 const errors = []
31
32 // Delete each path using Drive_remove
33 for (const path of paths) {
34 try {
35 await Drive_remove(path, user.email)
36 results.push({ path, success: true })
37 } catch (error) {
38 console.error(`Failed to delete ${path}:`, error)
39 errors.push({
40 path,
41 error: error instanceof Error ? error.message : 'Unknown error'
42 })
43 }
44 }
45
46 // Return results
47 const response = {
48 success: errors.length === 0,
49 message: errors.length === 0
50 ? `Successfully deleted ${results.length} item(s)`
51 : `Deleted ${results.length} item(s), failed to delete ${errors.length} item(s)`,
52 results,
53 errors
54 }
55
56 return NextResponse.json(response, {
57 status: errors.length === 0 ? 200 : 207 // 207 Multi-Status for partial success
58 })
59
60 } catch (error) {
61 console.error('Delete API error:', error)
62 return NextResponse.json(
63 { error: error instanceof Error ? error.message : 'Internal server error' },
64 { status: 500 }
65 )
66 }
67} \ No newline at end of file
diff --git a/frontend/components/drive/DriveDirectoryClient.tsx b/frontend/components/drive/DriveDirectoryClient.tsx
index c3c23a7..4657141 100644
--- a/frontend/components/drive/DriveDirectoryClient.tsx
+++ b/frontend/components/drive/DriveDirectoryClient.tsx
@@ -234,16 +234,37 @@ export function DriveDirectoryClient({ path, files, breadcrumbs }: DriveDirector
234 } 234 }
235 235
236 const handleDelete = async (itemPaths: string[]) => { 236 const handleDelete = async (itemPaths: string[]) => {
237 // TODO: Implement actual delete API calls 237 try {
238 setSelectedFiles(new Set()) 238 const response = await fetch('/api/delete', {
239 239 method: 'DELETE',
240 toast({ 240 headers: {
241 title: "Deleted successfully", 241 'Content-Type': 'application/json',
242 description: `${itemPaths.length} item(s) deleted`, 242 },
243 }) 243 body: JSON.stringify({ paths: itemPaths })
244 244 })
245 // Refresh page to show changes 245
246 window.location.reload() 246 const result = await response.json()
247
248 if (response.ok) {
249 setSelectedFiles(new Set())
250 toast({
251 title: "Deleted successfully",
252 description: result.message,
253 })
254
255 // Refresh page to show changes
256 window.location.reload()
257 } else {
258 throw new Error(result.error || `Delete failed with status ${response.status}`)
259 }
260 } catch (error) {
261 console.error('Delete error:', error)
262 toast({
263 title: "Delete failed",
264 description: error instanceof Error ? error.message : 'Unknown error occurred',
265 variant: "destructive"
266 })
267 }
247 } 268 }
248 269
249 const handleLogin = () => { 270 const handleLogin = () => {