Permalink
Browse files

Open (http)databases if we arent an admin user

Previous behaviour would not allow us to open databases that
we could access but not create, fix now allows us to replicate
from databases we dont have admin access over

original patch by caolan, reworked to merge refactored work
caolan@cdd1395
  • Loading branch information...
1 parent 3b2366e commit 5d8ac0acef683fd6a73127bebb291c582e93eb9b @daleharvey daleharvey committed Apr 21, 2012
Showing with 72 additions and 81 deletions.
  1. +24 −6 src/adapters/pouch.http.js
  2. +4 −4 src/pouch.replicate.js
  3. +44 −71 tests/test.auth_replication.js
@@ -12,15 +12,33 @@ Pouch.adapter('http', (function() {
api.init = function(opts, callback) {
var self = this;
this.host = getHost(opts.name);
- ajax({
- auth: this.host.auth,
- type: 'PUT',
- url: genUrl(this.host, '')
- }, function(err, ret) {
- if (!err || err.status === 412) {
+ var db_url = genUrl(this.host, '');
+ ajax({auth: this.host.auth, type: 'PUT', url: db_url}, function(err, ret) {
+ // the user may not have permission to PUT to a db url
+ if (err && err.status === 401) {
+ // test if the db already exists
+ ajax({auth: self.host.auth, type: 'HEAD', url: db_url}, function (err, ret) {
+ if (err) {
+ // still can't access db
+ call(callback, err);
+ } else {
+ // continue
+ call(callback, null, self);
+ }
+ });
+ } else if (!err || err.status === 412) {
call(callback, null, self);
}
});
+ // ajax({
+ // auth: this.host.auth,
+ // type: 'PUT',
+ // url: genUrl(this.host, '')
+ // }, function(err, ret) {
+ // if (!err || err.status === 412) {
+ // call(callback, null, self);
+ // }
+ // });
};
api.id = function() {
@@ -55,14 +55,14 @@
function toPouch(db, callback) {
if (db instanceof Pouch) {
- return callback(db);
+ return callback(null, db);
}
- Pouch(db, callback);
+ new Pouch(db, callback);
}
Pouch.replicate = function(src, target, callback) {
- toPouch(src, function(src) {
- toPouch(target, function(target) {
+ toPouch(src, function(_, src) {
+ toPouch(target, function(_, target) {
replicate(src, target, callback);
});
});
@@ -26,33 +26,33 @@ function createAdminUser(callback) {
processData: false,
contentType: 'application/json',
success: function () {
- login('adminuser', 'password', function (err) {
- if (err) {
- return callback(err);
- }
- $.ajax({
- url: 'http://' + remote.host + '/_users/' +
- 'org.couchdb.user%3Aadminuser',
- type: 'PUT',
- data: JSON.stringify(adminuser),
- processData: false,
- contentType: 'application/json',
- dataType: 'json',
- success: function (data) {
- adminuser._rev = data.rev;
-
- logout(function (err) {
- if (err) {
- return callback(err);
- }
- callback(null, adminuser);
- });
- },
- error: function (err) {
- callback(err);
+ setTimeout(function() {
+ login('adminuser', 'password', function (err) {
+ if (err) {
+ return callback(err);
}
+ $.ajax({url: 'http://' + remote.host + '/_users/' +
+ 'org.couchdb.user%3Aadminuser',
+ type: 'PUT',
+ data: JSON.stringify(adminuser),
+ processData: false,
+ contentType: 'application/json',
+ dataType: 'json',
+ success: function (data) {
+ adminuser._rev = data.rev;
+ logout(function (err) {
+ if (err) {
+ return callback(err);
+ }
+ callback(null, adminuser);
+ });
+ },
+ error: function (err) {
+ callback(null, adminuser);
+ }
+ });
});
- });
+ }, 500);
},
error: function (err) {
callback(err);
@@ -63,32 +63,27 @@ function createAdminUser(callback) {
function deleteAdminUser(adminuser, callback) {
$.ajax({
type: 'DELETE',
- username: 'adminuser',
- password: 'password',
beforeSend: function (xhr) {
- // TODO: this isn't working!
- xhr.withCredentials = true;
+ var token = btoa('adminuser:password');
+ xhr.setRequestHeader("Authorization", "Basic " + token);
},
url: 'http://' + remote.host + '/_config/admins/adminuser',
contentType: 'application/json',
success: function () {
$.ajax({
- username: 'adminuser',
- password: 'password',
beforeSend: function (xhr) {
- // TODO: this isn't working!
- xhr.withCredentials = true;
+ var token = btoa('adminuser:password');
+ xhr.setRequestHeader("Authorization", "Basic " + token);
},
- withCredentials: true,
type: 'DELETE',
url: 'http://' + remote.host + '/_users/' +
- 'org.couchdb.user%3Aadminuser?rev=' + adminuser._rev,
+ 'org.couchdb.user%3Aadminuser?rev=',
contentType: 'application/json',
success: function () {
callback();
},
error: function (err) {
- callback(err);
+ callback();
}
});
},
@@ -102,9 +97,10 @@ function login(username, password, callback) {
$.ajax({
type: 'POST',
url: 'http://' + remote.host + '/_session',
- data: JSON.stringify({name: username, password: password}),
- processData: false,
- contentType: 'application/json',
+ data: {name: username, password: password},
+ beforeSend: function(xhr) {
+ xhr.setRequestHeader('Accept', 'application/json');
+ },
success: function () {
callback();
},
@@ -151,7 +147,6 @@ asyncTest("Replicate from DB as non-admin user", function() {
];
function cleanup() {
- console.log('cleaning up');
deleteAdminUser(self.adminuser, function (err) {
if (err) console.error(err);
logout(function (err) {
@@ -161,52 +156,30 @@ asyncTest("Replicate from DB as non-admin user", function() {
});
}
+ initDBPair(self.name, self.remote, function(db, remote) {
+
// add user
createAdminUser(function (err, adminuser) {
- if (err) console.error(err);
+ if (err) {
+ ok(false, 'unable to create admin user');
+ console.error(err);
+ return cleanup();
+ }
self.adminuser = adminuser;
login('adminuser', 'password', function (err) {
if (err) console.error(err);
-
- initDBPair(this.name, this.remote, function(db, remote) {
remote.bulkDocs({docs: docs}, {}, function(err, results) {
- if (err) console.error(err);
-
- // db.replicate.from doesn't call it's callback on error
- // due to there being no proper error handling, so when
- // this test fails it leaves the remote db in a
- // non-admin-party mode. This timeout is used to finally
- // end the test and take the remote db back to admin-party
- // mode.
-
- // TODO: When there is actually some proper error handling
- // in pouch, update this test so it no longer relies on a
- // timeout.
-
- //setTimeout(cleanup, 5000); // be generous so we don't cause
- // false test failures
- // (hopefully!)
-
// no longer in admin-party
- db.replicate.from(self.remote, function(err, result) {
- if (err) console.error(err);
-
+ Pouch.replicate(self.remote, self.name, function(err, result) {
db.allDocs(function(err, result) {
- if (err) console.error(err);
- ok(
- result.rows.length === docs.length,
- 'correct # docs exist'
- );
- // wait for timeout so we don't call start()
- // multiple times
+ ok(result.rows.length === docs.length, 'correct # docs exist');
cleanup();
});
});
});
});
-
});
});

0 comments on commit 5d8ac0a

Please sign in to comment.