Socket
Socket
Sign inDemoInstall

express-dynacl

Package Overview
Dependencies
0
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.0 to 2.0.0

169

index.js

@@ -0,106 +1,127 @@

var dynacl = (function(){
// initiate variable to store options
var options = {};
// initiate variable to store options
var options = {};
// default options to be overriden by dynacl.config
const defaultOptions = {
roles: {},
// function to evaluate single permission
function evalPermission(permission,req){
userRoles: req => req.user ? req.user.roles : [],
// if permission is a function, then evaluate its return value
if(typeof permission == 'function') return (permission(req) === true);
defaultRole: "guest",
// if permission is boolean true, then evaluate the value
else if (permission === true) return true;
logString: (action,permission,role,req) => "DynACL " + (permission ? "OK" : "XX") + " ( action: " + action + (role ? ", role: " + role : "") + " )",
logConsole: false,
// if permission unspecified or misspecified, return false
else return false;
}
authorized: (req,res,next) => next(),
unauthorized: (req,res,next) => res.sendStatus(401)
}
// function to get user roles and evaluate permissions
async function checkCan(action,req,params){
// function to get user roles and evaluate permissions
function evalACL(resource,operation,req){
// get user roles
var userRoles = options.userRoles(req)
// get simple reference to acl roles
var aclRoles = options.roles || {};
// clear the user roles array
var currentRoles = [];
// add default role
if(options.defaultRole) userRoles.push(options.defaultRole);
// throw an error on invalid user roles
var rolesProperty = options.rolesProperty || "roles";
var userRoles = req.user && req.user[rolesProperty] ? req.user[rolesProperty] : [];
// add default roles
if(options.defaultRoles) userRoles = userRoles.concat(options.defaultRoles);
// add default user roles
if(options.userRoles) userRoles = userRoles.concat(options.userRoles);
// default is no permission
var permission = false;
// go through all roles and check if some has permission
var roleName;
while(!!(roleName = userRoles.shift())){
// if strict roles property is set to true, then nonexistent roles will throw error
if(options.strictRoles){
if(userRoles.some(role => !aclRoles[role])) throw new Error("Invalid role: " + role);
}
userRoles.push("dsaads");
// wait for the result
let result = await checkRoleCan(roleName,action,req,params);
// if permitted, save and stop going through the roles
if(result === true) {
permission = true;
break;
}
// set user roles
userRoles
.filter(role => aclRoles[role]) // filter out invalid roles
.forEach(role => currentRoles.push(aclRoles[role])); // assign roles to currentRoles array
}
// go through all roles and check if some has permission, otherwise return false
return currentRoles.some(role => {
// log permission check
if(options.logConsole){
let logString = options.logString(action,permission,roleName,req);
if(permission) console.log(logString);
else console.error(logString);
}
// in case we have set permission for resource and action
if(role[resource] && role[resource][operation]) return evalPermission(role[resource][operation],req);
// return the permission
return permission;
}
// in case we have set permission for resource and default action
else if(role[resource] && role[resource]["*"]) return evalPermission(role[resource]["*"],req);
async function checkRoleCan(roleName,action,req,params){
// in case we have set default permission
else if(role["*"]) return evalPermission(role["*"],req);
// get the role details
let role = options.roles[roleName];
// if role does not exists user can't
if(!role) return false;
// in case we have admin role, we dont have to check anything
if(role.admin) return true;
// if nothing is set, user does not have permission
else return false;
});
}
// in case we have set permission for resource and action
if(role.can[action]){
let permission = role.can[action];
// if permission is a function, then evaluate its return value, otherwise evaluate the permission,
// both Promise and static value will be resolved
let result = await Promise.resolve(typeof permission === 'function' ? permission(req,params) : permission);
if(result) return true;
}
// in case the role inherits, we check the parent role
if(role.inherits){
// middleware factory
function dynacl(resource,operation){
let result = await checkRoleCan(options.roles[role.inherits],action,req,params);
// return middleware function for ExpressJS
return function(req,res,next){
if(result) return true;
}
// evaluate permission
var result = evalACL(resource,operation,req);
return false;
}
// log access
var logString = "ACL " + (result ? "OK" : "XX") + ": " + resource + "/" + operation + (req.user ? " (user: " + req.user._id + "; roles: " + (req.user.roles ? req.user.roles.join(",") : "") + ")" : " (guest)");
if(options.logConsole) console.log(logString);
//TODO: logFile
// if permission granted, send execution to the next middleware/route
if(result) next();
// middleware factory
function dynacl(action){
// if permission not granted, then end request with 401 Unauthorized
else res.status(401).send("Unauthorized (" + (req.user ? "logged, no authorization" : "not logged") + ")");
// return middleware function for ExpressJS
return async function(req,res,next){
}
}
// evaluate permission
var result = await checkCan(action,req,{});
// function to configure DynACL
dynacl.config = function(setOptions){
// assign configurations
options = setOptions;
}
// if permission granted, send execution to the next middleware/route
if(result) options.authorized(req,res,next);
// just check the permission without using as middleware
dynacl.check = evalACL;
// if permission not granted, then end request with 401 Unauthorized
else options.unauthorized(req,res,next)
}
}
// function to configure DynACL
dynacl.config = function(userOptions){
// assign configurations
options = Object.assign({},defaultOptions,userOptions);
}
// just check the permission without using as middleware
dynacl.can = (action,req,params) => checkCan(action,req,params || {});
return dynacl;
})();
module.exports = dynacl;
{
"name": "express-dynacl",
"version": "1.0.0",
"version": "2.0.0",
"description": "Express dynamic access control list, that allows to grant access to queries based on request details",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -10,56 +10,41 @@ # express-dynacl

var guest = {
"nonalcoholic": {
// you can use a boolean as in standard ACL roles, default is false
"watch": true,
"drink": true
},
"alcoholic": {
"watch": true
}
};
var options = {
var guestWithId = {
"alcoholic": {
// or you can use a function of request
"drink": function(req){
return isEligibleToDrink(req) // check if over 18/21/...
roles: {
"guest": {
can: {
"posts:list": true,
"posts:edit": false
}
},
"user": {
can: {
"posts:create": true,
"posts:edit": (req,params) => {
return Post.find({_id:params.post.id}).then(post => post.owner === req.user.id);
}
},
inherits: "guest"
},
"moderator":{
can: {
"posts:edit": true
},
inherits: "user"
},
"admin: {
admin: true
}
}
};
var barowner = {
"*": true // give admin role
};
module.exports = {
"guest": guest,
"guestWithId": guestWithId,
"barowner": barowner
}
```
Import and configure the middleware:
```js
var acl = require("express-dynacl");
// configure DynACL
var aclOptions = {
// load roles (default is no roles)
roles: {
"guest": require("./roles").guest,
"guestWithId": require(".roles").guestWithId,
"barowner": require(".roles").barowner
},
},
userRoles: req => req.user ? req.user.roles : [], // get user roles
// set some of the roles as default - each request will expect that user has these roles (default is none)
defaultRoles: ["guest"],
defaultRole: "guest",
// enable logging to console (default is false)
logConsole: true,
logString: (role,action,result,req) => "DynACL " + (result ? "OK" : "XX") + " ( action: " + action + (result ? ", role: " + role : "") + " )", // log output string
logConsole: true, // enable logging to console (default is false)
// set the req.user property where roles are stored (default is req.user.roles)
rolesProperty: "roles"
authorized: (req,res,next) => next(), // middleware to use when authorized (default is send to next middleware)
unauthorized: (req,res,next) => res.sendStatus(401) // middleware to use when unauthorized (default is to respond with 401
}

@@ -66,0 +51,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc