summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBessenyei Balázs Donát <bessbd@users.noreply.github.com>2020-08-28 21:27:58 +0200
committerGitHub <noreply@github.com>2020-08-28 15:27:58 -0400
commit95a1f4e8fb420b9bd918849baefd116b2b3c0e8e (patch)
tree35bec4b1926250cea81b3e7b4fc558f3ed95768b
parent39514bdb1f1c002b8f7dec166f801b0e9e994a4f (diff)
downloadcouchdb-95a1f4e8fb420b9bd918849baefd116b2b3c0e8e.tar.gz
Make restricted partition search parameters return bad request (#3108)
According to https://docs.couchdb.org/en/master/ddocs/search.html there are parameters for searches that are not allowed for partitioned queries. Those restrictions were not enforced, thus making the software and docs inconsistent. This commit adds them to validation so that the behavior matches the one described in the docs. Co-authored-by: Joan Touzet <wohali@users.noreply.github.com>
-rw-r--r--src/dreyfus/src/dreyfus_httpd.erl22
-rw-r--r--src/dreyfus/test/elixir/test/partition_search_test.exs36
2 files changed, 50 insertions, 8 deletions
diff --git a/src/dreyfus/src/dreyfus_httpd.erl b/src/dreyfus/src/dreyfus_httpd.erl
index 4a2b76983..007dace8f 100644
--- a/src/dreyfus/src/dreyfus_httpd.erl
+++ b/src/dreyfus/src/dreyfus_httpd.erl
@@ -449,10 +449,15 @@ validate_search_restrictions(Db, DDoc, Args) ->
q = Query,
partition = Partition,
grouping = Grouping,
- limit = Limit
+ limit = Limit,
+ counts = Counts,
+ drilldown = Drilldown,
+ ranges = Ranges
} = Args,
#grouping{
- by = GroupBy
+ by = GroupBy,
+ limit = GroupLimit,
+ sort = GroupSort
} = Grouping,
case Query of
@@ -498,9 +503,18 @@ validate_search_restrictions(Db, DDoc, Args) ->
parse_non_negative_int_param("limit", Limit, "max_limit", MaxLimit)
end,
- case GroupBy /= nil andalso is_binary(Partition) of
+ DefaultArgs = #index_query_args{},
+
+ case is_binary(Partition) andalso (
+ Counts /= DefaultArgs#index_query_args.counts
+ orelse Drilldown /= DefaultArgs#index_query_args.drilldown
+ orelse Ranges /= DefaultArgs#index_query_args.ranges
+ orelse GroupSort /= DefaultArgs#index_query_args.grouping#grouping.sort
+ orelse GroupBy /= DefaultArgs#index_query_args.grouping#grouping.by
+ orelse GroupLimit /= DefaultArgs#index_query_args.grouping#grouping.limit
+ ) of
true ->
- Msg5 = <<"`group_by` and `partition` are incompatible">>,
+ Msg5 = <<"`partition` and any of `drilldown`, `ranges`, `group_field`, `group_sort`, `group_limit` or `group_by` are incompatible">>,
throw({bad_request, Msg5});
false ->
ok
diff --git a/src/dreyfus/test/elixir/test/partition_search_test.exs b/src/dreyfus/test/elixir/test/partition_search_test.exs
index 19a915ad3..121995449 100644
--- a/src/dreyfus/test/elixir/test/partition_search_test.exs
+++ b/src/dreyfus/test/elixir/test/partition_search_test.exs
@@ -21,7 +21,7 @@ defmodule PartitionSearchTest do
}
end
- resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}, query: %{w: 3})
+ resp = Couch.post("/#{db_name}/_bulk_docs", headers: ["Content-Type": "application/json"], body: %{:docs => docs}, query: %{w: 3})
assert resp.status_code in [201, 202]
end
@@ -166,7 +166,7 @@ defmodule PartitionSearchTest do
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 200
ids = get_ids(resp)
- assert ids == ["bar:1", "bar:5", "bar:9", "foo:2", "bar:3", "foo:4", "foo:6", "bar:7", "foo:8", "foo:10"]
+ assert Enum.sort(ids) == Enum.sort(["bar:1", "bar:5", "bar:9", "foo:2", "bar:3", "foo:4", "foo:6", "bar:7", "foo:8", "foo:10"])
end
@tag :with_db
@@ -179,7 +179,7 @@ defmodule PartitionSearchTest do
resp = Couch.get(url, query: %{q: "some:field"})
assert resp.status_code == 200
ids = get_ids(resp)
- assert ids == ["bar:1", "bar:5", "bar:9", "foo:2", "bar:3", "foo:4", "foo:6", "bar:7", "foo:8", "foo:10"]
+ assert Enum.sort(ids) == Enum.sort(["bar:1", "bar:5", "bar:9", "foo:2", "bar:3", "foo:4", "foo:6", "bar:7", "foo:8", "foo:10"])
end
@tag :with_db
@@ -192,7 +192,7 @@ defmodule PartitionSearchTest do
resp = Couch.get(url, query: %{q: "some:field", limit: 3})
assert resp.status_code == 200
ids = get_ids(resp)
- assert ids == ["bar:1", "bar:5", "bar:9"]
+ assert Enum.sort(ids) == Enum.sort(["bar:1", "bar:5", "bar:9"])
end
@tag :with_db
@@ -216,4 +216,32 @@ defmodule PartitionSearchTest do
resp = Couch.post(url, body: %{q: "some:field", partition: "bar"})
assert resp.status_code == 400
end
+
+ @tag :with_partitioned_db
+ test "restricted parameters are not allowed in query or body", context do
+ db_name = context[:db_name]
+ create_search_docs(db_name)
+ create_ddoc(db_name)
+
+ body = %{q: "some:field", partition: "foo"}
+
+ Enum.each(
+ [
+ {:counts, "[\"type\"]"},
+ {:group_field, "some"},
+ {:ranges, :jiffy.encode(%{price: %{cheap: "[0 TO 100]"}})},
+ {:drilldown, "[\"key\",\"a\"]"},
+ ],
+ fn {key, value} ->
+ url = "/#{db_name}/_partition/foo/_design/library/_search/books"
+ bannedparam = Map.put(body, key, value)
+ get_resp = Couch.get(url, query: bannedparam)
+ %{:body => %{"reason" => get_reason}} = get_resp
+ assert Regex.match?(~r/are incompatible/, get_reason)
+ post_resp = Couch.post(url, body: bannedparam)
+ %{:body => %{"reason" => post_reason}} = post_resp
+ assert Regex.match?(~r/are incompatible/, post_reason)
+ end
+ )
+ end
end