const express = require("express"); const router = express.Router(); const multer = require("multer"); const path = require("path"); const fs = require("fs").promises; const { requireAuth } = require("../middleware/auth"); const { pool } = require("../config/database"); // Configure multer for file uploads const storage = multer.diskStorage({ destination: async function (req, file, cb) { const uploadDir = path.join(__dirname, "..", "..", "website", "uploads"); try { await fs.mkdir(uploadDir, { recursive: true }); cb(null, uploadDir); } catch (error) { cb(error); } }, filename: function (req, file, cb) { // Generate unique filename const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); const ext = path.extname(file.originalname); const name = path .basename(file.originalname, ext) .replace(/[^a-z0-9]/gi, "-") .toLowerCase(); cb(null, name + "-" + uniqueSuffix + ext); }, }); const upload = multer({ storage: storage, limits: { fileSize: 5 * 1024 * 1024, // 5MB limit }, fileFilter: function (req, file, cb) { // Accept images only if (!file.mimetype.startsWith("image/")) { return cb(new Error("Only image files are allowed!"), false); } cb(null, true); }, }); // Upload multiple files router.post( "/upload", requireAuth, upload.array("files", 10), async (req, res) => { try { const uploadedBy = req.session.user?.id || null; const files = []; // Insert each file into database for (const file of req.files) { const result = await pool.query( `INSERT INTO uploads (filename, original_name, file_path, file_size, mime_type, uploaded_by, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW()) RETURNING id, filename, original_name, file_path, file_size, mime_type, created_at`, [ file.filename, file.originalname, `/uploads/${file.filename}`, file.size, file.mimetype, uploadedBy, ] ); files.push({ id: result.rows[0].id, filename: result.rows[0].filename, originalName: result.rows[0].original_name, size: result.rows[0].file_size, mimetype: result.rows[0].mime_type, path: result.rows[0].file_path, uploadDate: result.rows[0].created_at, }); } res.json({ success: true, message: `${files.length} file(s) uploaded successfully`, files: files, }); } catch (error) { console.error("Upload error:", error); // If database insert fails, clean up uploaded files if (req.files) { for (const file of req.files) { try { await fs.unlink(file.path); } catch (unlinkError) { console.error("Error cleaning up file:", unlinkError); } } } res.status(500).json({ success: false, error: error.message, }); } } ); // Get all uploaded files router.get("/uploads", requireAuth, async (req, res) => { try { // Query files from database const result = await pool.query( `SELECT id, filename, original_name, file_path, file_size, mime_type, uploaded_by, created_at, updated_at, used_in_type, used_in_id FROM uploads ORDER BY created_at DESC` ); const files = result.rows.map((row) => ({ id: row.id, filename: row.filename, originalName: row.original_name, size: row.file_size, mimetype: row.mime_type, path: row.file_path, uploadDate: row.created_at, uploadedBy: row.uploaded_by, usedInType: row.used_in_type, usedInId: row.used_in_id, })); res.json({ success: true, files: files, }); } catch (error) { console.error("Error listing files:", error); res.status(500).json({ success: false, error: error.message, }); } }); // Delete a file router.delete("/uploads/:filename", requireAuth, async (req, res) => { try { const filename = req.params.filename; const uploadDir = path.join(__dirname, "..", "..", "website", "uploads"); const filePath = path.join(uploadDir, filename); // Security check: ensure file is within uploads directory if (!filePath.startsWith(uploadDir)) { return res.status(403).json({ success: false, error: "Invalid file path", }); } // Start transaction: delete from database first const result = await pool.query( "DELETE FROM uploads WHERE filename = $1 RETURNING id", [filename] ); if (result.rowCount === 0) { return res.status(404).json({ success: false, error: "File not found in database", }); } // Then delete physical file try { await fs.unlink(filePath); } catch (fileError) { console.warn("File already deleted from disk:", filename); // Continue anyway since database record is deleted } res.json({ success: true, message: "File deleted successfully", }); } catch (error) { console.error("Error deleting file:", error); res.status(500).json({ success: false, error: error.message, }); } }); module.exports = router;