couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gar...@apache.org
Subject fauxton commit: updated refs/heads/master to f8269b6
Date Thu, 23 Feb 2017 06:26:38 GMT
Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master ecc084618 -> f8269b6cb


handle username and passwords correctly with base64 encoding


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/f8269b6c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/f8269b6c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/f8269b6c

Branch: refs/heads/master
Commit: f8269b6cb95d39cb6cd2b4a18e9af747ab09aa97
Parents: ecc0846
Author: Garren Smith <garren.smith@gmail.com>
Authored: Wed Feb 22 15:34:06 2017 +0200
Committer: Garren Smith <garren.smith@gmail.com>
Committed: Thu Feb 23 08:26:01 2017 +0200

----------------------------------------------------------------------
 app/addons/replication/__tests__/api.tests.js   | 73 +++++++++++++++++++-
 app/addons/replication/api.js                   | 49 +++++++++++--
 .../replication/components/newreplication.js    |  4 +-
 package.json                                    |  2 +-
 4 files changed, 119 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f8269b6c/app/addons/replication/__tests__/api.tests.js
----------------------------------------------------------------------
diff --git a/app/addons/replication/__tests__/api.tests.js b/app/addons/replication/__tests__/api.tests.js
index 29fb17e..f2ad098 100644
--- a/app/addons/replication/__tests__/api.tests.js
+++ b/app/addons/replication/__tests__/api.tests.js
@@ -18,7 +18,9 @@ import {
   addDocIdAndRev,
   getDocUrl,
   encodeFullUrl,
-  decodeFullUrl
+  decodeFullUrl,
+  getCredentialsFromUrl,
+  removeCredentialsFromUrl
 } from '../api';
 import Constants from '../constants';
 
@@ -51,6 +53,19 @@ describe('Replication API', () => {
       assert.deepEqual(source.headers, {Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
       assert.ok(/my%2Fdb/.test(source.url));
     });
+
+    it('returns remote source url and auth header', () => {
+      const source = getSource({
+        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
+        remoteSource: 'http://eddie:my-password@my-couchdb.com/my-db',
+        localSource: "local",
+        username: 'the-user',
+        password: 'password'
+      }, {origin: 'http://dev:6767'});
+
+      assert.deepEqual(source.headers, {Authorization:"Basic ZWRkaWU6bXktcGFzc3dvcmQ="});
+      assert.deepEqual('http://my-couchdb.com/my-db', source.url);
+    });
   });
 
   describe('getTarget', () => {
@@ -64,6 +79,19 @@ describe('Replication API', () => {
       }).url);
     });
 
