From 09351a0535fe9bc3fa780763c095fd6dc56175de Mon Sep 17 00:00:00 2001 From: John Christopher Anderson Date: Mon, 18 Jan 2010 03:45:54 +0000 Subject: normalize userCtx name and roles, also, no log in via a conflict doc git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@900275 13f79535-47bb-0310-9956-ffa450edef68 --- share/www/_sidebar.html | 4 +-- share/www/dialog/_create_admin.html | 2 +- share/www/dialog/_login.html | 4 +-- share/www/dialog/_signup.html | 2 +- share/www/script/couch.js | 8 ++--- share/www/script/couch_test_runner.js | 3 +- share/www/script/futon.js | 37 +++++++++---------- share/www/script/jquery.couch.js | 6 ++-- share/www/script/test/cookie_auth.js | 54 ++++++++++++++-------------- share/www/script/test/oauth.js | 2 +- share/www/script/test/security_validation.js | 2 +- share/www/script/test/users_db.js | 50 ++++++++++++++++++++------ 12 files changed, 102 insertions(+), 72 deletions(-) (limited to 'share') diff --git a/share/www/_sidebar.html b/share/www/_sidebar.html index 6c7abc99..13727cbd 100644 --- a/share/www/_sidebar.html +++ b/share/www/_sidebar.html @@ -35,12 +35,12 @@ specific language governing permissions and limitations under the License. Signup or Login - Welcome ?! + Welcome ?!
Logout
- Welcome ?! + Welcome ?!
Setup more admins or Logout diff --git a/share/www/dialog/_create_admin.html b/share/www/dialog/_create_admin.html index e4141e1d..d4aec95a 100644 --- a/share/www/dialog/_create_admin.html +++ b/share/www/dialog/_create_admin.html @@ -27,7 +27,7 @@ specific language governing permissions and limitations under the License.

- + diff --git a/share/www/dialog/_login.html b/share/www/dialog/_login.html index 959f7233..f05a5fdc 100644 --- a/share/www/dialog/_login.html +++ b/share/www/dialog/_login.html @@ -16,11 +16,11 @@ specific language governing permissions and limitations under the License.

Login

- Login to CouchDB with your username and password. + Login to CouchDB with your name and password.

- + diff --git a/share/www/dialog/_signup.html b/share/www/dialog/_signup.html index 884b4be2..7ba3448a 100644 --- a/share/www/dialog/_signup.html +++ b/share/www/dialog/_signup.html @@ -21,7 +21,7 @@ specific language governing permissions and limitations under the License.

