diff options
Diffstat (limited to 'test/javascript/tests/security_validation.js')
-rw-r--r-- | test/javascript/tests/security_validation.js | 330 |
1 files changed, 0 insertions, 330 deletions
diff --git a/test/javascript/tests/security_validation.js b/test/javascript/tests/security_validation.js deleted file mode 100644 index 365f716e6..000000000 --- a/test/javascript/tests/security_validation.js +++ /dev/null @@ -1,330 +0,0 @@ -// 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.elixir = true; -couchTests.security_validation = function(debug) { - - var db_name = get_random_db_name(); - var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"}); - db.createDb(); - var authDb_name = get_random_db_name() + "_authdb"; - var authDb = new CouchDB(authDb_name, {"X-Couch-Full-Commit":"false"}); - authDb.createDb(); - var adminDbA, adminDbB; // used later - if (debug) debugger; - - run_on_modified_server( - [{section: "httpd", - key: "authentication_handlers", - value: "{couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}"}, - {section: "couch_httpd_auth", - key: "authentication_db", value: authDb_name}, - {section: "chttpd_auth", - key: "authentication_db", value: authDb_name}], - - function () { - // the special case handler does not exist (any longer) in clusters, so we have - // to replicate the behavior using a "normal" DB even though tests might no more - // run universally (why the "X-Couch-Test-Auth" header was introduced). - // btw: this needs to be INSIDE configured server to propagate correctly ;-) - // At least they'd run in the build, though - T(authDb.save(CouchDB.prepareUserDoc({name: "tom"}, "cat")).ok); // Basic dG9tOmNhdA== - T(authDb.save(CouchDB.prepareUserDoc({name: "jerry"}, "mouse")).ok); // Basic amVycnk6bW91c2U= - T(authDb.save(CouchDB.prepareUserDoc({name: "spike"}, "dog")).ok); // Basic c3Bpa2U6ZG9n - authDb.ensureFullCommit(); - - // try saving document using the wrong credentials - var wrongPasswordDb = new CouchDB(db_name + "", - {"Authorization": "Basic c3Bpa2U6Y2F0"} // spike:cat - which is wrong - ); - - try { - wrongPasswordDb.save({foo:1,author:"Damien Katz"}); - T(false, "Can't get here. Should have thrown an error 1"); - } catch (e) { - T(e.error == "unauthorized"); - T(wrongPasswordDb.last_req.status == 401); - } - - // test force basic login - var resp = wrongPasswordDb.request("GET", "/_session?basic=true"); - var err = JSON.parse(resp.responseText); - T(err.error == "unauthorized"); - T(resp.status == 401); - - // Create the design doc that will run custom validation code - var designDoc = { - _id:"_design/test", - language: "javascript", - validate_doc_update: stringFun(function (newDoc, oldDoc, userCtx, secObj) { - if (secObj.admin_override) { - if (userCtx.roles.indexOf('_admin') != -1) { - // user is admin, they can do anything - return true; - } - } - // docs should have an author field. - if (!newDoc._deleted && !newDoc.author) { - throw {forbidden: - "Documents must have an author field"}; - } - if (oldDoc && oldDoc.author != userCtx.name) { - throw {unauthorized: - "You are '" + userCtx.name + "', not the author '" + oldDoc.author + "' of this document. You jerk."}; - } - }) - } - - // Save a document normally - var userDb = new CouchDB("" + db_name + "", - {"Authorization": "Basic amVycnk6bW91c2U="} // jerry - ); - // test session - TEquals("jerry", JSON.parse(userDb.request("GET", "/_session").responseText).userCtx.name); - - T(userDb.save({_id:"testdoc", foo:1, author:"jerry"}).ok); - - // Attempt to save the design as a non-admin - try { - userDb.save(designDoc); - T(false && "Can't get here. Should have thrown an error on design doc"); - } catch (e) { - // cluster changes from 401 unauthorized to 403 forbidden - TEquals("forbidden", e.error); - TEquals(403, userDb.last_req.status); - } - - // set user as the admin - T(db.setSecObj({ - admins : {names : ["jerry"]} - }).ok); - - // TODO: when _security is correctly honored (COUCHDB-2990), switch back - //T(userDb.save(designDoc).ok); - T(db.save(designDoc).ok); - - var user2Db = new CouchDB("" + db_name + "", - {"Authorization": "Basic dG9tOmNhdA=="} // tom - ); - // Attempt to save the design as a non-admin (in replication scenario) - designDoc.foo = "bar"; - designDoc._rev = "2-642e20f96624a0aae6025b4dba0c6fb2"; - try { - user2Db.save(designDoc, {new_edits : false}); - T(false && "Can't get here. Should have thrown an error on design doc"); - } catch (e) { - // cluster changes from 401 unauthorized to 403 forbidden - TEquals("forbidden", e.error); - TEquals(403, userDb.last_req.status); - } - - // test the _session API - var resp = userDb.request("GET", "/_session"); - var user = JSON.parse(resp.responseText).userCtx; - T(user.name == "jerry"); - // test that the roles are listed properly - TEquals(user.roles, []); - - - // 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 (before and after compaction) - for (var i=0; i<2; i++) { - try { - userDb.save({foo:1}); - T(false && "Can't get here. Should have thrown an error 2"); - } catch (e) { - T(e.error == "forbidden"); - T(userDb.last_req.status == 403); - } - // compact. - no more available on clusters (but: test is still valid w/out compaction) - /*T(db.compact().ok); - T(db.last_req.status == 202); - // compaction isn't instantaneous, loop until done - while (db.info().compact_running) {};*/ - } - - // Now attempt to update the document as a different user, Jan - var doc = user2Db.open("testdoc"); - doc.foo=3; - try { - user2Db.save(doc); - T(false && "Can't get here. Should have thrown an error 3"); - } catch (e) { - T(e.error == "unauthorized"); - T(user2Db.last_req.status == 401); - } - - // Now have jerry change the author to tom - doc = userDb.open("testdoc"); - doc.author="tom"; - T(userDb.save(doc).ok); - - // Now update the document as tom - doc = user2Db.open("testdoc"); - doc.foo = 3; - T(user2Db.save(doc).ok); - - // jerry can't delete it - try { - userDb.deleteDoc(doc); - T(false && "Can't get here. Should have thrown an error 4"); - } catch (e) { - T(e.error == "unauthorized"); - T(userDb.last_req.status == 401); - } - - // admin must save with author field unless admin override - var resp = db.request("GET", "/_session"); - var user = JSON.parse(resp.responseText).userCtx; - T(user.name == null); - // test that we are admin - TEquals(user.roles, ["_admin"]); - - // can't save the doc even though we are admin - var doc = db.open("testdoc"); - doc.foo=3; - try { - db.save(doc); - T(false && "Can't get here. Should have thrown an error 3"); - } catch (e) { - T(e.error == "unauthorized"); - T(db.last_req.status == 401); - } - - // now turn on admin override - T(db.setDbProperty("_security", {admin_override : true}).ok); - // TODO: re-include after COUCHDB-2990 - //T(db.save(doc).ok); - - // try to do something lame - try { - db.setDbProperty("_security", ["foo"]); - T(false && "can't do this"); - } catch(e) {} - - // go back to normal - T(db.setDbProperty("_security", {admin_override : false}).ok); - - // Now delete document - T(user2Db.deleteDoc(doc).ok); - - // now test bulk docs - var docs = [{_id:"bahbah",author:"jerry",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 - no more available on cluster -/* 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 = {"Authorization": "Basic c3Bpa2U6ZG9n"}; // spike - adminDbA = new CouchDB("" + db_name + "_a", {"X-Couch-Full-Commit":"false"}); - adminDbB = new CouchDB("" + db_name + "_b", {"X-Couch-Full-Commit":"false"}); - var dbA = new CouchDB("" + db_name + "_a", AuthHeaders); - var dbB = new CouchDB("" + db_name + "_b", AuthHeaders); - // looping does not really add value as the scenario is the same anyway (there's nothing 2 be gained from it) - var A = CouchDB.protocol + CouchDB.host + "/" + db_name + "_a"; - var B = CouchDB.protocol + CouchDB.host + "/" + db_name + "_b"; - - // (the databases never exist b4 - and we made sure they're deleted below) - //adminDbA.deleteDb(); - adminDbA.createDb(); - //adminDbB.deleteDb(); - adminDbB.createDb(); - - // save and replicate a documents that will and will not pass our design - // doc validation function. - T(dbA.save({_id:"foo1",value:"a",author:"tom"}).ok); - T(dbA.save({_id:"foo2",value:"a",author:"spike"}).ok); - T(dbA.save({_id:"bad1",value:"a"}).ok); - - 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 - T(adminDbA.save(designDoc).ok); - - // 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"; - T(dbB.save(foo1).ok); - - // this is a legal edit - var foo2 = dbB.open("foo2"); - foo2.value = "b"; - T(dbB.save(foo2).ok); - - var results = CouchDB.replicate({"url": B, "headers": AuthHeaders}, {"url": A, "headers": AuthHeaders}, {headers:AuthHeaders}); - T(results.ok); - TEquals(1, results.history[0].docs_written); - TEquals(2, results.history[0].doc_write_failures); - - // 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"); - }); - - // cleanup - db.deleteDb(); - if(adminDbA){ - adminDbA.deleteDb(); - } - if(adminDbB){ - adminDbB.deleteDb(); - } - authDb.deleteDb(); - // don't have to clean the backend authDb since this test only calls - // couch_auth_cache:get_admin/1 which doesn't auto-create the users db -}; |