can add images to forum posts and comments
This commit is contained in:
@@ -57,7 +57,38 @@ const uploadMessageImage = multer({
|
||||
}
|
||||
}).single('image');
|
||||
|
||||
// Configure storage for forum images
|
||||
const forumImageStorage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
cb(null, path.join(__dirname, '../uploads/forum'));
|
||||
},
|
||||
filename: function (req, file, cb) {
|
||||
const uniqueId = uuidv4();
|
||||
const ext = path.extname(file.originalname);
|
||||
cb(null, `${uniqueId}${ext}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Factory function to create forum image upload middleware
|
||||
const createForumImageUpload = (maxFiles) => {
|
||||
return multer({
|
||||
storage: forumImageStorage,
|
||||
fileFilter: imageFileFilter,
|
||||
limits: {
|
||||
fileSize: 5 * 1024 * 1024 // 5MB limit per file
|
||||
}
|
||||
}).array('images', maxFiles);
|
||||
};
|
||||
|
||||
// Create multer upload middleware for forum post images (up to 5 images)
|
||||
const uploadForumPostImages = createForumImageUpload(5);
|
||||
|
||||
// Create multer upload middleware for forum comment images (up to 3 images)
|
||||
const uploadForumCommentImages = createForumImageUpload(3);
|
||||
|
||||
module.exports = {
|
||||
uploadProfileImage,
|
||||
uploadMessageImage
|
||||
uploadMessageImage,
|
||||
uploadForumPostImages,
|
||||
uploadForumCommentImages
|
||||
};
|
||||
@@ -38,6 +38,11 @@ const ForumComment = sequelize.define('ForumComment', {
|
||||
isDeleted: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
images: {
|
||||
type: DataTypes.ARRAY(DataTypes.TEXT),
|
||||
allowNull: true,
|
||||
defaultValue: []
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -51,6 +51,11 @@ const ForumPost = sequelize.define('ForumPost', {
|
||||
model: 'ForumComments',
|
||||
key: 'id'
|
||||
}
|
||||
},
|
||||
images: {
|
||||
type: DataTypes.ARRAY(DataTypes.TEXT),
|
||||
allowNull: true,
|
||||
defaultValue: []
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ const express = require('express');
|
||||
const { Op } = require('sequelize');
|
||||
const { ForumPost, ForumComment, PostTag, User } = require('../models');
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
const { uploadForumPostImages, uploadForumCommentImages } = require('../middleware/upload');
|
||||
const logger = require('../utils/logger');
|
||||
const router = express.Router();
|
||||
|
||||
@@ -83,7 +84,7 @@ router.get('/posts', async (req, res) => {
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
attributes: ['id', 'tagName']
|
||||
}
|
||||
];
|
||||
|
||||
@@ -143,7 +144,7 @@ router.get('/posts/:id', async (req, res) => {
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
attributes: ['id', 'tagName']
|
||||
},
|
||||
{
|
||||
model: ForumComment,
|
||||
@@ -195,15 +196,28 @@ router.get('/posts/:id', async (req, res) => {
|
||||
});
|
||||
|
||||
// POST /api/forum/posts - Create new post
|
||||
router.post('/posts', authenticateToken, async (req, res) => {
|
||||
router.post('/posts', authenticateToken, uploadForumPostImages, async (req, res) => {
|
||||
try {
|
||||
const { title, content, category, tags } = req.body;
|
||||
let { title, content, category, tags } = req.body;
|
||||
|
||||
// Parse tags if they come as JSON string (from FormData)
|
||||
if (typeof tags === 'string') {
|
||||
try {
|
||||
tags = JSON.parse(tags);
|
||||
} catch (e) {
|
||||
tags = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Extract image filenames if uploaded
|
||||
const images = req.files ? req.files.map(file => file.filename) : [];
|
||||
|
||||
const post = await ForumPost.create({
|
||||
title,
|
||||
content,
|
||||
category,
|
||||
authorId: req.user.id
|
||||
authorId: req.user.id,
|
||||
images
|
||||
});
|
||||
|
||||
// Create tags if provided
|
||||
@@ -227,7 +241,7 @@ router.post('/posts', authenticateToken, async (req, res) => {
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
attributes: ['id', 'tagName']
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -297,7 +311,7 @@ router.put('/posts/:id', authenticateToken, async (req, res) => {
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
attributes: ['id', 'tagName']
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -388,7 +402,7 @@ router.patch('/posts/:id/status', authenticateToken, async (req, res) => {
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
attributes: ['id', 'tagName']
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -464,7 +478,7 @@ router.patch('/posts/:id/accept-answer', authenticateToken, async (req, res) =>
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
attributes: ['id', 'tagName']
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -490,7 +504,7 @@ router.patch('/posts/:id/accept-answer', authenticateToken, async (req, res) =>
|
||||
});
|
||||
|
||||
// POST /api/forum/posts/:id/comments - Add comment/reply
|
||||
router.post('/posts/:id/comments', authenticateToken, async (req, res) => {
|
||||
router.post('/posts/:id/comments', authenticateToken, uploadForumCommentImages, async (req, res) => {
|
||||
try {
|
||||
const { content, parentCommentId } = req.body;
|
||||
const post = await ForumPost.findByPk(req.params.id);
|
||||
@@ -507,11 +521,15 @@ router.post('/posts/:id/comments', authenticateToken, async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Extract image filenames if uploaded
|
||||
const images = req.files ? req.files.map(file => file.filename) : [];
|
||||
|
||||
const comment = await ForumComment.create({
|
||||
postId: req.params.id,
|
||||
authorId: req.user.id,
|
||||
content,
|
||||
parentCommentId: parentCommentId || null
|
||||
parentCommentId: parentCommentId || null,
|
||||
images
|
||||
});
|
||||
|
||||
// Increment comment count
|
||||
@@ -653,7 +671,7 @@ router.get('/my-posts', authenticateToken, async (req, res) => {
|
||||
{
|
||||
model: PostTag,
|
||||
as: 'tags',
|
||||
attributes: ['tagName']
|
||||
attributes: ['id', 'tagName']
|
||||
}
|
||||
],
|
||||
order: [['createdAt', 'DESC']]
|
||||
|
||||
@@ -131,8 +131,12 @@ app.use(
|
||||
})
|
||||
);
|
||||
|
||||
// Serve static files from uploads directory
|
||||
app.use("/uploads", express.static(path.join(__dirname, "uploads")));
|
||||
// Serve static files from uploads directory with CORS headers
|
||||
app.use(
|
||||
"/uploads",
|
||||
helmet.crossOriginResourcePolicy({ policy: "cross-origin" }),
|
||||
express.static(path.join(__dirname, "uploads"))
|
||||
);
|
||||
|
||||
// Public routes (no alpha access required)
|
||||
app.use("/api/alpha", alphaRoutes);
|
||||
|
||||
Reference in New Issue
Block a user