You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2019/08/10 07:57:48 UTC

[couchdb] branch access updated (46a05de -> 5ca0d46)

This is an automated email from the ASF dual-hosted git repository.

jan pushed a change to branch access
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


    from 46a05de  fix access deletes
     new 708a536  chore: cleanup
     new 5ca0d46  feat: implement _users role handling

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/couch/src/couch_btree.erl           |  8 +-------
 src/couch/src/couch_db.erl              |  2 +-
 src/couch/src/couch_db_updater.erl      | 21 ++++++++++++++-------
 src/couch/src/couch_httpd_auth.erl      |  6 +++---
 src/couch/test/couchdb_access_tests.erl | 21 ++++++++++++++++-----
 src/couch_mrview/src/couch_mrview.erl   |  3 ++-
 6 files changed, 37 insertions(+), 24 deletions(-)


[couchdb] 01/02: chore: cleanup

Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jan pushed a commit to branch access
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 708a53663c255a5b4587a2093b65da7e307b9170
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sat Aug 10 09:57:29 2019 +0200

    chore: cleanup
---
 src/couch/src/couch_btree.erl | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/src/couch/src/couch_btree.erl b/src/couch/src/couch_btree.erl
index f45d9e7..16c9e9f 100644
--- a/src/couch/src/couch_btree.erl
+++ b/src/couch/src/couch_btree.erl
@@ -98,17 +98,11 @@ full_reduce_with_options(Bt, Options0) ->
         {ok, couch_btree:final_reduce(Bt, PartialReds)}
     end,
     [UserName] = proplists:get_value(start_key, Options0, <<"">>),
-    % couch_log:info("~n Options0:~p~n", [Options0]),
-    % couch_log:info("~n UserName:~p~n", [UserName]),
     EndKey = {[UserName, {[]}]},
-    % couch_log:info("~n EndKey:~p~n", [EndKey]),
     Options = Options0 ++ [
         {end_key, EndKey}
     ],
-    % couch_log:info("~n Options:~p~n", [Options]),
-    R = fold_reduce(Bt, CountFun, 0, Options),
-    % couch_log:info("~n~n R: ~p ~n", [R]),
-    R.
+    fold_reduce(Bt, CountFun, 0, Options).
 
 full_reduce(#btree{root=nil,reduce=Reduce}) ->
     {ok, Reduce(reduce, [])};


[couchdb] 02/02: feat: implement _users role handling

Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jan pushed a commit to branch access
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 5ca0d46acb7aedc18472e98202fd54eba9a76df3
Author: Jan Lehnardt <ja...@apache.org>
AuthorDate: Sat Aug 10 09:57:39 2019 +0200

    feat: implement _users role handling
---
 src/couch/src/couch_db.erl              |  2 +-
 src/couch/src/couch_db_updater.erl      | 21 ++++++++++++++-------
 src/couch/src/couch_httpd_auth.erl      |  6 +++---
 src/couch/test/couchdb_access_tests.erl | 21 ++++++++++++++++-----
 src/couch_mrview/src/couch_mrview.erl   |  3 ++-
 5 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index 9231800..42a7176 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -765,7 +765,7 @@ check_name(UserName, Access) ->
 
 check_roles(Roles, Access) ->    
     UserRolesSet = ordsets:from_list(Roles),
-    RolesSet = ordsets:from_list(Access),
+    RolesSet = ordsets:from_list(Access ++ ["_users"]),
     not ordsets:is_disjoint(UserRolesSet, RolesSet).
 
 get_admins(#db{security=SecProps}) ->
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index ff6d366..47f1ff1 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -21,12 +21,15 @@
 -include("couch_db_int.hrl").
 
 -define(IDLE_LIMIT_DEFAULT, 61000).
-
+-define(DEFAULT_SECURITY_OBJECT, [
+ {<<"members">>,{[{<<"roles">>,[<<"_admin">>]}]}},
+ {<<"admins">>, {[{<<"roles">>,[<<"_admin">>]}]}}
+]).
 
 init({Engine, DbName, FilePath, Options0}) ->
     erlang:put(io_priority, {db_update, DbName}),
     update_idle_limit_from_config(),
-    DefaultSecObj = default_security_object(DbName),
+    DefaultSecObj = default_security_object(DbName, Options0),
     Options = [{default_security_object, DefaultSecObj} | Options0],
     try
         {ok, EngineState} = couch_db_engine:init(Engine, FilePath, Options),
@@ -770,20 +773,24 @@ get_meta_body_size(Meta) ->
     {ejson_size, ExternalSize} = lists:keyfind(ejson_size, 1, Meta),
     ExternalSize.
 
-
+default_security_object(DbName, []) ->
+    default_security_object(DbName);
+default_security_object(DbName, Options) ->
+    case lists:member({access, true}, Options) of
+        false -> default_security_object(DbName);
+        true -> ?DEFAULT_SECURITY_OBJECT
+    end.
 default_security_object(<<"shards/", _/binary>>) ->
     case config:get("couchdb", "default_security", "everyone") of
         "admin_only" ->
-            [{<<"members">>,{[{<<"roles">>,[<<"_admin">>]}]}},
-             {<<"admins">>,{[{<<"roles">>,[<<"_admin">>]}]}}];
+            ?DEFAULT_SECURITY_OBJECT;
         Everyone when Everyone == "everyone"; Everyone == "admin_local" ->
             []
     end;
 default_security_object(_DbName) ->
     case config:get("couchdb", "default_security", "everyone") of
         Admin when Admin == "admin_only"; Admin == "admin_local" ->
-            [{<<"members">>,{[{<<"roles">>,[<<"_admin">>]}]}},
-             {<<"admins">>,{[{<<"roles">>,[<<"_admin">>]}]}}];
+            ?DEFAULT_SECURITY_OBJECT;
         "everyone" ->
             []
     end.
diff --git a/src/couch/src/couch_httpd_auth.erl b/src/couch/src/couch_httpd_auth.erl
index b519534..9aa26ef 100644
--- a/src/couch/src/couch_httpd_auth.erl
+++ b/src/couch/src/couch_httpd_auth.erl
@@ -102,7 +102,7 @@ default_authentication_handler(Req, AuthModule) ->
                     true ->
                         Req#httpd{user_ctx=#user_ctx{
                             name=UserName,
-                            roles=couch_util:get_value(<<"roles">>, UserProps, [])
+                            roles=couch_util:get_value(<<"roles">>, UserProps, []) ++ [<<"_users">>]
                         }};
                     false ->
                         authentication_warning(Req, UserName),
