You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2012/01/03 20:33:21 UTC

[2/11] git commit: Fix whitespace

Fix whitespace


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

Branch: refs/heads/1.2.x
Commit: 225b39b5a42962a552eddeb904bbc68c1ea14a2b
Parents: 5ef0f3c
Author: Jan Lehnardt <ja...@apache.org>
Authored: Thu Nov 17 12:26:31 2011 +0100
Committer: Jan Lehnardt <ja...@apache.org>
Committed: Tue Jan 3 19:23:59 2012 +0100

----------------------------------------------------------------------
 share/www/script/couch_test_runner.js      |    8 +-
 share/www/script/test/cookie_auth.js       |   45 +++---
 share/www/script/test/users_db_security.js |  221 +++++++++++++++++++++++
 src/couchdb/couch_httpd_db.erl             |   20 +-
 src/couchdb/couch_view_group.erl           |    4 +-
 src/couchdb/couch_view_updater.erl         |    2 +-
 6 files changed, 261 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/225b39b5/share/www/script/couch_test_runner.js
----------------------------------------------------------------------
diff --git a/share/www/script/couch_test_runner.js b/share/www/script/couch_test_runner.js
index 6316e20..61823c0 100644
--- a/share/www/script/couch_test_runner.js
+++ b/share/www/script/couch_test_runner.js
@@ -141,7 +141,7 @@ function setupAdminParty(fun) {
           success : function() {
             removeAdmins(confs, doneFun);
           }
-        }, "admins", remove[0], null);        
+        }, "admins", remove[0], null);
       } else {
         doneFun();
       }
@@ -238,13 +238,13 @@ function saveTestReport(report) {
       report.db = db_info;
       $.couch.info({success : function(node_info) {
         report.node = node_info;
-        db.saveDoc(report);        
+        db.saveDoc(report);
       }});
     };
     var createDb = function() {
       db.create({success: function() {
-        db.info({success:saveReport});        
-      }});    
+        db.info({success:saveReport});
+      }});
     };
     db.info({error: createDb, success:saveReport});
   }

