express-reaccess
Advanced tools
Comparing version 0.0.3 to 0.0.4
{ | ||
"name": "express-reaccess", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "Express/Connect middleware to manage API access on a RegExp basis", | ||
@@ -36,3 +36,6 @@ "main": "src/index.js", | ||
"istanbul": "~0.3.0" | ||
}, | ||
"dependencies": { | ||
"escape-regexp-component": "^1.0.2" | ||
} | ||
} |
@@ -0,1 +1,3 @@ | ||
var escRegExp = require('escape-regexp-component'); | ||
function reaccess(options) { | ||
@@ -10,3 +12,3 @@ | ||
return function reaccessMiddleware(req, res, next) { | ||
var rights = getProp(req, options.rightsProp); | ||
var rights = getValues([req], options.rightsProp)[0]; | ||
var user; | ||
@@ -17,11 +19,17 @@ if(!(rights && rights instanceof Array)) { | ||
if(options.userProp) { | ||
user = getProp(req, options.userProp); | ||
user = getValues([req], options.userProp)[0]; | ||
} | ||
if(rights.some(function(right) { | ||
var path = user ? | ||
right.path.replace(/(.*\/|^):([a-z0-9_\-\.]+)(\/.*|$)/, | ||
var path = ''; | ||
if(!(right.methods && right.methods&reaccess[req.method.toUpperCase()])) { | ||
return false; | ||
} | ||
path = user ? | ||
right.path.replace(/(.*\/|^):([a-z0-9_\-\.\*\@\#]+)(\/.*|$)/, | ||
function($, $1, $2, $3) { | ||
var value = getProp(user, $2); | ||
if(value) { | ||
return $1 + value + $3; | ||
var values = getValues([user], $2); | ||
if(values.length) { | ||
return $1 + (1 === values.length ? | ||
escRegExp(values[0]) : | ||
'(' + values.map(escRegExp).join('|') + ')') + $3; | ||
} | ||
@@ -31,5 +39,3 @@ return ''; | ||
right.path; | ||
return right.methods && path && | ||
right.methods&reaccess[req.method.toUpperCase()] && | ||
new RegExp('^'+path+'$').test(req.path); | ||
return path && new RegExp('^'+path+'$').test(req.path); | ||
})) { | ||
@@ -57,13 +63,32 @@ next(); | ||
// Helpers | ||
function getProp(obj, prop) { | ||
var nodes = prop.split('.'); | ||
var node; | ||
do { | ||
node = nodes.shift(); | ||
if(!obj[node]) { | ||
return ''; | ||
function getValues(values, path) { | ||
var index = path.indexOf('.'); | ||
var part = -1 !== index ? path.substring(0, index) : path; | ||
path = -1 !== index ? path.substring(index + 1) : ''; | ||
values = values.reduce(function(values, value) { | ||
if((value instanceof Object) && '*' === part) { | ||
values = values.concat(Object.keys(value).map(function(key) { | ||
return value[key]; | ||
})); | ||
} | ||
obj = obj[node]; | ||
} while(nodes.length); | ||
return obj; | ||
if((value instanceof Object) && '@' === part) { | ||
values = values.concat(Object.keys(value).filter(function(key) { | ||
return /^[^0-9]+$/.test(key); | ||
}).map(function(key) { | ||
return value[key]; | ||
})); | ||
} | ||
if((value instanceof Array) && '#' === part) { | ||
values = values.concat(value); | ||
} | ||
if(-1 === ['@', '#', '*'].indexOf(part) && | ||
'undefined' !== typeof value[part]) { | ||
values.push(value[part]); | ||
} | ||
return values; | ||
}, []).filter(function(value) { | ||
return 'undefined' !== typeof value; | ||
}); | ||
return '' === path ? values : getValues(values, path); | ||
} | ||
@@ -70,0 +95,0 @@ |
@@ -9,5 +9,8 @@ var assert = require('assert'); | ||
it('when there is no rights', function(done) { | ||
testReq() | ||
// .expect('Unauthorized access!') | ||
.expect(500, done); | ||
testReq() | ||
.expect(500, 'Unauthorized access!') | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
}); | ||
}); | ||
@@ -21,4 +24,5 @@ it('when there is no rights matching the path', function(done) { | ||
}) | ||
.expect(/The rights property must be an array/) | ||
.expect(500, function() { | ||
.expect(500, /The rights property must be an array/) | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
@@ -38,4 +42,5 @@ }); | ||
}) | ||
.expect(/Unauthorized access!/) | ||
.expect(500, function() { | ||
.expect(500, /Unauthorized access!/) | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
@@ -45,6 +50,23 @@ }); | ||
it('when there is no rights matching the templated path', function(done) { | ||
testReq({ | ||
rightsObj: [{ | ||
path: '/bar', | ||
methods: reaccess.METHODS | ||
},{ | ||
path: '/plop', | ||
methods: reaccess.METHODS | ||
}] | ||
}) | ||
.expect(500, /Unauthorized access!/) | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
}); | ||
}); | ||
it('when there is no rights matching the method', function(done) { | ||
testReq({ | ||
rightsObj: [{ | ||
path: '/foo', | ||
path: '/foo/:bar.ba.pa.pa/plop', | ||
methods: reaccess.METHODS ^ reaccess.GET | ||
@@ -56,4 +78,5 @@ },{ | ||
}) | ||
.expect(/Unauthorized access!/) | ||
.expect(500, function() { | ||
.expect(500, /Unauthorized access!/) | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
@@ -71,10 +94,11 @@ }); | ||
path: '/foo', | ||
methods: reaccess.METHODS | ||
methods: reaccess.ALL_MASK | ||
},{ | ||
path: '/plop', | ||
methods: reaccess.METHODS | ||
methods: reaccess.ALL_MASK | ||
}] | ||
}) | ||
.expect('plop') | ||
.expect(200, function() { | ||
.expect(200, 'plop') | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
@@ -88,6 +112,6 @@ }); | ||
path: '/foo/:bar.ba.pa.pa/plop', | ||
methods: reaccess.METHODS | ||
methods: reaccess.ALL_MASK | ||
},{ | ||
path: '/plop/:foo/bar', | ||
methods: reaccess.METHODS | ||
methods: reaccess.ALL_MASK | ||
}], | ||
@@ -108,4 +132,5 @@ userProp: 'user.content', | ||
}, '/foo/1/plop') | ||
.expect('plop') | ||
.expect(200, function() { | ||
.expect(200, 'plop') | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
@@ -115,2 +140,127 @@ }); | ||
it('when a templated right contains special regexp chars', function(done) { | ||
testReq({ | ||
rightsObj: [{ | ||
path: '/foo/:bar/plop', | ||
methods: reaccess.ALL_MASK | ||
},{ | ||
path: '/plop/:foo/bar', | ||
methods: reaccess.ALL_MASK | ||
}], | ||
userProp: 'user.content', | ||
userObj: { | ||
bar: 'a', | ||
plop: '|)}' | ||
} | ||
}, { | ||
userProp: 'user.content' | ||
}, '/foo/a/plop') | ||
.expect(200, 'plop') | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
}); | ||
}); | ||
it('when there is one templated right with a wildcard that match', function(done) { | ||
testReq({ | ||
rightsObj: [{ | ||
path: '/foo/:bar.ba.*.pa.*.pa/plop', | ||
methods: reaccess.ALL_MASK | ||
},{ | ||
path: '/plop/:foo/bar', | ||
methods: reaccess.ALL_MASK | ||
}], | ||
userProp: 'user.content', | ||
userObj: { | ||
bar: { | ||
ba: [{ | ||
pa: { | ||
pip: { | ||
pa: 1 | ||
} | ||
} | ||
}] | ||
}, | ||
lol: 2 | ||
} | ||
}, { | ||
userProp: 'user.content' | ||
}, '/foo/1/plop') | ||
.expect(200, 'plop') | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
}); | ||
}); | ||
it('when there is one templated right with a #/@ special cards that match', function(done) { | ||
testReq({ | ||
rightsObj: [{ | ||
path: '/foo/:bar.ba.#.pa.@.pa/plop', | ||
methods: reaccess.ALL_MASK | ||
},{ | ||
path: '/plop/:foo/bar', | ||
methods: reaccess.ALL_MASK | ||
}], | ||
userProp: 'user.content', | ||
userObj: { | ||
bar: { | ||
ba: [{ | ||
pa: { | ||
plop: { | ||
pa: 1 | ||
} | ||
} | ||
}] | ||
}, | ||
lol: 2 | ||
} | ||
}, { | ||
userProp: 'user.content' | ||
}, '/foo/1/plop') | ||
.expect(200, 'plop') | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
}); | ||
}); | ||
it('when there is one templated right with a wildcard that match but is not the first', function(done) { | ||
testReq({ | ||
rightsObj: [{ | ||
path: '/foo/:bar.ba.*.pa.*.pa/plop', | ||
methods: reaccess.ALL_MASK | ||
},{ | ||
path: '/plop/:foo/bar', | ||
methods: reaccess.ALL_MASK | ||
}], | ||
userProp: 'user.content', | ||
userObj: { | ||
bar: { | ||
ba: [{ | ||
pa: { | ||
pa: { | ||
pa: 2 | ||
} | ||
} | ||
}, { | ||
pa: { | ||
pip: { | ||
pa: 1 | ||
} | ||
} | ||
}] | ||
} | ||
} | ||
}, { | ||
userProp: 'user.content' | ||
}, '/foo/1/plop') | ||
.expect(200, 'plop') | ||
.end(function(err, res){ | ||
if(err) throw err; | ||
done(); | ||
}); | ||
}); | ||
}); | ||
@@ -117,0 +267,0 @@ |
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
16165
365
1
+ Addedescape-regexp-component@1.0.2(transitive)