@@ -165,7 +165,7 @@ proxy_auth_user(Req) ->
             Roles = case header_value(Req, XHeaderRoles) of
                 undefined -> [];
                 Else ->
-                    [?l2b(R) || R <- string:tokens(Else, ",")]
+                    [?l2b(R) || R <- string:tokens(Else, ",")] ++ [<<"_users">>]
             end,
             case config:get("couch_httpd_auth", "proxy_use_secret", "false") of
                 "true" ->
@@ -231,7 +231,7 @@ cookie_authentication_handler(#httpd{mochi_req=MochiReq}=Req, AuthModule) ->
                                                 [User]),
                                 Req#httpd{user_ctx=#user_ctx{
                                     name=?l2b(User),
-                                    roles=couch_util:get_value(<<"roles">>, UserProps, [])
+                                    roles=couch_util:get_value(<<"roles">>, UserProps, []) ++ [<<"_users">>]
                                 }, auth={FullSecret, TimeLeft < Timeout*0.9}};
                             _Else ->
                                 Req
diff --git a/src/couch/test/couchdb_access_tests.erl b/src/couch/test/couchdb_access_tests.erl
index bba0da2..74ee77c 100644
--- a/src/couch/test/couchdb_access_tests.erl
+++ b/src/couch/test/couchdb_access_tests.erl
@@ -18,17 +18,22 @@
 -define(ADMIN_REQ_HEADERS, [?CONTENT_JSON, {basic_auth, {"a", "a"}}]).
 -define(USERX_REQ_HEADERS, [?CONTENT_JSON, {basic_auth, {"x", "x"}}]).
 -define(USERY_REQ_HEADERS, [?CONTENT_JSON, {basic_auth, {"y", "y"}}]).
+-define(SECURITY_OBJECT, {[
+ {<<"members">>,{[{<<"roles">>,[<<"_admin">>, <<"_users">>]}]}},
+ {<<"admins">>, {[{<<"roles">>,[<<"_admin">>]}]}}
+]}).
 
 url() ->
     Addr = config:get("httpd", "bind_address", "127.0.0.1"),
     lists:concat(["http://", Addr, ":", port()]).
 
 before_each(_) ->