+    it("encodes username and password for remote", () => {
+      const remoteTarget = 'http://jimi:my-password@remote-couchdb.com/my/db';
+      const target = getTarget({
+        replicationTarget: Constants.REPLICATION_TARGET.NEW_REMOTE_DATABASE,
+        remoteTarget: remoteTarget,
+        username: 'fake',
+        password: 'fake'
+      });
+
+      assert.deepEqual(target.url, 'http://remote-couchdb.com/my%2Fdb');
+      assert.deepEqual(target.headers, {Authorization:"Basic amltaTpteS1wYXNzd29yZA=="});
+    });
+
     it('returns existing local database', () => {
       const target = getTarget({
         replicationTarget: Constants.REPLICATION_TARGET.EXISTING_LOCAL_DATABASE,
@@ -122,6 +150,7 @@ describe('Replication API', () => {
       assert.deepEqual("http://dev:8000/my-new%2Fdb", target.url);
       assert.deepEqual({}, target.headers);
     });
+
   });
 
   describe('continuous', () => {
@@ -209,4 +238,46 @@ describe('Replication API', () => {
 
   });
 
+  describe("getCredentialsFromUrl", () => {
+
+    it("can get username and password", () => {
+      const {username, password } = getCredentialsFromUrl("https://bob:marley@my-couchdb.com/db");
+
+      assert.deepEqual(username, 'bob');
+      assert.deepEqual(password, 'marley');
+    });
+
+    it("can get username and password with special characters", () => {
+      const {username, password } = getCredentialsFromUrl("http://bob:m@:/rley@my-couchdb.com/db");
+
+      assert.deepEqual(username, 'bob');
+      assert.deepEqual(password, 'm@:/rley');
+    });
+
+    it("returns nothing for no username and password", () => {
+      const {username, password } = getCredentialsFromUrl("http://my-couchdb.com/db");
+
+      assert.deepEqual(username, '');
+      assert.deepEqual(password, '');
+    });
+  });
+
+  describe("removeCredentialsFromUrl", () => {
+
+    it("can remove username and password", () => {
+      const url = removeCredentialsFromUrl("https://bob:marley@my-couchdb.com/db");
+      assert.deepEqual(url, 'https://my-couchdb.com/db');
+    });
+
+    it("returns url if no password", () => {
+      const url = removeCredentialsFromUrl("https://my-couchdb.com/db");
+      assert.deepEqual(url, 'https://my-couchdb.com/db');
+    });
+
+    it("can remove username and password with special characters", () => {
+      const url = removeCredentialsFromUrl("https://bob:m@:/rley@my-couchdb.com/db");
+      assert.deepEqual(url, 'https://my-couchdb.com/db');
+    });
+
+  });
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f8269b6c/app/addons/replication/api.js
----------------------------------------------------------------------
diff --git a/app/addons/replication/api.js b/app/addons/replication/api.js
index 327d35d..f14e4eb 100644
--- a/app/addons/replication/api.js
+++ b/app/addons/replication/api.js
@@ -10,6 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+import 'url-polyfill';
 import Constants from './constants';
 import app from '../../app';
 import FauxtonAPI from '../../core/api';
@@ -41,6 +42,38 @@ export const getAuthHeaders = (username, password) => {
   };
 };
 
+export const getCredentialsFromUrl = (url) => {
+  const index = url.lastIndexOf('@');
+  if (index === -1) {
+    return {
+      username: '',
+      password: ''
+    };
+  }
+
+  const startIndex = url.startsWith("https") ? 8 : 7;
+  const rawCreds = url.slice(startIndex, index);
+  const colonIndex = rawCreds.indexOf(':');
+  const username = rawCreds.slice(0, colonIndex);
+  const password = rawCreds.slice(colonIndex + 1, rawCreds.length);
+
+  return {
+    username,
+    password
+  };
+};
+
+export const removeCredentialsFromUrl = (url) => {
+  const index = url.lastIndexOf('@');
+  if (index === -1) {
+    return url;
+  }
+
+  const protocol = url.startsWith("https") ? "https://" : 'http://';
+  const cleanUrl = url.slice(index + 1);
+  return protocol + cleanUrl;
+};
+
 export const getSource = ({
   replicationSource,
   localSource,
@@ -49,13 +82,19 @@ export const getSource = ({
   password
 },
 {origin} = window.location) => {
-  let url = remoteSource;
+  let url;
+  let headers;
   if (replicationSource === Constants.REPLICATION_SOURCE.LOCAL) {
     url = `${origin}/${localSource}`;
+    headers = getAuthHeaders(username, password);
+  } else {
+    const credentials = getCredentialsFromUrl(remoteSource);
+    headers = getAuthHeaders(credentials.username, credentials.password);
+    url = removeCredentialsFromUrl(remoteSource);
   }
 
   return {
-    headers: getAuthHeaders(username, password),
+    headers,
     url: encodeFullUrl(url)
   };
 };
@@ -78,9 +117,9 @@ export const getTarget = ({
   if (replicationTarget === Constants.REPLICATION_TARGET.NEW_REMOTE_DATABASE ||
         replicationTarget === Constants.REPLICATION_TARGET.EXISTING_REMOTE_DATABASE) {
 
-    const targetUrl = new URL(remoteTarget);
-    target = encodeFullUrl(remoteTarget);
-    headers = getAuthHeaders(targetUrl.username, targetUrl.password);
+    const credentials = getCredentialsFromUrl(remoteTarget);
+    target = encodeFullUrl(removeCredentialsFromUrl(remoteTarget));
+    headers = getAuthHeaders(credentials.username, credentials.password);
   }
 
   return {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f8269b6c/app/addons/replication/components/newreplication.js
----------------------------------------------------------------------
diff --git a/app/addons/replication/components/newreplication.js b/app/addons/replication/components/newreplication.js
index 075898d..7dc254f 100644
--- a/app/addons/replication/components/newreplication.js
+++ b/app/addons/replication/components/newreplication.js
@@ -163,8 +163,8 @@ export default class NewReplicationController extends React.Component
{
       replicationDocName,
       username,
       password,
-      localTarget: localTarget,
-      localSource: localSource,
+      localTarget,
+      localSource,
       remoteTarget,
       remoteSource,
       _rev

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/f8269b6c/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index 781e34d..dabe4dd 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
     "redux-devtools": "^3.3.1",
     "redux-mock-store": "^1.2.1",
     "sinon": "git+https://github.com/sinonjs/sinon.git",
-    "url-polyfill": "github/url-polyfill"
+    "url-polyfill": "git+https://github.com/webcomponents/URL.git"
   },
   "dependencies": {
     "async": "~0.2.6",


Mime
View raw message