Skip to content
This repository has been archived by the owner on Dec 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #6 from thaliproject/thaliidhandling
Browse files Browse the repository at this point in the history
adds handling of the /thali_ special processing
  • Loading branch information
cicorias committed Apr 9, 2016
2 parents e9e2674 + c725f36 commit 9acd3bc
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 43 deletions.
54 changes: 51 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/*jshint -W121 */
'use strict';
var assert = require('assert');

Expand All @@ -8,6 +9,7 @@ var NOTFOUND = -1;
var IDTOKEN = '{:id}';


/** Gets the req object, collection of paths, and path to validate */
function lookupPathVerb(req, paths, lookupPath) {
var pathExists = fast.indexOf(paths, lookupPath, 'path');

Expand All @@ -22,11 +24,33 @@ function lookupPathVerb(req, paths, lookupPath) {
debug('verb and path not found: req.Path: %s lookupPath: %s', req.path, lookupPath);
return false;
}

return true;
}

/** given the path it determines the ID and calls the callback with that ID */
function getThaliId(path, dbname, callback) {

var matches = path.match('^(\/' + dbname + '\/_local\/thali_)(.+)');
if (matches && matches.length > 1) {
if (matches[2]) {
return callback(matches[2]);
}
return false;
}
return false;
}

if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position){
position = position || 0;
return this.substr(position, searchString.length) === searchString;
};
}

module.exports = function(dbname, inAcl) {


module.exports = function(dbname, inAcl, callback) {

if (!dbname || typeof dbname !== 'string') {
throw new Error('invalid configuration - missing dbname');
Expand All @@ -35,7 +59,13 @@ module.exports = function(dbname, inAcl) {
if (!inAcl || !(inAcl instanceof Array)) {
throw new Error('invalid configuration - inAcl is not an array');
}

if(!callback || typeof callback !== 'function'){
throw new Error('invalid configuration - callback is NOT a function');
}

var thaliPrefix = '/' + dbname + '/_local/thali_';

var acl = JSON.parse(JSON.stringify(inAcl).replace(/{:db}/g, dbname));

//path.role.verb
Expand Down Expand Up @@ -75,9 +105,11 @@ module.exports = function(dbname, inAcl) {
return res.status(401).send(msg401);
}
else {
debug('found rawpath');
okPathVerb = true;
}
}

else {
//this section deals with /db/id, /db/_local/id, and /db/id/attachment stuff.
var pathParts = req.path.split('/');
Expand All @@ -98,16 +130,31 @@ module.exports = function(dbname, inAcl) {
return res.status(401).send(msg401);
}
else {
debug('found path and id');
okPathVerb = true;
}
}
else if (pathParts.length === 4 && pathParts[2] === '_local') {
//is this a /thali_ one?

//TODO:
var isThaliPrefix = req.path.startsWith(thaliPrefix);
if (isThaliPrefix && ! lookupPathVerb(req, paths, thaliPrefix + IDTOKEN)){
debug('unauthorized4.thaliPrefix: req.Path: %s path: %s', req.path, thaliPrefix);
return res.status(401).send(msg401);
}

if (isThaliPrefix && !getThaliId(req.path, dbname, callback)) {
debug('unauthorized4.thaliCallback: req.Path: %s path: %s', req.path, thaliPrefix);
return res.status(401).send(msg401);
}

if (!lookupPathVerb(req, paths, lookupPath)) {
debug('unauthorized4.2: req.Path: %s req.path: %s', req.path, lookupPath);
return res.status(401).send(msg401);
}
else {
debug('this should be authorized..');
debug('passed _local and thali checks.');
okPathVerb = true;
}
}
Expand All @@ -130,7 +177,8 @@ module.exports = function(dbname, inAcl) {

//might want to check if isvalid true too.
//All good - next in pipeline
debug('outside all ifs');
debug('outside all ifs okPathVerb: %s', okPathVerb);

assert.ok(okPathVerb);
next();

Expand Down
28 changes: 1 addition & 27 deletions lib/indexOf.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,7 @@
/* istanbul ignore next */
'use strict';

//taken from: https://github.com/codemix/fast.js/tree/master

// # The MIT License (MIT)
//
// Copyright (c) 2014 codemix.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.


/**
* Custom indexOf implementation from fast.js.
* Simple compare.
* @module indexOf
*/
function compareIt(source, target) {
Expand Down
2 changes: 1 addition & 1 deletion test/test-core-alldocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ describe('test-core-db-2.js - calling the /db path', function() {
})
//Norml middleware usage..0
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, path));
})
Expand Down
2 changes: 1 addition & 1 deletion test/test-core-attachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('test-core-attachment.js - calling the /db/id/attachment path', functio
})
//Norml middleware usage..0
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, path));
})
Expand Down
2 changes: 1 addition & 1 deletion test/test-core-bulkget.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('test-core-bulk-get - calling the /db/id path', function() {
})
//Norml middleware usage..0
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, path));
})
Expand Down
6 changes: 4 additions & 2 deletions test/test-core-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ describe('test-core-db.js - calling the /db path', function() {
describe('using repl identity', function() {
var app, router; app = express(); router = express.Router();
var dbName = 'foobar';

before(function() {
//mocker..
router.all('*', function(req, res, next) {
Expand All @@ -35,10 +36,11 @@ describe('test-core-db.js - calling the /db path', function() {
})
//Norml middleware usage..
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, dbName));
})

it('GET should be 200', function(done) {
request(app)
.get('/' + dbName)
Expand Down Expand Up @@ -86,7 +88,7 @@ describe('test-core-db.js - calling the /WRONG db path', function() {
})
//Norml middleware usage..
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, dbName));
})
Expand Down
2 changes: 1 addition & 1 deletion test/test-core-resources-local.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('test-core- LOCAL - calling the /db/_local/{id} path', function() {
})
//Norml middleware usage..0
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, path));
})
Expand Down
6 changes: 3 additions & 3 deletions test/test-core-resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('test-core-resources - just the /', function() {
})
//Norml middleware usage..0
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, path));
})
Expand All @@ -47,7 +47,7 @@ describe('test-core-resources - just the /', function() {
})
})

