You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by jc...@apache.org on 2010/02/12 06:38:58 UTC

svn commit: r909247 - in /couchdb/trunk: share/www/script/couch.js share/www/script/test/reader_acl.js share/www/script/test/security_validation.js src/couchdb/couch_db.erl src/couchdb/couch_httpd_db.erl

Author: jchris
Date: Fri Feb 12 05:38:57 2010
New Revision: 909247

URL: http://svn.apache.org/viewvc?rev=909247&view=rev
Log:
move from _admins / _readers / _security to just a single _security object

Modified:
    couchdb/trunk/share/www/script/couch.js
    couchdb/trunk/share/www/script/test/reader_acl.js
    couchdb/trunk/share/www/script/test/security_validation.js
    couchdb/trunk/src/couchdb/couch_db.erl
    couchdb/trunk/src/couchdb/couch_httpd_db.erl

Modified: couchdb/trunk/share/www/script/couch.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/couch.js?rev=909247&r1=909246&r2=909247&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/couch.js [utf-8] (original)
+++ couchdb/trunk/share/www/script/couch.js [utf-8] Fri Feb 12 05:38:57 2010
@@ -263,16 +263,16 @@
     return JSON.parse(this.last_req.responseText);
   }
 
-  this.setAdmins = function(adminsArray) {
-    this.last_req = this.request("PUT", this.uri + "_admins",{
-      body:JSON.stringify(adminsArray)
+  this.setSecObj = function(secObj) {
+    this.last_req = this.request("PUT", this.uri + "_security",{
+      body:JSON.stringify(secObj)
     });
     CouchDB.maybeThrowError(this.last_req);
     return JSON.parse(this.last_req.responseText);
   }
 
-  this.getAdmins = function() {
-    this.last_req = this.request("GET", this.uri + "_admins");
+  this.getSecObj = function() {
+    this.last_req = this.request("GET", this.uri + "_security");
     CouchDB.maybeThrowError(this.last_req);
     return JSON.parse(this.last_req.responseText);
   }

Modified: couchdb/trunk/share/www/script/test/reader_acl.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/reader_acl.js?rev=909247&r1=909246&r2=909247&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/reader_acl.js (original)
+++ couchdb/trunk/share/www/script/test/reader_acl.js Fri Feb 12 05:38:57 2010
@@ -35,9 +35,12 @@
       T(secretDb.save({_id:"baz",foo:"bar"}).ok);
       T(secretDb.open("baz").foo == "bar");
 
-      T(secretDb.setDbProperty("_readers", {
-        roles : ["super-secret-club"],
-        names : ["joe","barb"]}).ok);
+      T(secretDb.setSecObj({
+        "readers" : {
+          roles : ["super-secret-club"],
+          names : ["joe","barb"]
+        }
+      }).ok);
       // can't read it as jchris
       T(CouchDB.login("jchris@apache.org", "funnybone").ok);
       T(CouchDB.session().userCtx.name == "jchris@apache.org");
@@ -51,54 +54,76 @@
 
       CouchDB.logout();
       
-      // make top-secret an admin
-      T(secretDb.setDbProperty("_admins", {
-        roles : ["top-secret"],
-        names : []}).ok);
+      // make anyone with the top-secret role an admin
+      // db admins are automatically readers
+      T(secretDb.setSecObj({
+        "admins" : {
+          roles : ["top-secret"],
+          names : []
+        },
+        "readers" : {
+          roles : ["super-secret-club"],
+          names : ["joe","barb"]
+        }
+      }).ok);
 
       T(CouchDB.login("jchris@apache.org", "funnybone").ok);
 
       T(secretDb.open("baz").foo == "bar");
 
       CouchDB.logout();
-
-      T(secretDb.setDbProperty("_admins", {
-        roles : [],
-        names : []}).ok);
-
-      // admin now adds the top-secret role to the db's readers
       T(CouchDB.session().userCtx.roles.indexOf("_admin") != -1);
 
-      T(secretDb.setDbProperty("_readers", {
-        roles : ["super-secret-club", "top-secret"],
-        names : ["joe","barb"]}).ok);
+      // admin now adds the top-secret role to the db's readers
+      // and removes db-admins
+      T(secretDb.setSecObj({
+        "admins" : {
+          roles : [],
+          names : []
+        },
+        "readers" : {
+          roles : ["super-secret-club", "top-secret"],
+          names : ["joe","barb"]
+        }
+      }).ok);
 
-      // now top-secret users can read it
+      // server _admin can always read
       T(secretDb.open("baz").foo == "bar");
+
+      // 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");
       
       CouchDB.logout();
 
       // can't set non string reader names or roles
       try {
-        secretDb.setDbProperty("_readers", {
-          roles : ["super-secret-club", {"top-secret":"awesome"}],
-          names : ["joe","barb"]});
+        secretDb.setSecObj({
+          "readers" : {
+            roles : ["super-secret-club", {"top-secret":"awesome"}],
+            names : ["joe","barb"]
+          }
+        })
         T(false && "only string roles");
       } catch (e) {}
 
       try {
-        secretDb.setDbProperty("_readers", {
-          roles : ["super-secret-club", "top-secret"],
-          names : ["joe",22]});
+        secretDb.setSecObj({
+          "readers" : {
+            roles : ["super-secret-club", {"top-secret":"awesome"}],
+            names : ["joe",22]
+          }
+        });
         T(false && "only string names");
       } catch (e) {}
       
       try {
-        secretDb.setDbProperty("_readers", {
-          roles : ["super-secret-club", "top-secret"],
-          names : "joe"
+        secretDb.setSecObj({
+          "readers" : {
+            roles : ["super-secret-club", {"top-secret":"awesome"}],
+            names : "joe"
+          }
         });
         T(false && "only lists of names");
       } catch (e) {}

Modified: couchdb/trunk/share/www/script/test/security_validation.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/security_validation.js?rev=909247&r1=909246&r2=909247&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/security_validation.js (original)
+++ couchdb/trunk/share/www/script/test/security_validation.js Fri Feb 12 05:38:57 2010
@@ -105,7 +105,9 @@
       }
 
       // set user as the admin
-      T(db.setDbProperty("_admins", {names : ["Damien Katz"]}).ok);
+      T(db.setSecObj({
+        admins : {names : ["Damien Katz"]}
+      }).ok);
 
       T(userDb.save(designDoc).ok);
 

Modified: couchdb/trunk/src/couchdb/couch_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_db.erl?rev=909247&r1=909246&r2=909247&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_db.erl Fri Feb 12 05:38:57 2010
@@ -23,7 +23,7 @@
 -export([enum_docs_since_reduce_to_count/1,enum_docs_reduce_to_count/1]).
 -export([increment_update_seq/1,get_purge_seq/1,purge_docs/2,get_last_purged/1]).
 -export([start_link/3,open_doc_int/3,ensure_full_commit/1]).
--export([set_readers/2,get_readers/1,set_admins/2,get_admins/1,set_security/2,get_security/1]).
+-export([set_security/2,get_security/1]).
 -export([init/1,terminate/2,handle_call/3,handle_cast/2,code_change/3,handle_info/2]).
 -export([changes_since/5,changes_since/6,read_doc/2,new_revid/1]).
 
@@ -232,8 +232,8 @@
 
 check_is_admin(#db{user_ctx=#user_ctx{name=Name,roles=Roles}}=Db) ->
     {Admins} = get_admins(Db),
-    AdminRoles = [<<"_admin">> | proplists:get_value(roles, Admins, [])],
-    AdminNames = proplists:get_value(names, Admins,[]),
+    AdminRoles = [<<"_admin">> | proplists:get_value(<<"roles">>, Admins, [])],
+    AdminNames = proplists:get_value(<<"names">>, Admins,[]),
     case AdminRoles -- Roles of
     AdminRoles -> % same list, not an admin role
         case AdminNames -- [Name] of
@@ -251,9 +251,9 @@
     ok -> ok;
     _ ->
         {Readers} = get_readers(Db),
-        ReaderRoles = proplists:get_value(roles, Readers,[]),
+        ReaderRoles = proplists:get_value(<<"roles">>, Readers,[]),
         WithAdminRoles = [<<"_admin">> | ReaderRoles],
-        ReaderNames = proplists:get_value(names, Readers,[]),
+        ReaderNames = proplists:get_value(<<"names">>, Readers,[]),
         case ReaderRoles ++ ReaderNames of 
         [] -> ok; % no readers == public access
         _Else ->
@@ -273,64 +273,43 @@
     end.
 
 get_admins(#db{security=SecProps}) ->
-    proplists:get_value(admins, SecProps, {[]}).
-
-set_admins(#db{security=SecProps,update_pid=Pid}=Db, Admins) ->
-    check_is_admin(Db),
-    SecProps2 = update_sec_field(admins, SecProps, just_names_and_roles(Admins)),
-    gen_server:call(Pid, {set_security, SecProps2}, infinity).
+    proplists:get_value(<<"admins">>, SecProps, {[]}).
 
 get_readers(#db{security=SecProps}) ->
-    proplists:get_value(readers, SecProps, {[]}).
-
-set_readers(#db{security=SecProps,update_pid=Pid}=Db, Readers) ->
-    check_is_admin(Db),
-    SecProps2 = update_sec_field(readers, SecProps, just_names_and_roles(Readers)),
-    gen_server:call(Pid, {set_security, SecProps2}, infinity).
+    proplists:get_value(<<"readers">>, SecProps, {[]}).
 
 get_security(#db{security=SecProps}) ->
-    proplists:get_value(sec_obj, SecProps, {[]}).
+    {SecProps}.
 
-set_security(#db{security=SecProps, update_pid=Pid}=Db, {SecObjProps}) when is_list(SecObjProps) ->
+set_security(#db{update_pid=Pid}=Db, {NewSecProps}) when is_list(NewSecProps) ->
     check_is_admin(Db),
-    SecProps2 = update_sec_field(sec_obj, SecProps, {SecObjProps}),
-    gen_server:call(Pid, {set_security, SecProps2}, infinity);
+    ok = validate_security_object(NewSecProps),
+    gen_server:call(Pid, {set_security, NewSecProps}, infinity);
 set_security(_, _) ->
     throw(bad_request).
 
-update_sec_field(Field, SecProps, Value) ->
-    Admins = proplists:get_value(admins, SecProps, {[]}),
-    Readers = proplists:get_value(readers, SecProps, {[]}),
-    SecObj = proplists:get_value(sec_obj, SecProps, {[]}),
-    if Field == admins ->
-        [{admins, Value}];
-    true -> [{admins, Admins}] 
-    end ++ if Field == readers ->
-        [{readers, Value}];
-    true -> [{readers, Readers}] 
-    end ++ if Field == sec_obj ->
-        [{sec_obj, Value}];
-    true -> [{sec_obj, SecObj}]
-    end.
+validate_security_object(SecProps) ->
+    Admins = proplists:get_value(<<"admins">>, SecProps, {[]}),
+    Readers = proplists:get_value(<<"readers">>, SecProps, {[]}),
+    ok = validate_names_and_roles(Admins),
+    ok = validate_names_and_roles(Readers),
+    ok.
 
-% validate user input and convert proplist to atom keys
-just_names_and_roles({Props}) when is_list(Props) ->
-    Names = case proplists:get_value(<<"names">>,Props,[]) of
+% validate user input
+validate_names_and_roles({Props}) when is_list(Props) ->
+    case proplists:get_value(<<"names">>,Props,[]) of
     Ns when is_list(Ns) ->
             [throw("names must be a JSON list of strings") ||N <- Ns, not is_binary(N)],
             Ns;
     _ -> throw("names must be a JSON list of strings")
     end,
-    Roles = case proplists:get_value(<<"roles">>,Props,[]) of
+    case proplists:get_value(<<"roles">>,Props,[]) of
     Rs when is_list(Rs) ->
         [throw("roles must be a JSON list of strings") ||R <- Rs, not is_binary(R)],
         Rs;
     _ -> throw("roles must be a JSON list of strings")
     end,
-    {[
-        {names, Names},
-        {roles, Roles}
-    ]}.
+    ok.
 
 get_revs_limit(#db{revs_limit=Limit}) ->
     Limit.

Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=909247&r1=909246&r2=909247&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Fri Feb 12 05:38:57 2010
@@ -547,29 +547,6 @@
 db_req(#httpd{path_parts=[_,<<"_revs_diff">>]}=Req, _Db) ->
     send_method_not_allowed(Req, "POST");
 
-
-db_req(#httpd{method='PUT',path_parts=[_,<<"_admins">>]}=Req, Db) ->
-    Admins = couch_httpd:json_body(Req),
-    ok = couch_db:set_admins(Db, Admins),
-    send_json(Req, {[{<<"ok">>, true}]});
-
-db_req(#httpd{method='GET',path_parts=[_,<<"_admins">>]}=Req, Db) ->
-    send_json(Req, couch_db:get_admins(Db));
-
-db_req(#httpd{path_parts=[_,<<"_admins">>]}=Req, _Db) ->
-    send_method_not_allowed(Req, "PUT,GET");
-
-db_req(#httpd{method='PUT',path_parts=[_,<<"_readers">>]}=Req, Db) ->
-    Readers = couch_httpd:json_body(Req),
-    ok = couch_db:set_readers(Db, Readers),
-    send_json(Req, {[{<<"ok">>, true}]});
-
-db_req(#httpd{method='GET',path_parts=[_,<<"_readers">>]}=Req, Db) ->
-    send_json(Req, couch_db:get_readers(Db));
-
-db_req(#httpd{path_parts=[_,<<"_readers">>]}=Req, _Db) ->
-    send_method_not_allowed(Req, "PUT,GET");
-
 db_req(#httpd{method='PUT',path_parts=[_,<<"_security">>]}=Req, Db) ->
     SecObj = couch_httpd:json_body(Req),
     ok = couch_db:set_security(Db, SecObj),