diff --git a/package.json b/package.json index 4a19c3c..ca0a9dd 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,14 @@ "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "lucide-react": "^0.378.0", + "mime-types": "^2.1.35", "mongoose": "^8.4.0", "next": "^14.1.2", "react": "^18", "react-dom": "^18" }, "devDependencies": { + "@types/mime-types": "^2.1.4", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c6b507c..4cf64a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: lucide-react: specifier: ^0.378.0 version: 0.378.0(react@18.2.0) + mime-types: + specifier: ^2.1.35 + version: 2.1.35 mongoose: specifier: ^8.4.0 version: 8.4.0 @@ -37,6 +40,9 @@ dependencies: version: 18.2.0(react@18.2.0) devDependencies: + '@types/mime-types': + specifier: ^2.1.4 + version: 2.1.4 '@types/node': specifier: ^20 version: 20.11.28 @@ -2322,6 +2328,13 @@ packages: } dev: true + /@types/mime-types@2.1.4: + resolution: + { + integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w== + } + dev: true + /@types/node@20.11.28: resolution: { @@ -5000,6 +5013,24 @@ packages: picomatch: 2.3.1 dev: true + /mime-db@1.52.0: + resolution: + { + integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + } + engines: { node: '>= 0.6' } + dev: false + + /mime-types@2.1.35: + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + } + engines: { node: '>= 0.6' } + dependencies: + mime-db: 1.52.0 + dev: false + /mimic-fn@2.1.0: resolution: { diff --git a/src/app/api/drop/route.ts b/src/app/api/drop/route.ts index 6f77b59..f76fd6c 100644 --- a/src/app/api/drop/route.ts +++ b/src/app/api/drop/route.ts @@ -3,11 +3,10 @@ import { dbConnect } from '@/lib/db'; import FileModel from '@/lib/models/file'; import { getObject } from '@/lib/s3'; -export async function GET(req: NextRequest) { - const { searchParams } = new URL(req.url); - const id = searchParams.get('id'); +export async function POST(req: NextRequest) { + const body = (await req.json()) as { id: string }; - if (!id) { + if (!body.id) { return NextResponse.json( { error: 'Missing request body parameters' }, { status: 400 } @@ -17,9 +16,9 @@ export async function GET(req: NextRequest) { try { await dbConnect(); - const file = await FileModel.findById(id); + const file = await FileModel.findById(body.id); - if (!file || new Date().getDate() - file.toJSON().updatedAt.getDate() > 5) { + if (!file || file.toJSON().expires.getTime() - Date.now() <= 0) { return NextResponse.json({ error: 'File not found' }, { status: 404 }); } diff --git a/src/app/s/[id]/page.tsx b/src/app/s/[id]/page.tsx index 7bd8ade..f5006a8 100644 --- a/src/app/s/[id]/page.tsx +++ b/src/app/s/[id]/page.tsx @@ -1,4 +1,8 @@ +import { notFound } from 'next/navigation'; +import { extension as mimeExtention } from 'mime-types'; +import Link from 'next/link'; import { Download } from 'lucide-react'; +import { formatBytes } from '@/lib/utils'; import { Card, CardContent, @@ -8,14 +12,33 @@ import { CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; +import type { DropAPIRespData } from '@/types'; + +export const dynamic = 'force-dynamic'; + +type DetailsPageProps = { + params: { + id: string; + }; +}; + +export default async function DetailsPage({ params }: DetailsPageProps) { + const resp = await fetch(`${process.env.NEXT_PUBLIC_URL}/api/drop`, { + method: 'POST', + body: JSON.stringify({ + id: params.id + }) + }); + if (!resp.ok) return notFound(); + + const { success: data } = (await resp.json()) as DropAPIRespData; -export default function DetailsPage() { return (