You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2023/02/08 22:08:25 UTC
[couchdb] 01/01: Remove all javascript tests
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch remove-replace-javascript-tests
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 4966b595d49a9a18fdda180cbb582e862bbad941
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Wed Feb 8 17:00:39 2023 -0500
Remove all javascript tests
Most of them have been ported to Elixir except the two replication tests.
Add the two replication tests to couch_replicator and remove the whole javascript subfolder.
For the "replication_id" got a bit further and test that other fields are
correctly replaced or ignored.
---
.../test/eunit/couch_replicator_doc_ids_tests.erl | 83 ++++
.../couch_replicator_scheduler_docs_tests.erl | 78 ++++
.../test/eunit/couch_replicator_test_helper.erl | 2 +
test/javascript/tests/list_views.js | 502 --------------------
test/javascript/tests/proxyauth.js | 137 ------
test/javascript/tests/replicator_db_bad_rep_id.js | 103 -----
test/javascript/tests/replicator_db_by_doc_id.js | 128 -----
test/javascript/tests/rewrite.js | 513 ---------------------
test/javascript/tests/rewrite_js.js | 366 ---------------
test/javascript/tests/security_validation.js | 330 -------------
test/javascript/tests/show_documents.js | 376 ---------------
test/javascript/tests/users_db_security.js | 418 -----------------
12 files changed, 163 insertions(+), 2873 deletions(-)
diff --git a/src/couch_replicator/test/eunit/couch_replicator_doc_ids_tests.erl b/src/couch_replicator/test/eunit/couch_replicator_doc_ids_tests.erl
new file mode 100644
index 000000000..711224655
--- /dev/null
+++ b/src/couch_replicator/test/eunit/couch_replicator_doc_ids_tests.erl
@@ -0,0 +1,83 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(couch_replicator_doc_ids_tests).
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+
+-define(DOC1, <<"doc1">>).
+-define(DOC2, <<"doc2">>).
+-define(DDOC3, <<"_design/doc3">>).
+
+doc_ids_replication_test_() ->
+ {
+ "Doc IDs filtered replication tests",
+ {
+ foreach,
+ fun couch_replicator_test_helper:test_setup/0,
+ fun couch_replicator_test_helper:test_teardown/1,
+ [
+ ?TDEF_FE(t_should_replicate_with_ddoc_ids)
+ ]
+ }
+ }.
+
+t_should_replicate_with_ddoc_ids({_Ctx, {Source, Target}}) ->
+ create_docs(Source),
+ replicate(#{
+ <<"source">> => db_url(Source),
+ <<"target">> => db_url(Target),
+ <<"doc_ids">> => [?DOC1, ?DDOC3]
+ }),
+ %% FilteredFun is an Erlang version of following mango doc_ids
+ FilterFun = fun(DocId, #doc{}) ->
+ DocId == ?DOC1 orelse DocId == ?DDOC3
+ end,
+ {TargetDocCount, AllReplies} = compare_dbs(Source, Target, FilterFun),
+ % Target DB has proper number of docs
+ ?assertEqual(2, TargetDocCount),
+ % All the docs selected as expected
+ ?assert(lists:all(fun(Valid) -> Valid end, AllReplies)).
+
+compare_dbs(Source, Target, FilterFun) ->
+ {ok, TargetDocCount} = fabric:get_doc_count(Target),
+ Replies = lists:foldl(
+ fun({Id, Rev}, Acc) ->
+ SrcDoc = read_doc(Source, Id, Rev),
+ TgtDoc = read_doc(Target, Id, Rev),
+ case FilterFun(Id, SrcDoc) of
+ true ->
+ [is_record(TgtDoc, doc) | Acc];
+ false ->
+ [TgtDoc =:= not_found | Acc]
+ end
+ end,
+ [],
+ couch_replicator_test_helper:cluster_doc_revs(Source)
+ ),
+ {TargetDocCount, Replies}.
+
+read_doc(Db, DocId, Rev) ->
+ couch_replicator_test_helper:cluster_open_rev(Db, DocId, Rev).
+
+create_docs(DbName) ->
+ Doc1 = couch_doc:from_json_obj({[{<<"_id">>, ?DOC1}]}),
+ Doc2 = couch_doc:from_json_obj({[{<<"_id">>, ?DOC2}]}),
+ DDoc3 = couch_doc:from_json_obj({[{<<"_id">>, ?DDOC3}]}),
+ {ok, _} = fabric:update_docs(DbName, [Doc1, Doc2, DDoc3], [?ADMIN_CTX]).
+
+db_url(DbName) ->
+ couch_replicator_test_helper:cluster_db_url(DbName).
+
+replicate(RepObject) ->
+ couch_replicator_test_helper:replicate(RepObject).
diff --git a/src/couch_replicator/test/eunit/couch_replicator_scheduler_docs_tests.erl b/src/couch_replicator/test/eunit/couch_replicator_scheduler_docs_tests.erl
index 7d868eb11..1b11a447d 100644
--- a/src/couch_replicator/test/eunit/couch_replicator_scheduler_docs_tests.erl
+++ b/src/couch_replicator/test/eunit/couch_replicator_scheduler_docs_tests.erl
@@ -88,6 +88,17 @@ replicator_bdu_test_prefixed_db_test_() ->
])
}.
+t_replicator_doc_state_fields_test_() ->
+ {
+ setup,
+ fun setup_prefixed_replicator_db/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_doc_fields_are_replaced, 10),
+ ?TDEF(t_doc_fields_are_ignored, 10)
+ ])
+ }.
+
t_scheduler_docs_total_rows({_Ctx, {RepDb, Source, Target}}) ->
SourceUrl = couch_replicator_test_helper:cluster_db_url(Source),
TargetUrl = couch_replicator_test_helper:cluster_db_url(Target),
@@ -134,6 +145,73 @@ t_malformed_docs_are_rejected({_Ctx, {RepDb, _, _}}) ->
DocUrl2 = rep_doc_url(RepDb, <<"rep2">>),
?assertMatch({403, _}, req(put, DocUrl2, #{<<"foo">> => <<"bar">>})).
+t_doc_fields_are_replaced({_Ctx, {RepDb, Source, Target}}) ->
+ SourceUrl = couch_replicator_test_helper:cluster_db_url(Source),
+ TargetUrl = couch_replicator_test_helper:cluster_db_url(Target),
+ RepDoc = #{
+ <<"source">> => SourceUrl,
+ <<"target">> => TargetUrl,
+ <<"_replication_id">> => <<"foo3">>,
+ <<"_replication_state">> => <<"triggered">>,
+ <<"_replication_state_time">> => <<"foo5">>,
+ <<"_replication_state_reason">> => <<"foo6">>
+ },
+ RepDocUrl = rep_doc_url(RepDb, ?docid()),
+ {201, _} = req(put, RepDocUrl, RepDoc),
+ StateDoc = test_util:wait(
+ fun() ->
+ case req(get, RepDocUrl) of
+ {200, #{<<"_replication_state">> := <<"completed">>} = StDoc} -> StDoc;
+ {_, #{}} -> wait
+ end
+ end,
+ 10000,
+ 1000
+ ),
+ ?assertMatch(
+ #{
+ <<"_replication_state">> := <<"completed">>,
+ <<"_replication_state_time">> := <<_/binary>>,
+ <<"_replication_stats">> := #{}
+ },
+ StateDoc
+ ),
+ #{<<"_replication_state_time">> := StateTime} = StateDoc,
+ ?assertNotEqual(<<"foo5">>, StateTime),
+ ?assertNot(is_map_key(<<"_replicator_state_reason">>, StateDoc)),
+ ?assertNot(is_map_key(<<"_replication_id">>, StateDoc)).
+
+t_doc_fields_are_ignored({_Ctx, {RepDb, Source, Target}}) ->
+ SourceUrl = couch_replicator_test_helper:cluster_db_url(Source),
+ TargetUrl = couch_replicator_test_helper:cluster_db_url(Target),
+ RepDoc = #{
+ <<"source">> => SourceUrl,
+ <<"target">> => TargetUrl,
+ <<"replication_id">> => <<"foo1">>,
+ <<"id">> => <<"foo2">>,
+ <<"other_junk">> => true
+ },
+ RepDocUrl = rep_doc_url(RepDb, ?docid()),
+ {201, _} = req(put, RepDocUrl, RepDoc),
+ StateDoc = test_util:wait(
+ fun() ->
+ case req(get, RepDocUrl) of
+ {200, #{<<"_replication_state">> := <<"completed">>} = StDoc} -> StDoc;
+ {_, #{}} -> wait
+ end
+ end,
+ 10000,
+ 1000
+ ),
+ ?assertMatch(
+ #{
+ <<"replication_id">> := <<"foo1">>,
+ <<"id">> := <<"foo2">>,
+ <<"other_junk">> := true
+ },
+ StateDoc
+ ).
+
rep_doc_url(RepDb, DocId) when is_binary(RepDb) ->
rep_doc_url(binary_to_list(RepDb), DocId);
rep_doc_url(RepDb, DocId) when is_binary(DocId) ->
diff --git a/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl b/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl
index 03c2f13be..93755e137 100644
--- a/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl
+++ b/src/couch_replicator/test/eunit/couch_replicator_test_helper.erl
@@ -174,6 +174,8 @@ replicate(Source, Target) ->
]}
).
+replicate(#{} = RepObject) ->
+ replicate(jiffy:decode(jiffy:encode(RepObject)));
replicate({[_ | _]} = RepObject) ->
{ok, Rep} = couch_replicator_parse:parse_rep_doc(RepObject, ?ADMIN_USER),
ok = couch_replicator_scheduler:add_job(Rep),
diff --git a/test/javascript/tests/list_views.js b/test/javascript/tests/list_views.js
deleted file mode 100644
index 2d74586fe..000000000
--- a/test/javascript/tests/list_views.js
+++ /dev/null
@@ -1,502 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-couchTests.elixir = true;
-couchTests.list_views = function(debug) {
-
- var db_name = get_random_db_name();
- var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
- db.createDb();
- if (debug) debugger;
-
- var designDoc = {
- _id:"_design/lists",
- language: "javascript",
- views : {
- basicView : {
- map : stringFun(function(doc) {
- emit(doc.integer, doc.string);
- })
- },
- withReduce : {
- map : stringFun(function(doc) {
- emit(doc.integer, doc.string);
- }),
- reduce : stringFun(function(keys, values, rereduce) {
- if (rereduce) {
- return sum(values);
- } else {
- return values.length;
- }
- })
- }
- },
- lists: {
- basicBasic : stringFun(function(head, req) {
- send("head");
- var row;
- while(row = getRow()) {
- log("row: "+toJSON(row));
- send(row.key);
- };
- return "tail";
- }),
- basicJSON : stringFun(function(head, req) {
- start({"headers":{"Content-Type" : "application/json"}});
- send('{"head":'+toJSON(head)+', ');
- send('"req":'+toJSON(req)+', ');
- send('"rows":[');
- var row, sep = '';
- while (row = getRow()) {
- send(sep + toJSON(row));
- sep = ', ';
- }
- return "]}";
- }),
- simpleForm: stringFun(function(head, req) {
- log("simpleForm");
- send('<ul>');
- var row, row_number = 0, prevKey, firstKey = null;
- while (row = getRow()) {
- row_number += 1;
- if (!firstKey) firstKey = row.key;
- prevKey = row.key;
- send('\n<li>Key: '+row.key
- +' Value: '+row.value
- +' LineNo: '+row_number+'</li>');
- }
- return '</ul><p>FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'</p>';
- }),
- acceptSwitch: stringFun(function(head, req) {
- // respondWith takes care of setting the proper headers
- provides("html", function() {
- send("HTML <ul>");
-
- var row, num = 0;
- while (row = getRow()) {
- num ++;
- send('\n<li>Key: '
- +row.key+' Value: '+row.value
- +' LineNo: '+num+'</li>');
- }
-
- // tail
- return '</ul>';
- });
- }),
- qsParams: stringFun(function(head, req) {
- return toJSON(req.query) + "\n";
- }),
- stopIter: stringFun(function(req) {
- send("head");
- var row, row_number = 0;
- while(row = getRow()) {
- if(row_number > 2) break;
- send(" " + row_number);
- row_number += 1;
- };
- return " tail";
- }),
- stopIter2: stringFun(function(head, req) {
- provides("html", function() {
- send("head");
- var row, row_number = 0;
- while(row = getRow()) {
- if(row_number > 2) break;
- send(" " + row_number);
- row_number += 1;
- };
- return " tail";
- });
- }),
- tooManyGetRows : stringFun(function() {
- send("head");
- var row;
- while(row = getRow()) {
- send(row.key);
- };
- getRow();
- getRow();
- getRow();
- row = getRow();
- return "after row: "+toJSON(row);
- }),
- emptyList: stringFun(function() {
- return " ";
- }),
- rowError : stringFun(function(head, req) {
- send("head");
- var row = getRow();
- send(fooBarBam); // intentional error
- return "tail";
- }),
- docReference : stringFun(function(head, req) {
- send("head");
- var row = getRow();
- send(row.doc.integer);
- return "tail";
- }),
- secObj: stringFun(function(head, req) {
- return toJSON(req.secObj);
- }),
- setHeaderAfterGotRow: stringFun(function(head, req) {
- getRow();
- start({
- code: 400,
- headers: {
- "X-My-Header": "MyHeader"
- }
- });
- send("bad request");
- }),
- allDocs: stringFun(function(head, req){
- start({'headers': {'Content-Type': 'application/json'}});
- var resp = head;
- var rows = [];
- while(row=getRow()){
- rows.push(row);
- }
- resp.rows = rows;
- return toJSON(resp);
- })
- }
- };
- var viewOnlyDesignDoc = {
- _id:"_design/views",
- language: "javascript",
- views : {
- basicView : {
- map : stringFun(function(doc) {
- emit(-doc.integer, doc.string);
- })
- }
- }
- };
- var erlListDoc = {
- _id: "_design/erlang",
- language: "erlang",
- lists: {
- simple:
- 'fun(Head, {Req}) -> ' +
- ' Send(<<"[">>), ' +
- ' Fun = fun({Row}, Sep) -> ' +
- ' Val = couch_util:get_value(<<"key">>, Row, 23), ' +
- ' Send(list_to_binary(Sep ++ integer_to_list(Val))), ' +
- ' {ok, ","} ' +
- ' end, ' +
- ' {ok, _} = FoldRows(Fun, ""), ' +
- ' Send(<<"]">>) ' +
- 'end.'
- }
- };
-
- T(db.save(designDoc).ok);
-
- var docs = makeDocs(0, 10);
- db.bulkSave(docs);
-
- var view = db.view('lists/basicView');
- T(view.total_rows == 10);
-
- // standard get
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/basicBasic/basicView");
- T(xhr.status == 200, "standard get should be 200");
- T(/head0123456789tail/.test(xhr.responseText));
-
- // standard options - works though it does not make lots of sense
- var xhr = CouchDB.request("OPTIONS", "/" + db_name + "/_design/lists/_list/basicBasic/basicView");
- T(xhr.status == 200, "standard get should be 200");
- T(/head0123456789tail/.test(xhr.responseText));
-
- // TODO: test that etags are available - actually they're not (yet): https://issues.apache.org/jira/browse/COUCHDB-2859
- //var etag = xhr.getResponseHeader("etag");
- //xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/basicBasic/basicView", {
- // headers: {"if-none-match": etag}
- //});
- //T(xhr.status == 304);
-
- // confirm ETag changes with different POST bodies
- // (not yet - see above)
- //xhr = CouchDB.request("POST", "/" + db_name + "/_design/lists/_list/basicBasic/basicView",
- // {body: JSON.stringify({keys:[1]})}
- //);
- //var etag1 = xhr.getResponseHeader("etag");
- //xhr = CouchDB.request("POST", "/" + db_name + "/_design/lists/_list/basicBasic/basicView",
- // {body: JSON.stringify({keys:[2]})}
- //);
- //var etag2 = xhr.getResponseHeader("etag");
- //T(etag1 != etag2, "POST to map _list generates key-depdendent ETags");
-
- // test the richness of the arguments
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/basicJSON/basicView?update_seq=true");
- T(xhr.status == 200, "standard get should be 200");
- var resp = JSON.parse(xhr.responseText);
- TEquals(10, resp.head.total_rows);
- TEquals(0, resp.head.offset);
- // we don't have a (meaningful) update seq in a clustered env
- //TEquals(11, resp.head.update_seq);
-
- T(resp.rows.length == 10);
- TEquals(resp.rows[0], {"id": "0","key": 0,"value": "0"});
-
- TEquals(resp.req.info.db_name, "" + db_name + "");
- TEquals(resp.req.method, "GET");
- TEquals(resp.req.path, [
- "" + db_name + "",
- "_design",
- "lists",
- "_list",
- "basicJSON",
- "basicView"
- ]);
- T(resp.req.headers.Accept);
- T(resp.req.headers.Host);
- T(resp.req.headers["User-Agent"]);
- T(resp.req.cookie);
- TEquals("/" + db_name + "/_design/lists/_list/basicJSON/basicView?update_seq=true",
- resp.req.raw_path, "should include raw path");
-
- // get with query params
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/basicView?startkey=3&endkey=8");
- T(xhr.status == 200, "with query params");
- T(!(/Key: 1/.test(xhr.responseText)));
- T(/FirstKey: 3/.test(xhr.responseText));
- T(/LastKey: 8/.test(xhr.responseText));
-
- // with 0 rows
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/basicView?startkey=30");
- T(xhr.status == 200, "0 rows");
- T(/<\/ul>/.test(xhr.responseText));
-
- //too many Get Rows
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/tooManyGetRows/basicView");
- T(xhr.status == 200, "tooManyGetRows");
- T(/9after row: null/.test(xhr.responseText));
-
-
- // reduce with 0 rows
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?startkey=30");
- T(xhr.status == 200, "reduce 0 rows");
- T(/LastKey: undefined/.test(xhr.responseText));
-
- // when there is a reduce present, but not used
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?reduce=false");
- T(xhr.status == 200, "reduce false");
- T(/Key: 1/.test(xhr.responseText));
-
-
- // when there is a reduce present, and used
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?group=true");
- T(xhr.status == 200, "group reduce");
- T(/Key: 1/.test(xhr.responseText));
-
- // there should be etags on reduce as well
- // (see above 4 etags)
- //var etag = xhr.getResponseHeader("etag");
- //T(etag, "Etags should be served with reduce lists");
- //xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?group=true", {
- // headers: {"if-none-match": etag}
- //});
- //T(xhr.status == 304);
-
- // confirm ETag changes with different POST bodies
- // (see above)
- //xhr = CouchDB.request("POST", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?group=true",
- // {body: JSON.stringify({keys:[1]})}
- //);
- //var etag1 = xhr.getResponseHeader("etag");
- //xhr = CouchDB.request("POST", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?group=true",
- // {body: JSON.stringify({keys:[2]})}
- //);
- //var etag2 = xhr.getResponseHeader("etag");
- //T(etag1 != etag2, "POST to reduce _list generates key-depdendent ETags");
-
- // verify the etags expire correctly
- var docs = makeDocs(11, 12);
- db.bulkSave(docs);
-
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?group=true", {
- // will always be 200 as etags don't make sense (see above)
- //headers: {"if-none-match": etag}
- });
- T(xhr.status == 200, "reduce etag");
-
- // empty list
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/emptyList/basicView");
- T(xhr.responseText.match(/^ $/));
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/emptyList/withReduce?group=true");
- T(xhr.responseText.match(/^ $/));
-
- // multi-key fetch
- var xhr = CouchDB.request("POST", "/" + db_name + "/_design/lists/_list/simpleForm/basicView", {
- body: '{"keys":[2,4,5,7]}'
- });
- T(xhr.status == 200, "multi key");
- T(!(/Key: 1 /.test(xhr.responseText)));
- T(/Key: 2/.test(xhr.responseText));
- T(/FirstKey: 2/.test(xhr.responseText));
- T(/LastKey: 7/.test(xhr.responseText));
-
- // multi-key fetch with GET
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/simpleForm/basicView" +
- "?keys=[2,4,5,7]");
-
- T(xhr.status == 200, "multi key");
- T(!(/Key: 1 /.test(xhr.responseText)));
- T(/Key: 2/.test(xhr.responseText));
- T(/FirstKey: 2/.test(xhr.responseText));
- T(/LastKey: 7/.test(xhr.responseText));
-
- // no multi-key fetch allowed when group=false
- xhr = CouchDB.request("POST", "/" + db_name + "/_design/lists/_list/simpleForm/withReduce?group=false", {
- body: '{"keys":[2,4,5,7]}'
- });
- T(xhr.status == 400);
- T(/query_parse_error/.test(xhr.responseText));
-
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/rowError/basicView");
- T(/ReferenceError/.test(xhr.responseText));
-
-
- // with include_docs and a reference to the doc.
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/docReference/basicView?include_docs=true");
- T(xhr.responseText.match(/head0tail/));
-
- // now with extra qs params
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/qsParams/basicView?foo=blam");
- T(xhr.responseText.match(/blam/));
-
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/stopIter/basicView");
- // T(xhr.getResponseHeader("Content-Type") == "text/plain");
- T(xhr.responseText.match(/^head 0 1 2 tail$/) && "basic stop");
-
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/stopIter2/basicView", {
- headers : {
- "Accept" : "text/html"
- }
- });
- T(xhr.responseText.match(/^head 0 1 2 tail$/) && "stop 2");
-
- // aborting iteration with reduce
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/stopIter/withReduce?group=true");
- T(xhr.responseText.match(/^head 0 1 2 tail$/) && "reduce stop");
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/stopIter2/withReduce?group=true", {
- headers : {
- "Accept" : "text/html"
- }
- });
- T(xhr.responseText.match(/^head 0 1 2 tail$/) && "reduce stop 2");
-
- // with accept headers for HTML
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/acceptSwitch/basicView", {
- headers: {
- "Accept": 'text/html'
- }
- });
- T(xhr.getResponseHeader("Content-Type") == "text/html; charset=utf-8");
- T(xhr.responseText.match(/HTML/));
- T(xhr.responseText.match(/Value/));
-
- // Test we can run lists and views from separate docs.
- T(db.save(viewOnlyDesignDoc).ok);
- var url = "/" + db_name + "/_design/lists/_list/simpleForm/views/basicView" +
- "?startkey=-3";
- xhr = CouchDB.request("GET", url);
- T(xhr.status == 200, "multiple design docs.");
- T(!(/Key: -4/.test(xhr.responseText)));
- T(/FirstKey: -3/.test(xhr.responseText));
- T(/LastKey: 0/.test(xhr.responseText));
-
- // Test we do multi-key requests on lists and views in separate docs.
- var url = "/" + db_name + "/_design/lists/_list/simpleForm/views/basicView";
- xhr = CouchDB.request("POST", url, {
- body: '{"keys":[-2,-4,-5,-7]}'
- });
-
- T(xhr.status == 200, "multi key separate docs");
- T(!(/Key: -3/.test(xhr.responseText)));
- T(/Key: -7/.test(xhr.responseText));
- T(/FirstKey: -2/.test(xhr.responseText));
- T(/LastKey: -7/.test(xhr.responseText));
-
- // Test if secObj is available
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/secObj/basicView");
- T(xhr.status == 200, "standard get should be 200");
- var resp = JSON.parse(xhr.responseText);
- T(typeof(resp) == "object");
-
- var erlViewTest = function() {
- T(db.save(erlListDoc).ok);
- var url = "/" + db_name + "/_design/erlang/_list/simple/views/basicView" +
- "?startkey=-3";
- xhr = CouchDB.request("GET", url);
- T(xhr.status == 200, "multiple languages in design docs.");
- var list = JSON.parse(xhr.responseText);
- T(list.length == 4);
- for(var i = 0; i < list.length; i++)
- {
- T(list[i] + 3 == i);
- }
- };
-
- // make _config available 4 tests or leave commented out
- //run_on_modified_server([{
- // section: "native_query_servers",
- // key: "erlang",
- // value: "{couch_native_process, start_link, []}"
- //}], erlViewTest);
-
- // COUCHDB-1113
- var ddoc = {
- _id: "_design/test",
- views: {
- me: {
- map: (function(doc) { emit(null,null)}).toString()
- }
- },
- lists: {
- you: (function(head, req) {
- var row;
- while(row = getRow()) {
- send(row);
- }
- }).toString()
- }
- };
- db.save(ddoc);
-
- var resp = CouchDB.request("GET", "/" + db.name + "/_design/test/_list/you/me", {
- headers: {
- "Content-Type": "application/x-www-form-urlencoded"
- }
- });
- TEquals(200, resp.status, "should return a 200 response");
-
- // TEST HTTP header response set after getRow() called in _list function.
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/setHeaderAfterGotRow/basicView");
- T(xhr.status == 400);
- T(xhr.getResponseHeader("X-My-Header") == "MyHeader");
- T(xhr.responseText.match(/^bad request$/));
-
- // test handling _all_docs by _list functions. the result should be equal
- var xhr_lAllDocs = CouchDB.request("GET", "/" + db_name + "/_design/lists/_list/allDocs/_all_docs");
- T(xhr_lAllDocs.status == 200, "standard get should be 200");
- var xhr_allDocs = CouchDB.request("GET", "/" + db_name + "/_all_docs");
- var allDocs = JSON.parse(xhr_allDocs.responseText);
- var lAllDocs = JSON.parse(xhr_lAllDocs.responseText);
- TEquals(allDocs.total_rows, lAllDocs.total_rows, "total_rows mismatch");
- TEquals(allDocs.offset, lAllDocs.offset, "offset mismatch");
- TEquals(allDocs.rows.length, lAllDocs.rows.length, "amount of rows mismatch");
- TEquals(allDocs.rows, lAllDocs.rows, "rows mismatch");
-
- // cleanup
- db.deleteDb();
-};
diff --git a/test/javascript/tests/proxyauth.js b/test/javascript/tests/proxyauth.js
deleted file mode 100644
index 7f2e097e8..000000000
--- a/test/javascript/tests/proxyauth.js
+++ /dev/null
@@ -1,137 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-
-couchTests.elixir = true;
-couchTests.proxyauth = function(debug) {
- // this test proxy authentification handler
- return console.log('done in test/elixir/test/proxyauth_test.exs');
- var users_db_name = get_random_db_name();
- var usersDb = new CouchDB(users_db_name, {"X-Couch-Full-Commit":"false"});
- usersDb.createDb();
-
- var db_name = get_random_db_name();
- var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
- db.createDb();
-
- if (debug) debugger;
-
- // Simple secret key generator
- function generateSecret(length) {
- var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- var secret = '';
- for (var i=0; i<length; i++) {
- secret += tab.charAt(Math.floor(Math.random() * 64));
- }
- return secret;
- }
-
- var secret = generateSecret(64);
-
- function TestFun() {
-
- var benoitcUserDoc = CouchDB.prepareUserDoc({
- name: "benoitc@apache.org"
- }, "test");
- T(usersDb.save(benoitcUserDoc).ok);
-
- T(CouchDB.session().userCtx.name == null);
-
- // test that you can use basic auth aginst the users db
- var s = CouchDB.session({
- headers : {
- "Authorization" : "Basic YmVub2l0Y0BhcGFjaGUub3JnOnRlc3Q="
- }
- });
- T(s.userCtx.name == "benoitc@apache.org");
- T(s.info.authenticated == "default");
-
- CouchDB.logout();
-
-/* XXX: None of the rest of this is supported yet in 2.0
- var headers = {
- "X-Auth-CouchDB-UserName": "benoitc@apache.org",
- "X-Auth-CouchDB-Roles": "test",
- "X-Auth-CouchDB-Token": hex_hmac_sha1(secret, "benoitc@apache.org")
- };
-
- var designDoc = {
- _id:"_design/test",
- language: "javascript",
-
- shows: {
- "welcome": stringFun(function(doc,req) {
- return "Welcome " + req.userCtx["name"];
- }),
- "role": stringFun(function(doc, req) {
- return req.userCtx['roles'][0];
- })
- }
- };
-
- db.save(designDoc);
-
- var req = CouchDB.request("GET", "/" + db_name + "/_design/test/_show/welcome",
- {headers: headers});
- T(req.responseText == "Welcome benoitc@apache.org", req.responseText);
-
- req = CouchDB.request("GET", "/" + db_name + "/_design/test/_show/role",
- {headers: headers});
- T(req.responseText == "test");
-
- var xhr = CouchDB.request("PUT", "/_node/node1@127.0.0.1/_config/couch_httpd_auth/proxy_use_secret",{
- body : JSON.stringify("true"),
- headers: {"X-Couch-Persist": "false"}
- });
- T(xhr.status == 200);
-
- req = CouchDB.request("GET", "/" + db_name + "/_design/test/_show/welcome",
- {headers: headers});
- T(req.responseText == "Welcome benoitc@apache.org");
-
- req = CouchDB.request("GET", "/" + db_name + "/_design/test/_show/role",
- {headers: headers});
- T(req.responseText == "test");
-*/
-
- }
-
- run_on_modified_server(
- [{section: "httpd",
- key: "authentication_handlers",
- value:"{chttpd_auth, proxy_authentication_handler}, {chttpd_auth, default_authentication_handler}"},
- {section: "chttpd_auth",
- key: "authentication_db",
- value: users_db_name},
- {section: "chttpd_auth",
- key: "secret",
- value: secret},
- {section: "chttpd_auth",
- key: "x_auth_username",
- value: "X-Auth-CouchDB-UserName"},
- {section: "chttpd_auth",
- key: "x_auth_roles",
- value: "X-Auth-CouchDB-Roles"},
- {section: "chttpd_auth",
- key: "x_auth_token",
- value: "X-Auth-CouchDB-Token"},
- {section: "chttpd_auth",
- key: "proxy_use_secret",
- value: "false"}],
- TestFun
- );
-
- // cleanup
- db.deleteDb();
- usersDb.deleteDb();
-
-};
diff --git a/test/javascript/tests/replicator_db_bad_rep_id.js b/test/javascript/tests/replicator_db_bad_rep_id.js
deleted file mode 100644
index 30a124505..000000000
--- a/test/javascript/tests/replicator_db_bad_rep_id.js
+++ /dev/null
@@ -1,103 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-couchTests.replicator_db_bad_rep_id = function(debug) {
- //return console.log('TODO');
- if (debug) debugger;
-
- var populate_db = replicator_db.populate_db;
- var docs1 = replicator_db.docs1;
- // TODO: dice DBs (at least target)
- var dbA = replicator_db.dbA;
- var dbB = replicator_db.dbB;
- //var repDb = replicator_db.repDb;
- var replDb = new CouchDB("_replicator");
- var wait = replicator_db.wait;
- var waitForRep = replicator_db.waitForRep;
- var waitForSeq = replicator_db.waitForSeq;
-
- function rep_doc_with_bad_rep_id() {
- populate_db(dbA, docs1);
- populate_db(dbB, []);
-
- var repDoc = {
- _id: "foo_rep",
-// TODO: fix DB name issue and remove absolute URL again
- source: 'http://localhost:15984/'+dbA.name,
- target: 'http://localhost:15984/'+dbB.name,
- replication_id: "1234abc"
- };
- T(replDb.save(repDoc).ok);
-
- T(waitForRep(replDb, repDoc, "completed", "error") == "completed");
- for (var i = 0; i < docs1.length; i++) {
- var doc = docs1[i];
- var copy = dbB.open(doc._id);
- T(copy !== null);
- T(copy.value === doc.value);
- }
-
- var repDoc1 = replDb.open(repDoc._id);
- T(repDoc1 !== null);
- T(repDoc1.source === repDoc.source);
- T(repDoc1.target === repDoc.target);
- T(repDoc1._replication_state === "completed",
- "replication document with bad replication id failed");
- T(typeof repDoc1._replication_state_time === "string");
- T(typeof repDoc1._replication_id === "undefined");
- }
-
- /*var server_config = [
- {
- section: "couch_httpd_auth",
- key: "iterations",
- value: "1"
- },
- {
- section: "replicator",
- key: "db",
- value: null //repDb.name
- }
- ];*/
-
- //repDb.deleteDb();
- // don't run on modified server as it would be strange on cluster
- // but use "normal" replication DB, create a doc, reliably clear after run
- // on delete fail, the next tests would all fail
- function handleReplDoc(show) {
- var replDoc = replDb.open("foo_rep");
- if(replDoc!=null) {
- if(show) {
- //console.log(JSON.stringify(replDoc));
- }
- replDb.deleteDoc(replDoc);
- }
- }
-
- handleReplDoc();
- try {
- rep_doc_with_bad_rep_id();
- } finally {
- // cleanup or log
- try {
- handleReplDoc(true);
- } catch (e2) {
- console.log("Error during cleanup " + e2);
- }
- }
- //run_on_modified_server(server_config, rep_doc_with_bad_rep_id);
-
- // cleanup
- //repDb.deleteDb();
- dbA.deleteDb();
- dbB.deleteDb();
-}
diff --git a/test/javascript/tests/replicator_db_by_doc_id.js b/test/javascript/tests/replicator_db_by_doc_id.js
deleted file mode 100644
index a3ca05272..000000000
--- a/test/javascript/tests/replicator_db_by_doc_id.js
+++ /dev/null
@@ -1,128 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-couchTests.replicator_db_by_doc_id = function(debug) {
- //return console.log('TODO');
-
- if (debug) debugger;
-
- var populate_db = replicator_db.populate_db;
- var docs1 = replicator_db.docs1;
- // TODO: dice DBs (at least target)
- var dbA = replicator_db.dbA;
- var dbB = replicator_db.dbB;
- //var repDb = replicator_db.repDb;
- var replDb = new CouchDB("_replicator");
- var wait = replicator_db.wait;
- var waitForRep = replicator_db.waitForRep;
- var waitForSeq = replicator_db.waitForSeq;
-
- function by_doc_ids_replication() {
- // to test that we can replicate docs with slashes in their IDs
- var docs2 = docs1.concat([
- {
- _id: "_design/mydesign",
- language : "javascript"
- }
- ]);
-
- populate_db(dbA, docs2);
- populate_db(dbB, []);
-
- var repDoc = {
- _id: "foo_cont_rep_doc",
- source: "http://" + CouchDB.host + "/" + dbA.name,
- // TODO: fix DB name issue and remove absolute URL again
- target: 'http://localhost:15984/' + dbB.name,
- doc_ids: ["foo666", "foo3", "_design/mydesign", "foo999", "foo1"]
- };
- T(replDb.save(repDoc).ok);
-
- waitForRep(replDb, repDoc, "completed");
- var copy = dbB.open("foo1");
- T(copy !== null);
- T(copy.value === 11);
-
- copy = dbB.open("foo2");
- T(copy === null);
-
- copy = dbB.open("foo3");
- T(copy !== null);
- T(copy.value === 33);
-
- copy = dbB.open("foo666");
- T(copy === null);
-
- copy = dbB.open("foo999");
- T(copy === null);
-
- copy = dbB.open("_design/mydesign");
- // TODO: recheck - but I believe this should be in the target! (see also #written below)
- T(copy !== null);
-
- repDoc = replDb.open(repDoc._id);
- T(typeof repDoc._replication_stats === "object", "doc has stats");
- var stats = repDoc._replication_stats;
- TEquals(3, stats.revisions_checked, "right # of revisions_checked");
- TEquals(3, stats.missing_revisions_found, "right # of missing_revisions_found");
- TEquals(3, stats.docs_read, "right # of docs_read");
- TEquals(3, stats.docs_written, "right # of docs_written");
- TEquals(0, stats.doc_write_failures, "right # of doc_write_failures");
- // sequences are no more meaningful in a cluster
- //TEquals(dbA.info().update_seq, stats.checkpointed_source_seq, "right checkpointed_source_seq");
- }
-
- /*var server_config = [
- {
- section: "chttpd_auth",
- key: "iterations",
- value: "1"
- },
- {
- section: "replicator",
- key: "db",
- value: repDb.name
- }
- ];*/
-
- //repDb.deleteDb();
- // don't run on modified server as it would be strange on cluster
- // but use "normal" replication DB, create a doc, reliably clear after run
- // on delete fail, the next tests would all fail
- function handleReplDoc(show) {
- var replDoc = replDb.open("foo_cont_rep_doc");
- if(replDoc!=null) {
- if(show) {
- //console.log(JSON.stringify(replDoc));
- }
- replDb.deleteDoc(replDoc);
- }
- }
-
- handleReplDoc();
- try {
- by_doc_ids_replication();
- } finally {
- // cleanup or log
- try {
- handleReplDoc(true);
- } catch (e2) {
- console.log("Error during cleanup " + e2);
- }
- }
- //run_on_modified_server(server_config, by_doc_ids_replication);
-
- // cleanup
- //repDb.deleteDb();
- dbA.deleteDb();
- dbB.deleteDb();
-}
diff --git a/test/javascript/tests/rewrite.js b/test/javascript/tests/rewrite.js
deleted file mode 100644
index a470eaee6..000000000
--- a/test/javascript/tests/rewrite.js
+++ /dev/null
@@ -1,513 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-couchTests.elixir = true;
-
-couchTests.rewrite = function(debug) {
- if (debug) debugger;
- var dbNames = ["test_suite_db", "test_suite_db/with_slashes"];
- for (var i=0; i < dbNames.length; i++) {
- var db = new CouchDB(dbNames[i]);
- var dbName = encodeURIComponent(dbNames[i]);
- db.deleteDb();
- db.createDb();
-
-
- run_on_modified_server(
- [{section: "httpd",
- key: "authentication_handlers",
- value: "{couch_httpd_auth, special_test_authentication_handler}"},
- {section:"chttpd",
- key: "WWW-Authenticate",
- value: "X-Couch-Test-Auth"}],
-
- function(){
- var designDoc = {
- _id:"_design/test",
- language: "javascript",
- _attachments:{
- "foo.txt": {
- content_type:"text/plain",
- data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
- }
- },
- rewrites: [
- {
- "from": "foo",
- "to": "foo.txt"
- },
- {
- "from": "foo2",
- "to": "foo.txt",
- "method": "GET"
- },
- {
- "from": "hello/:id",
- "to": "_update/hello/:id",
- "method": "PUT"
- },
- {
- "from": "/welcome",
- "to": "_show/welcome"
- },
- {
- "from": "/welcome/:name",
- "to": "_show/welcome",
- "query": {
- "name": ":name"
- }
- },
- {
- "from": "/welcome2",
- "to": "_show/welcome",
- "query": {
- "name": "user"
- }
- },
- {
- "from": "/welcome3/:name",
- "to": "_update/welcome2/:name",
- "method": "PUT"
- },
- {
- "from": "/welcome3/:name",
- "to": "_show/welcome2/:name",
- "method": "GET"
- },
- {
- "from": "/welcome4/*",
- "to" : "_show/welcome3",
- "query": {
- "name": "*"
- }
- },
- {
- "from": "/welcome5/*",
- "to" : "_show/*",
- "query": {
- "name": "*"
- }
- },
- {
- "from": "basicView",
- "to": "_view/basicView",
- },
- {
- "from": "simpleForm/basicView",
- "to": "_list/simpleForm/basicView",
- },
- {
- "from": "simpleForm/basicViewFixed",
- "to": "_list/simpleForm/basicView",
- "query": {
- "startkey": 3,
- "endkey": 8
- }
- },
- {
- "from": "simpleForm/basicViewPath/:start/:end",
- "to": "_list/simpleForm/basicView",
- "query": {
- "startkey": ":start",
- "endkey": ":end"
- },
- "formats": {
- "start": "int",
- "end": "int"
- }
- },
- {
- "from": "simpleForm/complexView",
- "to": "_list/simpleForm/complexView",
- "query": {
- "key": [1, 2]
- }
- },
- {
- "from": "simpleForm/complexView2",
- "to": "_list/simpleForm/complexView",
- "query": {
- "key": ["test", {}]
- }
- },
- {
- "from": "simpleForm/complexView3",
- "to": "_list/simpleForm/complexView",
- "query": {
- "key": ["test", ["test", "essai"]]
- }
- },
- {
- "from": "simpleForm/complexView4",
- "to": "_list/simpleForm/complexView2",
- "query": {
- "key": {"c": 1}
- }
- },
- {
- "from": "simpleForm/complexView5/:a/:b",
- "to": "_list/simpleForm/complexView3",
- "query": {
- "key": [":a", ":b"]
- }
- },
- {
- "from": "simpleForm/complexView6",
- "to": "_list/simpleForm/complexView3",
- "query": {
- "key": [":a", ":b"]
- }
- },
- {
- "from": "simpleForm/complexView7/:a/:b",
- "to": "_view/complexView3",
- "query": {
- "key": [":a", ":b"],
- "include_docs": ":doc"
- },
- "format": {
- "doc": "bool"
- }
-
- },
- {
- "from": "/",
- "to": "_view/basicView",
- },
- {
- "from": "/db/*",
- "to": "../../*"
- }
- ],
- lists: {
- simpleForm: stringFun(function(head, req) {
- log("simpleForm");
- send('<ul>');
- var row, row_number = 0, prevKey, firstKey = null;
- while (row = getRow()) {
- row_number += 1;
- if (!firstKey) firstKey = row.key;
- prevKey = row.key;
- send('\n<li>Key: '+row.key
- +' Value: '+row.value
- +' LineNo: '+row_number+'</li>');
- }
- return '</ul><p>FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'</p>';
- }),
- },
- shows: {
- "welcome": stringFun(function(doc,req) {
- return "Welcome " + req.query["name"];
- }),
- "welcome2": stringFun(function(doc, req) {
- return "Welcome " + doc.name;
- }),
- "welcome3": stringFun(function(doc,req) {
- return "Welcome " + req.query["name"];
- })
- },
- updates: {
- "hello" : stringFun(function(doc, req) {
- if (!doc) {
- if (req.id) {
- return [{
- _id : req.id
- }, "New World"]
- }
- return [null, "Empty World"];
- }
- doc.world = "hello";
- doc.edited_by = req.userCtx;
- return [doc, "hello doc"];
- }),
- "welcome2": stringFun(function(doc, req) {
- if (!doc) {
- if (req.id) {
- return [{
- _id: req.id,
- name: req.id
- }, "New World"]
- }
- return [null, "Empty World"];
- }
- return [doc, "hello doc"];
- })
- },
- views : {
- basicView : {
- map : stringFun(function(doc) {
- if (doc.integer) {
- emit(doc.integer, doc.string);
- }
-
- })
- },
- complexView: {
- map: stringFun(function(doc) {
- if (doc.type == "complex") {
- emit([doc.a, doc.b], doc.string);
- }
- })
- },
- complexView2: {
- map: stringFun(function(doc) {
- if (doc.type == "complex") {
- emit(doc.a, doc.string);
- }
- })
- },
- complexView3: {
- map: stringFun(function(doc) {
- if (doc.type == "complex") {
- emit(doc.b, doc.string);
- }
- })
- }
- }
- }
-
- db.save(designDoc);
-
- var docs = makeDocs(0, 10);
- db.bulkSave(docs);
-
- var docs2 = [
- {"a": 1, "b": 1, "string": "doc 1", "type": "complex"},
- {"a": 1, "b": 2, "string": "doc 2", "type": "complex"},
- {"a": "test", "b": {}, "string": "doc 3", "type": "complex"},
- {"a": "test", "b": ["test", "essai"], "string": "doc 4", "type": "complex"},
- {"a": {"c": 1}, "b": "", "string": "doc 5", "type": "complex"}
- ];
-
- db.bulkSave(docs2);
-
- // test simple rewriting
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo");
- T(req.responseText == "This is a base64 encoded text");
- T(req.getResponseHeader("Content-Type") == "text/plain");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo2");
- T(req.responseText == "This is a base64 encoded text");
- T(req.getResponseHeader("Content-Type") == "text/plain");
-
-
- // test POST
- // hello update world
-
- var doc = {"word":"plankton", "name":"Rusty"}
- var resp = db.save(doc);
- T(resp.ok);
- var docid = resp.id;
-
- xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/hello/"+docid);
- T(xhr.status == 201);
- T(xhr.responseText == "hello doc");
- T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")))
-
- doc = db.open(docid);
- T(doc.world == "hello");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome?name=user");
- T(req.responseText == "Welcome user");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome/user");
- T(req.responseText == "Welcome user");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome2");
- T(req.responseText == "Welcome user");
-
- xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
- T(xhr.status == 201);
- T(xhr.responseText == "New World");
- T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
- T(xhr.responseText == "Welcome test");
-
-/* // XXX: THESE ARE BUGGED and I don't know what the right response is
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome4/user");
- T(req.responseText == "Welcome user", req.responseText);
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome5/welcome3");
- T(req.responseText == "Welcome welcome3", req.responseText);
-*/
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/basicView");
- T(xhr.status == 200, "view call");
- T(/{"total_rows":9/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/");
- T(xhr.status == 200, "view call");
- T(/{"total_rows":9/.test(xhr.responseText));
-
-
- // get with query params
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicView?startkey=3&endkey=8");
- T(xhr.status == 200, "with query params");
- T(!(/Key: 1/.test(xhr.responseText)));
- T(/FirstKey: 3/.test(xhr.responseText));
- T(/LastKey: 8/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewFixed");
- T(xhr.status == 200, "with query params");
- T(!(/Key: 1/.test(xhr.responseText)));
- T(/FirstKey: 3/.test(xhr.responseText));
- T(/LastKey: 8/.test(xhr.responseText));
-
- // get with query params
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewFixed?startkey=4");
- T(xhr.status == 200, "with query params");
- T(!(/Key: 1/.test(xhr.responseText)));
- T(/FirstKey: 3/.test(xhr.responseText));
- T(/LastKey: 8/.test(xhr.responseText));
-
- // get with query params
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewPath/3/8");
- T(xhr.status == 200, "with query params");
- T(!(/Key: 1/.test(xhr.responseText)));
- T(/FirstKey: 3/.test(xhr.responseText));
- T(/LastKey: 8/.test(xhr.responseText));
-
- // get with query params
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView");
- T(xhr.status == 200, "with query params");
- T(/FirstKey: [1, 2]/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView2");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 3/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView3");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 4/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView4");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 5/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView5/test/essai");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 4/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView6?a=test&b=essai");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 4/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView7/test/essai?doc=true");
- T(xhr.status == 200, "with query params");
- var result = JSON.parse(xhr.responseText);
- T(typeof(result.rows[0].doc) === "object");
-
- // COUCHDB-2031 - path normalization versus qs params
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/db/_design/test?meta=true");
- T(xhr.status == 200, "path normalization works with qs params");
- var result = JSON.parse(xhr.responseText);
- T(result['_id'] == "_design/test");
- T(typeof(result['_revs_info']) === "object");
-
- // test path relative to server
- T(db.save({
- _id: "_design/test2",
- rewrites: [{
- "from": "uuids",
- "to": "../../../_uuids"
- }]
- }).ok);
-
- var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test2/_rewrite/uuids");
- T(xhr.status == 500);
- var result = JSON.parse(xhr.responseText);
- T(result.error == "insecure_rewrite_rule");
-
- run_on_modified_server(
- [{section: "chttpd",
- key: "secure_rewrites",
- value: "false"}],
- function() {
- var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test2/_rewrite/uuids?cache=bust");
- T(xhr.status == 200);
- var result = JSON.parse(xhr.responseText);
- T(result.uuids.length == 1);
- var first = result.uuids[0];
- });
- });
-
-/* // XXX: we have actual failures here that we need to get to
- // test invalid rewrites
- // string
- var ddoc = {
- _id: "_design/invalid",
- rewrites: "[{\"from\":\"foo\",\"to\":\"bar\"}]"
- }
- db.save(ddoc);
- var res = CouchDB.request("GET", "/"+dbName+"/_design/invalid/_rewrite/foo");
- TEquals(400, res.status, "should return 400");
-
- var ddoc_requested_path = {
- _id: "_design/requested_path",
- rewrites:[
- {"from": "show", "to": "_show/origin/0"},
- {"from": "show_rewritten", "to": "_rewrite/show"}
- ],
- shows: {
- origin: stringFun(function(doc, req) {
- return req.headers["x-couchdb-requested-path"];
- })}
- };
-
- db.save(ddoc_requested_path);
- var url = "/"+dbName+"/_design/requested_path/_rewrite/show";
- var res = CouchDB.request("GET", url);
- TEquals(url, res.responseText, "should return the original url");
-
- var url = "/"+dbName+"/_design/requested_path/_rewrite/show_rewritten";
- var res = CouchDB.request("GET", url);
- TEquals(url, res.responseText, "returned the original url");
-*/
-
- var ddoc_loop = {
- _id: "_design/loop",
- rewrites: [{ "from": "loop", "to": "_rewrite/loop"}]
- };
- db.save(ddoc_loop);
-
- // Assert loop detection
- run_on_modified_server(
- [{section: "chttpd",
- key: "rewrite_limit",
- value: "2"}],
- function(){
- var url = "/"+dbName+"/_design/loop/_rewrite/loop";
- var xhr = CouchDB.request("GET", url);
- TEquals(400, xhr.status);
- });
-
- // Assert serial execution is not spuriously counted as loop
- run_on_modified_server(
- [{section: "chttpd",
- key: "rewrite_limit",
- value: "2"},
- {section: "chttpd",
- key: "secure_rewrites",
- value: "false"}],
- function(){
- var url = "/"+dbName+"/_design/test/_rewrite/foo";
- for (var i=0; i < 5; i++) {
- var xhr = CouchDB.request("GET", url);
- TEquals(200, xhr.status);
- }
- });
- // cleanup
- db.deleteDb();
- }
-}
diff --git a/test/javascript/tests/rewrite_js.js b/test/javascript/tests/rewrite_js.js
deleted file mode 100644
index 7179fc9f5..000000000
--- a/test/javascript/tests/rewrite_js.js
+++ /dev/null
@@ -1,366 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-
-
-couchTests.elixir = true;
-couchTests.rewrite = function(debug) {
- if (debug) debugger;
- var dbNames = [get_random_db_name(), get_random_db_name() + "test_suite_db/with_slashes"];
- for (var i=0; i < dbNames.length; i++) {
- var db = new CouchDB(dbNames[i]);
- var dbName = encodeURIComponent(dbNames[i]);
- db.deleteDb();
- db.createDb();
-
- var designDoc = {
- _id:"_design/test",
- language: "javascript",
- _attachments:{
- "foo.txt": {
- content_type:"text/plain",
- data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
- }
- },
- rewrites: stringFun(function(req) {
- prefix = req.path[4];
- if (prefix === 'foo') {
- return 'foo.txt';
- }
- if (prefix === 'foo2') {
- return {path: 'foo.txt', method: 'GET'};
- }
- if (prefix === 'hello') {
- if (req.method != 'PUT') {
- return
- }
- id = req.path[5];
- return {path: '_update/hello/' + id};
- }
- if (prefix === 'welcome') {
- if (req.path.length == 6){
- name = req.path[5];
- return {path: '_show/welcome', query: {'name': name}};
- }
- return '_show/welcome';
- }
- if (prefix === 'welcome2') {
- return {path: '_show/welcome', query: {'name': 'user'}};
- }
- if (prefix === 'welcome3') {
- name = req.path[5];
- if (req.method == 'PUT') {
- path = '_update/welcome2/' + name;
- } else if (req.method == 'GET') {
- path = '_show/welcome2/' + name;
- } else {
- return;
- }
- return path;
- }
- if (prefix === 'welcome4') {
- return {path: '_show/welcome3', query: {name: req.path[5]}};
- }
- if (prefix === 'welcome5') {
- rest = req.path.slice(5).join('/');
- return {path: '_show/' + rest, query: {name: rest}};
- }
- if (prefix === 'basicView') {
- rest = req.path.slice(5).join('/');
- return {path: '_view/basicView'};
- }
- if (req.path.slice(4).join('/') === 'simpleForm/basicView') {
- return {path: '_list/simpleForm/basicView'};
- }
- if (req.path.slice(4).join('/') === 'simpleForm/basicViewFixed') {
- return {path: '_list/simpleForm/basicView',
- query: {startkey: '"3"', endkey: '"8"'}};
- }
- if (req.path.slice(4).join('/') === 'simpleForm/complexView') {
- return {path: '_list/simpleForm/complexView',
- query: {key: JSON.stringify([1,2])}};
- }
- if (req.path.slice(4).join('/') === 'simpleForm/complexView2') {
- return {path: '_list/simpleForm/complexView',
- query: {key: JSON.stringify(['test', {}])}};
- }
- if (req.path.slice(4).join('/') === 'simpleForm/complexView3') {
- return {path: '_list/simpleForm/complexView',
- query: {key: JSON.stringify(['test', ['test', 'essai']])}};
- }
- if (req.path.slice(4).join('/') === 'simpleForm/complexView4') {
- return {path: '_list/simpleForm/complexView2',
- query: {key: JSON.stringify({"c": 1})}};
- }
- if (req.path.slice(4).join('/') === 'simpleForm/sendBody1') {
- return {path: '_list/simpleForm/complexView2',
- method: 'POST',
- query: {limit: '1'},
- headers:{'Content-type':'application/json'},
- body: JSON.stringify( {keys: [{"c": 1}]} )};
- }
- if (req.path.slice(4).join('/') === '/') {
- return {path: '_view/basicView'};
- }
- if (prefix === 'db') {
- return {path: '../../' + req.path.slice(5).join('/')};
- }
- }),
- lists: {
- simpleForm: stringFun(function(head, req) {
- send('<ul>');
- var row, row_number = 0, prevKey, firstKey = null;
- while (row = getRow()) {
- row_number += 1;
- if (!firstKey) firstKey = row.key;
- prevKey = row.key;
- send('\n<li>Key: '+row.key
- +' Value: '+row.value
- +' LineNo: '+row_number+'</li>');
- }
- return '</ul><p>FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'</p>';
- }),
- },
- shows: {
- "welcome": stringFun(function(doc,req) {
- return "Welcome " + req.query["name"];
- }),
- "welcome2": stringFun(function(doc, req) {
- return "Welcome " + doc.name;
- }),
- "welcome3": stringFun(function(doc,req) {
- return "Welcome " + req.query["name"];
- })
- },
- updates: {
- "hello" : stringFun(function(doc, req) {
- if (!doc) {
- if (req.id) {
- return [{
- _id : req.id
- }, "New World"]
- }
- return [null, "Empty World"];
- }
- doc.world = "hello";
- doc.edited_by = req.userCtx;
- return [doc, "hello doc"];
- }),
- "welcome2": stringFun(function(doc, req) {
- if (!doc) {
- if (req.id) {
- return [{
- _id: req.id,
- name: req.id
- }, "New World"]
- }
- return [null, "Empty World"];
- }
- return [doc, "hello doc"];
- })
- },
- views : {
- basicView : {
- map : stringFun(function(doc) {
- if (doc.integer) {
- emit(doc.integer, doc.string);
- }
-
- })
- },
- complexView: {
- map: stringFun(function(doc) {
- if (doc.type == "complex") {
- emit([doc.a, doc.b], doc.string);
- }
- })
- },
- complexView2: {
- map: stringFun(function(doc) {
- if (doc.type == "complex") {
- emit(doc.a, doc.string);
- }
- })
- },
- complexView3: {
- map: stringFun(function(doc) {
- if (doc.type == "complex") {
- emit(doc.b, doc.string);
- }
- })
- }
- }
- }
-
- db.save(designDoc);
-
- var docs = makeDocs(0, 10);
- db.bulkSave(docs);
-
- var docs2 = [
- {"a": 1, "b": 1, "string": "doc 1", "type": "complex"},
- {"a": 1, "b": 2, "string": "doc 2", "type": "complex"},
- {"a": "test", "b": {}, "string": "doc 3", "type": "complex"},
- {"a": "test", "b": ["test", "essai"], "string": "doc 4", "type": "complex"},
- {"a": {"c": 1}, "b": "", "string": "doc 5", "type": "complex"}
- ];
-
- db.bulkSave(docs2);
-
- // test simple rewriting
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo");
- T(req.responseText == "This is a base64 encoded text");
- T(req.getResponseHeader("Content-Type") == "text/plain");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo2");
- T(req.responseText == "This is a base64 encoded text");
- T(req.getResponseHeader("Content-Type") == "text/plain");
-
-
- // test POST
- // hello update world
-
- var doc = {"word":"plankton", "name":"Rusty"}
- var resp = db.save(doc);
- T(resp.ok);
- var docid = resp.id;
-
- xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/hello/"+docid);
- T(xhr.status == 201);
- T(xhr.responseText == "hello doc");
- T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")))
-
- doc = db.open(docid);
- T(doc.world == "hello");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome?name=user");
- T(req.responseText == "Welcome user");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome/user");
- T(req.responseText == "Welcome user");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome2");
- T(req.responseText == "Welcome user");
-
- xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
- T(xhr.status == 201);
- T(xhr.responseText == "New World");
- T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
- T(xhr.responseText == "Welcome test");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome4/user");
- T(req.responseText == "Welcome user");
-
- req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome5/welcome3");
- T(req.responseText == "Welcome welcome3");
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/basicView");
- T(xhr.status == 200, "view call");
- T(/{"total_rows":9/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView");
- T(xhr.status == 200, "with query params");
- T(/FirstKey: [1, 2]/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView2");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 3/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView3");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 4/.test(xhr.responseText));
-
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView4");
- T(xhr.status == 200, "with query params");
- T(/Value: doc 5/.test(xhr.responseText));
-
- // COUCHDB-1612 - send body rewriting get to post
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/sendBody1");
- T(xhr.status == 200, "get->post rewrite failed:\n"+xhr.responseText);
- T(/Value: doc 5 LineNo: 1/.test(xhr.responseText), "get->post rewrite responded wrong:\n"+xhr.responseText);
-
- // COUCHDB-2031 - path normalization versus qs params
- xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/db/_design/test?meta=true");
- T(xhr.status == 200, "path normalization works with qs params");
- var result = JSON.parse(xhr.responseText);
- T(result['_id'] == "_design/test");
- T(typeof(result['_revs_info']) === "object");
-
- // test early response
- var ddoc = {
- _id: "_design/response",
- rewrites: stringFun(function(req){
- status = parseInt(req.query.status);
- return {code: status,
- body: JSON.stringify({"status": status}),
- headers: {'x-foo': 'bar', 'Content-Type': 'application/json'}};
- })
- }
- T(db.save(ddoc).ok);
- var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=200");
- T(xhr.status == 200);
- T(xhr.headers['x-foo'] == 'bar');
- T(xhr.responseText == '{"status":200}');
- var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=451");
- T(xhr.status == 451);
- T(xhr.headers['Content-Type'] == 'application/json');
- var xhr = CouchDB.request("GET", "/"+dbName+"/_design/response/_rewrite?status=600");
- T(xhr.status == 500);
-
-
- // test path relative to server
- var ddoc = {
- _id: "_design/relative",
- rewrites: stringFun(function(req){
- return '../../../_uuids'
- })
- }
- T(db.save(ddoc).ok);
- var xhr = CouchDB.request("GET", "/"+dbName+"/_design/relative/_rewrite/uuids");
- T(xhr.status == 200);
- var result = JSON.parse(xhr.responseText);
- T(result.uuids.length == 1);
-
- // test loop
- var ddoc_loop = {
- _id: "_design/loop",
- rewrites: stringFun(function(req) {
- return '_rewrite/loop';
- })
- };
- db.save(ddoc_loop);
- var url = "/"+dbName+"/_design/loop/_rewrite/loop";
- var xhr = CouchDB.request("GET", url);
- TEquals(400, xhr.status);
-
- // test requests with body preserve the query string rewrite
- var ddoc_qs = {
- "_id": "_design/qs",
- "rewrites": "function (r) { return {path: '../../_changes', query: {'filter': '_doc_ids'}};};"
- }
- db.save(ddoc_qs);
- db.save({"_id": "qs1", "foo": "bar"});
- db.save({"_id": "qs2", "foo": "bar"});
-
- var url = "/"+dbName+"/_design/qs/_rewrite";
-
- var xhr = CouchDB.request("POST", url, {body: JSON.stringify({"doc_ids": ["qs2"]})});
- var result = JSON.parse(xhr.responseText);
- T(xhr.status == 200);
- T(result.results.length == 1, "Only one doc is expected");
- TEquals(result.results[0].id, "qs2");
- // cleanup
- db.deleteDb();
- }
-}
\ No newline at end of file
diff --git a/test/javascript/tests/security_validation.js b/test/javascript/tests/security_validation.js
deleted file mode 100644
index 365f716e6..000000000
--- a/test/javascript/tests/security_validation.js
+++ /dev/null
@@ -1,330 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-couchTests.elixir = true;
-couchTests.security_validation = function(debug) {
-
- var db_name = get_random_db_name();
- var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
- db.createDb();
- var authDb_name = get_random_db_name() + "_authdb";
- var authDb = new CouchDB(authDb_name, {"X-Couch-Full-Commit":"false"});
- authDb.createDb();
- var adminDbA, adminDbB; // used later
- if (debug) debugger;
-
- run_on_modified_server(
- [{section: "httpd",
- key: "authentication_handlers",
- value: "{couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}"},
- {section: "couch_httpd_auth",
- key: "authentication_db", value: authDb_name},
- {section: "chttpd_auth",
- key: "authentication_db", value: authDb_name}],
-
- function () {
- // the special case handler does not exist (any longer) in clusters, so we have
- // to replicate the behavior using a "normal" DB even though tests might no more
- // run universally (why the "X-Couch-Test-Auth" header was introduced).
- // btw: this needs to be INSIDE configured server to propagate correctly ;-)
- // At least they'd run in the build, though
- T(authDb.save(CouchDB.prepareUserDoc({name: "tom"}, "cat")).ok); // Basic dG9tOmNhdA==
- T(authDb.save(CouchDB.prepareUserDoc({name: "jerry"}, "mouse")).ok); // Basic amVycnk6bW91c2U=
- T(authDb.save(CouchDB.prepareUserDoc({name: "spike"}, "dog")).ok); // Basic c3Bpa2U6ZG9n
- authDb.ensureFullCommit();
-
- // try saving document using the wrong credentials
- var wrongPasswordDb = new CouchDB(db_name + "",
- {"Authorization": "Basic c3Bpa2U6Y2F0"} // spike:cat - which is wrong
- );
-
- try {
- wrongPasswordDb.save({foo:1,author:"Damien Katz"});
- T(false, "Can't get here. Should have thrown an error 1");
- } catch (e) {
- T(e.error == "unauthorized");
- T(wrongPasswordDb.last_req.status == 401);
- }
-
- // test force basic login
- var resp = wrongPasswordDb.request("GET", "/_session?basic=true");
- var err = JSON.parse(resp.responseText);
- T(err.error == "unauthorized");
- T(resp.status == 401);
-
- // Create the design doc that will run custom validation code
- var designDoc = {
- _id:"_design/test",
- language: "javascript",
- validate_doc_update: stringFun(function (newDoc, oldDoc, userCtx, secObj) {
- if (secObj.admin_override) {
- if (userCtx.roles.indexOf('_admin') != -1) {
- // user is admin, they can do anything
- return true;
- }
- }
- // docs should have an author field.
- if (!newDoc._deleted && !newDoc.author) {
- throw {forbidden:
- "Documents must have an author field"};
- }
- if (oldDoc && oldDoc.author != userCtx.name) {
- throw {unauthorized:
- "You are '" + userCtx.name + "', not the author '" + oldDoc.author + "' of this document. You jerk."};
- }
- })
- }
-
- // Save a document normally
- var userDb = new CouchDB("" + db_name + "",
- {"Authorization": "Basic amVycnk6bW91c2U="} // jerry
- );
- // test session
- TEquals("jerry", JSON.parse(userDb.request("GET", "/_session").responseText).userCtx.name);
-
- T(userDb.save({_id:"testdoc", foo:1, author:"jerry"}).ok);
-
- // Attempt to save the design as a non-admin
- try {
- userDb.save(designDoc);
- T(false && "Can't get here. Should have thrown an error on design doc");
- } catch (e) {
- // cluster changes from 401 unauthorized to 403 forbidden
- TEquals("forbidden", e.error);
- TEquals(403, userDb.last_req.status);
- }
-
- // set user as the admin
- T(db.setSecObj({
- admins : {names : ["jerry"]}
- }).ok);
-
- // TODO: when _security is correctly honored (COUCHDB-2990), switch back
- //T(userDb.save(designDoc).ok);
- T(db.save(designDoc).ok);
-
- var user2Db = new CouchDB("" + db_name + "",
- {"Authorization": "Basic dG9tOmNhdA=="} // tom
- );
- // Attempt to save the design as a non-admin (in replication scenario)
- designDoc.foo = "bar";
- designDoc._rev = "2-642e20f96624a0aae6025b4dba0c6fb2";
- try {
- user2Db.save(designDoc, {new_edits : false});
- T(false && "Can't get here. Should have thrown an error on design doc");
- } catch (e) {
- // cluster changes from 401 unauthorized to 403 forbidden
- TEquals("forbidden", e.error);
- TEquals(403, userDb.last_req.status);
- }
-
- // test the _session API
- var resp = userDb.request("GET", "/_session");
- var user = JSON.parse(resp.responseText).userCtx;
- T(user.name == "jerry");
- // test that the roles are listed properly
- TEquals(user.roles, []);
-
-
- // update the document
- var doc = userDb.open("testdoc");
- doc.foo=2;
- T(userDb.save(doc).ok);
-
- // Save a document that's missing an author field (before and after compaction)
- for (var i=0; i<2; i++) {
- try {
- userDb.save({foo:1});
- T(false && "Can't get here. Should have thrown an error 2");
- } catch (e) {
- T(e.error == "forbidden");
- T(userDb.last_req.status == 403);
- }
- // compact. - no more available on clusters (but: test is still valid w/out compaction)
- /*T(db.compact().ok);
- T(db.last_req.status == 202);
- // compaction isn't instantaneous, loop until done
- while (db.info().compact_running) {};*/
- }
-
- // Now attempt to update the document as a different user, Jan
- var doc = user2Db.open("testdoc");
- doc.foo=3;
- try {
- user2Db.save(doc);
- T(false && "Can't get here. Should have thrown an error 3");
- } catch (e) {
- T(e.error == "unauthorized");
- T(user2Db.last_req.status == 401);
- }
-
- // Now have jerry change the author to tom
- doc = userDb.open("testdoc");
- doc.author="tom";
- T(userDb.save(doc).ok);
-
- // Now update the document as tom
- doc = user2Db.open("testdoc");
- doc.foo = 3;
- T(user2Db.save(doc).ok);
-
- // jerry can't delete it
- try {
- userDb.deleteDoc(doc);
- T(false && "Can't get here. Should have thrown an error 4");
- } catch (e) {
- T(e.error == "unauthorized");
- T(userDb.last_req.status == 401);
- }
-
- // admin must save with author field unless admin override
- var resp = db.request("GET", "/_session");
- var user = JSON.parse(resp.responseText).userCtx;
- T(user.name == null);
- // test that we are admin
- TEquals(user.roles, ["_admin"]);
-
- // can't save the doc even though we are admin
- var doc = db.open("testdoc");
- doc.foo=3;
- try {
- db.save(doc);
- T(false && "Can't get here. Should have thrown an error 3");
- } catch (e) {
- T(e.error == "unauthorized");
- T(db.last_req.status == 401);
- }
-
- // now turn on admin override
- T(db.setDbProperty("_security", {admin_override : true}).ok);
- // TODO: re-include after COUCHDB-2990
- //T(db.save(doc).ok);
-
- // try to do something lame
- try {
- db.setDbProperty("_security", ["foo"]);
- T(false && "can't do this");
- } catch(e) {}
-
- // go back to normal
- T(db.setDbProperty("_security", {admin_override : false}).ok);
-
- // Now delete document
- T(user2Db.deleteDoc(doc).ok);
-
- // now test bulk docs
- var docs = [{_id:"bahbah",author:"jerry",foo:"bar"},{_id:"fahfah",foo:"baz"}];
-
- // Create the docs
- var results = db.bulkSave(docs);
-
- T(results[0].rev)
- T(results[0].error == undefined)
- T(results[1].rev === undefined)
- T(results[1].error == "forbidden")
-
- T(db.open("bahbah"));
- T(db.open("fahfah") == null);
-
-
- // now all or nothing with a failure - no more available on cluster
-/* var docs = [{_id:"booboo",author:"Damien Katz",foo:"bar"},{_id:"foofoo",foo:"baz"}];
-
- // Create the docs
- var results = db.bulkSave(docs, {all_or_nothing:true});
-
- T(results.errors.length == 1);
- T(results.errors[0].error == "forbidden");
- T(db.open("booboo") == null);
- T(db.open("foofoo") == null);
-*/
-
- // Now test replication
- var AuthHeaders = {"Authorization": "Basic c3Bpa2U6ZG9n"}; // spike
- adminDbA = new CouchDB("" + db_name + "_a", {"X-Couch-Full-Commit":"false"});
- adminDbB = new CouchDB("" + db_name + "_b", {"X-Couch-Full-Commit":"false"});
- var dbA = new CouchDB("" + db_name + "_a", AuthHeaders);
- var dbB = new CouchDB("" + db_name + "_b", AuthHeaders);
- // looping does not really add value as the scenario is the same anyway (there's nothing 2 be gained from it)
- var A = CouchDB.protocol + CouchDB.host + "/" + db_name + "_a";
- var B = CouchDB.protocol + CouchDB.host + "/" + db_name + "_b";
-
- // (the databases never exist b4 - and we made sure they're deleted below)
- //adminDbA.deleteDb();
- adminDbA.createDb();
- //adminDbB.deleteDb();
- adminDbB.createDb();
-
- // save and replicate a documents that will and will not pass our design
- // doc validation function.
- T(dbA.save({_id:"foo1",value:"a",author:"tom"}).ok);
- T(dbA.save({_id:"foo2",value:"a",author:"spike"}).ok);
- T(dbA.save({_id:"bad1",value:"a"}).ok);
-
- T(CouchDB.replicate(A, B, {headers:AuthHeaders}).ok);
- T(CouchDB.replicate(B, A, {headers:AuthHeaders}).ok);
-
- T(dbA.open("foo1"));
- T(dbB.open("foo1"));
- T(dbA.open("foo2"));
- T(dbB.open("foo2"));
-
- // save the design doc to dbA
- delete designDoc._rev; // clear rev from previous saves
- T(adminDbA.save(designDoc).ok);
-
- // no affect on already saved docs
- T(dbA.open("bad1"));
-
- // Update some docs on dbB. Since the design hasn't replicated, anything
- // is allowed.
-
- // this edit will fail validation on replication to dbA (no author)
- T(dbB.save({_id:"bad2",value:"a"}).ok);
-
- // this edit will fail security on replication to dbA (wrong author
- // replicating the change)
- var foo1 = dbB.open("foo1");
- foo1.value = "b";
- T(dbB.save(foo1).ok);
-
- // this is a legal edit
- var foo2 = dbB.open("foo2");
- foo2.value = "b";
- T(dbB.save(foo2).ok);
-
- var results = CouchDB.replicate({"url": B, "headers": AuthHeaders}, {"url": A, "headers": AuthHeaders}, {headers:AuthHeaders});
- T(results.ok);
- TEquals(1, results.history[0].docs_written);
- TEquals(2, results.history[0].doc_write_failures);
-
- // bad2 should not be on dbA
- T(dbA.open("bad2") == null);
-
- // The edit to foo1 should not have replicated.
- T(dbA.open("foo1").value == "a");
-
- // The edit to foo2 should have replicated.
- T(dbA.open("foo2").value == "b");
- });
-
- // cleanup
- db.deleteDb();
- if(adminDbA){
- adminDbA.deleteDb();
- }
- if(adminDbB){
- adminDbB.deleteDb();
- }
- authDb.deleteDb();
- // don't have to clean the backend authDb since this test only calls
- // couch_auth_cache:get_admin/1 which doesn't auto-create the users db
-};
diff --git a/test/javascript/tests/show_documents.js b/test/javascript/tests/show_documents.js
deleted file mode 100644
index e604f3058..000000000
--- a/test/javascript/tests/show_documents.js
+++ /dev/null
@@ -1,376 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-couchTests.elixir = true
-couchTests.show_documents = function(debug) {
-
- var db_name = get_random_db_name();
- var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
- db.createDb();
- if (debug) debugger;
-
- var designDoc = {
- _id:"_design/template",
- language: "javascript",
- shows: {
- "hello" : stringFun(function(doc, req) {
- log("hello fun");
- if (doc) {
- return "Hello World";
- } else {
- if(req.id) {
- return "New World";
- } else {
- return "Empty World";
- }
- }
- }),
- "just-name" : stringFun(function(doc, req) {
- if (doc) {
- return {
- body : "Just " + doc.name
- };
- } else {
- return {
- body : "No such doc",
- code : 404
- };
- }
- }),
- "json" : stringFun(function(doc, req) {
- return {
- json : doc
- }
- }),
- "req-info" : stringFun(function(doc, req) {
- return {
- json : req
- }
- }),
- "show-deleted" : stringFun(function(doc, req) {
- if(doc) {
- return doc._id;
- } else {
- return "No doc " + req.id;
- }
- }),
- "render-error" : stringFun(function(doc, req) {
- return noSuchVariable;
- }),
- "empty" : stringFun(function(doc, req) {
- return "";
- }),
- "fail" : stringFun(function(doc, req) {
- return doc._id;
- }),
- "no-set-etag" : stringFun(function(doc, req) {
- return {
- headers : {
- "Etag" : "skipped"
- },
- "body" : "something"
- }
- }),
- "list-api" : stringFun(function(doc, req) {
- start({"X-Couch-Test-Header": "Yeah"});
- send("Hey");
- }),
- "list-api-provides" : stringFun(function(doc, req) {
- provides("text", function(){
- send("foo, ");
- send("bar, ");
- send("baz!");
- })
- }),
- "list-api-provides-and-return" : stringFun(function(doc, req) {
- provides("text", function(){
- send("4, ");
- send("5, ");
- send("6, ");
- return "7!";
- })
- send("1, ");
- send("2, ");
- return "3, ";
- }),
- "list-api-mix" : stringFun(function(doc, req) {
- start({"X-Couch-Test-Header": "Yeah"});
- send("Hey ");
- return "Dude";
- }),
- "list-api-mix-with-header" : stringFun(function(doc, req) {
- start({"X-Couch-Test-Header": "Yeah"});
- send("Hey ");
- return {
- headers: {
- "X-Couch-Test-Header-Awesome": "Oh Yeah!"
- },
- body: "Dude"
- };
- }),
- "accept-switch" : stringFun(function(doc, req) {
- if (req.headers["Accept"].match(/image/)) {
- return {
- // a 16x16 px version of the CouchDB logo
- "base64" :
-["iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAsV",
-"BMVEUAAAD////////////////////////5ur3rEBn////////////////wDBL/",
-"AADuBAe9EB3IEBz/7+//X1/qBQn2AgP/f3/ilpzsDxfpChDtDhXeCA76AQH/v7",
-"/84eLyWV/uc3bJPEf/Dw/uw8bRWmP1h4zxSlD6YGHuQ0f6g4XyQkXvCA36MDH6",
-"wMH/z8/yAwX64ODeh47BHiv/Ly/20dLQLTj98PDXWmP/Pz//39/wGyJ7Iy9JAA",
-"AADHRSTlMAbw8vf08/bz+Pv19jK/W3AAAAg0lEQVR4Xp3LRQ4DQRBD0QqTm4Y5",
-"zMxw/4OleiJlHeUtv2X6RbNO1Uqj9g0RMCuQO0vBIg4vMFeOpCWIWmDOw82fZx",
-"vaND1c8OG4vrdOqD8YwgpDYDxRgkSm5rwu0nQVBJuMg++pLXZyr5jnc1BaH4GT",
-"LvEliY253nA3pVhQqdPt0f/erJkMGMB8xucAAAAASUVORK5CYII="].join(''),
- headers : {
- "Content-Type" : "image/png",
- "Vary" : "Accept" // we set this for proxy caches
- }
- };
- } else {
- return {
- "body" : "accepting text requests",
- headers : {
- "Content-Type" : "text/html",
- "Vary" : "Accept"
- }
- };
- }
- }),
- "provides" : stringFun(function(doc, req) {
- registerType("foo", "application/foo","application/x-foo");
-
- provides("html", function() {
- return "Ha ha, you said \"" + doc.word + "\".";
- });
-
- provides("foo", function() {
- return "foofoo";
- });
- }),
- "withSlash": stringFun(function(doc, req) {
- return { json: doc }
- }),
- "secObj": stringFun(function(doc, req) {
- return { json: req.secObj };
- })
- }
- };
- T(db.save(designDoc).ok);
-
- var doc = {"word":"plankton", "name":"Rusty"}
- var resp = db.save(doc);
- T(resp.ok);
- var docid = resp.id;
-
- // show error
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/");
- T(xhr.status == 404, 'Should be missing');
- T(JSON.parse(xhr.responseText).reason == "Invalid path.");
-
- // hello template world
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/hello/"+docid);
- T(xhr.responseText == "Hello World", "hello");
- T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")));
-
-
- // Fix for COUCHDB-379
- T(equals(xhr.getResponseHeader("Server").substr(0,7), "CouchDB"));
-
- // // error stacktraces
- // xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/render-error/"+docid);
- // T(JSON.parse(xhr.responseText).error == "render_error");
-
- // hello template world (no docid)
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/hello");
- T(xhr.responseText == "Empty World");
-
- // hello template world (no docid)
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/empty");
- T(xhr.responseText == "");
-
- // // hello template world (non-existing docid)
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/fail/nonExistingDoc");
- T(xhr.status == 404);
- var resp = JSON.parse(xhr.responseText);
- T(resp.error == "not_found");
-
- // show with doc
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/just-name/"+docid);
- T(xhr.responseText == "Just Rusty");
-
- // show with missing doc
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/just-name/missingdoc");
- T(xhr.status == 404);
- TEquals("No such doc", xhr.responseText);
-
- // show with missing func
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/missing/"+docid);
- T(xhr.status == 404, "function is missing");
-
- // missing design doc
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/missingddoc/_show/just-name/"+docid);
- T(xhr.status == 404);
- var resp = JSON.parse(xhr.responseText);
- T(resp.error == "not_found");
-
- // query parameters
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/req-info/"+docid+"?foo=bar", {
- headers: {
- "Accept": "text/html;text/plain;*/*",
- "X-Foo" : "bar"
- }
- });
- var resp = JSON.parse(xhr.responseText);
- T(equals(resp.headers["X-Foo"], "bar"));
- T(equals(resp.query, {foo:"bar"}));
- T(equals(resp.method, "GET"));
- T(equals(resp.path[5], docid));
- T(equals(resp.info.db_name, "" + db_name + ""));
-
- // accept header switching
- // different mime has different etag
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/accept-switch/"+docid, {
- headers: {"Accept": "text/html;text/plain;*/*"}
- });
- var ct = xhr.getResponseHeader("Content-Type");
- T(/text\/html/.test(ct))
- T("Accept" == xhr.getResponseHeader("Vary"));
- var etag = xhr.getResponseHeader("etag");
-
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/accept-switch/"+docid, {
- headers: {"Accept": "image/png;*/*"}
- });
- T(xhr.responseText.match(/PNG/))
- T("image/png" == xhr.getResponseHeader("Content-Type"));
- var etag2 = xhr.getResponseHeader("etag");
- T(etag2 != etag);
-
- // proper etags
- // show with doc
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/just-name/"+docid);
- // extract the ETag header values
- etag = xhr.getResponseHeader("etag");
- // get again with etag in request
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/just-name/"+docid, {
- headers: {"if-none-match": etag}
- });
- // should be 304
- T(xhr.status == 304);
-
- // update the doc
- doc.name = "Crusty";
- resp = db.save(doc);
- T(resp.ok);
- // req with same etag
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/just-name/"+docid, {
- headers: {"if-none-match": etag}
- });
- // status is 200
- T(xhr.status == 200);
-
- // JS can't set etag
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/no-set-etag/"+docid);
- // extract the ETag header values
- etag = xhr.getResponseHeader("etag");
- T(etag != "skipped")
-
- // test the provides mime matcher
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/provides/"+docid, {
- headers: {
- "Accept": 'text/html,application/atom+xml; q=0.9'
- }
- });
- var ct = xhr.getResponseHeader("Content-Type");
- T(/charset=utf-8/.test(ct))
- T(/text\/html/.test(ct))
- T(xhr.responseText == "Ha ha, you said \"plankton\".");
-
- // registering types works
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/provides/"+docid, {
- headers: {
- "Accept": "application/x-foo"
- }
- });
- T(xhr.getResponseHeader("Content-Type") == "application/x-foo");
- T(xhr.responseText.match(/foofoo/));
-
- // test the provides mime matcher without a match
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/provides/"+docid, {
- headers: {
- "Accept": 'text/monkeys'
- }
- });
- var rs = JSON.parse(xhr.responseText);
- T(rs.error == "not_acceptable")
-
-
- // test inclusion of conflict state
- var doc1 = {_id:"foo", a:1};
- var doc2 = {_id:"foo", a:2};
- db.save(doc1);
-
- var doc3 = {_id:"a/b/c", a:1};
- db.save(doc3);
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/withSlash/a/b/c");
- T(xhr.status == 200);
-
- // hello template world (non-existing docid)
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/hello/nonExistingDoc");
- T(xhr.responseText == "New World");
-
- // test list() compatible API
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/list-api/foo");
- T(xhr.responseText == "Hey");
- TEquals("Yeah", xhr.getResponseHeader("X-Couch-Test-Header"), "header should be cool");
-
- // test list() compatible API with provides function
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/list-api-provides/foo?format=text");
- TEquals(xhr.responseText, "foo, bar, baz!", "should join chunks to response body");
-
- // should keep next result order: chunks + return value + provided chunks + provided return value
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/list-api-provides-and-return/foo?format=text");
- TEquals(xhr.responseText, "1, 2, 3, 4, 5, 6, 7!", "should not break 1..7 range");
-
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/list-api-mix/foo");
- T(xhr.responseText == "Hey Dude");
- TEquals("Yeah", xhr.getResponseHeader("X-Couch-Test-Header"), "header should be cool");
-
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/list-api-mix-with-header/foo");
- T(xhr.responseText == "Hey Dude");
- TEquals("Yeah", xhr.getResponseHeader("X-Couch-Test-Header"), "header should be cool");
- TEquals("Oh Yeah!", xhr.getResponseHeader("X-Couch-Test-Header-Awesome"), "header should be cool");
-
- // test deleted docs
- var doc = {_id:"testdoc",foo:1};
- db.save(doc);
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/show-deleted/testdoc");
- TEquals("testdoc", xhr.responseText, "should return 'testdoc'");
-
- db.deleteDoc(doc);
- var xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/show-deleted/testdoc");
- TEquals("No doc testdoc", xhr.responseText, "should return 'no doc testdoc'");
-
- // (we don't need no modified server!)
- T(db.setDbProperty("_security", {foo: true}).ok);
- T(db.save({_id:"testdoc",foo:1}).ok);
- // nasty source of Heisenbugs - it replicates after a short time, so give it some tries
- // (needs PR #400 and #401 to be merged)
- retry_part(function(){
- xhr = CouchDB.request("GET", "/" + db_name + "/_design/template/_show/secObj");
- var resp = JSON.parse(xhr.responseText);
- T(resp.foo == true);
- }, 10);
-
- // cleanup
- db.deleteDb();
-
-};
diff --git a/test/javascript/tests/users_db_security.js b/test/javascript/tests/users_db_security.js
deleted file mode 100644
index 3e293c5eb..000000000
--- a/test/javascript/tests/users_db_security.js
+++ /dev/null
@@ -1,418 +0,0 @@
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy of
-// the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-couchTests.elixir = true;
-couchTests.users_db_security = function(debug) {
- var db_name = '_users';
- var usersDb = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
- try { usersDb.createDb(); } catch (e) { /* ignore if exists*/ }
-
- if (debug) debugger;
-
- var loginUser = function(username) {
- var pws = {
- jan: "apple",
- jchris: "mp3",
- jchris1: "couch",
- fdmanana: "foobar",
- benoitc: "test"
- };
- // we are changing jchris’s password further down
- // the next two lines keep the code cleaner in
- // the actual tests
- var username1 = username.replace(/[0-9]$/, "");
- var password = pws[username];
- T(CouchDB.login(username1, pws[username]).ok);
- };
-
- var open_as = function(db, docId, username) {
- loginUser(username);
- try {
- return db.open(docId, {"anti-cache": Math.round(Math.random() * 100000)});
- } finally {
- CouchDB.logout();
- }
- };
-
- var view_as = function(db, viewname, username) {
- loginUser(username);
- try {
- return db.view(viewname);
- } finally {
- CouchDB.logout();
- }
- };
-
- var save_as = function(db, doc, username)
- {
- loginUser(username);
- try {
- return db.save(doc);
- } catch (ex) {
- return ex;
- } finally {
- CouchDB.logout();
- }
- };
-
- var changes_as = function(db, username)
- {
- loginUser(username);
- try {
- return db.changes();
- } catch(ex) {
- return ex;
- } finally {
- CouchDB.logout();
- }
- };
-
- var request_as = function(db, ddoc_path, username) {
- loginUser(username);
- try {
- var uri = db.uri + ddoc_path;
- var req = CouchDB.request("GET", uri);
- return req;
- } finally {
- CouchDB.logout();
- }
- };
-
- var testFun = function()
- {
-
- // _users db
- // a doc with a field 'password' should be hashed to 'derived_key'
- // with salt and salt stored in 'salt', 'password' is set to null.
- // Exising 'derived_key' and 'salt' fields are overwritten with new values
- // when a non-null 'password' field exists.
- // anonymous should be able to create a user document
- var userDoc = {
- _id: "org.couchdb.user:jchris",
- type: "user",
- name: "jchris",
- password: "mp3",
- roles: []
- };
-
- // jan's gonna be admin as he's the first user
- TEquals(true, usersDb.save(userDoc).ok, "should save document");
- wait(5000)
- userDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris");
- TEquals(undefined, userDoc.password, "password field should be null 1");
- TEquals(40, userDoc.derived_key.length, "derived_key should exist");
- TEquals(32, userDoc.salt.length, "salt should exist");
-
- // create server admin
-
- // anonymous should not be able to read an existing user's user document
- var res = usersDb.open("org.couchdb.user:jchris");
- TEquals(null, res, "anonymous user doc read should be not found");
-
- // anonymous should not be able to read /_users/_changes
- try {
- var ch = usersDb.changes();
- T(false, "anonymous can read _changes");
- } catch(e) {
- TEquals("unauthorized", e.error, "anoymous can't read _changes");
- }
-
- // user should be able to read their own document
- var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris");
- TEquals("org.couchdb.user:jchris", jchrisDoc._id);
-
- // user should not be able to read /_users/_changes
- var changes = changes_as(usersDb, "jchris");
- TEquals("unauthorized", changes.error, "user can't read _changes");
-
- // new 'password' fields should trigger new hashing routine
- jchrisDoc.password = "couch";
-
- TEquals(true, save_as(usersDb, jchrisDoc, "jchris").ok);
- // wait(10000);
- var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jan");
-
- TEquals(undefined, jchrisDoc.password, "password field should be null 2");
- TEquals(40, jchrisDoc.derived_key.length, "derived_key should exist");
- TEquals(32, jchrisDoc.salt.length, "salt should exist");
-
- TEquals(true, userDoc.salt != jchrisDoc.salt, "should have new salt");
- TEquals(true, userDoc.derived_key != jchrisDoc.derived_key,
- "should have new derived_key");
-
- // user should not be able to read another user's user document
- var fdmananaDoc = {
- _id: "org.couchdb.user:fdmanana",
- type: "user",
- name: "fdmanana",
- password: "foobar",
- roles: []
- };
-
- usersDb.save(fdmananaDoc);
- var fdmananaDocAsReadByjchris = open_as(usersDb, "org.couchdb.user:fdmanana", "jchris1");
- TEquals(null, fdmananaDocAsReadByjchris,
- "should not_found opening another user's user doc");
-
-
- // save a db admin
- var benoitcDoc = {
- _id: "org.couchdb.user:benoitc",
- type: "user",
- name: "benoitc",
- password: "test",
- roles: ["user_admin"]
- };
- save_as(usersDb, benoitcDoc, "jan");
-
- TEquals(true, CouchDB.login("jan", "apple").ok);
- T(usersDb.setSecObj({
- "admins" : {
- roles : [],
- names : ["benoitc"]
- }
- }).ok);
- CouchDB.logout();
-
- // user should not be able to read from any view
- var ddoc = {
- _id: "_design/user_db_auth",
- views: {
- test: {
- map: "function(doc) { emit(doc._id, null); }"
- }
- },
- lists: {
- names: "function(head, req) { "
- + "var row; while (row = getRow()) { send(row.key + \"\\n\"); }"
- + "}"
- },
- shows: {
- name: "function(doc, req) { return doc.name; }"
- }
- };
-
- save_as(usersDb, ddoc, "jan");
-
- try {
- usersDb.view("user_db_auth/test");
- T(false, "user had access to view in admin db");
- } catch(e) {
- TEquals("forbidden", e.error,
- "non-admins should not be able to read a view");
- }
-
- // admin should be able to read from any view
- var result = view_as(usersDb, "user_db_auth/test", "jan");
- TEquals(3, result.total_rows, "should allow access and list four users to admin");
-
- // db admin should be able to read from any view
- var result = view_as(usersDb, "user_db_auth/test", "benoitc");
- TEquals(3, result.total_rows, "should allow access and list four users to db admin");
-
-
- // non-admins can't read design docs
- try {
- open_as(usersDb, "_design/user_db_auth", "jchris1");
- T(false, "non-admin read design doc, should not happen");
- } catch(e) {
- TEquals("forbidden", e.error, "non-admins can't read design docs");
- }
-
- // admin shold be able to read _list
- var listPath = ddoc["_id"] + "/_list/names/test";
- var result = request_as(usersDb, listPath, "jan");
- var lines = result.responseText.split("\n");
- T(result.status == 200, "should allow access to db admin");
- TEquals(4, lines.length, "should list users to db admin");
-
- // non-admins can't read _list
- var result = request_as(usersDb, listPath, "jchris1");
- T(result.status == 403, "should deny access to non-admin");
-
- // admin should be able to read _show
- var showPath = ddoc["_id"] + "/_show/name/org.couchdb.user:jchris";
- var result = request_as(usersDb, showPath, "jan");
- T(result.status == 200, "should allow access to db admin");
- TEquals("jchris", result.responseText, "should show username to db admin");
-
- // non-admin should be able to access own _show
- var result = request_as(usersDb, showPath, "jchris1");
- T(result.status == 200, "should allow access to own user record");
- TEquals("jchris", result.responseText, "should show own username");
-
- // non-admin can't read other's _show
- var showPath = ddoc["_id"] + "/_show/name/org.couchdb.user:jan";
- var result = request_as(usersDb, showPath, "jchris1");
- T(result.status == 404, "non-admin can't read others's user docs");
-
- // admin should be able to read and edit any user doc
- fdmananaDoc.password = "mobile";
- var result = save_as(usersDb, fdmananaDoc, "jan");
- TEquals(true, result.ok, "admin should be able to update any user doc");
-
- // admin should be able to read and edit any user doc
- fdmananaDoc.password = "mobile1";
- var result = save_as(usersDb, fdmananaDoc, "benoitc");
- TEquals(true, result.ok, "db admin by role should be able to update any user doc");
-
- TEquals(true, CouchDB.login("jan", "apple").ok);
- T(usersDb.setSecObj({
- "admins" : {
- roles : ["user_admin"],
- names : []
- }
- }).ok);
- CouchDB.logout();
-
- // db admin should be able to read and edit any user doc
- fdmananaDoc.password = "mobile2";
- var result = save_as(usersDb, fdmananaDoc, "benoitc");
- TEquals(true, result.ok, "db admin should be able to update any user doc");
-
- // ensure creation of old-style docs still works
- var robertDoc = CouchDB.prepareUserDoc({ name: "robert" }, "anchovy");
- var result = usersDb.save(robertDoc);
- TEquals(true, result.ok, "old-style user docs should still be accepted");
-
- // log in one last time so run_on_modified_server can clean up the admin account
- TEquals(true, CouchDB.login("jan", "apple").ok);
-
- // run_on_modified_server([
- // {
- // section: "couch_httpd_auth",
- // key: "iterations",
- // value: "1"
- // },
- // {
- // section: "couch_httpd_auth",
- // key: "public_fields",
- // value: "name,type"
- // },
- // {
- // section: "couch_httpd_auth",
- // key: "users_db_public",
- // value: "true"
- // },
- // {
- // section: "admins",
- // key: "jan",
- // value: "apple"
- // }
- // ], function() {
- // var res = usersDb.open("org.couchdb.user:jchris");
- // TEquals("jchris", res.name);
- // TEquals("user", res.type);
- // TEquals(undefined, res.roles);
- // TEquals(undefined, res.salt);
- // TEquals(undefined, res.password_scheme);
- // TEquals(undefined, res.derived_key);
- //
- // TEquals(true, CouchDB.login("jan", "apple").ok);
- //
- // var all = usersDb.allDocs({ include_docs: true });
- // T(all.rows);
- // if (all.rows) {
- // T(all.rows.every(function(row) {
- // if (row.doc) {
- // return Object.keys(row.doc).every(function(key) {
- // return key === 'name' || key === 'type';
- // });
- // } else {
- // if(row.id[0] == "_") {
- // // ignore design docs
- // return true
- // } else {
- // return false;
- // }
- // }
- // }));
- // }
- // // log in one last time so run_on_modified_server can clean up the admin account
- // TEquals(true, CouchDB.login("jan", "apple").ok);
- // });
-
- run_on_modified_server([
- {
- section: "couch_httpd_auth",
- key: "public_fields",
- value: "name"
- },
- {
- section: "couch_httpd_auth",
- key: "users_db_public",
- value: "false"
- }
- ], function() {
- TEquals(true, CouchDB.login("jchris", "couch").ok);
-
- try {
- var all = usersDb.allDocs({ include_docs: true });
- T(false); // should never hit
- } catch(e) {
- TEquals("unauthorized", e.error, "should throw");
- }
-
- // COUCHDB-1888 make sure admins always get all fields
- TEquals(true, CouchDB.login("jan", "apple").ok);
- var all_admin = usersDb.allDocs({ include_docs: "true" });
- TEquals("user", all_admin.rows[2].doc.type,
- "should return type");
-
-
- // log in one last time so run_on_modified_server can clean up the admin account
- TEquals(true, CouchDB.login("jan", "apple").ok);
- });
- };
-
- run_on_modified_server(
- [
- {
- section:"couchdb",
- key:"users_db_security_editable",
- value:"true"
- },
- {
- section: "couch_httpd_auth",
- key: "iterations",
- value: "1"
- },
- {
- section: "admins",
- key: "jan",
- value: "apple"
- }],
- function() {
- try {
- testFun();
- } finally {
- CouchDB.login("jan", "apple");
- usersDb.deleteDb(); // cleanup
- waitForSuccess(function() {
- var req = CouchDB.request("GET", db_name);
- if (req.status == 404) {
- return true
- }
- throw({});
- }, 'usersDb.deleteDb')
- usersDb.createDb();
- waitForSuccess(function() {
- var req = CouchDB.request("GET", db_name);
- if (req.status == 200) {
- return true
- }
- throw({});
- }, 'usersDb.creteDb')
- }
- }
- );
- CouchDB.logout();
-};