From 617a77b80982eba9eea263cd88a41b803e70a6b6 Mon Sep 17 00:00:00 2001 From: garrettmills Date: Sat, 8 Feb 2020 11:16:04 -0600 Subject: [PATCH] Task #21 - add page controller and page/node api endpoints --- app/controllers/api/v1/Page.controller.js | 104 +++++++++++++++++- app/models/api/Node.model.js | 5 + app/routing/Middleware.js | 1 + .../api/GuaranteeRootNode.middleware.js | 43 ++++++++ app/routing/routers/api/v1.routes.js | 2 + 5 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 app/routing/middleware/api/GuaranteeRootNode.middleware.js diff --git a/app/controllers/api/v1/Page.controller.js b/app/controllers/api/v1/Page.controller.js index dd8168a..a99d3b7 100644 --- a/app/controllers/api/v1/Page.controller.js +++ b/app/controllers/api/v1/Page.controller.js @@ -1,5 +1,6 @@ const Controller = require('libflitter/controller/Controller') const PageModel = require('../../../models/api/Page.model') +const Node = require('../../../models/api/Node.model') /* * Page Controller @@ -29,7 +30,7 @@ class Page extends Controller { } else { page = new PageModel page.CreatedUserId = req.user.id - page.OrgUserId = req.user.id + page.OrgUserId = req.user._id } if ( !req.body.Name ) return res.status(400).message('Missing required: Name').api({}) @@ -52,10 +53,107 @@ class Page extends Controller { } page.UpdatedAt = new Date - page.UpdateUserId = req.user.id + page.UpdateUserId = req.user._id await page.save() - return req.api(page) + return res.api(page) + } + + async get_nodes(req, res) { + const PageId = req.params.PageId + + let page; + if ( PageId ) { + page = await PageModel.findOne({UUID: PageId}) + if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) + if ( !page.accessible_by(req.user) ) return req.security.deny() + } + + const nodes = await Node.find({PageId: page.UUID}); + const assoc_nodes = {} + nodes.forEach(node => { + assoc_nodes[node.UUID] = node + }) + + const return_nodes = []; + for ( const uuid of page.NodeIds ) { + return_nodes.push(assoc_nodes[uuid]) + } + return res.api(return_nodes); + } + + async save_nodes(req, res) { + const PageId = req.params.PageId + + let page; + if ( PageId ) { + page = await PageModel.findOne({UUID: PageId}) + if ( !page ) return res.status(404).message('Page not found with that ID.').api({}) + if ( !page.accessible_by(req.user, 'update') ) return req.security.deny() + } + + const nodes = await Node.find({PageId: page.UUID}) + const assoc_nodes = {} + nodes.forEach(node => { + assoc_nodes[node.UUID] = node + }) + + if ( !Array.isArray(req.body) ) return res.status(400).message('Invalid request body. Should be array of nodes.').api({}) + + const updated_node_ids = [] + for ( let node of req.body ) { + if ( node.UUID && Object.keys(assoc_nodes).includes(node.UUID) ) updated_node_ids.push(node.UUID) + } + + console.log('req body', req.body) + + const updated_nodes = [] + for ( let node of req.body ) { + if ( node.UUID && assoc_nodes[node.UUID] ) { + assoc_nodes[node.UUID].update_from_raw(node) + assoc_nodes[node.UUID].UpdatedAt = new Date + assoc_nodes[node.UUID].UpdateUserId = req.user._id + updated_nodes.push(assoc_nodes[node.UUID]) + } else { + const node_obj = new Node({ + Type: node.Type, + Value: node.Value, + PageId, + CreatedUserId: req.user._id, + UpdateUserId: req.user._id, + }) + await node_obj.save() + + updated_nodes.push(node_obj) + } + } + + // console.log('updated nodes', updated_nodes) + + let delete_nodes = nodes + for ( const node of updated_nodes ) { + await node.save() + delete_nodes = delete_nodes.filter(n => { + return n.UUID !== node.UUID + }) + } + + for ( const node of delete_nodes ) { + await node.delete() + } + + console.log('updated nodes', updated_nodes) + + page.NodeIds = updated_nodes.map(x => x.UUID) + console.log({page}) + await page.save() + + res.api(updated_nodes) + + // Step 1: make sure the updated nodes are updated + // Make sure the deleted nodes are deleted + // Make sure the new nodes are created + // Make sure the order is correct } } diff --git a/app/models/api/Node.model.js b/app/models/api/Node.model.js index 5d92763..5d374ee 100644 --- a/app/models/api/Node.model.js +++ b/app/models/api/Node.model.js @@ -29,6 +29,11 @@ class Node extends Model { const Page = this.model.get("api:Page") return this.belongs_to_one(Page, "PageId", "_id") } + + update_from_raw(data) { + if ( data.Type ) this.Type = data.Type + if ( data.Value ) this.Value = data.Value + } } module.exports = exports = Node; diff --git a/app/routing/Middleware.js b/app/routing/Middleware.js index 7959413..4e5f621 100644 --- a/app/routing/Middleware.js +++ b/app/routing/Middleware.js @@ -10,6 +10,7 @@ */ const Middleware = [ "auth:Utility", + "api:GuaranteeRootNode", // 'MiddlewareName', diff --git a/app/routing/middleware/api/GuaranteeRootNode.middleware.js b/app/routing/middleware/api/GuaranteeRootNode.middleware.js new file mode 100644 index 0000000..76a2424 --- /dev/null +++ b/app/routing/middleware/api/GuaranteeRootNode.middleware.js @@ -0,0 +1,43 @@ +const Middleware = require('libflitter/middleware/Middleware') + +/* + * GuaranteeRootNode Middleware + * ------------------------------------------------------------- + * Put some description here! + */ +class GuaranteeRootNode extends Middleware { + static get services() { + return [...super.services, 'models'] + } + + /* + * Run the middleware test. + * This method is required by all Flitter middleware. + * It should either call the next function in the stack, + * or it should handle the response accordingly. + */ + async test(req, res, next, args = {}){ + const Page = this.models.get('api:Page') + if ( req.user ) { + const root_page = await Page.findOne({ OrgUserId: req.user._id, ParentId: "0" }) + if ( !root_page ) { + const new_page = new Page({ + Name: `${req.user.uid} virtual root`, + OrgUserId: req.user._id, + ParentId: "0", + CreatedUserId: req.user.id, + UpdateUserId: req.user.id, + }) + + await new_page.save() + } + } + + /* + * Call the next function in the stack. + */ + next() + } +} + +module.exports = exports = GuaranteeRootNode diff --git a/app/routing/routers/api/v1.routes.js b/app/routing/routers/api/v1.routes.js index 28a9d4b..7ead9e4 100644 --- a/app/routing/routers/api/v1.routes.js +++ b/app/routing/routers/api/v1.routes.js @@ -38,10 +38,12 @@ const index = { get: { '/hello_world': ['controller::api:v1:Misc.hello_world'], '/page/:PageId': ['controller::api:v1:Page.get_page'], + '/page/:PageId/nodes': ['controller::api:v1:Page.get_nodes'], }, post: { '/page/:PageId/save': ['controller::api:v1:Page.save_page'], + '/page/:PageId/nodes/save': ['controller::api:v1:Page.save_nodes'], }, }