From 3809d6eb32aa15c4f75c0a4ebd9cdc8d250a9a7c Mon Sep 17 00:00:00 2001 From: Alex Kocharin Date: Wed, 23 Jul 2014 01:45:28 +0400 Subject: [PATCH] add a bunch of tests for htpasswd --- .gitignore | 1 + .npmignore | 1 + lib/config.js | 2 +- lib/htpasswd.js | 8 +++-- package.yaml | 6 ++-- test/functional/adduser.js | 36 ++++++++++++++++++++++ test/functional/config-1.yaml | 3 ++ test/functional/index.js | 1 + test/functional/lib/server.js | 8 ++++- test/unit/htpasswd.js | 56 +++++++++++++++++++++++++++++++++++ 10 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 test/functional/adduser.js create mode 100644 test/unit/htpasswd.js diff --git a/.gitignore b/.gitignore index 086cffe33..a05fec011 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ sinopia-*.tgz ### bin/storage* +bin/htpasswd bin/*.yaml test-storage* diff --git a/.npmignore b/.npmignore index d452cb0b9..99ecbe0f0 100644 --- a/.npmignore +++ b/.npmignore @@ -5,6 +5,7 @@ sinopia-*.tgz ### bin/storage* +bin/htpasswd bin/*.yaml test-storage* diff --git a/lib/config.js b/lib/config.js index 196890b56..a634e20c0 100644 --- a/lib/config.js +++ b/lib/config.js @@ -171,7 +171,7 @@ Config.prototype.authenticate = function(user, password, cb) { Config.prototype.add_user = function(user, password, cb) { if (this.users && this.users[user]) return cb(new UError({ - status: 409, + status: 403, message: 'this user already exists', })) diff --git a/lib/htpasswd.js b/lib/htpasswd.js index cc052e5ff..50fa23bf7 100644 --- a/lib/htpasswd.js +++ b/lib/htpasswd.js @@ -66,12 +66,12 @@ module.exports = function(path) { function sanity_check() { if (users[user]) { return new UError({ - status: 409, + status: 403, message: 'this user already exists', }) } else if (Object.keys(users).length >= maxusers) { return new UError({ - status: 409, + status: 403, message: 'maximum amount of users reached', }) } @@ -135,3 +135,7 @@ module.exports = function(path) { return result } +// exports for unit tests +module.exports._parse_htpasswd = parse_htpasswd +module.exports._verify_password = verify_password +module.exports._add_user_to_htpasswd = add_user_to_htpasswd diff --git a/package.yaml b/package.yaml index 38c9dcbb4..4c03faebf 100644 --- a/package.yaml +++ b/package.yaml @@ -31,14 +31,14 @@ dependencies: optionalDependencies: fs-ext: '>= 0.3.2' - crypt3: 'sendanor/node-crypt3' + crypt3: '*' devDependencies: rimraf: '>= 2.2.5' mocha: '>= 1.17.0' # linting tools - eslint: '>= 0.6' + eslint: '~ 0.6.0' # for debugging memory leaks, it'll be require()'d if # installed, but I don't want it to be installed everytime @@ -56,7 +56,7 @@ keywords: scripts: test: mocha ./test/functional ./test/unit lint: eslint -c ./.eslint.yaml ./lib - prepublish: js-yaml package.yaml > package.json + #prepublish: js-yaml package.yaml > package.json # we depend on streams2 stuff # it can be replaced with isaacs/readable-stream, ask if you need to use 0.8 diff --git a/test/functional/adduser.js b/test/functional/adduser.js new file mode 100644 index 000000000..ff807ca6d --- /dev/null +++ b/test/functional/adduser.js @@ -0,0 +1,36 @@ +var assert = require('assert') +var Server = require('./lib/server') + +module.exports = function() { + var server = new Server('http://localhost:55551/') + + describe('adduser', function() { + var user = String(Math.random()) + var pass = String(Math.random()) + before(function(cb) { + server.auth(user, pass, function(res, body) { + assert.equal(res.statusCode, 201) + assert(body.ok.match(/user .* created/)) + cb() + }) + }) + + it('creating new user', function(){}) + + it('should log in', function(cb) { + server.auth(user, pass, function(res, body) { + assert.equal(res.statusCode, 201) + assert(body.ok.match(/you are authenticated as/)) + cb() + }) + }) + + it('should not register more users', function(cb) { + server.auth(String(Math.random()), String(Math.random()), function(res, body) { + assert.equal(res.statusCode, 403) + assert(body.error.match(/maximum amount of users reached/)) + cb() + }) + }) + }) +} diff --git a/test/functional/config-1.yaml b/test/functional/config-1.yaml index 0e61fa4a8..b8b0c3530 100644 --- a/test/functional/config-1.yaml +++ b/test/functional/config-1.yaml @@ -4,6 +4,9 @@ users: test: password: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 +users_file: ./test-storage/htpasswd +max_users: 1 + uplinks: express: url: http://localhost:55550/ diff --git a/test/functional/index.js b/test/functional/index.js index ca51de53d..1bdaad115 100644 --- a/test/functional/index.js +++ b/test/functional/index.js @@ -46,6 +46,7 @@ describe('Func', function() { require('./race')() require('./racycrash')() require('./security')() + require('./adduser')() require('./addtag')() }) diff --git a/test/functional/lib/server.js b/test/functional/lib/server.js index 094057eb5..7c0ea3d40 100644 --- a/test/functional/lib/server.js +++ b/test/functional/lib/server.js @@ -36,7 +36,13 @@ Server.prototype.auth = function(user, pass, cb) { uri: '/-/user/org.couchdb.user:'+encodeURIComponent(user)+'/-rev/undefined', method: 'PUT', json: { - content: "doesn't matter, 'cause sinopia uses info from Authorization header anywayz", + name: user, + password: pass, + email: 'test@example.com', + _id: 'org.couchdb.user:' + user, + type: 'user', + roles: [], + date: new Date(), } }, prep(cb)) } diff --git a/test/unit/htpasswd.js b/test/unit/htpasswd.js new file mode 100644 index 000000000..98a7c3d5e --- /dev/null +++ b/test/unit/htpasswd.js @@ -0,0 +1,56 @@ +var assert = require('assert') + , parse_htpasswd = require('../../lib/htpasswd')._parse_htpasswd + , verify_password = require('../../lib/htpasswd')._verify_password + , add_user_to_htpasswd = require('../../lib/htpasswd')._add_user_to_htpasswd + +describe('parse_htpasswd', function() { + // TODO +}) + +describe('verify_password', function() { + it('should verify plain', function() { + assert(verify_password('user', 'pass', '{PLAIN}pass')) + assert(!verify_password('user', 'p', '{PLAIN}pass')) + }) + it('should verify sha', function() { + assert(verify_password('user', 'pass', '{SHA}nU4eI71bcnBGqeO0t9tXvY1u5oQ=')) + assert(!verify_password('user', 'p', '{SHA}nU4eI71bcnBGqeO0t9tXvY1u5oQ=')) + }) + it('should verify crypt', function() { + assert(verify_password('user', 'pass', 'ulINxGnqObi36')) + assert(!verify_password('user', 'p', 'ulINxGnqObi36')) + }) + it('should verify crypt-sha', function() { + assert(verify_password('user', 'pass', '$6$Qx0eNSKPbxocgA==$ugjO0.z9yOFiaJXJK4ulvGYIxF/KZBV4lGqasArYPqPPT4orZ6NlnIE5KhtiOVs.5EoWxLg1sjp318G8RpI2x1')) + assert(!verify_password('user', 'p', '$6$Qx0eNSKPbxocgA==$ugjO0.z9yOFiaJXJK4ulvGYIxF/KZBV4lGqasArYPqPPT4orZ6NlnIE5KhtiOVs.5EoWxLg1sjp318G8RpI2x1')) + }) +}) + +describe('add_user_to_htpasswd', function() { + it('should add user to empty file', function() { + var res = add_user_to_htpasswd('', 'user', 'passwd') + assert(res.match(/^user:[^:\n]+:autocreated [^\n]+\n$/)) + }) + + it('should append user / newline checks', function() { + var res = add_user_to_htpasswd('testtest', 'user', 'passwd') + assert(res.match(/^testtest\nuser:[^:\n]+:autocreated [^\n]+\n$/)) + var res = add_user_to_htpasswd('testtest\n', 'user', 'passwd') + assert(res.match(/^testtest\nuser:[^:\n]+:autocreated [^\n]+\n$/)) + var res = add_user_to_htpasswd('testtest\n\n', 'user', 'passwd') + assert(res.match(/^testtest\n\nuser:[^:\n]+:autocreated [^\n]+\n$/)) + }) + + it('should not append invalid users', function() { + assert.throws(function() { + add_user_to_htpasswd('', 'us:er', 'passwd') + }, /non-uri-safe/) + assert.throws(function() { + add_user_to_htpasswd('', 'us\ner', 'passwd') + }, /non-uri-safe/) + assert.throws(function() { + add_user_to_htpasswd('', 'us#er', 'passwd') + }, /non-uri-safe/) + }) +}) +