import passport from "passport" import createError from "http-errors" import autobind from "autobind-decorator" import { catchAll } from "." // The list of functions you can list in options.nonAdmin is: // // listItems // createItem // updateItem // getItem // deleteItem @autobind export class BaseRoutes { constructor(options) { const { container } = options this.options = options this.log = container.log this.db = container.db const basePath = "/" + options.model.collection.collectionName const app = container.app app .route(basePath) .get( passport.authenticate("bearer", { session: false }), catchAll(this.listItems) ) .post( passport.authenticate("bearer", { session: false }), catchAll(this.createItem) ) .put( passport.authenticate("bearer", { session: false }), catchAll(this.updateItem) ) app .route(basePath + "/:_id([a-f0-9]{24})") .get( passport.authenticate("bearer", { session: false }), catchAll(this.getItem) ) .delete( passport.authenticate("bearer", { session: false }), catchAll(this.deleteItem) ) } async listItems(req, res, next) { const isAdmin = !!req.user.administrator if (!this.options.nonAdmin.listItems && !isAdmin) { throw createError.Forbidden() } const ItemModel = this.options.model const limit = req.query.limit || 20 const skip = req.query.skip || 0 const partial = !!req.query.partial let query = {} const total = await ItemModel.count({}) let items = [] let cursor = ItemModel.find(query) .limit(limit) .skip(skip) .cursor() .map((doc) => { return doc.toClient(partial) }) cursor.on("data", (doc) => { items.push(doc) }) cursor.on("end", () => { res.json({ total: total, offset: skip, count: items.length, items: items, }) }) cursor.on("error", (err) => { throw createError.InternalServerError(err.message) }) } async createItem(req, res) { const isAdmin = !!req.user.administrator if (!this.options.nonAdmin.createItem && !isAdmin) { throw createError.Forbidden() } const ItemModel = this.options.model let item = new ItemModel(req.body) const newItem = await item.save() res.json(newItem.toClient()) } async updateItem(req, res) { const isAdmin = !!req.user.administrator if (!this.options.nonAdmin.updateItem && !isAdmin) { throw createError.Forbidden() } // Do this here because Mongoose will add it automatically otherwise if (!req.body._id) { throw createError.BadRequest("No _id given in body") } let ItemModel = this.options.model let item = await ItemModel.findById(req.body._id) if (!item) { throw createError.NotFound(`Item with _id ${_id} was not found`) } item.merge(new ItemModel(req.body)) const savedItem = await item.save() res.json(savedItem.toClient()) } async getItem(req, res) { const isAdmin = !!req.user.administrator if (!this.options.nonAdmin.getItem && !isAdmin) { throw createError.Forbidden() } const ItemModel = this.options.model const _id = req.params._id const item = await ItemModel.findById(_id) if (!item) { throw createError.NotFound(`Item with _id ${_id} not found`) } res.json(item.toClient()) } async deleteItem(req, res) { const isAdmin = !!req.user.administrator if (!this.options.nonAdmin.deleteItem && !isAdmin) { throw createError.Forbidden() } const ItemModel = this.options.model const _id = req.params._id const item = await ItemModel.remove({ _id }) if (!item) { throw createError.NotFound(`Item with _id ${_id} not found`) } res.json({}) } }