From 9007e2d21dea8b0185c0096b30364a8ee40a3867 Mon Sep 17 00:00:00 2001 From: John Christopher Anderson Date: Fri, 13 Mar 2009 22:15:34 +0000 Subject: Commit Damien's rep_security branch to trunk. Changes bulk_docs conflict checking. Breaks file format, see mailing list for data upgrade procedure, or http://wiki.apache.org/couchdb/Breaking_changes git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@753448 13f79535-47bb-0310-9956-ffa450edef68 --- share/www/script/test/security_validation.js | 165 +++++++++++++++++++++++---- 1 file changed, 141 insertions(+), 24 deletions(-) (limited to 'share/www/script/test/security_validation.js') diff --git a/share/www/script/test/security_validation.js b/share/www/script/test/security_validation.js index 61f56b39..a41d8d70 100644 --- a/share/www/script/test/security_validation.js +++ b/share/www/script/test/security_validation.js @@ -31,28 +31,27 @@ couchTests.security_validation = function(debug) { // the "username:password" string, it's sent completely plain text. // Firefox and Safari both deal with this correctly (which is to say // they correctly do nothing special). - - + + var db = new CouchDB("test_suite_db"); db.deleteDb(); db.createDb(); if (debug) debugger; - + run_on_modified_server( [{section: "httpd", key: "authentication_handler", value: "{couch_httpd, special_test_authentication_handler}"}, - {section:"httpd", + {section:"httpd", key: "WWW-Authenticate", value: "X-Couch-Test-Auth"}], - - function () { + function () { // try saving document usin the wrong credentials var wrongPasswordDb = new CouchDB("test_suite_db", {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:foo"} ); - + try { wrongPasswordDb.save({foo:1,author:"Damien Katz"}); T(false && "Can't get here. Should have thrown an error 1"); @@ -60,8 +59,8 @@ couchTests.security_validation = function(debug) { T(e.error == "unauthorized"); T(wrongPasswordDb.last_req.status == 401); } - - + + // Create the design doc that will run custom validation code var designDoc = { _id:"_design/test", @@ -83,9 +82,9 @@ couchTests.security_validation = function(debug) { var userDb = new CouchDB("test_suite_db", {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:pecan pie"} ); - + T(userDb.save({_id:"testdoc", foo:1, author:"Damien Katz"}).ok); - + // Attempt to save the design as a non-admin try { userDb.save(designDoc); @@ -94,17 +93,17 @@ couchTests.security_validation = function(debug) { T(e.error == "unauthorized"); T(userDb.last_req.status == 401); } - - // add user as admin - db.setAdmins(["Damien Katz"]); - + + // set user as the admin + T(db.setDbProperty("_admins", ["Damien Katz"]).ok); + T(userDb.save(designDoc).ok); - + // update the document var doc = userDb.open("testdoc"); doc.foo=2; T(userDb.save(doc).ok); - + // Save a document that's missing an author field. try { userDb.save({foo:1}); @@ -113,12 +112,12 @@ couchTests.security_validation = function(debug) { T(e.error == "forbidden"); T(userDb.last_req.status == 403); } - + // Now attempt to update the document as a different user, Jan var user2Db = new CouchDB("test_suite_db", {"WWW-Authenticate": "X-Couch-Test-Auth Jan Lehnardt:apple"} ); - + var doc = user2Db.open("testdoc"); doc.foo=3; try { @@ -128,17 +127,17 @@ couchTests.security_validation = function(debug) { T(e.error == "unauthorized"); T(user2Db.last_req.status == 401); } - + // Now have Damien change the author to Jan doc = userDb.open("testdoc"); doc.author="Jan Lehnardt"; T(userDb.save(doc).ok); - + // Now update the document as Jan doc = user2Db.open("testdoc"); doc.foo = 3; T(user2Db.save(doc).ok); - + // Damien can't delete it try { userDb.deleteDoc(doc); @@ -147,8 +146,126 @@ couchTests.security_validation = function(debug) { T(e.error == "unauthorized"); T(userDb.last_req.status == 401); } - + // Now delete document - T(user2Db.deleteDoc(doc).ok); + T(user2Db.deleteDoc(doc).ok); + + // now test bulk docs + var docs = [{_id:"bahbah",author:"Damien Katz",foo:"bar"},{_id:"fahfah",foo:"baz"}]; + + // Create the docs + var results = db.bulkSave(docs); + + T(results[0].rev) + T(results[0].error == undefined) + T(results[1].rev === undefined) + T(results[1].error == "forbidden") + + T(db.open("bahbah")); + T(db.open("fahfah") == null); + + + // now all or nothing with a failure + var docs = [{_id:"booboo",author:"Damien Katz",foo:"bar"},{_id:"foofoo",foo:"baz"}]; + + // Create the docs + var results = db.bulkSave(docs, {all_or_nothing:true}); + + T(results.errors.length == 1); + T(results.errors[0].error == "forbidden"); + T(db.open("booboo") == null); + T(db.open("foofoo") == null); + + + // Now test replication + var AuthHeaders = {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"}; + var host = CouchDB.host; + var dbPairs = [ + {source:"test_suite_db_a", + target:"test_suite_db_b"}, + + {source:"test_suite_db_a", + target:{url: "http://" + host + "/test_suite_db_b", + headers: AuthHeaders}}, + + {source:{url:"http://" + host + "/test_suite_db_a", + headers: AuthHeaders}, + target:"test_suite_db_b"}, + + {source:{url:"http://" + host + "/test_suite_db_a", + headers: AuthHeaders}, + target:{url:"http://" + host + "/test_suite_db_b", + headers: AuthHeaders}}, + ] + var adminDbA = new CouchDB("test_suite_db_a"); + var adminDbB = new CouchDB("test_suite_db_b"); + var dbA = new CouchDB("test_suite_db_a", + {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"}); + var dbB = new CouchDB("test_suite_db_b", + {"WWW-Authenticate": "X-Couch-Test-Auth Christopher Lenz:dog food"}); + var xhr; + for (var testPair = 0; testPair < dbPairs.length; testPair++) { + var A = dbPairs[testPair].source + var B = dbPairs[testPair].target + + adminDbA.deleteDb(); + adminDbA.createDb(); + adminDbB.deleteDb(); + adminDbB.createDb(); + + // save and replicate a documents that will and will not pass our design + // doc validation function. + dbA.save({_id:"foo1",value:"a",author:"Noah Slater"}); + dbA.save({_id:"foo2",value:"a",author:"Christopher Lenz"}); + dbA.save({_id:"bad1",value:"a"}); + + T(CouchDB.replicate(A, B, {headers:AuthHeaders}).ok); + T(CouchDB.replicate(B, A, {headers:AuthHeaders}).ok); + + T(dbA.open("foo1")); + T(dbB.open("foo1")); + T(dbA.open("foo2")); + T(dbB.open("foo2")); + + // save the design doc to dbA + delete designDoc._rev; // clear rev from previous saves + adminDbA.save(designDoc); + + // no affect on already saved docs + T(dbA.open("bad1")); + + // Update some docs on dbB. Since the design hasn't replicated, anything + // is allowed. + + // this edit will fail validation on replication to dbA (no author) + T(dbB.save({_id:"bad2",value:"a"}).ok); + + // this edit will fail security on replication to dbA (wrong author + // replicating the change) + var foo1 = dbB.open("foo1"); + foo1.value = "b"; + dbB.save(foo1); + + // this is a legal edit + var foo2 = dbB.open("foo2"); + foo2.value = "b"; + dbB.save(foo2); + + var results = CouchDB.replicate(B, A, {headers:AuthHeaders}); + + T(results.ok); + + T(results.history[0].docs_written == 1); + T(results.history[0].doc_write_failures == 2); + + // bad2 should not be on dbA + T(dbA.open("bad2") == null); + + // The edit to foo1 should not have replicated. + T(dbA.open("foo1").value == "a"); + + // The edit to foo2 should have replicated. + T(dbA.open("foo2").value == "b"); + } }); }; -- cgit v1.2.3