diff --git a/controllers/resourceController.js b/controllers/resourceController.js index d38e247..f8a114b 100644 --- a/controllers/resourceController.js +++ b/controllers/resourceController.js @@ -7,21 +7,34 @@ exports.fetch = async (req, res) => { // get from query params page and limit (if not provided, default to 1 and 10) const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; + const category = req.query.category || null; // calculateOffset const offset = (page - 1) * limit; const where = {} + if(category) { + where.categoryId = category; + } + // query the database const query = { limit: limit, offset: offset, - where: where + where: where, + include: [ + { + model: models.ResourceCategory, + as: 'category', + attributes: ['id', 'name'], + }, + ], + order: [['updatedAt', 'DESC']], } - const entries = await models.Resource.findAndCountAll(query) + const entries = await models.ResourceEntry.findAndCountAll(query) // return the entries return res.status(200).json(entries); @@ -30,4 +43,201 @@ exports.fetch = async (req, res) => { console.error(error); return res.status(500).json({ message: msg.error.default }); } +} + +exports.fetchOne = async (req, res) => { + try { + const id = req.params.id || null; + + const entry = await models.ResourceEntry.findByPk(id, { + include: [ + { + model: models.ResourceCategory, + as: 'category', + attributes: ['id', 'name'], + }, + ], + }) + + if(!entry) { + return res.status(400).json({ message: msg.error.default }); + } + + return res.status(200).json(entry); + } catch (error) { + console.error(error); + return res.status(500).json({ message: msg.error.default }); + } +} + +exports.create = async (req, res) => { + try { + const { title, description, url, categoryId } = req.body; + + // check the category id exists + + const category = await models.ResourceCategory.findByPk(categoryId) + + if(!category) { + return res.status(400).json({ message: msg.error.default }); + } + + const entry = await models.ResourceEntry.create({ + title, + categoryId, + description: description || null, + url + }) + + return res.status(200).json(entry); + } catch (error) { + console.error(error); + return res.status(500).json({ message: msg.error.default }); + } +} + +exports.update = async (req, res) => { + try { + const id = req.params.id || null; + const { title, description, url, categoryId } = req.body; + + const category = await models.ResourceCategory.findByPk(categoryId) + + if(!category) { + return res.status(400).json({ message: msg.error.default }); + } + + const entry = await models.ResourceEntry.findByPk(id) + + if(!entry) { + return res.status(400).json({ message: msg.error.default }); + } + + + entry.title = title; + entry.categoryId = categoryId; + entry.description = description; + entry.url = url; + await entry.save() + + return res.status(200).json(entry); + } catch (error) { + console.error(error); + return res.status(500).json({ message: msg.error.default }); + } +} + +exports.delete = async (req, res) => { + try { + const id = req.params.id || null; + + const entry = await models.ResourceEntry.findByPk(id) + + if(!entry) { + return res.status(400).json({ message: msg.error.default }); + } + + await entry.destroy(); + + return res.status(200).send() + } catch (error) { + console.error(error); + return res.status(500).json({ message: msg.error.default }); + } +} + +exports.fetchCategories = async (req, res) => { + try { + const categories = await models.ResourceCategory.findAll({ + attributes: ['id', 'name'], + }); + + return res.status(200).json(categories); + } catch (error) { + console.error(error); + return res.status(500).json({ message: msg.error.default }); + } +} + + +exports.createCategory = async (req, res) => { + try { + // get all categories + const { name } = req.body; + + + + const category = await models.ResourceCategory.create({ + name + }) + + return res.status(200).json(category); + + } catch (error) { + console.error(error); + res.status(500).json({ message: msg.error.default }); + } +} + +exports.updateCategory = async (req, res) => { + try { + + const id = req.params.id || null; + + // get all categories + const { name } = req.body; + + const category = await models.ResourceCategory.findByPk(id) + + if(!category) { + return res.status(400).json({ message: msg.error.default }); + } + + category.name = name; + await category.save() + + return res.status(200).json(category); + + } catch (error) { + console.error(error); + res.status(500).json({ message: msg.error.default }); + } +} + +exports.deleteCategory = async (req, res) => { + try { + + const id = req.params.id || null; + + // get all categories + const { categoryId } = req.body; + + const category = await models.ResourceCategory.findByPk(id) + + if(!category) { + return res.status(400).json({ message: msg.error.default }); + } + + const categoryToMigrate = await models.ResourceCategory.findByPk(categoryId) + + if(!categoryToMigrate) { + return res.status(400).json({ message: msg.error.default }); + } + + await models.ResourceEntry.update({ + categoryId: categoryToMigrate.id + }, { + where: { + categoryId: category.id + } + }) + + await category.destroy(); + + return res.status(200).send() + + } catch (error) { + console.error(error); + res.status(500).json({ message: msg.error.default }); + } } \ No newline at end of file diff --git a/routes/resource.js b/routes/resource.js index 38221d6..d588441 100644 --- a/routes/resource.js +++ b/routes/resource.js @@ -1,11 +1,11 @@ const express = require('express'); -const { check, query } = require('express-validator'); +const { check, query, body, param } = require('express-validator'); const validate = require('../middlewares/validate'); const authorize = require('../middlewares/authorize'); const requiresAnon = require('../middlewares/requiresAnon'); const constants = require('../services/constants'); -const ResourceController = require('../controllers/memberController'); +const ResourceController = require('../controllers/resourceController'); const msg = require('../utils/messages'); const uploader = require('../middlewares/s3'); @@ -21,6 +21,92 @@ const router = express.Router(); // PUT /:id // DELETE /:id // ----------------------------------------------- +router.get('/', + [ + query('page').optional().isInt().withMessage(msg.validationError.integer), + query('limit').optional().isInt().withMessage(msg.validationError.integer), + query('category').optional().isInt().withMessage(msg.validationError.integer), + ], + validate, + ResourceController.fetch +) + +router.post('/', + authorize(constants.ROLES.ADMINISTRATOR), + [ + check('title').isString().withMessage("TODO"), + check('categoryId').isInt().withMessage("TODO"), + check('description').optional().isString().withMessage("TODO"), + check('url').isURL().withMessage("Debe ser una URL válida"), + ], + validate, + ResourceController.create +) + + +router.get('/category', + ResourceController.fetchCategories +) + +router.post('/category', + authorize(constants.ROLES.ADMINISTRATOR), + [ + body('name').isString().withMessage("El nuevo nombre es requerido"), + ], + validate, + ResourceController.createCategory +) + +router.put('/category/:id', + authorize(constants.ROLES.ADMINISTRATOR), + [ + param('id').not().isEmpty().withMessage('id is required'), + body('name').isString().withMessage("El nuevo nombre es requerido"), + ], + validate, + ResourceController.updateCategory +) + +router.delete('/category/:id', + authorize(constants.ROLES.ADMINISTRATOR), + [ + param('id').not().isEmpty().withMessage('id is required'), + body('categoryId').isInt().withMessage("El nuevo nombre es requerido"), + ], + validate, + ResourceController.deleteCategory +) + +router.get('/:id', + [ + check('id').isInt().withMessage(msg.validationError.integer), + ], + validate, + ResourceController.fetchOne +); + + +router.put('/:id', + authorize(constants.ROLES.ADMINISTRATOR), + [ + check('title').isString().withMessage("TODO"), + check('categoryId').isInt().withMessage("TODO"), + check('description').optional().isString().withMessage("TODO"), + check('url').isURL().withMessage("Debe ser una URL válida"), + ], + validate, + ResourceController.update +); + +router.delete('/:id', + authorize(constants.ROLES.ADMINISTRATOR), + [ + check('id').isInt().withMessage(msg.validationError.integer), + ], + validate, + ResourceController.delete +); + // -----------------------------------------------