From 1b73282e90df66b068d66f9a73fa349e2833c568 Mon Sep 17 00:00:00 2001 From: Tomas Bures Date: Mon, 15 May 2017 16:22:06 -0400 Subject: [PATCH] WiP on namespaces and users --- app.js | 2 + config/default.toml | 15 +++ lib/knex.js | 15 +++ lib/models/namespaces.js | 8 ++ package.json | 1 + public/fancytree/jquery.fancytree-all.min.js | 50 ++++++++ .../skin-bootstrap/ui.fancytree.min.css | 6 + public/fancytree/skin-bootstrap/vline-rtl.gif | Bin 0 -> 842 bytes public/fancytree/skin-bootstrap/vline.gif | Bin 0 -> 844 bytes routes/namespaces.js | 68 +++++++++++ setup/knex/config.js | 9 ++ setup/knex/knexfile.js | 8 ++ setup/knex/migrations/20170506102634_base.js | 75 ++++++++++++ .../20170507083345_create_namespaces.js | 31 +++++ .../20170507084114_create_permissions.js | 51 ++++++++ views/layout.hbs | 24 ++++ views/namespaces/edit.hbs | 39 ++++++ views/namespaces/namespaces.hbs | 111 ++++++++++++++++++ 18 files changed, 513 insertions(+) create mode 100644 lib/knex.js create mode 100644 lib/models/namespaces.js create mode 100644 public/fancytree/jquery.fancytree-all.min.js create mode 100644 public/fancytree/skin-bootstrap/ui.fancytree.min.css create mode 100644 public/fancytree/skin-bootstrap/vline-rtl.gif create mode 100644 public/fancytree/skin-bootstrap/vline.gif create mode 100644 routes/namespaces.js create mode 100644 setup/knex/config.js create mode 100644 setup/knex/knexfile.js create mode 100644 setup/knex/migrations/20170506102634_base.js create mode 100644 setup/knex/migrations/20170507083345_create_namespaces.js create mode 100644 setup/knex/migrations/20170507084114_create_permissions.js create mode 100644 views/namespaces/edit.hbs create mode 100644 views/namespaces/namespaces.hbs diff --git a/app.js b/app.js index f8bad1bf..bbceeceb 100644 --- a/app.js +++ b/app.js @@ -42,6 +42,7 @@ const grapejs = require('./routes/grapejs'); const mosaico = require('./routes/mosaico'); const reports = require('./routes/reports'); const reportsTemplates = require('./routes/report-templates'); +const namespaces = require('./routes/namespaces'); const app = express(); @@ -213,6 +214,7 @@ app.use('/api', api); app.use('/editorapi', editorapi); app.use('/grapejs', grapejs); app.use('/mosaico', mosaico); +app.use('/namespaces', namespaces); if (config.reports && config.reports.enabled === true) { app.use('/reports', reports); diff --git a/config/default.toml b/config/default.toml index 64d45fbe..19067c6f 100644 --- a/config/default.toml +++ b/config/default.toml @@ -177,3 +177,18 @@ templates=[["demo", "Demo Template"]] # The bottom line is that if people who are creating report templates or have write access to the DB cannot be trusted, # then it's safer to switch off the reporting functionality below. enabled=false + + +[shares.list.master] +name="Master" +description="All permissions" +permissions=["view"] + + +[shares.namespace.master] +name="Master" +description="All permissions" + +[shares.namespace.master.permissions] +list=["view"] +namespace=["view", "edit", "create", "delete", "create list"] \ No newline at end of file diff --git a/lib/knex.js b/lib/knex.js new file mode 100644 index 00000000..4a542c42 --- /dev/null +++ b/lib/knex.js @@ -0,0 +1,15 @@ +'use strict'; + +const config = require('config'); + +const knex = require('knex')({ + client: 'mysql', + connection: config.mysql, + migrations: { + directory: __dirname + '/../setup/knex/migrations' + } +}); + +knex.migrate.latest(); + +module.exports = knex; diff --git a/lib/models/namespaces.js b/lib/models/namespaces.js new file mode 100644 index 00000000..51a59005 --- /dev/null +++ b/lib/models/namespaces.js @@ -0,0 +1,8 @@ +'use strict'; + +const config = require('config'); +const knex = require('../knex'); + +module.exports.list = () => { + return knex('namespaces'); +}; diff --git a/package.json b/package.json index 7d82f7cd..20d6140a 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "jquery-file-upload-middleware": "^0.1.8", "jsdom": "^9.12.0", "juice": "^4.0.2", + "knex": "^0.13.0", "libmime": "^3.1.0", "marked": "^0.3.6", "memory-cache": "^0.1.6", diff --git a/public/fancytree/jquery.fancytree-all.min.js b/public/fancytree/jquery.fancytree-all.min.js new file mode 100644 index 00000000..14f7192e --- /dev/null +++ b/public/fancytree/jquery.fancytree-all.min.js @@ -0,0 +1,50 @@ +/*! jQuery Fancytree Plugin - 2.22.4 - 2017-05-06T06:26:23Z + * https://github.com/mar10/fancytree + * Copyright (c) 2017 Martin Wendt; Licensed MIT */ +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + define( [ "jquery" ], factory ); + } else { + factory( jQuery ); + } +}(function( $ ) { + +!function(a,b,c,d){"use strict";function e(b,c){b||(c=c?": "+c:"",a.error("Fancytree assertion failed"+c))}function f(a,c){var d,e,f=b.console?b.console[a]:null;if(f)try{f.apply(b.console,c)}catch(g){for(e="",d=0;dh;return!0}function i(a,b,c,d,e){var f=function(){var c=b[a],f=d[a],g=b.ext[e],h=function(){return c.apply(b,arguments)},i=function(a){return c.apply(b,a)};return function(){var a=b._local,c=b._super,d=b._superApply;try{return b._local=g,b._super=h,b._superApply=i,f.apply(b,arguments)}finally{b._local=a,b._super=c,b._superApply=d}}}();return f}function j(b,c,d,e){for(var f in d)"function"==typeof d[f]?"function"==typeof b[f]?b[f]=i(f,b,c,d,e):"_"===f.charAt(0)?b.ext[e][f]=i(f,b,c,d,e):a.error("Could not override tree."+f+". Use prefix '_' to create tree."+e+"._"+f):"options"!==f&&(b.ext[e][f]=d[f])}function k(b,c){return b===d?a.Deferred(function(){this.resolve()}).promise():a.Deferred(function(){this.resolveWith(b,c)}).promise()}function l(b,c){return b===d?a.Deferred(function(){this.reject()}).promise():a.Deferred(function(){this.rejectWith(b,c)}).promise()}function m(a,b){return function(){a.resolveWith(b)}}function n(b){var c=a.extend({},b.data()),d=c.json;return delete c.fancytree,delete c.uiFancytree,d&&(delete c.json,c=a.extend(c,d)),c}function o(a){return(""+a).replace(y,function(a){return B[a]})}function p(a){return(""+a).replace(z,function(a){return B[a]})}function q(a){return a=a.toLowerCase(),function(b){return b.title.toLowerCase().indexOf(a)>=0}}function r(a){var b=new RegExp("^"+a,"i");return function(a){return b.test(a.title)}}function s(b,c){var d,f,g,h;for(this.parent=b,this.tree=b.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},d=0,f=H.length;dul.fancytree-container").remove();var c,e={tree:this};this.rootNode=new s(e,{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,c=a("
    ",{"class":"ui-fancytree fancytree-container fancytree-plain"}).appendTo(this.$div),this.$container=c,this.rootNode.ul=c[0],null==this.options.debugLevel&&(this.options.debugLevel=w.debugLevel)}if(a.ui&&a.ui.fancytree)return void a.ui.fancytree.warn("Fancytree: ignored duplicate include");var u,v,w=null,x=new RegExp(/\.|\//),y=/[&<>"'\/]/g,z=/[<>"'\/]/g,A="$recursive_request",B={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},C={16:!0,17:!0,18:!0},D={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},E={0:"",1:"left",2:"middle",3:"right"},F="active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),G={},H="expanded extraClasses folder hideCheckbox icon key lazy refKey selected statusNodeType title tooltip unselectable".split(" "),I={},J={},K={active:!0,children:!0,data:!0,focus:!0};for(u=0;u=0,"insertBefore must be an existing child"),this.children.splice.apply(this.children,[g,0].concat(k))),h&&!c){for(d=0,f=k.length;d=0;d--)e=this.children[d],"paging"===e.statusNodeType&&this.removeChild(e);return void(this.partload=!1)}return b=a.extend({title:this.tree.options.strings.moreData,statusNodeType:"paging",icon:!1},b),this.partload=!0,this.addNode(b,c)},appendSibling:function(a){return this.addNode(a,"after")},applyPatch:function(b){if(null===b)return this.remove(),k(this);var c,d,e,f={children:!0,expanded:!0,parent:!0};for(c in b)e=b[c],f[c]||a.isFunction(e)||(I[c]?this[c]=e:this.data[c]=e);return b.hasOwnProperty("children")&&(this.removeChildren(),b.children&&this._setChildren(b.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),d=b.hasOwnProperty("expanded")?this.setExpanded(b.expanded):k(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(a,b,c){return a.addNode(this.toDict(!0,c),b)},countChildren:function(a){var b,c,d,e=this.children;if(!e)return 0;if(d=e.length,a!==!1)for(b=0,c=d;b=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},discardMarkup:function(a){var b=a?"nodeRemoveMarkup":"nodeRemoveChildMarkup";this.tree._callHook(b,this)},findAll:function(b){b=a.isFunction(b)?b:q(b);var c=[];return this.visit(function(a){b(a)&&c.push(a)}),c},findFirst:function(b){b=a.isFunction(b)?b:q(b);var c=null;return this.visit(function(a){if(b(a))return c=a,!1}),c},_changeSelectStatusAttrs:function(a){var b=!1;switch(a){case!1:b=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:b=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case d:b=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:e(!1,"invalid state: "+a)}return b&&this.renderStatus(),b},fixSelection3AfterClick:function(){var a=this.isSelected();this.visit(function(b){b._changeSelectStatusAttrs(a)}),this.fixSelection3FromEndNodes()},fixSelection3FromEndNodes:function(){function a(b){var c,e,f,g,h,i,j,k=b.children;if(k&&k.length){for(i=!0,j=!1,c=0,e=k.length;c=1&&(Array.prototype.unshift.call(arguments,this.toString()),f("info",arguments))},isActive:function(){return this.tree.activeNode===this},isChildOf:function(a){return this.parent&&this.parent===a},isDescendantOf:function(a){if(!a||a.tree!==this.tree)return!1;for(var b=this.parent;b;){if(b===a)return!0;b=b.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var a=this.parent;return!a||a.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var a=this.parent;return!a||a.children[a.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||this.hasChildren()!==d},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isPartload:function(){return!!this.partload},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isPagingNode:function(){return"paging"===this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return this.hasChildren()===d},isVisible:function(){var a,b,c=this.getParentList(!1,!1);for(a=0,b=c.length;a=0;c--)e.push(g[c].setExpanded(!0,b));return a.when.apply(a,e).done(function(){j?d.scrollIntoView(i).done(function(){f.resolve()}):f.resolve()}),f.promise()},moveTo:function(b,c,f){c===d||"over"===c?c="child":"firstChild"===c&&(b.children&&b.children.length?(c="before",b=b.children[0]):c="child");var g,h=this.parent,i="child"===c?b:b.parent;if(this!==b){if(this.parent?i.isDescendantOf(this)&&a.error("Cannot move a node to its own descendant"):a.error("Cannot move system root"),i!==h&&h.triggerModifyChild("remove",this),1===this.parent.children.length){if(this.parent===i)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else g=a.inArray(this,this.parent.children),e(g>=0,"invalid source parent"),this.parent.children.splice(g,1);if(this.parent=i,i.hasChildren())switch(c){case"child":i.children.push(this);break;case"before":g=a.inArray(b,i.children),e(g>=0,"invalid target parent"),i.children.splice(g,0,this);break;case"after":g=a.inArray(b,i.children),e(g>=0,"invalid target parent"),i.children.splice(g+1,0,this);break;default:a.error("Invalid mode "+c)}else i.children=[this];f&&b.visit(f,!0),i===h?i.triggerModifyChild("move",this):i.triggerModifyChild("add",this),this.tree!==b.tree&&(this.warn("Cross-tree moveTo is experimantal!"),this.visit(function(a){a.tree=b.tree},!0)),h.isDescendantOf(i)||h.render(),i.isDescendantOf(h)||i===h||i.render()}},navigate:function(b,c){function d(d){if(d){try{d.makeVisible({scrollIntoView:!1})}catch(e){}return a(d.span).is(":visible")?c===!1?d.setFocus():d.setActive():(d.debug("Navigate: skipping hidden node"),void d.navigate(b,c))}}var e,f,g,h=!0,i=a.ui.keyCode,j=null;switch(b){case i.BACKSPACE:this.parent&&this.parent.parent&&(g=d(this.parent));break;case i.HOME:this.tree.visit(function(b){if(a(b.span).is(":visible"))return g=d(b),!1});break;case i.END:this.tree.visit(function(b){a(b.span).is(":visible")&&(g=b)}),g&&(g=d(g));break;case i.LEFT:this.expanded?(this.setExpanded(!1),g=d(this)):this.parent&&this.parent.parent&&(g=d(this.parent));break;case i.RIGHT:this.expanded||!this.children&&!this.lazy?this.children&&this.children.length&&(g=d(this.children[0])):(this.setExpanded(),g=d(this));break;case i.UP:for(j=this.getPrevSibling();j&&!a(j.span).is(":visible");)j=j.getPrevSibling();for(;j&&j.expanded&&j.children&&j.children.length;)j=j.children[j.children.length-1];!j&&this.parent&&this.parent.parent&&(j=this.parent),g=d(j);break;case i.DOWN:if(this.expanded&&this.children&&this.children.length)j=this.children[0];else for(f=this.getParentList(!1,!0),e=f.length-1;e>=0;e--){for(j=f[e].getNextSibling();j&&!a(j.span).is(":visible");)j=j.getNextSibling();if(j)break}g=d(j);break;default:h=!1}return g||k()},remove:function(){return this.parent.removeChild(this)},removeChild:function(a){return this.tree._callHook("nodeRemoveChild",this,a)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},removeClass:function(a){return this.toggleClass(a,!1)},render:function(a,b){return this.tree._callHook("nodeRender",this,a,b)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},replaceWith:function(b){var c,d=this.parent,f=a.inArray(this,d.children),g=this;return e(this.isPagingNode(),"replaceWith() currently requires a paging status node"),c=this.tree._callHook("nodeLoadChildren",this,b),c.done(function(a){var b=g.children;for(u=0;uv+u-t&&(z=j+q-u+t,y&&(e(y.isRootNode()||a(y.span).is(":visible"),"topNode must be visible"),id?1:-1},e.sort(a),b)for(c=0,d=e.length;c=0,c=c===d?!f:!!c)f||(l+=e+" ",j=!0);else for(;l.indexOf(" "+e+" ")>-1;)l=l.replace(" "+e+" "," ");return this.extraClasses=a.trim(l),j},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return""},triggerModifyChild:function(b,c,d){var e,f=this.tree.options.modifyChild;f&&(c&&c.parent!==this&&a.error("childNode "+c+" is not a child of "+this),e={node:this,tree:this.tree,operation:b,childNode:c||null},d&&a.extend(e,d),f({type:"modifyChild"},e))},triggerModify:function(a,b){this.parent.triggerModifyChild(a,this,b)},visit:function(a,b){var c,d,e=!0,f=this.children;if(b===!0&&(e=a(this),e===!1||"skip"===e))return e;if(f)for(c=0,d=f.length;c=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},enableUpdate:function(a){return a=a!==!1,!!this._enableUpdate==!!a?a:(this._enableUpdate=a,a?(this.debug("enableUpdate(true): redraw ",this._dirtyRoots),this.render()):this.debug("enableUpdate(false)..."),!a)},findAll:function(a){return this.rootNode.findAll(a)},findFirst:function(a){return this.rootNode.findFirst(a)},findNextNode:function(b,c,d){var e=null,f=c.parent.children,g=null,h=function(a,b,c){var d,e,f=a.children,g=f.length,i=f[b];if(i&&c(i)===!1)return!1;if(i&&i.children&&i.expanded&&h(i,0,c)===!1)return!1;for(d=b+1;d