-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Staging sync #263
base: prod
Are you sure you want to change the base?
Staging sync #263
Changes from all commits
e41a1a7
1362a86
f3b702e
83c3e08
084c3a8
abffc7f
e34569e
f3872a3
779c814
fb22fcd
c95f059
a082791
11a3785
e050d11
f54aba0
0070b80
8d0ef44
d0e6cea
e7ba945
e9bae51
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,6 +2,7 @@ import { NextResponse } from "next/server"; | |||||||||||
import Eventmodel from "@/models/Events"; | ||||||||||||
import connectMongoDB from "@/lib/dbConnect"; | ||||||||||||
import { v4 as uuidv4 } from "uuid"; | ||||||||||||
import { cloudinary } from '@/Cloudinary'; | ||||||||||||
/** | ||||||||||||
* @swagger | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
* /api/events: | ||||||||||||
|
@@ -353,6 +354,38 @@ export async function DELETE(request: Request) { | |||||||||||
{ status: 400 } | ||||||||||||
); | ||||||||||||
} | ||||||||||||
const event = await Eventmodel.findOne({ id: eventid }); | ||||||||||||
|
||||||||||||
if (!event) { | ||||||||||||
return NextResponse.json( | ||||||||||||
{ error: "Event not found" }, | ||||||||||||
{ status: 404 } | ||||||||||||
); | ||||||||||||
} | ||||||||||||
|
||||||||||||
// If there's an image URL, delete it from Cloudinary | ||||||||||||
if (event.imageURL) { | ||||||||||||
try { | ||||||||||||
// Extract public_id from the Cloudinary URL | ||||||||||||
const matches = event.imageURL.match(/\/v\d+\/(.+?)\./); | ||||||||||||
const publicId = matches ? matches[1] : null; | ||||||||||||
|
||||||||||||
if (publicId) { | ||||||||||||
console.log('Attempting to delete image with public ID:', publicId); | ||||||||||||
const result = await cloudinary.uploader.destroy(publicId); | ||||||||||||
console.log('Cloudinary deletion result:', result); | ||||||||||||
} else { | ||||||||||||
console.warn('Could not extract public ID from URL:', event.imageURL); | ||||||||||||
} | ||||||||||||
} catch (cloudinaryError) { | ||||||||||||
console.error("Error deleting image from Cloudinary:", cloudinaryError); | ||||||||||||
// Log detailed error for debugging | ||||||||||||
if (cloudinaryError instanceof Error) { | ||||||||||||
console.error("Error details:", cloudinaryError.message); | ||||||||||||
} | ||||||||||||
// Continue with event deletion even if image deletion fails | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
await Eventmodel.deleteOne({ id: eventid }); | ||||||||||||
return NextResponse.json( | ||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,167 @@ | ||||||||||||||||||||||||||||
import { NextResponse } from "next/server"; | ||||||||||||||||||||||||||||
import { Readable } from "stream"; | ||||||||||||||||||||||||||||
import { cloudinary } from "@/Cloudinary"; | ||||||||||||||||||||||||||||
import { UploadApiResponse } from "cloudinary"; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||
* Handles file uploads and uploads the file to Cloudinary. | ||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||
* @param {Request} request - The incoming HTTP request | ||||||||||||||||||||||||||||
* @returns {Promise<Response>} - A response containing the uploaded image URL or an error message | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
* @swagger | ||||||||||||||||||||||||||||
* /api/upload: | ||||||||||||||||||||||||||||
* post: | ||||||||||||||||||||||||||||
* summary: Upload an image file to Cloudinary | ||||||||||||||||||||||||||||
* description: This endpoint handles image file uploads and uploads the file to Cloudinary. | ||||||||||||||||||||||||||||
* tags: | ||||||||||||||||||||||||||||
* - Events | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
* requestBody: | ||||||||||||||||||||||||||||
* required: true | ||||||||||||||||||||||||||||
* content: | ||||||||||||||||||||||||||||
* multipart/form-data: | ||||||||||||||||||||||||||||
* schema: | ||||||||||||||||||||||||||||
* type: object | ||||||||||||||||||||||||||||
* properties: | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
* file: | ||||||||||||||||||||||||||||
* type: string | ||||||||||||||||||||||||||||
* format: binary | ||||||||||||||||||||||||||||
* description: The image file to be uploaded. | ||||||||||||||||||||||||||||
* responses: | ||||||||||||||||||||||||||||
* 200: | ||||||||||||||||||||||||||||
* description: Successfully uploaded the image | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
* content: | ||||||||||||||||||||||||||||
* application/json: | ||||||||||||||||||||||||||||
* schema: | ||||||||||||||||||||||||||||
* type: object | ||||||||||||||||||||||||||||
* properties: | ||||||||||||||||||||||||||||
* imageUrl: | ||||||||||||||||||||||||||||
* type: string | ||||||||||||||||||||||||||||
* description: The secure URL of the uploaded image | ||||||||||||||||||||||||||||
* 400: | ||||||||||||||||||||||||||||
* description: Bad request, no file uploaded | ||||||||||||||||||||||||||||
* content: | ||||||||||||||||||||||||||||
* application/json: | ||||||||||||||||||||||||||||
* schema: | ||||||||||||||||||||||||||||
* type: object | ||||||||||||||||||||||||||||
* properties: | ||||||||||||||||||||||||||||
* message: | ||||||||||||||||||||||||||||
* type: string | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
* example: "Bad Request" | ||||||||||||||||||||||||||||
* details: | ||||||||||||||||||||||||||||
* type: string | ||||||||||||||||||||||||||||
* example: "No file uploaded" | ||||||||||||||||||||||||||||
* 500: | ||||||||||||||||||||||||||||
* description: Internal server error during upload | ||||||||||||||||||||||||||||
* content: | ||||||||||||||||||||||||||||
* application/json: | ||||||||||||||||||||||||||||
* schema: | ||||||||||||||||||||||||||||
* type: object | ||||||||||||||||||||||||||||
* properties: | ||||||||||||||||||||||||||||
* message: | ||||||||||||||||||||||||||||
* type: string | ||||||||||||||||||||||||||||
* example: "Cloudinary Upload Failed" | ||||||||||||||||||||||||||||
* details: | ||||||||||||||||||||||||||||
* type: string | ||||||||||||||||||||||||||||
* example: "Unknown upload error" | ||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||
export async function POST(request: Request): Promise<Response> { | ||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||
// Parse the form data from the incoming request | ||||||||||||||||||||||||||||
const formData = await request.formData(); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// Retrieve the uploaded file from the form data | ||||||||||||||||||||||||||||
const image: File | null = formData.get("file") as File; | ||||||||||||||||||||||||||||
const name: string | null = formData.get("name") as string; | ||||||||||||||||||||||||||||
const existingUrl: string | null = formData.get("existingUrl") as string; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// Validate if a file was uploaded | ||||||||||||||||||||||||||||
if (!image || !name) { | ||||||||||||||||||||||||||||
return NextResponse.json( | ||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
message: "Bad Request", | ||||||||||||||||||||||||||||
details: "No file uploaded", | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
{ status: 400 } // HTTP 400 Bad Request | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// If there's an existing image, extract its public_id and delete it | ||||||||||||||||||||||||||||
if (existingUrl) { | ||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||
const publicId = existingUrl.split('/').slice(-1)[0].split('.')[0]; | ||||||||||||||||||||||||||||
if (publicId) { | ||||||||||||||||||||||||||||
await cloudinary.uploader.destroy(`events/${publicId}`); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} catch (deleteError) { | ||||||||||||||||||||||||||||
console.error("Error deleting existing image:", deleteError); | ||||||||||||||||||||||||||||
// Continue with upload even if delete fails | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
// Generating a unique public_id using the event name and timestamp | ||||||||||||||||||||||||||||
const uniquePublicId = `${name}-${Date.now()}`; | ||||||||||||||||||||||||||||
// Convert the uploaded file (File object) to a Buffer | ||||||||||||||||||||||||||||
const arrayBuffer = await image.arrayBuffer(); | ||||||||||||||||||||||||||||
const buffer = Buffer.from(arrayBuffer); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// Create a readable stream from the Buffer | ||||||||||||||||||||||||||||
const stream = Readable.from(buffer); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||
// Upload the image to Cloudinary | ||||||||||||||||||||||||||||
const uploadResult: UploadApiResponse = await new Promise( | ||||||||||||||||||||||||||||
(resolve, reject) => { | ||||||||||||||||||||||||||||
const uploadStream = cloudinary.uploader.upload_stream( | ||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
folder: "events", | ||||||||||||||||||||||||||||
public_id: uniquePublicId, | ||||||||||||||||||||||||||||
overwrite: false // Prevent accidental overwrites | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
(error, result) => { | ||||||||||||||||||||||||||||
if (error || !result) { | ||||||||||||||||||||||||||||
reject(error); // Handle upload errors | ||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||
resolve(result); // Resolve with the upload result | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// Pipe the readable stream into the Cloudinary upload stream | ||||||||||||||||||||||||||||
stream.pipe(uploadStream); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// Return the secure URL of the uploaded image as the response | ||||||||||||||||||||||||||||
return NextResponse.json({ | ||||||||||||||||||||||||||||
imageUrl: uploadResult.secure_url, | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
} catch (uploadError) { | ||||||||||||||||||||||||||||
// Log and handle errors during the Cloudinary upload process | ||||||||||||||||||||||||||||
console.error("Cloudinary upload error:", uploadError); | ||||||||||||||||||||||||||||
return NextResponse.json( | ||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
message: "Cloudinary Upload Failed", | ||||||||||||||||||||||||||||
details: | ||||||||||||||||||||||||||||
uploadError instanceof Error | ||||||||||||||||||||||||||||
? uploadError.message | ||||||||||||||||||||||||||||
: "Unknown upload error", | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
{ status: 500 } // HTTP 500 Internal Server Error | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} catch (parseError) { | ||||||||||||||||||||||||||||
// Log and handle errors while parsing form data | ||||||||||||||||||||||||||||
console.error("Error parsing form data:", parseError); | ||||||||||||||||||||||||||||
return NextResponse.json( | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
message: "Invalid Request", | ||||||||||||||||||||||||||||
details: | ||||||||||||||||||||||||||||
parseError instanceof Error | ||||||||||||||||||||||||||||
? parseError.message | ||||||||||||||||||||||||||||
: "Unable to process request", | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
{ status: 400 } // HTTP 400 Bad Request | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.