-    {ok, _, _, _} = test_request:put(url() ++ "/db?q=1&n=1&access=true", ?ADMIN_REQ_HEADERS, ""),
+    {ok, 201, _, _} = test_request:put(url() ++ "/db?q=1&n=1&access=true", ?ADMIN_REQ_HEADERS, ""),
+    {ok, _, _, _} = test_request:put(url() ++ "/db/_security", ?ADMIN_REQ_HEADERS, jiffy:encode(?SECURITY_OBJECT)),
     url().
 
 after_each(_, Url) ->
-    {ok, _, _, _} = test_request:delete(Url ++ "/db", ?ADMIN_REQ_HEADERS),
+    {ok, 200, _, _} = test_request:delete(Url ++ "/db", ?ADMIN_REQ_HEADERS),
     ok.
 
 before_all() ->
@@ -38,7 +43,7 @@ before_all() ->
 
     % cleanup and setup
     {ok, _, _, _} = test_request:delete(url() ++ "/db", ?ADMIN_REQ_HEADERS),
-    {ok, _, _, _} = test_request:put(url() ++ "/db?q=1&n=1&access=true", ?ADMIN_REQ_HEADERS, ""),
+    % {ok, _, _, _} = test_request:put(url() ++ "/db?q=1&n=1&access=true", ?ADMIN_REQ_HEADERS, ""),
 
     % create users
     UserDbUrl = url() ++ "/_users?q=1&n=1",
@@ -59,6 +64,7 @@ after_all(_) ->
 
 access_test_() ->
     Tests = [
+        fun should_not_let_anonymous_user_create_doc/2,
         fun should_let_admin_create_doc_with_access/2,
         fun should_let_user_create_doc_for_themselves/2,
         fun should_not_let_user_create_doc_for_someone_else/2,
@@ -91,8 +97,13 @@ make_test_cases(Mod, Funs) ->
     }.
 
 % Doc creation
-should_let_admin_create_doc_with_access(_PortType, Url) ->
+
+should_not_let_anonymous_user_create_doc(_PortType, Url) ->
     {ok, Code, _, _} = test_request:put(Url ++ "/db/a", "{\"a\":1,\"_access\":[\"x\"]}"),
+    ?_assertEqual(401, Code).
+
+should_let_admin_create_doc_with_access(_PortType, Url) ->
+    {ok, Code, _, _} = test_request:put(Url ++ "/db/a", ?ADMIN_REQ_HEADERS, "{\"a\":1,\"_access\":[\"x\"]}"),
     ?_assertEqual(201, Code).
 
 should_let_user_create_doc_for_themselves(_PortType, Url) ->
@@ -154,7 +165,7 @@ should_let_user_fetch_their_own_all_docs(_PortType, Url) ->
     {ok, 200, _, Body} = test_request:get(Url ++ "/db/_all_docs?include_docs=true", ?USERX_REQ_HEADERS),
     {Json} = jiffy:decode(Body),
     ?_assertEqual(2, length(proplists:get_value(<<"rows">>, Json))).
-% TODO    ?_assertEqual(2, proplists:get_value(<<"total_rows">>, Json)).
+    % TODO    ?_assertEqual(2, proplists:get_value(<<"total_rows">>, Json)).
 
 % _changes
 should_let_admin_fetch_changes(_PortType, Url) ->
diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl
index 8222dde..72fbb92 100644
--- a/src/couch_mrview/src/couch_mrview.erl
+++ b/src/couch_mrview/src/couch_mrview.erl
@@ -594,7 +594,8 @@ all_docs_fold(Db, #mrargs{direction=Dir, keys=Keys0}=Args, Callback, UAcc) ->
 map_fold(Db, View, Args, Callback, UAcc) ->
     {ok, Total} = case View#mrview.def of
         <<"_access/by-id-map">> ->
-            {ok, 0}; % TODO: couch_mrview_util:get_access_row_count(View, Args#mrargs.start_key);
+            % TODO: couch_mrview_util:get_access_row_count(View, [Args#mrargs.start_key]);
+            {ok, 0};
         _Else ->
             couch_mrview_util:get_row_count(View)
     end,