periodicjs.ext.user_access_control
Version:
A user access control extension for Periodicjs that uses user roles and user privleges to controll access
755 lines (709 loc) • 25.4 kB
JavaScript
'use strict';
var path = require('path'),
Promisie = require('promisie'),
userController,
CoreUtilities,
CoreController,
appSettings,
mongoose,
User,
Userrole,
Userprivilege,
Usergroup,
logger;
/**
* creates a new uac document (user role, user group, or use privilege)
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var createUACObject = function(req,res,next, reqcontrollerdatauacobject, model, redirectpath){
if(reqcontrollerdatauacobject){
CoreController.handleDocumentQueryRender({
req:req,
res:res,
responseData:{
result:'success',
data:{
doc:reqcontrollerdatauacobject
}
}
});
}
else{
var newuacobject = CoreUtilities.removeEmptyObjectValues(req.body);
newuacobject.name = CoreUtilities.makeNiceName(newuacobject.title);
newuacobject.author = req.user._id;
CoreController.createModel({
model:model,
newdoc:newuacobject,
res:res,
req:req,
successredirect:redirectpath,
appendid:true
});
}
};
/**
* create a new user group
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var createUsergroup = function(req, res, next) {
var reqcontrollerdataobj = (req.controllerData.usergroup)? req.controllerData.usergroup : null;
createUACObject(req, res, next, reqcontrollerdataobj, Usergroup, '/p-admin/uac/usergroup/edit/');
};
/**
* create a new user role
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var createUserrole = function(req, res, next) {
var reqcontrollerdataobj = (req.controllerData.userrole)? req.controllerData.userrole : null;
createUACObject(req, res, next, reqcontrollerdataobj, Userrole, '/p-admin/uac/userrole/edit/');
};
/**
* create a new user privilege
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var createUserprivilege = function(req, res, next) {
var reqcontrollerdataobj = (req.controllerData.userprivilege)? req.controllerData.userprivilege : null;
createUACObject(req, res, next, reqcontrollerdataobj, Userprivilege, '/p-admin/uac/userprivilege/edit/');
};
var skipInvalid = function(req,res, next){
req.controllerData = (req.controllerData)?req.controllerData:{};
req.controllerData.skipIfInvalid =true;
next();
};
/**
* loads a UAC document (privilege,role or group) with population
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUacObject = function(req,res,next,population,model,objecttype){
var params = req.params,
docid = params.id;
// console.log("docid",docid);
req.controllerData = (req.controllerData)?req.controllerData:{};
CoreController.loadModel({
docid:docid,
model:model,
population:population,
callback:function(err,doc){
if(err){
CoreController.handleDocumentQueryErrorResponse({
err:err,
res:res,
req:req
});
}
else if(!doc && req.controllerData.skipIfInvalid){
next();
}
else if(!doc){
CoreController.handleDocumentQueryErrorResponse({
err:new Error('invalid request'),
res:res,
req:req
});
}
else{
switch(objecttype){
case 'usergroup':
req.controllerData.usergroup = doc;
next();
break;
case 'userrole':
req.controllerData.userrole = doc;
next();
break;
case 'userprivilege':
req.controllerData.userprivilege = doc;
next();
break;
}
}
}
});
};
/**
* loads a user group, populated with it's roles
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUsergroup = function(req,res,next){
loadUacObject(req, res, next, 'roles', Usergroup, 'usergroup');
};
/**
* loads a user role, populated with it's privileges
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUserrole = function(req,res,next){
loadUacObject(req, res, next, 'privileges', Userrole, 'userrole');
};
/**
* loads a user privilege
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUserprivilege = function(req,res,next){
loadUacObject(req, res, next, null, Userprivilege, 'userprivilege');
};
/**
* loads a uac objects
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUacObjects = function(req,res,next,population,model,objecttype){
var query,
offset = req.query.offset,
sort = req.query.sort,
limit = req.query.limit,
searchRegEx = new RegExp(CoreUtilities.stripTags(req.query.search), 'gi');
req.controllerData = (req.controllerData)?req.controllerData:{};
if(req.query.search===undefined || req.query.search.length<1){
query={};
}
else{
query = {
$or: [{
title: searchRegEx,
}, {
'name': searchRegEx,
}]
};
}
CoreController.searchModel({
model:model,
query:query,
sort:sort,
limit:limit,
offset:offset,
population:population,
callback:function(err,documents){
if(err){
CoreController.handleDocumentQueryErrorResponse({
err:err,
res:res,
req:req
});
}
else{
switch(objecttype){
case 'usergroup':
req.controllerData.usergroups = documents;
next();
break;
case 'userrole':
req.controllerData.userroles = documents;
next();
break;
case 'userprivilege':
req.controllerData.userprivileges = documents;
next();
break;
}
}
}
});
};
/**
* loads a user groups, populated with roles
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUsergroups = function(req,res,next){
loadUacObjects(req, res, next, 'roles', Usergroup, 'usergroup');
};
/**
* loads a user roles, populated with privileges
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUserroles = function(req,res,next){
loadUacObjects(req, res, next, 'privileges', Userrole, 'userrole');
};
/**
* loads a user privileges
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUserprivileges = function(req,res,next){
loadUacObjects(req, res, next, null, Userprivilege, 'userprivilege');
};
/**
* loads a user groups, populated with roles
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var searchResults = function(title,data,req,res){
CoreController.getPluginViewDefaultTemplate(
{
viewname:'search/index',
themefileext:appSettings.templatefileextension
},
function(err,templatepath){
CoreController.handleDocumentQueryRender({
res:res,
req:req,
renderView:templatepath,
responseData:{
pagedata: {
title:title
},
uacdata:data,
user: CoreUtilities.removePrivateInfo(req.user)
}
});
}
);
};
/**
* search results for user roles
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var userroleResults = function(req,res,next){
searchResults('User Role Search Results',req.controllerData.userroles,req,res,next);
};
/**
* search results for user privileges
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var userprivilegeResults = function(req,res,next){
searchResults('User Privilege Search Results',req.controllerData.userprivileges,req,res,next);
};
/**
* search results for user groups
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var usergroupResults = function(req,res,next){
searchResults('User Group Search Results',req.controllerData.usergroups,req,res,next);
};
/**
* load users with access control populated
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUacUsers = function(req,res,next){
var query,
population = 'extensionattributes userasset userroles',
orQuery = [];
userController.getUsersData({
req: req,
res: res,
next: next,
population: population,
query: query,
orQuery: orQuery
});
};
/**
* loads user groups
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var loadUserAccesControls = function(req,res,next){
var query,
offset = req.query.offset,
sort = req.query.sort,
limit = req.query.limit,
population = 'privileges',
searchRegEx = new RegExp(CoreUtilities.stripTags(req.query.search), 'gi');
req.controllerData = (req.controllerData)?req.controllerData:{};
if(req.query.search===undefined || req.query.search.length<1){
query={};
}
else{
query = {
$or: [{
title: searchRegEx,
}, {
'name': searchRegEx,
}]
};
}
CoreController.searchModel({
model:Userrole,
query:query,
sort:sort,
limit:limit,
offset:offset,
population:population,
callback:function(err,documents){
if(err){
CoreController.handleDocumentQueryErrorResponse({
err:err,
res:res,
req:req
});
}
else{
req.controllerData.userroles = documents;
next();
}
}
});
};
/**
* searches uac objects
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var uacSearchResults = function(req,res,next,objecttype){
var responseData ={};
switch(objecttype){
case 'usergroup':
responseData = {
pagedata: {
title: 'User Group Results'
},
usergroups: req.controllerData.usergroups,
user: CoreUtilities.removePrivateInfo(req.user)
};
break;
case 'userrole':
responseData = {
pagedata: {
title: 'User Roles Results'
},
userroles: req.controllerData.userroles,
user: CoreUtilities.removePrivateInfo(req.user)
};
break;
case 'userprivilege':
responseData = {
pagedata: {
title: 'User Roles Results'
},
userprivileges: req.controllerData.userprivileges,
user: CoreUtilities.removePrivateInfo(req.user)
};
break;
}
CoreController.getPluginViewDefaultTemplate({
viewname: 'search/index',
themefileext: appSettings.templatefileextension
},
function (err, templatepath) {
CoreController.handleDocumentQueryRender({
res: res,
req: req,
renderView: templatepath,
responseData: responseData
});
}
);
};
/**
* searches user roles
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var userroleSearchResults = function(req,res,next){
uacSearchResults(req,res,next,'userrole');
};
/**
* searches user privileges
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var userprivilegeSearchResults = function(req,res,next){
uacSearchResults(req,res,next,'userprivilege');
};
/**
* searches user groups
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var usergroupSearchResults = function(req,res,next){
uacSearchResults(req,res,next,'usergroup');
};
var stageUserRoles = function (user) {
return Promisie.promisify(User.populate, User)(user, {
path: 'userroles.privileges',
model: 'Userprivilege'
})
.then(populated => {
let privileges = {};
for (let i = 0; i < populated.userroles.length; i++) {
let roles = populated.userroles[i];
for (let x = 0; x < roles.privileges.length; x++) {
privileges[roles.privileges[x].userprivilegeid] = roles.privileges[x];
}
}
return privileges;
})
.catch(e => Promisie.reject(e));
};
var loadUserRoles = function(req,res,next){
var requserroles = {};
req.controllerData = (req.controllerData)?req.controllerData:{};
if(req.isAuthenticated()){
if(req.session && req.session.userprivilegesdata /* && true===false */){
req.user.privileges = req.session.userprivilegesdata;
req.controllerData.userprivileges = req.session.userprivilegesdata;
next();
}
else{
if (req.user && Array.isArray(req.user.userroles) && req.user.userroles[0] && !req.user.userroles.privileges) {
Promisie.promisify(User.populate, User)(req.user, {
path: 'userroles',
model: 'Userrole'
})
.then(stageUserRoles)
.then(privileges => {
req.user.privileges = privileges;
req.session.userprivilegesdata = privileges;
req.controllerData.userprivileges = privileges;
next();
})
.catch(next);
}
else {
stageUserRoles(req.user)
.then(privileges => {
req.user.privileges = privileges;
req.session.userprivilegesdata = privileges;
req.controllerData.userprivileges = privileges;
next();
})
.catch(next);
}
}
}
else{
next();
}
};
/**
* check user access for admin section
* @param {object} req
* @param {object} res
* @return {object} reponds with an error page or requested view
*/
var check_user_access = function(req,res,next){
var httpmethod = req.method,
httpurl = path.resolve(req.originalUrl.toLowerCase());
// console.log(req.user.acounttype);
// console.log(req.method,req.originalUrl);
// http://stackoverflow.com/questions/6579308/javascript-inoperant-switch-case-with-a-regex
// var testme = "pwd_foo", response;
// var reg = /^pwd.+/;
switch (true) {
// case testme=='pwd':
// response = 'case1';
// break;
// case reg.test(testme):
// response = 'case2';
// break;
case httpurl==='/p-admin/items' || httpurl==='/p-admin/collections' || httpurl==='/p-admin/contenttypes' || httpurl==='/p-admin/tags' || httpurl==='/p-admin/categories' || httpurl==='/p-admin/assets' :
if(!User.hasPrivilege(req.user,110)){
next(new Error('EXT-UAC110: You don\'t have access to view content'));
}
else{
next();
}
break;
case httpurl==='/p-admin/item/new' || httpurl==='/p-admin/collection/new' || httpurl==='/item/new' || httpurl==='/tag/new' || httpurl==='/collection/new' || httpurl==='/category/new' || httpurl==='/contenttype/new':
if(!User.hasPrivilege(req.user,110)){
next(new Error('EXT-UAC110: You don\'t have access to create content'));
}
else if(!User.hasPrivilege(req.user,310)){
next(new Error('EXT-UAC310: You don\'t have access to create content'));
}
else{
next();
}
break;
case httpurl==='/item/new':
if(httpmethod==='POST' && !User.hasPrivilege(req.user,310)){
next(new Error('EXT-UAC310: You don\'t have access to publish new content'));
}
else{
next();
}
break;
case (/p-admin\/item/gi.test(httpurl)) :
if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,710)){
next(new Error('EXT-UAC710: You don\'t have access to modify content'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,710)){
next(new Error('EXT-UAC710: You don\'t have access to delete content'));
}
else{
next();
}
break;
case (/p-admin\/collection/gi.test(httpurl)) :
if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,710)){
next(new Error('EXT-UAC710: You don\'t have access to modify content'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,910)){
next(new Error('EXT-UAC910: You don\'t have access to delete content'));
}
else{
next();
}
break;
case (/p-admin\/theme/gi.test(httpurl)) :
if(!User.hasPrivilege(req.user,120)){
next(new Error('EXT-UAC120: You don\'t have access to view themes'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,320)){
next(new Error('EXT-UAC320: You don\'t have access to install themes'));
}
else if(/enable/gi.test(httpurl) && !User.hasPrivilege(req.user,720)){
next(new Error('EXT-UAC720: You don\'t have access to modify themes'));
}
else if(/delete/gi.test(httpurl) && !User.hasPrivilege(req.user,920)){
next(new Error('EXT-UAC920: You don\'t have access to delete themes'));
}
else{
next();
}
break;
case (/p-admin\/extension/gi.test(httpurl)) :
if(!User.hasPrivilege(req.user,130)){
next(new Error('EXT-UAC130: You don\'t have access to view extensions'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,330)){
next(new Error('EXT-UAC330: You don\'t have access to install extensions'));
}
else if(/enable/gi.test(httpurl) && !User.hasPrivilege(req.user,730)){
next(new Error('EXT-UAC730: You don\'t have access to modify extensions'));
}
else if(/disable/gi.test(httpurl) && !User.hasPrivilege(req.user,730)){
next(new Error('EXT-UAC730: You don\'t have access to modify extensions'));
}
else if(/delete/gi.test(httpurl) && !User.hasPrivilege(req.user,930)){
next(new Error('EXT-UAC920: You don\'t have access to delete extensions'));
}
else{
next();
}
break;
case (/p-admin\/setting/gi.test(httpurl)) :
if(!User.hasPrivilege(req.user,140)){
next(new Error('EXT-UAC140: You don\'t have access to view settings'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,740)){
next(new Error('EXT-UAC740: You don\'t have access to modify settings'));
}
else{
next();
}
break;
case httpurl==='/p-admin/users':
if(!User.hasPrivilege(req.user,150)){
next(new Error('EXT-UAC150: You don\'t have access to view users'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,350)){
next(new Error('EXT-UAC350: You don\'t have access to add new users'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,750)){
next(new Error('EXT-UAC750: You don\'t have access to modify users'));
}
else if(/delete/gi.test(httpurl) && !User.hasPrivilege(req.user,950)){
next(new Error('EXT-UAC950: You don\'t have access to delete users'));
}
else{
next();
}
break;
case (/p-admin\/userrole/gi.test(httpurl)) :
if(!User.hasPrivilege(req.user,160)){
next(new Error('EXT-UAC160: You don\'t have access to view users access'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,360)){
next(new Error('EXT-UAC320: You don\'t have access to modify user access'));
}
else if(httpmethod.toLowerCase()==='post' && !User.hasPrivilege(req.user,760)){
next(new Error('EXT-UAC750: You don\'t have access to modify user access'));
}
else if(/delete/gi.test(httpurl) && !User.hasPrivilege(req.user,960)){
next(new Error('EXT-UAC960: You don\'t have access to delete user roles'));
}
else{
next();
}
break;
default:
next();
break;
}
};
/**
* user access control controller
* @module uacController
* @{@link https://github.com/typesettin/periodicjs.ext.user_access_control}
* @author Yaw Joseph Etse
* @copyright Copyright (c) 2014 Typesettin. All rights reserved.
* @license MIT
* @requires module:periodicjs.core.utilities
* @requires module:periodicjs.core.controller
* @requires module:path
* @param {object} resources variable injection from current periodic instance with references to the active logger and mongo session
* @return {object} userlogin
*/
var controller = function(resources,UserModel,UserController){
logger = resources.logger;
mongoose = resources.mongoose;
appSettings = resources.settings;
CoreController = resources.core.controller;
CoreUtilities = resources.core.utilities;
User = UserModel || mongoose.model('User');
Userrole = mongoose.model('Userrole');
Userprivilege = mongoose.model('Userprivilege');
Usergroup = mongoose.model('Usergroup');
userController = UserController || resources.app.controller.native.user;
// console.log('userController',userController);
return{
skipInvalid: skipInvalid,
createUserprivilege:createUserprivilege,
loadUserprivilege:loadUserprivilege,
loadUserprivileges:loadUserprivileges,
userprivilegeSearchResults:userprivilegeSearchResults,
userprivilegeResults:userprivilegeResults,
createUserrole:createUserrole,
loadUserrole:loadUserrole,
loadUserroles:loadUserroles,
userroleSearchResults:userroleSearchResults,
userroleResults:userroleResults,
createUsergroup:createUsergroup,
loadUsergroup:loadUsergroup,
loadUsergroups:loadUsergroups,
usergroupSearchResults:usergroupSearchResults,
usergroupResults:usergroupResults,
loadUserRoles:loadUserRoles,
check_user_access:check_user_access,
loadUacUsers:loadUacUsers,
loadUserAccesControls:loadUserAccesControls
};
};
module.exports = controller;