From fd8e018e2a55ae977369f57d23829b13432b5648 Mon Sep 17 00:00:00 2001 From: Marais Devis Date: Wed, 24 Jul 2024 16:47:09 +0200 Subject: [PATCH] Add api route for cloudinary --- .env.example | 5 ++- app/api/imageUpload/route.ts | 18 ++++++++ app/api/postedEvents/deleteEvent/route.ts | 44 ++++++++++++++++++++ app/api/postedEvents/route.ts | 10 ++--- app/profile/[username]/DeleteProfileForm.tsx | 5 +-- package.json | 1 + pnpm-lock.yaml | 22 ++++++++++ 7 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 app/api/imageUpload/route.ts create mode 100644 app/api/postedEvents/deleteEvent/route.ts diff --git a/.env.example b/.env.example index 9d1faa7..a5850ec 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,7 @@ PGDATABASE=xxxxxxxxxxxxxx PGUSERNAME=xxxxxxxxxxxxxx PGPASSWORD=xxxxxxxxxxxxxx -# NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="" +NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=xxxxxx +NEXT_PUBLIC_CLOUDINARY_API_KEY=xxxxxx +CLOUDINARY_API_SECRET=xxxxxx +CLOUDINARY_URL=xxxxxx diff --git a/app/api/imageUpload/route.ts b/app/api/imageUpload/route.ts new file mode 100644 index 0000000..7ba0f88 --- /dev/null +++ b/app/api/imageUpload/route.ts @@ -0,0 +1,18 @@ +import { v2 as cloudinary } from 'cloudinary'; +import { NextRequest, NextResponse } from 'next/server'; + +// eslint-disable-next-line no-restricted-syntax +export async function POST(request: NextRequest): Promise { + const body = (await request.json()) as { + paramsToSign: Record; + }; + + const { paramsToSign } = body; + + const signature = cloudinary.utils.api_sign_request( + paramsToSign, + process.env.CLOUDINARY_API_SECRET as string, + ); + + return NextResponse.json({ signature }); +} diff --git a/app/api/postedEvents/deleteEvent/route.ts b/app/api/postedEvents/deleteEvent/route.ts new file mode 100644 index 0000000..f3f68ee --- /dev/null +++ b/app/api/postedEvents/deleteEvent/route.ts @@ -0,0 +1,44 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { deleteEvent } from '../../../../database/events'; + +type DeleteEventResponseBody = + | { message: string; event?: any } + | { message: string; error?: string }; + +export async function DELETE( + request: NextRequest, +): Promise> { + const { searchParams } = new URL(request.url); + const eventId = searchParams.get('eventId'); + const { sessionToken } = await request.json(); + + if (!sessionToken || !eventId) { + return NextResponse.json( + { + message: 'Invalid request', + error: 'Session token or eventId is missing', + }, + { status: 400 }, + ); + } + + try { + const event = await deleteEvent(sessionToken, parseInt(eventId, 10)); + if (event) { + return NextResponse.json( + { message: 'Event deleted successfully', event }, + { status: 200 }, + ); + } else { + return NextResponse.json( + { message: 'Event not found or session expired' }, + { status: 404 }, + ); + } + } catch (error) { + return NextResponse.json( + { message: 'Internal server error', error: (error as Error).message }, + { status: 500 }, + ); + } +} diff --git a/app/api/postedEvents/route.ts b/app/api/postedEvents/route.ts index e5a149a..7af52f8 100644 --- a/app/api/postedEvents/route.ts +++ b/app/api/postedEvents/route.ts @@ -13,12 +13,10 @@ export type PostEventsResponseBodyPost = export async function POST( request: Request, ): Promise> { - // Task: Create a note for the current logged in user - - // 1. Get the note data from the request + // 1. Get the event data from the request const body = await request.json(); - // 2. Validate notes data with zod + // 2. Validate events data with zod const result = eventSchema.safeParse(body); if (!result.success) { @@ -55,10 +53,10 @@ export async function POST( archived: result.data.archived, })); - // 5. If the note creation fails, return an error + // 5. If the event creation fails, return an error if (!postEvent) { return NextResponse.json( - { error: 'Note not created or access denied creating note' }, + { error: 'Event not created or access denied creating event' }, { status: 500, }, diff --git a/app/profile/[username]/DeleteProfileForm.tsx b/app/profile/[username]/DeleteProfileForm.tsx index 05cd829..dd5285d 100644 --- a/app/profile/[username]/DeleteProfileForm.tsx +++ b/app/profile/[username]/DeleteProfileForm.tsx @@ -15,7 +15,7 @@ export default function DeleteProfileForm({ const handleDelete = async (event: React.FormEvent) => { event.preventDefault(); - const response = await fetch('/api/user/delete', { + const response = await fetch('/api/postedEvents/deleteEvent', { method: 'DELETE', headers: { 'Content-Type': 'application/json', @@ -24,10 +24,9 @@ export default function DeleteProfileForm({ }); if (response.ok) { - router.push('/login'); // Redirect to login page after deletion router.refresh(); } else { - console.error('Failed to delete user'); + console.error('Failed to delete event'); } }; diff --git a/package.json b/package.json index a9a175f..4230df7 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dependencies": { "@upleveled/ley": "^0.8.6", "bcrypt": "^5.1.1", + "cloudinary": "^2.3.0", "dotenv-safe": "^9.1.0", "next": "15.0.0-canary.67", "next-cloudinary": "^6.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3be72c2..86510f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: bcrypt: specifier: ^5.1.1 version: 5.1.1(encoding@0.1.13) + cloudinary: + specifier: ^2.3.0 + version: 2.3.0 dotenv-safe: specifier: ^9.1.0 version: 9.1.0(dotenv@16.4.5) @@ -1386,6 +1389,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + cloudinary@2.3.0: + resolution: {integrity: sha512-QBa/ePVVfVcVOB1Vut236rjAbTZAArzOm0e2IWUkQJSZFS65Sjf+i3DyRGen4QX8GZzrcbzvKI9b8BTHAv1zqQ==} + engines: {node: '>=9'} + co@4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -3164,6 +3171,14 @@ packages: pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + q@1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + deprecated: |- + You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) + querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -5344,6 +5359,11 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + cloudinary@2.3.0: + dependencies: + lodash: 4.17.21 + q: 1.5.1 + co@4.6.0: {} collect-v8-coverage@1.0.2: {} @@ -7518,6 +7538,8 @@ snapshots: pure-rand@6.1.0: {} + q@1.5.1: {} + querystringify@2.2.0: {} queue-microtask@1.2.3: {}