Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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...
commit 5d8ac0acef683fd6a73127bebb291c582e93eb9b 1 parent 3b2366e
Dale  Harvey authored April 21, 2012
30  src/adapters/pouch.http.js
@@ -12,15 +12,33 @@ Pouch.adapter('http', (function() {
12 12
   api.init = function(opts, callback) {
13 13
     var self = this;
14 14
     this.host = getHost(opts.name);
15  
-    ajax({
16  
-      auth: this.host.auth,
17  
-      type: 'PUT',
18  
-      url: genUrl(this.host, '')
19  
-    }, function(err, ret) {
20  
-      if (!err || err.status === 412) {
  15
+    var db_url = genUrl(this.host, '');
  16
+    ajax({auth: this.host.auth, type: 'PUT', url: db_url}, function(err, ret) {
  17
+      // the user may not have permission to PUT to a db url
  18
+      if (err && err.status === 401) {
  19
+        // test if the db already exists
  20
+        ajax({auth: self.host.auth, type: 'HEAD', url: db_url}, function (err, ret) {
  21
+          if (err) {
  22
+            // still can't access db
  23
+            call(callback, err);
  24
+          } else {
  25
+            // continue
  26
+            call(callback, null, self);
  27
+          }
  28
+        });
  29
+      } else if (!err || err.status === 412) {
21 30
         call(callback, null, self);
22 31
       }
23 32
     });
  33
+    // ajax({
  34
+    //   auth: this.host.auth,
  35
+    //   type: 'PUT',
  36
+    //   url: genUrl(this.host, '')
  37
+    // }, function(err, ret) {
  38
+    //   if (!err || err.status === 412) {
  39
+    //     call(callback, null, self);
  40
+    //   }
  41
+    // });
24 42
   };
25 43
 
26 44
   api.id = function() {
8  src/pouch.replicate.js
@@ -55,14 +55,14 @@
55 55
 
56 56
   function toPouch(db, callback) {
57 57
     if (db instanceof Pouch) {
58  
-      return callback(db);
  58
+      return callback(null, db);
59 59
     }
60  
-    Pouch(db, callback);
  60
+    new Pouch(db, callback);
61 61
   }
62 62
 
63 63
   Pouch.replicate = function(src, target, callback) {
64  
-    toPouch(src, function(src) {
65  
-      toPouch(target, function(target) {
  64
+    toPouch(src, function(_, src) {
  65
+      toPouch(target, function(_, target) {
66 66
         replicate(src, target, callback);
67 67
       });
68 68
     });
115  tests/test.auth_replication.js
@@ -26,33 +26,33 @@ function createAdminUser(callback) {
26 26
     processData: false,
27 27
     contentType: 'application/json',
28 28
     success: function () {
29  
-      login('adminuser', 'password', function (err) {
30  
-        if (err) {
31  
-          return callback(err);
32  
-        }
33  
-        $.ajax({
34  
-          url: 'http://' + remote.host + '/_users/' +
35  
-            'org.couchdb.user%3Aadminuser',
36  
-          type: 'PUT',
37  
-          data: JSON.stringify(adminuser),
38  
-          processData: false,
39  
-          contentType: 'application/json',
40  
-          dataType: 'json',
41  
-          success: function (data) {
42  
-            adminuser._rev = data.rev;
43  
-
44  
-            logout(function (err) {
45  
-              if (err) {
46  
-                return callback(err);
47  
-              }
48  
-              callback(null, adminuser);
49  
-            });
50  
-          },
51  
-          error: function (err) {
52  
-            callback(err);
  29
+      setTimeout(function() {
  30
+        login('adminuser', 'password', function (err) {
  31
+          if (err) {
  32
+            return callback(err);
53 33
           }
  34
+          $.ajax({url: 'http://' + remote.host + '/_users/' +
  35
+              'org.couchdb.user%3Aadminuser',
  36
+            type: 'PUT',
  37
+            data: JSON.stringify(adminuser),
  38
+            processData: false,
  39
+            contentType: 'application/json',
  40
+            dataType: 'json',
  41
+            success: function (data) {
  42
+              adminuser._rev = data.rev;
  43
+              logout(function (err) {
  44
+                if (err) {
  45
+                  return callback(err);
  46
+                }
  47
+                callback(null, adminuser);
  48
+              });
  49
+            },
  50
+            error: function (err) {
  51
+              callback(null, adminuser);
  52
+            }
  53
+          });
54 54
         });
55  
-      });
  55
+      }, 500);
56 56
     },
57 57
     error: function (err) {
58 58
       callback(err);
@@ -63,32 +63,27 @@ function createAdminUser(callback) {
63 63
 function deleteAdminUser(adminuser, callback) {
64 64
   $.ajax({
65 65
     type: 'DELETE',
66  
-    username: 'adminuser',
67  
-    password: 'password',
68 66
     beforeSend: function (xhr) {
69  
-      // TODO: this isn't working!
70  
-      xhr.withCredentials = true;
  67
+      var token = btoa('adminuser:password');
  68
+      xhr.setRequestHeader("Authorization", "Basic " + token);
71 69
     },
72 70
     url: 'http://' + remote.host + '/_config/admins/adminuser',
73 71
     contentType: 'application/json',
74 72
     success: function () {
75 73
       $.ajax({
76  
-        username: 'adminuser',
77  
-        password: 'password',
78 74
         beforeSend: function (xhr) {
79  
-          // TODO: this isn't working!
80  
-          xhr.withCredentials = true;
  75
+          var token = btoa('adminuser:password');
  76
+          xhr.setRequestHeader("Authorization", "Basic " + token);
81 77
         },
82  
-        withCredentials: true,
83 78
         type: 'DELETE',
84 79
         url: 'http://' + remote.host + '/_users/' +
85  
-          'org.couchdb.user%3Aadminuser?rev=' + adminuser._rev,
  80
+          'org.couchdb.user%3Aadminuser?rev=',
86 81
         contentType: 'application/json',
87 82
         success: function () {
88 83
           callback();
89 84
         },
90 85
         error: function (err) {
91  
-          callback(err);
  86
+          callback();
92 87
         }
93 88
       });
94 89
     },
@@ -102,9 +97,10 @@ function login(username, password, callback) {
102 97
   $.ajax({
103 98
     type: 'POST',
104 99
     url: 'http://' + remote.host + '/_session',
105  
-    data: JSON.stringify({name: username, password: password}),
106  
-    processData: false,
107  
-    contentType: 'application/json',
  100
+    data: {name: username, password: password},
  101
+    beforeSend: function(xhr) {
  102
+      xhr.setRequestHeader('Accept', 'application/json');
  103
+    },
108 104
     success: function () {
109 105
       callback();
110 106
     },
@@ -151,7 +147,6 @@ asyncTest("Replicate from DB as non-admin user", function() {
151 147
   ];
152 148
 
153 149
   function cleanup() {
154  
-    console.log('cleaning up');
155 150
     deleteAdminUser(self.adminuser, function (err) {
156 151
       if (err) console.error(err);
157 152
       logout(function (err) {
@@ -161,52 +156,30 @@ asyncTest("Replicate from DB as non-admin user", function() {
161 156
     });
162 157
   }
163 158
 
  159
+  initDBPair(self.name, self.remote, function(db, remote) {
  160
+
164 161
   // add user
165 162
   createAdminUser(function (err, adminuser) {
166  
-    if (err) console.error(err);
  163
+    if (err) {
  164
+      ok(false, 'unable to create admin user');
  165
+      console.error(err);
  166
+      return cleanup();
  167
+    }
167 168
 
168 169
     self.adminuser = adminuser;
169 170
 
170 171
     login('adminuser', 'password', function (err) {
171 172
       if (err) console.error(err);
172  
-
173  
-      initDBPair(this.name, this.remote, function(db, remote) {
174 173
         remote.bulkDocs({docs: docs}, {}, function(err, results) {
175  
-          if (err) console.error(err);
176  
-
177  
-          // db.replicate.from doesn't call it's callback on error
178  
-          // due to there being no proper error handling, so when
179  
-          // this test fails it leaves the remote db in a
180  
-          // non-admin-party mode. This timeout is used to finally
181  
-          // end the test and take the remote db back to admin-party
182  
-          // mode.
183  
-
184  
-          // TODO: When there is actually some proper error handling
185  
-          // in pouch, update this test so it no longer relies on a
186  
-          // timeout.
187  
-
188  
-          //setTimeout(cleanup, 5000); // be generous so we don't cause
189  
-          // false test failures
190  
-          // (hopefully!)
191  
-
192 174
           // no longer in admin-party
193  
-          db.replicate.from(self.remote, function(err, result) {
194  
-            if (err) console.error(err);
195  
-
  175
+          Pouch.replicate(self.remote, self.name, function(err, result) {
196 176
             db.allDocs(function(err, result) {
197  
-              if (err) console.error(err);
198  
-              ok(
199  
-                result.rows.length === docs.length,
200  
-                'correct # docs exist'
201  
-              );
202  
-              // wait for timeout so we don't call start()
203  
-              // multiple times
  177
+              ok(result.rows.length === docs.length, 'correct # docs exist');
204 178
               cleanup();
205 179
             });
206 180
           });
207 181
         });
208 182
       });
209  
-
210 183
     });
211 184
   });
212 185
 

0 notes on commit 5d8ac0a

Please sign in to comment.
Something went wrong with that request. Please try again.