cansecurity
Advanced tools
Comparing version 0.6.0 to 0.6.1
@@ -8,3 +8,3 @@ /*jslint node:true, nomen:true */ | ||
*/ | ||
pathRegexp = function(path, sensitive, strict) { | ||
pathRegexp = function(path, keys, sensitive, strict) { | ||
if (path && path.toString() === '[object RegExp]') { | ||
@@ -20,2 +20,3 @@ return path; | ||
.replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){ | ||
keys.push({ name: key, optional: !! optional }); | ||
slash = slash || ''; | ||
@@ -50,3 +51,3 @@ return String( | ||
// [verb, url, param, default, condition] | ||
var entry, verb; | ||
var entry, verb, keys = [], re; | ||
rule = rule || []; | ||
@@ -67,2 +68,3 @@ // only 4, so we have no param or loggedIn | ||
verb = rule[0].toLowerCase(); | ||
re = pathRegexp(rule[1],keys); | ||
entry = { | ||
@@ -75,3 +77,4 @@ verb: verb, | ||
condition: rule[5], | ||
re: pathRegexp(rule[1]) | ||
re: re, | ||
keys: keys | ||
}; | ||
@@ -85,9 +88,17 @@ routes[verb] = routes[verb] || []; | ||
// authorized: false = send a 403, else next() | ||
var authenticated = true, authorized = true; | ||
var authenticated = true, authorized = true, user = req[csauth], keys, match, oldParams = req.params; | ||
// first check verb, then check route regexp match, then check params | ||
_.each(routes[req.method.toLowerCase()],function (entry) { | ||
var useRule = false, isCondition = false; | ||
keys = {}; | ||
// path match check | ||
if ((req.path||"").match(entry.re)) { | ||
match = (req.path||"").match(entry.re); | ||
if (match) { | ||
useRule = true; | ||
// create the important parameters | ||
_.each(entry.keys || [], function(p,i) { | ||
keys[p.name] = match[i+1]; | ||
}); | ||
// this is so that req.param() or req.params will work | ||
req.params = keys; | ||
// next check if we use param - will be false unless no param, or param is match | ||
@@ -109,3 +120,3 @@ if (entry.param) { | ||
try { | ||
isCondition = vm.runInNewContext(entry.condition,{req:req,res:res}); | ||
isCondition = vm.runInNewContext(entry.condition,{req:req,user:user}); | ||
} catch (e) { | ||
@@ -120,2 +131,4 @@ isCondition = false; | ||
}); | ||
// now reset req.params | ||
req.params = oldParams; | ||
if (!authenticated) { | ||
@@ -122,0 +135,0 @@ res.send(401,errors.unauthenticated()); |
{ | ||
"name": "cansecurity", | ||
"description": "cansecurity is your all-in-one security library for user authentication, authorization and management in node expressjs apps", | ||
"version": "0.6.0", | ||
"version": "0.6.1", | ||
"url": "http://github.com/deitch/cansecurity", | ||
@@ -6,0 +6,0 @@ "author": "Avi Deitcher <avi@deitcher.net>", |
@@ -58,8 +58,8 @@ # cansecurity | ||
// [verb,path,default,[test params,] test condition] | ||
["GET","/api/user","deny","req.user.roles.admin === true"], | ||
["GET","/api/user/:user","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["GET","/api/user/:user",{"private":"true"},"deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["PUT","/api/user/:user","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["GET","/api/user/:user/roles","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["PUT","/api/user/:user/roles","deny","req.user.roles.admin === true"] | ||
["GET","/api/user","deny","user.roles.admin === true"], | ||
["GET","/api/user/:user","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["GET","/api/user/:user",{"private":"true"},"deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["PUT","/api/user/:user","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["GET","/api/user/:user/roles","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["PUT","/api/user/:user/roles","deny","user.roles.admin === true"] | ||
] | ||
@@ -544,8 +544,8 @@ } | ||
// [verb,path,default,[test params,] test condition] | ||
["GET","/api/user","deny","req.user.roles.admin === true"], | ||
["GET","/api/user/:user","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["GET","/api/user/:user",{"private":"true"},"deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["PUT","/api/user/:user","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["GET","/api/user/:user/roles","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["PUT","/api/user/:user/roles","deny","req.user.roles.admin === true"] | ||
["GET","/api/user","deny","user.roles.admin === true"], | ||
["GET","/api/user/:user","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["GET","/api/user/:user",{"private":"true"},"deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["PUT","/api/user/:user","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["GET","/api/user/:user/roles","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
["PUT","/api/user/:user/roles","deny","user.roles.admin === true"] | ||
] | ||
@@ -591,28 +591,34 @@ } | ||
````JavaScript | ||
// when GET /api/user, deny access unless req.user.roles.admin === true | ||
["GET","/api/user","deny","req.user.roles.admin === true"], | ||
// when GET /api/user, deny access unless user.roles.admin === true | ||
["GET","/api/user","deny","user.roles.admin === true"], | ||
// when GET /api/user, require logged in, and if logged in deny access unless req.user.roles.admin === true | ||
["GET","/api/user",true,"deny","req.user.roles.admin === true"], | ||
// when GET /api/user, require logged in, and if logged in deny access unless user.roles.admin === true | ||
["GET","/api/user",true,"deny","user.roles.admin === true"], | ||
// when GET /api/user/:user, deny access unless req.user.roles.admin === true, OR req.user.id === req.param('user') | ||
["GET","/api/user/:user","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
// when GET /api/user/:user, deny access unless user.roles.admin === true, OR user.id === req.param('user') | ||
["GET","/api/user/:user","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
// when GET /api/user/:user AND ?private=true (or in the body), deny unless req.user.roles.admin === true || req.user.id === req.param('user') | ||
// when GET /api/user/:user AND ?private=true (or in the body), deny unless user.roles.admin === true || user.id === req.param('user') | ||
// if private !== true (or is unset or anything else), then this rule is not applied, and access is allowed | ||
["GET","/api/user/:user",{"private":"true"},"deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["GET","/api/user/:user",{"private":"true"},"deny","user.roles.admin === true || user.id === req.param('user')"], | ||
// same as previous example, but check for user logged in first | ||
["GET","/api/user/:user",{"private":"true"},true,"deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
["GET","/api/user/:user",{"private":"true"},true,"deny","user.roles.admin === true || user.id === req.param('user')"], | ||
// when PUT /api/user/:user, deny unless req.user.roles.admin === true || req.user.id === req.param('user') | ||
["PUT","/api/user/:user","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
// when PUT /api/user/:user, deny unless user.roles.admin === true || user.id === req.param('user') | ||
["PUT","/api/user/:user","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
// when GET /api/user/:user/roles, deny unless req.user.roles.admin === true || req.user.id === req.param('user') | ||
["GET","/api/user/:user/roles","deny","req.user.roles.admin === true || req.user.id === req.param('user')"], | ||
// when GET /api/user/:user/roles, deny unless user.roles.admin === true || user.id === req.param('user') | ||
["GET","/api/user/:user/roles","deny","user.roles.admin === true || user.id === req.param('user')"], | ||
// when PUT /api/user/:user/roles, deny unless req.user.roles.admin === true | ||
["PUT","/api/user/:user/roles","deny","req.user.roles.admin === true"] | ||
// when PUT /api/user/:user/roles, deny unless user.roles.admin === true | ||
["PUT","/api/user/:user/roles","deny","user.roles.admin === true"] | ||
```` | ||
#### Context for the Condition | ||
The condition string is run inside its own new context. Besides the usual nodejs environment, it has the following variable available to it: | ||
1. `req`: the actual express `req` object, normally found on each route whose signature is `function(req,res,next)`. | ||
2. `user`: the user object if you used cansecurity authentication. This is the equivalent of calling `cansec.getUser(req)`. | ||
#### What It Returns | ||
@@ -619,0 +625,0 @@ The authorizer has one of three possible results: |
{ | ||
"routes": [ | ||
["GET","/secure/loggedIn","deny","req.user !== undefined && req.user !== null"], | ||
["GET","/secure/loggedIn","deny","user !== undefined && user !== null"], | ||
["GET","/secure/denyAll","deny","false === true"], | ||
@@ -17,4 +17,6 @@ ["GET","/secure/allowAll","allow","false === true"], | ||
["GET","/secure/login",true,"deny","req.param('abc') === 'abc'"], | ||
["GET","/secure/loginParam",{"private":"true"},true,"deny","req.param('abc') === 'abc'"] | ||
["GET","/secure/loginParam",{"private":"true"},true,"deny","req.param('abc') === 'abc'"], | ||
["GET","/secure/user/:user","deny","req.param('user') === '1'"] | ||
] | ||
} |
@@ -35,2 +35,10 @@ /*jslint node:true, nomen:true */ | ||
}); | ||
describe('user in condition', function(){ | ||
it('should deny if user is not logged in', function(done){ | ||
r.get('/secure/loggedIn').expect(403,done); | ||
}); | ||
it('should allow if user is logged in', function(done){ | ||
r.get('/secure/loggedIn').auth("john","1234").expect(200,done); | ||
}); | ||
}); | ||
describe('deny vs allow', function(){ | ||
@@ -83,2 +91,10 @@ it('should always deny denyAll', function(done){ | ||
}); | ||
describe('path parameter', function(){ | ||
it('should deny the route if param not matched', function(done){ | ||
r.get('/secure/user/10').expect(403,done); | ||
}); | ||
it('should allow the route if param is matched', function(done){ | ||
r.get('/secure/user/1').expect(200,done); | ||
}); | ||
}); | ||
describe('login required', function(){ | ||
@@ -85,0 +101,0 @@ describe('with only login option', function(){ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
88975
1368
684