const User = require('../../models/User'); const Category = require('../../models/Category'); const Post = require('../../models/Post'); const config = require('../../config'); const { authenticateEndpoint } = require('./authfunctions'); const mongoose = require('mongoose'); const { body, param, validationResult } = require('express-validator'); const express = require('express'); const app = express.Router(); mongoose.connect(config.mongoUrl, {useNewUrlParser: true, useUnifiedTopology: true}); const rateLimit = require("express-rate-limit"); const createLimiter = rateLimit({ windowMs: 2 * 60 * 1000, max: 10, }); app.post('/category/create', [ createLimiter, body('title').not().isEmpty().trim().isLength({ min: 3, max: 32 }).escape() ], authenticateEndpoint(async (req, res, user) => { const errors = validationResult(req); if (!errors.isEmpty()) { res.status(400).json({ error: true, message: 'ERROR_REQUEST_INVALID_DATA', errors: errors.array() }); return; } const title = req.body.title; const category = await Category.create({ title: title, creator: user._id, posts: [] }); res.status(200).json({ error: false, message: 'SUCCESS_CATEGORY_CREATED', category: category.getPublicObject() }); }, undefined, config.roleMap.USER)); app.post('/post/create', [ createLimiter, body('category').not().isEmpty().trim().escape().isLength({ min: 24, max: 24 }), body('title').not().isEmpty().trim().isLength({ min: 3, max: 32 }).escape(), body('body').not().isEmpty().trim().isLength({ min: 3, max: 1000 }).escape(), ], authenticateEndpoint(async (req, res, user) => { const errors = validationResult(req); if (!errors.isEmpty()) { res.status(400).json({ error: true, message: 'ERROR_REQUEST_INVALID_DATA', errors: errors.array() }); return; } const category = req.body.category; const title = req.body.title; const content = req.body.body; const post = new Post(); post.title = title; post.body = content; post.creator = user._id; post.category = category; const r = await Category.updateOne({ _id: category }, { $push: { posts: post } }); if (r.n < 1) { res.status(404).json({ error: true, message: 'ERROR_CATEGORY_NOT_FOUND' }); return; } res.status(200).json({ error: false, message: 'SUCCESS_POST_CREATED', post: { _id: post._id } }); }, undefined, config.roleMap.USER)); app.get('/category/:category/info', [ param('category').not().isEmpty().trim().escape().isLength({ min: 24, max: 24 }) ], authenticateEndpoint(async (req, res, user) => { const errors = validationResult(req); if (!errors.isEmpty()) { res.status(400).json({ error: true, message: 'ERROR_REQUEST_INVALID_DATA', errors: errors.array() }); return; } const categoryId = req.params.category; const category = await Category.findById(categoryId).populate('posts.creator', User.getPulicFields()); // TODO: Implement subscribing to a channel and stuff const users = await User.find().sort({ _id: -1 }).limit(50).select(User.getPulicFields()) if (!category) { res.status(404).json({ error: true, message: 'ERROR_CATEGORY_NOT_FOUND' }); return; } res.status(200).json({ error: false, message: 'SUCCESS_CATEGORY_DATA_FETCHED', category: category.getPublicObject(), userInfo: { userListLimit: 50, users: users } }); }, undefined, config.roleMap.USER)); app.get('/category/list', authenticateEndpoint(async (req, res, user) => { let count = parseInt(req.query.count); if (!Number.isInteger(count)) { count = 10; } // TODO: This is probably not efficient const categories = await Category.find().sort({ _id: -1 }).limit(count).select('-posts -__v').populate('creator', User.getPulicFields()); res.status(200).json({ error: false, message: 'SUCCESS_CATEGORY_LIST_FETCHED', categories }); }, undefined, config.roleMap.USER)); module.exports = app;