describe('test-core- resource calling the /db/{id} path', function() {
describe('test-core-resources calling the /db/{id} path', function() {
describe('using repl identity', function() {
var app, router; app = express(); router = express.Router();

Expand All @@ -59,7 +59,7 @@ describe('test-core- resource calling the /db/{id} path', function() {
})
//Norml middleware usage..0
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl));
router.all('*', lib('foobar', acl, function(){}));
//mock handlers
app.use('/', genericHandlers(router, path));
})
Expand Down
4 changes: 2 additions & 2 deletions test/test-noaclfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('test-noaclfile.js - should let all through', function() {
req.connection.pskIdentity = 'public';
next();
})
router.all('*', lib('foobar', [{}]));
router.all('*', lib('foobar', [{}], function(){}));
app.use('/', genericHandlers(router));
})
it('should be 401', function(done) {
Expand All @@ -70,7 +70,7 @@ describe('test-noaclfile.js - should let all through', function() {
next();
})
//Norml middleware usage..
router.all('*', lib('foobar', [{}]));
router.all('*', lib('foobar', [{}], function(){}));
//mock handlers
app.use('/', genericHandlers(router));
})
Expand Down
18 changes: 16 additions & 2 deletions test/test-parmchecks.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,28 @@ describe('some parm checking', function() {
})
it('should throw exception when 2nd parm is not an array', function(done) {
assert.throws(function() {
var tv = lib('foobar', 'notarray');
var tv = lib('foobar', 'notarray', function(){});
});
done();

})
it('should NOT throw exception as parm 1 is string parm 2 is array', function(done) {
var tv = lib('foobar', ['foo', 'bar']);
var tv = lib('foobar', ['foo', 'bar'], function(){});
done();

})

it('should not throw exception as parm 3 is fn', function(done){
var tv = lib('foobar', ['foo'], function(){});
done();
})


it('should throw exception as parm 3 is fn', function(done){
assert.throws(function(){
var tv = lib('foobar', ['foo'], 'foo');
})
done();
})

})
104 changes: 104 additions & 0 deletions test/test-thali-callback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';

var request = require('supertest'),
express = require('express'),
fspath = require('path'),
colors = require('colors'),
assert = require('assert');


var lib = require(fspath.join(__dirname, '../lib/index'));
var dbName = 'foobar';
var pathPrefix = '/' + dbName + '/_local/thali__ID_';

var validId = 'zz-xx--bb';


function verifyThaliUser(idToCheck) {
console.log(colors.green('checking ID: %s'), idToCheck);
return validId === idToCheck;
}

function genericHandlers(router, path) {
var handlers = require('./handlers2');
router.get(path, handlers.get);
router.post(path, handlers.post);
router.put(path, handlers.put);
router.head(path, handlers.head);
router.options(path, handlers.options);
router.delete(path, handlers.options);
return router;
}

describe('We are validating requests that look like /db/_local/thali_:ID', function() {
describe('if the request is ../thali_ and nothing', function(done) {
var app, router; app = express(); router = express.Router();

var rootPath = '/' + dbName + '/_local/thali_';
var pathWithId = rootPath + validId;

before(function() {
//mocker..
router.all('*', function(req, res, next) {
req.connection.pskRole = 'repl';
next();
})
//Norml middleware usage..0
var acl = require('./acl-block.1.js');
router.all('*', lib('foobar', acl, verifyThaliUser));
//mock handlers
app.use('/', genericHandlers(router, pathWithId));
})

/** mapped paths mix of verbs */
it('GET should be OK - we are using ' + validId, function(done) {
request(app)
.get(pathWithId)
.set('Accept', 'application/json')
.expect(200, done);
})

//
it('GET should fail as it does not match valid ID ' + rootPath + 'zzz', function(done) {
request(app)
.get(rootPath + 'zzz')
.set('Accept', 'application/json')
.expect(401, done);
})


it('PUT should be OK - we are using ' + validId, function(done) {
request(app)
.put(pathWithId)
.set('Accept', 'application/json')
.expect(200, done);
})
it('DELETE should be OK - we are using ' + validId, function(done) {
request(app)
.delete(pathWithId)
.set('Accept', 'application/json')
.expect(200, done);
})
it('POST should fail no acl for verb - we are using ' + validId, function(done) {
request(app)
.post(pathWithId)
.set('Accept', 'application/json')
.expect(401, done);
})

/** unmapped paths */
it('should fail with a 401 as not valid', function(done) {
request(app)
.get(rootPath)
.set('Accept', 'application/json')
.expect(401, done);
})

it('should OK as full path', function(done) {
request(app)
.get(pathWithId)
.set('Accept', 'application/json')
.expect(200, done);
})
})
})

0 comments on commit 9acd3bc

Please sign in to comment.