deafmissoula-website/server/src/middleware/upload.ts
friday-bot ef8d281b2b v2: MongoDB backend + /manage dashboard
- Replace Express 4 backend with Express 5 + Mongoose 8 + TypeScript 5.8
- Add MongoDB 8.0 container via docker-compose
- Add JWT auth (jose), argon2 password hashing, zod validation, multer uploads
- Models: BoardMember, Event, GalleryItem, Sponsor, Minute, Member, User
- Full CRUD REST API for all content types
- Seed script to populate MongoDB from hardcoded data
- Wire all frontend components to fetch from API (no JSX changes)
- Add /manage dashboard: login + tabs for Board, Events, Gallery, Sponsors, Minutes, Members
- Uploads volume for persistent file storage across deploys
2026-05-27 16:23:12 -06:00

33 lines
1.5 KiB
TypeScript

import multer from 'multer';
import path from 'path';
import fs from 'fs';
const uploadsBase = path.join(__dirname, '../../../uploads');
function storageFor(subdir: string) {
return multer.diskStorage({
destination: (_req, _file, cb) => {
const dir = path.join(uploadsBase, subdir);
fs.mkdirSync(dir, { recursive: true });
cb(null, dir);
},
filename: (_req, file, cb) => {
const unique = `${Date.now()}-${Math.round(Math.random() * 1e6)}`;
cb(null, unique + path.extname(file.originalname));
},
});
}
const imageFilter: multer.Options['fileFilter'] = (_req, file, cb) => {
const allowed = /jpeg|jpg|png|gif|webp/;
cb(null, allowed.test(path.extname(file.originalname).toLowerCase()) && allowed.test(file.mimetype));
};
const pdfFilter: multer.Options['fileFilter'] = (_req, file, cb) => {
cb(null, file.mimetype === 'application/pdf' || path.extname(file.originalname).toLowerCase() === '.pdf');
};
export const uploadHeadshot = multer({ storage: storageFor('headshots'), fileFilter: imageFilter, limits: { fileSize: 5 * 1024 * 1024 } });
export const uploadPhoto = multer({ storage: storageFor('photos'), fileFilter: imageFilter, limits: { fileSize: 10 * 1024 * 1024 } });
export const uploadLogo = multer({ storage: storageFor('sponsors'), fileFilter: imageFilter, limits: { fileSize: 5 * 1024 * 1024 } });
export const uploadMinutes = multer({ storage: storageFor('minutes'), fileFilter: pdfFilter, limits: { fileSize: 20 * 1024 * 1024 } });