Skip to content

Commit 1cac613

Browse files
committed
feat: add access handling to show/list/update w/tests
1 parent 4a31f80 commit 1cac613

3 files changed

Lines changed: 124 additions & 3 deletions

File tree

src/chttpd/src/chttpd_show.erl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ handle_doc_show(Req, Db, DDoc, ShowName, Doc) ->
7979

8080
handle_doc_show(Req, Db, DDoc, ShowName, Doc, DocId) ->
8181
%% Will throw an exception if the _show handler is missing
82-
couch_log:notice("~n DDoc: '~p'~n", [DDoc]),
82+
ok = couch_db:validate_access(Db, DDoc),
8383
couch_util:get_nested_json_value(DDoc#doc.body, [<<"shows">>, ShowName]),
8484
% get responder for ddoc/showname
8585
CurrentEtag = show_etag(Req, Doc, DDoc, []),
@@ -138,6 +138,7 @@ handle_doc_update_req(Req, _Db, _DDoc) ->
138138

139139
send_doc_update_response(Req, Db, DDoc, UpdateName, Doc, DocId) ->
140140
%% Will throw an exception if the _update handler is missing
141+
% ok = couch_db:validate_access(Db, DDoc),
141142
couch_util:get_nested_json_value(DDoc#doc.body, [<<"updates">>, UpdateName]),
142143
JsonReq = chttpd_external:json_req_obj(Req, Db, DocId),
143144
JsonDoc = couch_query_servers:json_doc(Doc),
@@ -250,6 +251,7 @@ handle_view_list_req(Req, _Db, _DDoc) ->
250251

251252
handle_view_list(Req, Db, DDoc, LName, {ViewDesignName, ViewName}, Keys) ->
252253
%% Will throw an exception if the _list handler is missing
254+
ok = couch_db:validate_access(Db, DDoc),
253255
couch_util:get_nested_json_value(DDoc#doc.body, [<<"lists">>, LName]),
254256
DbName = couch_db:name(Db),
255257
{ok, VDoc} = ddoc_cache:open(DbName, <<"_design/", ViewDesignName/binary>>),

src/couch/test/eunit/couchdb_access_tests.erl

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,16 @@ access_test_() ->
120120
fun should_allow_admin_query_view_from_ddoc_without_access/2,
121121
fun should_not_allow_user_query_view_from_ddoc_without_access/2,
122122

123+
% show, list & view
124+
fun should_allow_admin_show_view_from_ddoc_without_access/2,
125+
fun should_not_allow_user_show_view_from_ddoc_without_access/2,
126+
fun should_allow_admin_list_view_from_ddoc_without_access/2,
127+
fun should_not_allow_user_list_view_from_ddoc_without_access/2,
128+
fun should_allow_admin_update_with_ddoc_without_access/2,
129+
fun should_not_allow_user_update_with_ddoc_without_access/2,
130+
% once we allow access ddocs, we must not allow updating a doc
131+
% that does not belong to us
132+
123133
% replication
124134
fun should_allow_admin_to_replicate_from_access_to_access/2,
125135
fun should_allow_admin_to_replicate_from_no_access_to_access/2,
@@ -651,6 +661,116 @@ should_not_allow_user_query_view_from_ddoc_without_access(_PortType, Url) ->
651661
),
652662
?_assertEqual(403, Code1).
653663

664+
% show, list & updates
665+
666+
-define(SHOW_DDOC, #{
667+
views => #{
668+
foo => #{
669+
map => <<"function() {}">>
670+
}
671+
},
672+
shows => #{
673+
show1 => <<"function(doc) { return 'hi' }">>
674+
}
675+
}).
676+
677+
should_allow_admin_show_view_from_ddoc_without_access(_PortType, Url) ->
678+
{ok, Code, _, _} = test_request:put(
679+
Url ++ "/db/_design/a",
680+
?ADMIN_REQ_HEADERS,
681+
jiffy:encode(?SHOW_DDOC)
682+
),
683+
?assertEqual(201, Code),
684+
{ok, Code1, _, _} = test_request:get(
685+
Url ++ "/db/_design/a/_show/show1",
686+
?ADMIN_REQ_HEADERS
687+
),
688+
?_assertEqual(200, Code1).
689+
690+
should_not_allow_user_show_view_from_ddoc_without_access(_PortType, Url) ->
691+
{ok, Code, _, _} = test_request:put(
692+
Url ++ "/db/_design/a",
693+
?ADMIN_REQ_HEADERS,
694+
jiffy:encode(?SHOW_DDOC)
695+
),
696+
?assertEqual(201, Code),
697+
{ok, Code1, _, _} = test_request:get(
698+
Url ++ "/db/_design/a/_show/show1",
699+
?USERX_REQ_HEADERS
700+
),
701+
?_assertEqual(403, Code1).
702+
703+
-define(LIST_DDOC, #{
704+
views => #{
705+
foo => #{
706+
map => <<"function() {}">>
707+
}
708+
},
709+
lists => #{
710+
list1 => <<"function(head, req) { send('hi') }">>
711+
}
712+
}).
713+
714+
should_allow_admin_list_view_from_ddoc_without_access(_PortType, Url) ->
715+
{ok, Code, _, _} = test_request:put(
716+
Url ++ "/db/_design/a",
717+
?ADMIN_REQ_HEADERS,
718+
jiffy:encode(?LIST_DDOC)
719+
),
720+
?assertEqual(201, Code),
721+
{ok, Code1, _, _} = test_request:get(
722+
Url ++ "/db/_design/a/_list/list1/foo",
723+
?ADMIN_REQ_HEADERS
724+
),
725+
?_assertEqual(200, Code1).
726+
727+
should_not_allow_user_list_view_from_ddoc_without_access(_PortType, Url) ->
728+
{ok, Code, _, _} = test_request:put(
729+
Url ++ "/db/_design/a",
730+
?ADMIN_REQ_HEADERS,
731+
jiffy:encode(?LIST_DDOC)
732+
),
733+
?assertEqual(201, Code),
734+
{ok, Code1, _, _} = test_request:get(
735+
Url ++ "/db/_design/a/_list/list1/foo",
736+
?USERX_REQ_HEADERS
737+
),
738+
?_assertEqual(403, Code1).
739+
740+
-define(UPDATE_DDOC, #{
741+
updates => #{
742+
update1 => <<"function(doc) { return [{_id: 'yay', a: 2}, 'done!']; }">>
743+
}
744+
}).
745+
746+
should_allow_admin_update_with_ddoc_without_access(_PortType, Url) ->
747+
{ok, Code, _, _} = test_request:put(
748+
Url ++ "/db/_design/a",
749+
?ADMIN_REQ_HEADERS,
750+
jiffy:encode(?UPDATE_DDOC)
751+
),
752+
?assertEqual(201, Code),
753+
{ok, Code1, _, _} = test_request:post(
754+
Url ++ "/db/_design/a/_update/update1",
755+
?ADMIN_REQ_HEADERS,
756+
jiffy:encode(#{a => 1})
757+
),
758+
?_assertEqual(201, Code1).
759+
760+
should_not_allow_user_update_with_ddoc_without_access(_PortType, Url) ->
761+
{ok, Code, _, _} = test_request:put(
762+
Url ++ "/db/_design/a",
763+
?ADMIN_REQ_HEADERS,
764+
jiffy:encode(?UPDATE_DDOC)
765+
),
766+
?assertEqual(201, Code),
767+
{ok, Code1, _, _} = test_request:post(
768+
Url ++ "/db/_design/a/_update/update1",
769+
?USERX_REQ_HEADERS,
770+
jiffy:encode(#{a => 1})
771+
),
772+
?_assertEqual(403, Code1).
773+
654774
% replication
655775

656776
should_allow_admin_to_replicate_from_access_to_access(_PortType, Url) ->

src/couch/test/eunit/couchdb_mrview_cors_tests.erl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
-define(DDOC,
1919
{[
2020
{<<"_id">>, <<"_design/foo">>},
21-
{<<"_access">>, [<<"user_a">>]},
2221
{<<"shows">>,
2322
{[
2423
{<<"bar">>, <<"function(doc, req) {return '<h1>wosh</h1>';}">>}
@@ -98,7 +97,7 @@ should_make_shows_request(_, {Host, DbName}) ->
9897
end).
9998

10099
create_db(backdoor, DbName) ->
101-
{ok, Db} = couch_db:create(DbName, [?ADMIN_CTX, {access, true}]),
100+
{ok, Db} = couch_db:create(DbName, [?ADMIN_CTX]),
102101
couch_db:close(Db);
103102
create_db(clustered, DbName) ->
104103
{ok, Status, _, _} = test_request:put(db_url(DbName), [?AUTH], ""),

0 commit comments

Comments
 (0)