http://git-wip-us.apache.org/repos/asf/couchdb/blob/225b39b5/share/www/script/test/cookie_auth.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/cookie_auth.js b/share/www/script/test/cookie_auth.js
index 09bfd69..180d42e 100644
--- a/share/www/script/test/cookie_auth.js
+++ b/share/www/script/test/cookie_auth.js
@@ -12,7 +12,7 @@
 
 couchTests.cookie_auth = function(debug) {
   // This tests cookie-based authentication.
-  
+
   var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
   db.deleteDb();
   db.createDb();
@@ -34,13 +34,14 @@ couchTests.cookie_auth = function(debug) {
       // try using an invalid cookie
       var usersDb = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"});
       usersDb.deleteDb();
-      
+      usersDb.createDb();
+
       // test that the users db is born with the auth ddoc
       var ddoc = usersDb.open("_design/_auth");
       T(ddoc.validate_doc_update);
-      
+
       // TODO test that changing the config so an existing db becomes the users db installs the ddoc also
-      
+
       var password = "3.141592653589";
 
       // Create a user
@@ -48,11 +49,11 @@ couchTests.cookie_auth = function(debug) {
         name: "Jason Davies",
         roles: ["dev"]
       }, password);
-      T(usersDb.save(jasonUserDoc).ok);      
-      
+      T(usersDb.save(jasonUserDoc).ok);
+
       var checkDoc = usersDb.open(jasonUserDoc._id);
       T(checkDoc.name == "Jason Davies");
-      
+
       var jchrisUserDoc = CouchDB.prepareUserDoc({
         name: "jchris@apache.org"
       }, "funnybone");
@@ -70,7 +71,7 @@ couchTests.cookie_auth = function(debug) {
         T(e.error == "conflict");
         T(usersDb.last_req.status == 409);
       }
-      
+
       // we can't create _names
       var underscoreUserDoc = CouchDB.prepareUserDoc({
         name: "_why"
@@ -83,12 +84,12 @@ couchTests.cookie_auth = function(debug) {
         T(e.error == "forbidden");
         T(usersDb.last_req.status == 403);
       }
-      
+
       // we can't create docs with malformed ids
       var badIdDoc = CouchDB.prepareUserDoc({
         name: "foo"
       }, "bar");
-      
+
       badIdDoc._id = "org.apache.couchdb:w00x";
 
       try {
@@ -98,11 +99,11 @@ couchTests.cookie_auth = function(debug) {
         T(e.error == "forbidden");
         T(usersDb.last_req.status == 403);
       }
-      
+
       // login works
       T(CouchDB.login('Jason Davies', password).ok);
       T(CouchDB.session().userCtx.name == 'Jason Davies');
-      
+
       // JSON login works
       var xhr = CouchDB.request("POST", "/_session", {
         headers: {"Content-Type": "application/json"},
@@ -153,12 +154,12 @@ couchTests.cookie_auth = function(debug) {
        }
 
       // test users db validations
-      // 
+      //
       // test that you can't update docs unless you are logged in as the user (or are admin)
       T(CouchDB.login("jchris@apache.org", "funnybone").ok);
       T(CouchDB.session().userCtx.name == "jchris@apache.org");
       T(CouchDB.session().userCtx.roles.length == 0);
-      
+
       jasonUserDoc.foo=3;
 
       try {
@@ -171,7 +172,7 @@ couchTests.cookie_auth = function(debug) {
 
       // test that you can't edit roles unless you are admin
       jchrisUserDoc.roles = ["foo"];
-      
+
       try {
         usersDb.save(jchrisUserDoc);
         T(false && "Can't set roles unless you are admin. Should have thrown an error.");
@@ -179,16 +180,16 @@ couchTests.cookie_auth = function(debug) {
         T(e.error == "forbidden");
         T(usersDb.last_req.status == 403);
       }
-      
+
       T(CouchDB.logout().ok);
-      T(CouchDB.session().userCtx.roles[0] == "_admin");      
+      T(CouchDB.session().userCtx.roles[0] == "_admin");
 
       jchrisUserDoc.foo = ["foo"];
       T(usersDb.save(jchrisUserDoc).ok);
 
       // test that you can't save system (underscore) roles even if you are admin
       jchrisUserDoc.roles = ["_bar"];
-      
+
       try {
         usersDb.save(jchrisUserDoc);
         T(false && "Can't add system roles to user's db. Should have thrown an error.");
@@ -196,18 +197,18 @@ couchTests.cookie_auth = function(debug) {
         T(e.error == "forbidden");
         T(usersDb.last_req.status == 403);
       }
-      
+
       // make sure the foo role has been applied
       T(CouchDB.login("jchris@apache.org", "funnybone").ok);
       T(CouchDB.session().userCtx.name == "jchris@apache.org");
       T(CouchDB.session().userCtx.roles.indexOf("_admin") == -1);
       T(CouchDB.session().userCtx.roles.indexOf("foo") != -1);
-      
+
       // now let's make jchris a server admin
       T(CouchDB.logout().ok);
       T(CouchDB.session().userCtx.roles[0] == "_admin");
       T(CouchDB.session().userCtx.name == null);
-      
+
       // set the -hashed- password so the salt matches
       // todo ask on the ML about this
       run_on_modified_server([{section: "admins",
@@ -233,7 +234,7 @@ couchTests.cookie_auth = function(debug) {
           T(s.info.authentication_db == "test_suite_users");
           // test that jchris still has the foo role
           T(CouchDB.session().userCtx.roles.indexOf("foo") != -1);
-        });      
+        });
 
     } finally {
       // Make sure we erase any auth cookies so we don't affect other tests

http://git-wip-us.apache.org/repos/asf/couchdb/blob/225b39b5/share/www/script/test/users_db_security.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/users_db_security.js b/share/www/script/test/users_db_security.js
new file mode 100644
index 0000000..8ea93db
--- /dev/null
+++ b/share/www/script/test/users_db_security.js
@@ -0,0 +1,221 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+couchTests.users_db_security = function(debug) {
+  var usersDb = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"});
+  if (debug) debugger;
+
+  var loginUser = function(username) {
+    var pws = {
+      jan: "apple",
+      jchris: "mp3",
+      jchris1: "couch",
+      fdmanana: "foobar",
+      benoitc: "test"
+    };
+    var username1 = username.replace(/[0-9]$/, "");
+    var password = pws[username];
+    //console.log("Logging in '" + username1 + "' with password '" + password + "'");
+    T(CouchDB.login(username1, pws[username]).ok);
+  };
+
+  var open_as = function(db, docId, username) {
+    loginUser(username);
+    try {
+      return db.open(docId, {"anti-cache": Math.round(Math.random() * 100000)});
+    } finally {
+      CouchDB.logout();
+    }
+  };
+
+  var view_as = function(db, viewname, username) {
+    loginUser(username);
+    try {
+      return db.view(viewname);
+    } finally {
+      CouchDB.logout();
+    }
+  };
+
+  var save_as = function(db, doc, username)
+  {
+    loginUser(username);
+    try {
+      return db.save(doc);
+    } catch (ex) {
+      return ex;
+    } finally {
+      CouchDB.logout();
+    }
+  };
+
+  var testFun = function()
+  {
+    usersDb.deleteDb();
+    usersDb.createDb();
+
+    // _users db
+    // a doc with a field 'password' should be hashed to 'password_sha'
+    //  with salt and salt stored in 'salt', 'password' is set to null.
+    //  Exising 'password_sha' and 'salt' fields are overwritten with new values
+    //  when a non-null 'password' field exists.
+    // anonymous should be able to create a user document
+    var userDoc = {
+      _id: "org.couchdb.user:jchris",
+      type: "user",
+      name: "jchris",
+      password: "mp3",
+      roles: []
+    };
+
+    // jan's gonna be admin as he's the first user
+    TEquals(true, usersDb.save(userDoc).ok, "should save document");
+    userDoc = usersDb.open("org.couchdb.user:jchris");
+    TEquals(undefined, userDoc.password, "password field should be null 1");
+    TEquals(40, userDoc.password_sha.length, "password_sha should exist");
+    TEquals(32, userDoc.salt.length, "salt should exist");
+
+    // create server admin
+    run_on_modified_server([
+        {
+          section: "admins",
+          key: "jan",
+          value: "apple"
+        }
+      ], function() {
+
+      // anonymous should not be able to read an existing user's user document
+      var res = usersDb.open("org.couchdb.user:jchris");
+      TEquals(null, res, "anonymous user doc read should be not found");
+
+      // user should be able to read their own document
+
+      var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris");
+      TEquals("org.couchdb.user:jchris", jchrisDoc._id);
+
+      // user should bt able to update their own document
+      // new 'password' fields should trigger new hashing routine
+      jchrisDoc.password = "couch";
+
+      TEquals(true, save_as(usersDb, jchrisDoc, "jchris").ok);
+      var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris1");
+
+      TEquals(undefined, jchrisDoc.password, "password field should be null 2");
+      TEquals(40, jchrisDoc.password_sha.length, "password_sha should exist");
+      TEquals(32, jchrisDoc.salt.length, "salt should exist");
+
+      TEquals(true, userDoc.salt != jchrisDoc.salt, "should have new salt");
+      TEquals(true, userDoc.password_sha != jchrisDoc.password_sha,
+        "should have new password_sha");
+
+      // user should not be able to read another user's user document
+      var fdmananaDoc = {
+        _id: "org.couchdb.user:fdmanana",
+        type: "user",
+        name: "fdmanana",
+        password: "foobar",
+        roles: []
+      };
+
+      usersDb.save(fdmananaDoc);
+
+      var fdmananaDocAsReadByjchris =
+        open_as(usersDb, "org.couchdb.user:fdmanana", "jchris1");
+      TEquals(null, fdmananaDocAsReadByjchris,
+        "should not_found opening another user's user doc");
+
+
+      // save a db admin
+      var benoitcDoc = {
+        _id: "org.couchdb.user:benoitc",
+        type: "user",
+        name: "benoitc",
+        password: "test",
+        roles: []
+      };
+      usersDb.save(benoitcDoc);
+
+      TEquals(true, CouchDB.login("jan", "apple").ok);
+
+      T(usersDb.setSecObj({
+        "admins" : {
+          roles : [],
+          names : ["benoitc"]
+        }
+      }).ok);
+      CouchDB.logout();
+
+      // user should not be able to read from any view
+      var ddoc = {
+        _id: "_design/user_db_auth",
+        views: {
+          test: {
+            map: "function(doc) { emit(doc._id, null); }"
+          }
+        }
+      };
+
+      save_as(usersDb, ddoc, "jan");
+
+      try {
+        usersDb.view("user_db_auth/test");
+        T(false, "user had access to view in admin db");
+      } catch(e) {
+        TEquals("forbidden", e.error,
+        "non-admins should not be able to read a view");
+      }
+
+      // admin should be able to read from any view
+      var result = view_as(usersDb, "user_db_auth/test", "jan");
+      TEquals(3, result.total_rows, "should allow access and list two users to admin");
+
+      // db admin should be able to read from any view
+      var result = view_as(usersDb, "user_db_auth/test", "benoitc");
+      TEquals(3, result.total_rows, "should allow access and list two users to db admin");
+
+      // non-admins can't read design docs
+      try {
+        open_as(usersDb, "_design/user_db_auth", "jchris1");
+        T(false, "non-admin read design doc, should not happen");
+      } catch(e) {
+        TEquals("forbidden", e.error, "non-admins can't read design docs");
+      }
+
+      // admin should be able to read and edit any user doc
+      fdmananaDoc.password = "mobile";
+      var result = save_as(usersDb, fdmananaDoc, "jan");
+      TEquals(true, result.ok, "admin should be able to update any user doc");
+
+      // db admin should be able to read and edit any user doc
+      fdmananaDoc.password = "mobile1";
+      var result = save_as(usersDb, fdmananaDoc, "benoitc");
+      TEquals(true, result.ok, "db admin should be able to update any user doc");
+
+      // ensure creation of old-style docs still works
+      var robertDoc = CouchDB.prepareUserDoc({ name: "robert" }, "anchovy");
+      var result = usersDb.save(robertDoc);
+      TEquals(true, result.ok, "old-style user docs should still be accepted");
+
+      // log in one last time so run_on_modified_server can clean up the admin account
+      TEquals(true, CouchDB.login("jan", "apple").ok);
+    });
+  };
+
+  usersDb.deleteDb();
+  run_on_modified_server(
+    [{section: "couch_httpd_auth",
+      key: "authentication_db", value: usersDb.name}],
+    testFun
+  );
+  usersDb.deleteDb(); // cleanup
+
+};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/225b39b5/src/couchdb/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index ff4d3ec..f2fab56 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -237,7 +237,7 @@ db_req(#httpd{method='POST',path_parts=[DbName]}=Req, Db) ->
                     ?LOG_INFO("Batch doc error (~s): ~p",[DocId, Error])
                 end
             end),
-            
+
         send_json(Req, 202, [], {[
             {ok, true},
             {id, DocId}
@@ -699,7 +699,7 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) ->
         update_type = UpdateType
     } = parse_doc_query(Req),
     couch_doc:validate_docid(DocId),
-    
+
     Loc = absolute_uri(Req, "/" ++ ?b2l(Db#db.name) ++ "/" ++ ?b2l(DocId)),
     RespHeaders = [{"Location", Loc}],
     case couch_util:to_list(couch_httpd:header_value(Req, "Content-Type")) of
@@ -721,7 +721,7 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) ->
         "ok" ->
             % batch
             Doc = couch_doc_from_req(Req, DocId, couch_httpd:json_body(Req)),
-        
+
             spawn(fun() ->
                     case catch(couch_db:update_doc(Db, Doc, [])) of
                     {ok, _} -> ok;
@@ -786,7 +786,7 @@ send_doc_efficiently(#httpd{mochi_req = MochiReq} = Req,
             send_json(Req, 200, Headers, couch_doc:to_json_obj(Doc, Options));
         true ->
             Boundary = couch_uuids:random(),
-            JsonBytes = ?JSON_ENCODE(couch_doc:to_json_obj(Doc, 
+            JsonBytes = ?JSON_ENCODE(couch_doc:to_json_obj(Doc,
                     [attachments, follows, att_encoding_info | Options])),
             {ContentType, Len} = couch_doc:len_doc_to_multi_part_stream(
                     Boundary,JsonBytes, Atts, true),
@@ -803,7 +803,7 @@ send_docs_multipart(Req, Results, Options1) ->
     OuterBoundary = couch_uuids:random(),
     InnerBoundary = couch_uuids:random(),
     Options = [attachments, follows, att_encoding_info | Options1],
-    CType = {"Content-Type", 
+    CType = {"Content-Type",
         "multipart/mixed; boundary=\"" ++ ?b2l(OuterBoundary) ++ "\""},
     {ok, Resp} = start_chunked_response(Req, 200, [CType]),
     couch_httpd:send_chunk(Resp, <<"--", OuterBoundary/binary>>),
@@ -821,8 +821,8 @@ send_docs_multipart(Req, Results, Options1) ->
         ({{not_found, missing}, RevId}) ->
              RevStr = couch_doc:rev_to_str(RevId),
              Json = ?JSON_ENCODE({[{"missing", RevStr}]}),
-             couch_httpd:send_chunk(Resp, 
-                [<<"\r\nContent-Type: application/json; error=\"true\"\r\n\r\n">>, 
+             couch_httpd:send_chunk(Resp,
+                [<<"\r\nContent-Type: application/json; error=\"true\"\r\n\r\n">>,
                 Json,
                 <<"\r\n--", OuterBoundary/binary>>])
          end, Results),
@@ -858,7 +858,7 @@ receive_request_data(Req, LenLeft) when LenLeft > 0 ->
     {Data, fun() -> receive_request_data(Req, LenLeft - iolist_size(Data)) end};
 receive_request_data(_Req, _) ->
     throw(<<"expected more data">>).
-    
+
 make_content_range(From, To, Len) ->
     ?l2b(io_lib:format("bytes ~B-~B/~B", [From, To, Len])).
 
@@ -1102,8 +1102,8 @@ db_attachment_req(#httpd{method=Method,mochi_req=MochiReq}=Req, Db, DocId, FileN
                             _Else ->
                                 ok
                         end,
-                        
-                        
+
+
                         fun(Size) -> couch_httpd:recv(Req, Size) end
                     end,
                 att_len = case couch_httpd:header_value(Req,"Content-Length") of

http://git-wip-us.apache.org/repos/asf/couchdb/blob/225b39b5/src/couchdb/couch_view_group.erl
----------------------------------------------------------------------
diff --git a/src/couchdb/couch_view_group.erl b/src/couchdb/couch_view_group.erl
index 62bc5af..10a16fd 100644
--- a/src/couchdb/couch_view_group.erl
+++ b/src/couchdb/couch_view_group.erl
@@ -357,7 +357,7 @@ handle_info({'EXIT', UpPid, reset},
 handle_info({'EXIT', _, reset}, State) ->
     %% message from an old (probably pre-compaction) updater; ignore
     {noreply, State};
-    
+
 handle_info({'EXIT', _FromPid, normal}, State) ->
     {noreply, State};
 
@@ -669,7 +669,7 @@ init_group(Db, Fd, #group{def_lang=Lang,views=Views}=
                         UserReds),
                     {Count, Reduced}
                 end,
-            
+
             case couch_util:get_value(<<"collation">>, Options, <<"default">>) of
             <<"default">> ->
                 Less = fun couch_view:less_json_ids/2;

http://git-wip-us.apache.org/repos/asf/couchdb/blob/225b39b5/src/couchdb/couch_view_updater.erl
----------------------------------------------------------------------
diff --git a/src/couchdb/couch_view_updater.erl b/src/couchdb/couch_view_updater.erl
index c4483fa..084ce77 100644
--- a/src/couchdb/couch_view_updater.erl
+++ b/src/couchdb/couch_view_updater.erl
@@ -156,7 +156,7 @@ load_doc(Db, DocInfo, MapQueue, DocOpts, IncludeDesign) ->
             couch_work_queue:queue(MapQueue, {Seq, Doc})
         end
     end.
-    
+
 do_maps(#group{query_server = Qs} = Group, MapQueue, WriteQueue) ->
     case couch_work_queue:dequeue(MapQueue) of
     closed ->