From cb1feec984306aec167cc1909d48fd068f8d6d48 Mon Sep 17 00:00:00 2001 From: Parwat Kunwar Date: Mon, 23 Dec 2024 17:00:54 -0400 Subject: [PATCH] update link routes and add shared_access post api to get the user details from shared linkl --- Client/src/app/api/links/route.ts | 26 +++++++++-- Client/src/app/api/links/shared_access.ts | 54 +++++++++++++++++++++++ Client/src/services/linkService.ts | 8 +++- 3 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 Client/src/app/api/links/shared_access.ts diff --git a/Client/src/app/api/links/route.ts b/Client/src/app/api/links/route.ts index 2e0374a..5fd32b4 100644 --- a/Client/src/app/api/links/route.ts +++ b/Client/src/app/api/links/route.ts @@ -14,8 +14,18 @@ export async function GET(req: NextRequest): Promise { return createErrorResponse('link Id is required.', 400); } - const signedUrl = await LinkService.getFileFromLink(linkIdFromParams); - return NextResponse.json({ message: 'Link URL generated', data: { signedUrl } }, { status: 200 }); + const link = await prisma.link.findUnique({ + where: { + linkId: linkIdFromParams, + }, + }); + + if (!link?.hasSharingOptions && link?.isPublic) { + const signedUrl = await LinkService.getFileFromLink(linkIdFromParams); + return NextResponse.json({ message: 'Link URL generated', data: { signedUrl } }, { status: 200 }); + } else { + return NextResponse.json({ message: 'Link has sharing options enabled', data: { link } }, { status: 200 }); + } } catch (error) { return createErrorResponse('Server error.', 500, error); } @@ -24,21 +34,29 @@ export async function GET(req: NextRequest): Promise { export async function POST(req: NextRequest): Promise { try { const userId = await authenticate(req); - const { documentId, friendlyName, isPublic, emailRequired, passwordRequired, password, linkUrl, expirationTime } = await req.json(); + const { documentId, friendlyName, isPublic, password, expirationTime, hasSharingOptions } = await req.json(); if (!documentId) { return createErrorResponse('Document ID is required.', 400); } + const { linkUrl, linkId } = LinkService.generateLinkDetails(); + + if (expirationTime && new Date(expirationTime) < new Date()) { + return createErrorResponse('Expiration time cannot be in the past.', 400); + } + const newLink = await prisma.link.create({ data: { userId, + linkId, linkUrl, documentId, isPublic: isPublic, - password: password || null, + password: password || null, //TODO: hash password friendlyName: friendlyName || "", expirationTime: expirationTime || null, + hasSharingOptions: hasSharingOptions || false, }, }); diff --git a/Client/src/app/api/links/shared_access.ts b/Client/src/app/api/links/shared_access.ts new file mode 100644 index 0000000..2736bb9 --- /dev/null +++ b/Client/src/app/api/links/shared_access.ts @@ -0,0 +1,54 @@ +import { NextRequest, NextResponse } from 'next/server'; +import LinkService from '@/services/linkService'; +import prisma from '@lib/prisma'; + +export async function POST(req: NextRequest): Promise { + try { + const { linkId, first_name, last_name, email, password } = await req.json(); + + if (!linkId || !first_name || !last_name || !email || !password) { + return createErrorResponse('Link ID, firstName, lastName, email and password are required.', 400); + } + + const link = await prisma.link.findUnique({ + where: { id: linkId }, + }); + + if (!link) { + return createErrorResponse('Link not found.', 404); + } + + if (!link.hasSharingOptions) { + return createErrorResponse('This link does not require sharing options.', 400); + } + + if (password !== link.password) { + return createErrorResponse('Password invalid.', 403); + } + + const linkRecipient = await prisma.linkRecipients.create({ + data: { + linkId, + first_name, + last_name, + email + } + }); + + const signedUrl = await LinkService.getFileFromLink(linkId); + return NextResponse.json({ message: 'Link URL generated', data: { signedUrl } }, { status: 200 }); + } catch (error) { + return createErrorResponse('Server error.', 500, error); + } +} + +function createErrorResponse(message: string, status: number, details?: any) { + if (Array.isArray(details) && details.length === 2) { + const [errorCode, errorMessage] = details; + console.error(`[${new Date().toISOString()}] ${errorMessage}`, details); + return NextResponse.json({ error: errorMessage, details }, { status: errorCode }); + } else { + console.error(`[${new Date().toISOString()}] ${message}`, details); + return NextResponse.json({ error: message, details }, { status }); + } +} diff --git a/Client/src/services/linkService.ts b/Client/src/services/linkService.ts index 2d88a51..f5e2c50 100644 --- a/Client/src/services/linkService.ts +++ b/Client/src/services/linkService.ts @@ -4,10 +4,14 @@ import { SupabaseProvider } from '@/providers/storage/supabase/supabaseProvider' export default class LinkService { - static generateLinkUrl(host: string): string { + static generateLinkDetails(): { linkUrl: string, linkId: string; } { const uniqueId = uuidv4(); + const HOST = process.env.HOST || 'http://localhost:3000'; - return `${host}/${uniqueId}`; + return { + linkId: uniqueId, + linkUrl: `${HOST}/api/links/${uniqueId}` + }; } static async deleteLink(linkId: string): Promise {