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) => { 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) => { 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;