feat: enhance image upload validation and management in CoffeeController

This commit is contained in:
seaznCode 2025-11-29 13:50:48 +01:00
parent 8aebdbb607
commit 1fce1f1831

View File

@ -36,6 +36,14 @@ exports.create = async (req, res) => {
let original_filename = null;
let uploadedKey = null;
if (req.file) {
const allowedMime = ['image/jpeg','image/png','image/webp'];
if (!allowedMime.includes(req.file.mimetype)) {
return res.status(400).json({ error: 'Invalid image type. Allowed: JPG, PNG, WebP' });
}
const maxBytes = 10 * 1024 * 1024; // 10MB
if (req.file.size > maxBytes) {
return res.status(400).json({ error: 'Image exceeds 10MB limit' });
}
const s3 = new S3Client({
region: process.env.EXOSCALE_REGION,
endpoint: process.env.EXOSCALE_ENDPOINT,
@ -50,6 +58,7 @@ exports.create = async (req, res) => {
Key: key,
Body: req.file.buffer,
ContentType: req.file.mimetype,
ACL: 'public-read'
}));
object_storage_id = key;
original_filename = req.file.originalname;
@ -103,11 +112,20 @@ exports.update = async (req, res) => {
const currency = req.body.currency;
const is_featured = req.body.is_featured === undefined ? undefined : (req.body.is_featured === 'true' || req.body.is_featured === true);
const state = req.body.state === undefined ? undefined : (req.body.state === 'false' || req.body.state === false ? false : true);
const removePicture = req.body.removePicture === 'true';
let object_storage_id;
let original_filename;
let uploadedKey = null;
if (req.file) {
const allowedMime = ['image/jpeg','image/png','image/webp'];
if (!allowedMime.includes(req.file.mimetype)) {
return res.status(400).json({ error: 'Invalid image type. Allowed: JPG, PNG, WebP' });
}
const maxBytes = 10 * 1024 * 1024; // 10MB
if (req.file.size > maxBytes) {
return res.status(400).json({ error: 'Image exceeds 10MB limit' });
}
const s3 = new S3Client({
region: process.env.EXOSCALE_REGION,
endpoint: process.env.EXOSCALE_ENDPOINT,
@ -117,7 +135,7 @@ exports.update = async (req, res) => {
},
});
const key = `coffee/products/${Date.now()}_${req.file.originalname}`;
await s3.send(new PutObjectCommand({ Bucket: process.env.EXOSCALE_BUCKET, Key: key, Body: req.file.buffer, ContentType: req.file.mimetype }));
await s3.send(new PutObjectCommand({ Bucket: process.env.EXOSCALE_BUCKET, Key: key, Body: req.file.buffer, ContentType: req.file.mimetype, ACL: 'public-read' }));
object_storage_id = key;
original_filename = req.file.originalname;
uploadedKey = key;
@ -127,6 +145,29 @@ exports.update = async (req, res) => {
const current = await CoffeeService.get(id);
if (!current) return res.status(404).json({ error: 'Not found' });
// If removePicture requested and no new file uploaded, clear existing object_storage_id
if (removePicture && !object_storage_id) {
object_storage_id = null;
original_filename = null;
// Delete previous object if exists
if (current && current.object_storage_id) {
try {
const s3del = new S3Client({
region: process.env.EXOSCALE_REGION,
endpoint: process.env.EXOSCALE_ENDPOINT,
credentials: {
accessKeyId: process.env.EXOSCALE_ACCESS_KEY,
secretAccessKey: process.env.EXOSCALE_SECRET_KEY,
},
});
await s3del.send(new DeleteObjectCommand({ Bucket: process.env.EXOSCALE_BUCKET, Key: current.object_storage_id }));
logger.info('[CoffeeController.update] removed existing picture', { id });
} catch (delErr) {
logger.warn('[CoffeeController.update] remove existing picture failed', { id, msg: delErr.message });
}
}
}
const updated = await CoffeeService.update(id, {
title: title ?? current.title,
description: description ?? current.description,