- + diff --git a/share/www/script/couch.js b/share/www/script/couch.js index 21ea39b3..cb6fab89 100644 --- a/share/www/script/couch.js +++ b/share/www/script/couch.js @@ -121,7 +121,7 @@ function CouchDB(name, httpHeaders) { CouchDB.maybeThrowError(this.last_req); var results = JSON.parse(this.last_req.responseText); for (var i = 0; i < docs.length; i++) { - if(results[i].rev) { + if(results[i] && results[i].rev) { docs[i]._rev = results[i].rev; } } @@ -322,11 +322,11 @@ function CouchDB(name, httpHeaders) { // Use this from callers to check HTTP status or header values of requests. CouchDB.last_req = null; -CouchDB.login = function(username, password) { +CouchDB.login = function(name, password) { CouchDB.last_req = CouchDB.request("POST", "/_session", { headers: {"Content-Type": "application/x-www-form-urlencoded", "X-CouchDB-WWW-Authenticate": "Cookie"}, - body: "username=" + encodeURIComponent(username) + "&password=" + body: "name=" + encodeURIComponent(name) + "&password=" + encodeURIComponent(password) }); return JSON.parse(CouchDB.last_req.responseText); @@ -350,7 +350,7 @@ CouchDB.session = function(options) { CouchDB.user_prefix = "org.couchdb.user:"; CouchDB.prepareUserDoc = function(user_doc, new_password) { - user_doc._id = user_doc._id || CouchDB.user_prefix + user_doc.username; + user_doc._id = user_doc._id || CouchDB.user_prefix + user_doc.name; if (new_password) { // handle the password crypto user_doc.salt = CouchDB.newUuids(1)[0]; diff --git a/share/www/script/couch_test_runner.js b/share/www/script/couch_test_runner.js index 237f9312..ec5069e5 100644 --- a/share/www/script/couch_test_runner.js +++ b/share/www/script/couch_test_runner.js @@ -138,7 +138,8 @@ function setupAdminParty(fun) { } }; $.couch.session({ - success : function(userCtx) { + success : function(resp) { + var userCtx = resp.userCtx; if (userCtx.name && userCtx.roles.indexOf("_admin") != -1) { // admin but not admin party. dialog offering to make admin party $.showDialog("dialog/_admin_party.html", { diff --git a/share/www/script/futon.js b/share/www/script/futon.js index 9b5ba2d0..e2bdb468 100644 --- a/share/www/script/futon.js +++ b/share/www/script/futon.js @@ -14,9 +14,9 @@ function Session() { - function doLogin(username, password, callback) { + function doLogin(name, password, callback) { $.couch.login({ - username : username, + name : name, password : password, success : function() { $.futon.session.sidebar(); @@ -24,36 +24,36 @@ }, error : function(code, error, reason) { $.futon.session.sidebar(); - callback({username : "Error logging in: "+reason}); + callback({name : "Error logging in: "+reason}); } }); }; - function doSignup(username, password, callback, runLogin) { + function doSignup(name, password, callback, runLogin) { $.couch.signup({ - username : username + name : name }, password, { success : function() { if (runLogin) { - doLogin(username, password, callback); + doLogin(name, password, callback); } else { callback(); } }, error : function(status, error, reason) { $.futon.session.sidebar(); - if (error = "conflict") { - callback({username : "Name '"+username+"' is taken"}); + if (error == "conflict") { + callback({name : "Name '"+name+"' is taken"}); } else { - callback({username : "Signup error: "+reason}); + callback({name : "Signup error: "+reason}); } } }); }; function validateUsernameAndPassword(data, callback) { - if (!data.username || data.username.length == 0) { - callback({username: "Please enter a username."}); + if (!data.name || data.name.length == 0) { + callback({name: "Please enter a name."}); return false; }; if (!data.password || data.password.length == 0) { @@ -70,10 +70,10 @@ $.couch.config({ success : function() { callback(); - doLogin(data.username, data.password, callback); - doSignup(data.username, null, callback, false); + doLogin(data.name, data.password, callback); + doSignup(data.name, null, callback, false); } - }, "admins", data.username, data.password); + }, "admins", data.name, data.password); } }); return false; @@ -83,7 +83,7 @@ $.showDialog("dialog/_login.html", { submit: function(data, callback) { if (!validateUsernameAndPassword(data, callback)) return; - doLogin(data.username, data.password, callback); + doLogin(data.name, data.password, callback); } }); return false; @@ -101,7 +101,7 @@ $.showDialog("dialog/_signup.html", { submit: function(data, callback) { if (!validateUsernameAndPassword(data, callback)) return; - doSignup(data.username, data.password, callback, true); + doSignup(data.name, data.password, callback, true); } }); return false; @@ -118,9 +118,10 @@ // get users db info? $("#userCtx span").hide(); $.couch.session({ - success : function(userCtx) { + success : function(r) { + var userCtx = r.userCtx; if (userCtx.name) { - $("#userCtx .username").text(userCtx.name).attr({href : "/_utils/document.html?"+encodeURIComponent(userCtx.info.user_db)+"/org.couchdb.user%3A"+userCtx.name}); + $("#userCtx .name").text(userCtx.name).attr({href : "/_utils/document.html?"+encodeURIComponent(r.info.authentication_db)+"/org.couchdb.user%3A"+userCtx.name}); if (userCtx.roles.indexOf("_admin") != -1) { $("#userCtx .loggedinadmin").show(); } else { diff --git a/share/www/script/jquery.couch.js b/share/www/script/jquery.couch.js index 7e8a0236..0203fd45 100644 --- a/share/www/script/jquery.couch.js +++ b/share/www/script/jquery.couch.js @@ -28,7 +28,7 @@ return; } var user_prefix = "org.couchdb.user:"; - user_doc._id = user_doc._id || user_prefix + user_doc.username; + user_doc._id = user_doc._id || user_prefix + user_doc.name; if (new_password) { // handle the password crypto user_doc.salt = $.couch.newUUID(); @@ -102,7 +102,7 @@ userDb : function(callback) { $.couch.session({ success : function(resp) { - var userDb = $.couch.db(resp.info.user_db); + var userDb = $.couch.db(resp.info.authentication_db); callback(userDb); } }); @@ -121,7 +121,7 @@ options = options || {}; $.ajax({ type: "POST", url: "/_session", dataType: "json", - data: {username: options.username, password: options.password}, + data: {name: options.name, password: options.password}, complete: function(req) { var resp = $.httpData(req, "json"); if (req.status == 200) { diff --git a/share/www/script/test/cookie_auth.js b/share/www/script/test/cookie_auth.js index 125a6dcb..68ec882d 100644 --- a/share/www/script/test/cookie_auth.js +++ b/share/www/script/test/cookie_auth.js @@ -46,22 +46,22 @@ couchTests.cookie_auth = function(debug) { // Create a user var jasonUserDoc = CouchDB.prepareUserDoc({ - username: "Jason Davies", + name: "Jason Davies", roles: ["dev"] }, password); T(usersDb.save(jasonUserDoc).ok); var checkDoc = usersDb.open(jasonUserDoc._id); - T(checkDoc.username == "Jason Davies"); + T(checkDoc.name == "Jason Davies"); var jchrisUserDoc = CouchDB.prepareUserDoc({ - username: "jchris@apache.org" + name: "jchris@apache.org" }, "funnybone"); T(usersDb.save(jchrisUserDoc).ok); // make sure we cant create duplicate users var duplicateJchrisDoc = CouchDB.prepareUserDoc({ - username: "jchris@apache.org" + name: "jchris@apache.org" }, "eh, Boo-Boo?"); try { @@ -72,9 +72,9 @@ couchTests.cookie_auth = function(debug) { T(usersDb.last_req.status == 409); } - // we can't create _usernames + // we can't create _names var underscoreUserDoc = CouchDB.prepareUserDoc({ - username: "_why" + name: "_why" }, "copperfield"); try { @@ -87,7 +87,7 @@ couchTests.cookie_auth = function(debug) { // we can't create docs with malformed ids var badIdDoc = CouchDB.prepareUserDoc({ - username: "foo" + name: "foo" }, "bar"); badIdDoc._id = "org.apache.couchdb:w00x"; @@ -102,12 +102,12 @@ couchTests.cookie_auth = function(debug) { // login works T(CouchDB.login('Jason Davies', password).ok); - T(CouchDB.session().name == 'Jason Davies'); + T(CouchDB.session().userCtx.name == 'Jason Davies'); // update one's own credentials document jasonUserDoc.foo=2; T(usersDb.save(jasonUserDoc).ok); - T(CouchDB.session().roles.indexOf("_admin") == -1); + T(CouchDB.session().userCtx.roles.indexOf("_admin") == -1); // can't delete another users doc unless you are admin try { usersDb.deleteDoc(jchrisUserDoc); @@ -122,12 +122,12 @@ couchTests.cookie_auth = function(debug) { T(!CouchDB.login('Robert Allen Zimmerman', 'd00d').ok); // a failed login attempt should log you out - T(CouchDB.session().name != 'Jason Davies'); + T(CouchDB.session().userCtx.name != 'Jason Davies'); // test redirect xhr = CouchDB.request("POST", "/_session?next=/", { headers: {"Content-Type": "application/x-www-form-urlencoded"}, - body: "username=Jason%20Davies&password="+encodeURIComponent(password) + body: "name=Jason%20Davies&password="+encodeURIComponent(password) }); // should this be a redirect code instead of 200? // The cURL adapter is returning the expected 302 here. @@ -145,8 +145,8 @@ couchTests.cookie_auth = function(debug) { // // 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().name == "jchris@apache.org"); - T(CouchDB.session().roles.length == 0); + T(CouchDB.session().userCtx.name == "jchris@apache.org"); + T(CouchDB.session().userCtx.roles.length == 0); jasonUserDoc.foo=3; @@ -170,7 +170,7 @@ couchTests.cookie_auth = function(debug) { } T(CouchDB.logout().ok); - T(CouchDB.session().roles[0] == "_admin"); + T(CouchDB.session().userCtx.roles[0] == "_admin"); jchrisUserDoc.foo = ["foo"]; T(usersDb.save(jchrisUserDoc).ok); @@ -188,24 +188,24 @@ couchTests.cookie_auth = function(debug) { // make sure the foo role has been applied T(CouchDB.login("jchris@apache.org", "funnybone").ok); - T(CouchDB.session().name == "jchris@apache.org"); - T(CouchDB.session().roles.indexOf("_admin") == -1); - T(CouchDB.session().roles.indexOf("foo") != -1); + 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().roles[0] == "_admin"); - T(CouchDB.session().name == null); + 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", key: "jchris@apache.org", value: "funnybone"}], function() { T(CouchDB.login("jchris@apache.org", "funnybone").ok); - T(CouchDB.session().name == "jchris@apache.org"); - T(CouchDB.session().roles.indexOf("_admin") != -1); + T(CouchDB.session().userCtx.name == "jchris@apache.org"); + T(CouchDB.session().userCtx.roles.indexOf("_admin") != -1); // test that jchris still has the foo role - T(CouchDB.session().roles.indexOf("foo") != -1); + T(CouchDB.session().userCtx.roles.indexOf("foo") != -1); // should work even when user doc has no password jchrisUserDoc = usersDb.open(jchrisUserDoc._id); @@ -215,13 +215,13 @@ couchTests.cookie_auth = function(debug) { T(CouchDB.logout().ok); T(CouchDB.login("jchris@apache.org", "funnybone").ok); var s = CouchDB.session(); - T(s.name == "jchris@apache.org"); - T(s.roles.indexOf("_admin") != -1); + T(s.userCtx.name == "jchris@apache.org"); + T(s.userCtx.roles.indexOf("_admin") != -1); // test session info - T(s.info.authenticated == "{couch_httpd_auth, cookie_authentication_handler}"); - T(s.info.user_db == "test_suite_users"); + T(s.info.authenticated == "cookie"); + T(s.info.authentication_db == "test_suite_users"); // test that jchris still has the foo role - T(CouchDB.session().roles.indexOf("foo") != -1); + T(CouchDB.session().userCtx.roles.indexOf("foo") != -1); }); } finally { diff --git a/share/www/script/test/oauth.js b/share/www/script/test/oauth.js index d55d13e8..55f2f430 100644 --- a/share/www/script/test/oauth.js +++ b/share/www/script/test/oauth.js @@ -116,7 +116,7 @@ couchTests.oauth = function(debug) { // Create a user var jasonUserDoc = CouchDB.prepareUserDoc({ - username: "jason", + name: "jason", roles: ["test"] }, "testpassword"); T(usersDb.save(jasonUserDoc).ok); diff --git a/share/www/script/test/security_validation.js b/share/www/script/test/security_validation.js index d07195e1..43968426 100644 --- a/share/www/script/test/security_validation.js +++ b/share/www/script/test/security_validation.js @@ -105,7 +105,7 @@ couchTests.security_validation = function(debug) { // test the _whoami endpoint var resp = userDb.request("GET", "/_session"); - var user = JSON.parse(resp.responseText) + var user = JSON.parse(resp.responseText).userCtx; T(user.name == "Damien Katz"); // test that the roles are listed properly TEquals(user.roles, []); diff --git a/share/www/script/test/users_db.js b/share/www/script/test/users_db.js index c287ce68..d2cd0a4c 100644 --- a/share/www/script/test/users_db.js +++ b/share/www/script/test/users_db.js @@ -32,11 +32,11 @@ couchTests.users_db = function(debug) { // test that you can login as a user using basic auth var jchrisUserDoc = CouchDB.prepareUserDoc({ - username: "jchris@apache.org" + name: "jchris@apache.org" }, "funnybone"); T(usersDb.save(jchrisUserDoc).ok); - T(CouchDB.session().name == null); + T(CouchDB.session().userCtx.name == null); // test that you can use basic auth aginst the users db var s = CouchDB.session({ @@ -44,20 +44,48 @@ couchTests.users_db = function(debug) { "Authorization" : "Basic amNocmlzQGFwYWNoZS5vcmc6ZnVubnlib25l" } }); - T(s.name == "jchris@apache.org"); - T(s.user_doc._id == "org.couchdb.user:jchris@apache.org"); - T(s.info.authenticated == "{couch_httpd_auth, default_authentication_handler}"); - T(s.info.user_db == "test_suite_users"); - TEquals(["{couch_httpd_oauth, oauth_authentication_handler}", - "{couch_httpd_auth, cookie_authentication_handler}", - "{couch_httpd_auth, default_authentication_handler}"], s.info.handlers); + T(s.userCtx.name == "jchris@apache.org"); + T(s.info.authenticated == "default"); + T(s.info.authentication_db == "test_suite_users"); + TEquals(["oauth", "cookie", "default"], s.info.authentication_handlers); var s = CouchDB.session({ headers : { - "Authorization" : "Basic Xzpf" // username and pass of _:_ + "Authorization" : "Basic Xzpf" // name and pass of _:_ } }); T(s.name == null); - T(s.info.authenticated == "{couch_httpd_auth, default_authentication_handler}"); + T(s.info.authenticated == "default"); + + + // ok, now create a conflicting edit on the jchris doc, and make sure there's no login. + var jchrisUser2 = JSON.parse(JSON.stringify(jchrisUserDoc)); + jchrisUser2.foo = "bar"; + T(usersDb.save(jchrisUser2).ok); + try { + usersDb.save(jchrisUserDoc); + T(false && "should be an update conflict") + } catch(e) { + T(true); + } + // save as bulk with new_edits=false to force conflict save + var resp = usersDb.bulkSave([jchrisUserDoc],{all_or_nothing : true}); + + var jchrisWithConflict = usersDb.open(jchrisUserDoc._id, {conflicts : true}); + T(jchrisWithConflict._conflicts.length == 1) + + // no login with conflicted user doc + try { + var s = CouchDB.session({ + headers : { + "Authorization" : "Basic amNocmlzQGFwYWNoZS5vcmc6ZnVubnlib25l" + } + }); + T(false && "this will throw") + } catch(e) { + T(e.error == "unauthorized") + T(/conflict/.test(e.reason)) + } + }; run_on_modified_server( -- cgit v1.2.3