blob: a43b4d1df854480767d8fdd27b574f209d01ad01 [file] [log] [blame]
// 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.reader_acl = function(debug) {
// this tests read access control
var users_db_name = get_random_db_name();
var usersDb = new CouchDB(users_db_name, {"X-Couch-Full-Commit":"false"});
var db_name = get_random_db_name();
var secretDb = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
function testFun() {
try {
// usersDb.deleteDb();
try {
usersDb.createDb();
} catch(e) {
if(usersDb.last_req.status != 412) {
throw e;
}
}
// secretDb.deleteDb();
secretDb.createDb();
// create a user with top-secret-clearance
var jchrisUserDoc = CouchDB.prepareUserDoc({
name: "jchris@apache.org",
roles : ["top-secret"]
}, "funnybone");
T(usersDb.save(jchrisUserDoc).ok);
usersDb.ensureFullCommit();
T(CouchDB.session().userCtx.name == null);
// set secret db to be read controlled
T(secretDb.save({_id:"baz",foo:"bar"}).ok);
T(secretDb.open("baz").foo == "bar");
T(secretDb.setSecObj({
"members" : {
roles : ["super-secret-club"],
names : ["joe","barb"]
}
}).ok);
} finally {
CouchDB.logout();
}
try {
// can't read it as jchris b/c he's missing the needed role
T(CouchDB.login("jchris@apache.org", "funnybone").ok);
T(CouchDB.session().userCtx.name == "jchris@apache.org");
try {
secretDb.open("baz");
T(false && "can't open a doc from a secret db") ;
} catch(e) {
T(true)
}
CouchDB.logout();
// make anyone with the top-secret role an admin
// db admins are automatically members
T(secretDb.setSecObj({
"admins" : {
roles : ["top-secret"],
names : []
},
"members" : {
roles : ["super-secret-club"],
names : ["joe","barb"]
}
}).ok);
T(CouchDB.login("jchris@apache.org", "funnybone").ok);
// db admin can read
// retry as propagation could take time
retry_part(function(){
T(secretDb.open("baz").foo == "bar");
});
// and run temp views - they don't exist any more, so leave out
/*TEquals(secretDb.query(function(doc) {
emit(null, null)
}).total_rows, 1);*/
CouchDB.logout();
T(CouchDB.session().userCtx.roles.indexOf("_admin") != -1);
// admin now adds the top-secret role to the db's members
// and removes db-admins
T(secretDb.setSecObj({
"admins" : {
roles : [],
names : []
},
"members" : {
roles : ["super-secret-club", "top-secret"],
names : ["joe","barb"]
}
}).ok);
// server _admin can always read
T(secretDb.open("baz").foo == "bar");
// and run temp views - they don't exist any more, so leave out
/*TEquals(secretDb.query(function(doc) {
emit(null, null)
}).total_rows, 1);*/
T(secretDb.save({
"_id" : "_design/foo",
views : {
bar : {
map : "function(doc){emit(null, null)}"
}
}
}).ok)
// now top-secret users can read too
T(CouchDB.login("jchris@apache.org", "funnybone").ok);
T(CouchDB.session().userCtx.roles.indexOf("_admin") == -1);
T(secretDb.open("baz").foo == "bar");
// members can query stored views
T(secretDb.view("foo/bar").total_rows == 1);
// members can't do temp views - they don't exist any more, so leave out
/*try {
var results = secretDb.query(function(doc) {
emit(null, null);
});
T(false && "temp view should be admin only");
} catch (e) {
T(true && "temp view is admin only");
}*/
CouchDB.logout();
// works with readers (backwards compat with 1.0)
T(secretDb.setSecObj({
"admins" : {
roles : [],
names : []
},
"readers" : {
roles : ["super-secret-club", "top-secret"],
names : ["joe","barb"]
}
}).ok);
T(CouchDB.login("jchris@apache.org", "funnybone").ok);
T(CouchDB.session().userCtx.roles.indexOf("_admin") == -1);
// retry as propagation could take time
retry_part(function(){
T(secretDb.open("baz").foo == "bar");
});
// can't set non string reader names or roles
try {
secretDb.setSecObj({
"members" : {
roles : ["super-secret-club", {"top-secret":"awesome"}],
names : ["joe","barb"]
}
})
T(false && "only string roles");
} catch (e) {}
try {
secretDb.setSecObj({
"members" : {
roles : ["super-secret-club", {"top-secret":"awesome"}],
names : ["joe",22]
}
});
T(false && "only string names");
} catch (e) {}
try {
secretDb.setSecObj({
"members" : {
roles : ["super-secret-club", {"top-secret":"awesome"}],
names : "joe"
}
});
T(false && "only lists of names");
} catch (e) {}
} finally {
CouchDB.logout();
}
};
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: users_db_name},
{section: "chttpd_auth",
key: "authentication_db", value: users_db_name}],
testFun // stick to the essentials and do it all in one
);
usersDb.deleteDb();
// have to delete the backside version now too :(
var req = CouchDB.newXhr();
req.open("DELETE", "http://127.0.0.1:15986/" + users_db_name, false);
req.send("");
CouchDB.maybeThrowError(req);
secretDb.deleteDb();
}