summaryrefslogtreecommitdiff
path: root/test/javascript/tests/security_validation.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/javascript/tests/security_validation.js')
-rw-r--r--test/javascript/tests/security_validation.js330
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
-};