diff --git a/src/mango/src/mango_cursor_view.erl b/src/mango/src/mango_cursor_view.erl index e97311c72b..538877cbcf 100644 --- a/src/mango/src/mango_cursor_view.erl +++ b/src/mango/src/mango_cursor_view.erl @@ -85,17 +85,20 @@ execute(#cursor{db = Db, index = Idx} = Cursor0, UserFun, UserAcc) -> end_key = mango_idx:end_key(Idx, Cursor#cursor.ranges), include_docs = true }, - Args = apply_opts(Cursor#cursor.opts, BaseArgs), + #cursor{opts = Opts} = Cursor, + Args = apply_opts(Opts, BaseArgs), + UserCtx = couch_util:get_value(user_ctx, Opts, #user_ctx{}), + DbOpts = [{user_ctx, UserCtx}], Result = case mango_idx:def(Idx) of all_docs -> CB = fun ?MODULE:handle_all_docs_message/2, - fabric:all_docs(Db, CB, Cursor, Args); + fabric:all_docs(Db, DbOpts, CB, Cursor, Args); _ -> CB = fun ?MODULE:handle_message/2, % Normal view DDoc = ddocid(Idx), Name = mango_idx:name(Idx), - fabric:query_view(Db, DDoc, Name, CB, Cursor, Args) + fabric:query_view(Db, DbOpts, DDoc, Name, CB, Cursor, Args) end, case Result of {ok, LastCursor} -> diff --git a/src/mango/src/mango_httpd.erl b/src/mango/src/mango_httpd.erl index a088276493..5bc61f57ac 100644 --- a/src/mango/src/mango_httpd.erl +++ b/src/mango/src/mango_httpd.erl @@ -85,7 +85,8 @@ handle_index_req(#httpd{method='POST', path_parts=[_, _]}=Req, Db) -> {ok, Opts} = mango_opts:validate_idx_create(chttpd:json_body_obj(Req)), {ok, Idx0} = mango_idx:new(Db, Opts), {ok, Idx} = mango_idx:validate_new(Idx0, Db), - {ok, DDoc} = mango_util:load_ddoc(Db, mango_idx:ddoc(Idx)), + DbOpts = [{user_ctx, Req#httpd.user_ctx}, deleted, ejson_body], + {ok, DDoc} = mango_util:load_ddoc(Db, mango_idx:ddoc(Idx), DbOpts), Id = Idx#idx.ddoc, Name = Idx#idx.name, Status = case mango_idx:add(DDoc, Idx) of diff --git a/src/mango/src/mango_util.erl b/src/mango/src/mango_util.erl index c3513dced3..a7347178e9 100644 --- a/src/mango/src/mango_util.erl +++ b/src/mango/src/mango_util.erl @@ -17,6 +17,7 @@ open_doc/2, open_ddocs/1, load_ddoc/2, + load_ddoc/3, defer/3, do_defer/3, @@ -104,7 +105,10 @@ open_ddocs(Db) -> load_ddoc(Db, DDocId) -> - case open_doc(Db, DDocId, [deleted, ejson_body]) of + load_ddoc(Db, DDocId, [deleted, ejson_body]). + +load_ddoc(Db, DDocId, DbOpts) -> + case open_doc(Db, DDocId, DbOpts) of {ok, Doc} -> {ok, check_lang(Doc)}; not_found -> diff --git a/src/mango/test/13-users-db-find-test.py b/src/mango/test/13-users-db-find-test.py new file mode 100644 index 0000000000..d8d32ad939 --- /dev/null +++ b/src/mango/test/13-users-db-find-test.py @@ -0,0 +1,83 @@ +# -*- coding: latin-1 -*- +# 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. + + +import mango, requests + + +class UsersDbFindTests(mango.UsersDbTests): + + def test_simple_find(self): + docs = self.db.find({"name": {"$eq": "demo02"}}) + assert len(docs) == 1 + assert docs[0]["_id"] == "org.couchdb.user:demo02" + + def test_multi_cond_and(self): + self.db.create_index(["type", "roles"]) + docs = self.db.find({"type": "user", "roles": {"$eq": ["reader"]}}) + assert len(docs) == 1 + assert docs[0]["_id"] == "org.couchdb.user:demo02" + + def test_multi_cond_or(self): + docs = self.db.find({ + "$and":[ + {"type": "user"}, + {"$or": [ + {"order": 1}, + {"order": 3} + ]} + ] + }) + assert len(docs) == 2 + assert docs[0]["_id"] == "org.couchdb.user:demo01" + assert docs[1]["_id"] == "org.couchdb.user:demo03" + + def test_sort(self): + self.db.create_index(["order", "name"]) + selector = {"name": {"$gt": "demo01"}} + docs1 = self.db.find(selector, sort=[{"order": "asc"}]) + docs2 = list(sorted(docs1, key=lambda d: d["order"])) + assert docs1 is not docs2 and docs1 == docs2 + + docs1 = self.db.find(selector, sort=[{"order": "desc"}]) + docs2 = list(reversed(sorted(docs1, key=lambda d: d["order"]))) + assert docs1 is not docs2 and docs1 == docs2 + + def test_fields(self): + selector = {"name": {"$eq": "demo02"}} + docs = self.db.find(selector, fields=["name", "order"]) + assert len(docs) == 1 + assert sorted(docs[0].keys()) == ["name", "order"] + + def test_empty(self): + docs = self.db.find({}) + assert len(docs) == 3 + + +class UsersDbIndexFindTests(UsersDbFindTests): + + def setUp(self): + self.db.create_index(["name"]) + + def test_multi_cond_and(self): + self.db.create_index(["type", "roles"]) + super(UsersDbIndexFindTests, self).test_multi_cond_and() + + def test_multi_cond_or(self): + self.db.create_index(["type", "order"]) + super(UsersDbIndexFindTests, self).test_multi_cond_or() + + def test_sort(self): + self.db.create_index(["order", "name"]) + super(UsersDbIndexFindTests, self).test_sort() + diff --git a/src/mango/test/mango.py b/src/mango/test/mango.py index da51180b14..bd34edcec4 100644 --- a/src/mango/test/mango.py +++ b/src/mango/test/mango.py @@ -192,6 +192,17 @@ def find_one(self, *args, **kwargs): return None +class UsersDbTests(unittest.TestCase): + + @classmethod + def setUpClass(klass): + klass.db = Database("127.0.0.1", "15984", "_users") + user_docs.setup_users(klass.db) + + def setUp(self): + self.db = self.__class__.db + + class DbPerClass(unittest.TestCase): @classmethod diff --git a/src/mango/test/user_docs.py b/src/mango/test/user_docs.py index e2f1705b0f..41d8602875 100644 --- a/src/mango/test/user_docs.py +++ b/src/mango/test/user_docs.py @@ -54,6 +54,11 @@ import copy +def setup_users(db, **kwargs): + db.recreate() + db.save_docs(copy.deepcopy(USERS_DOCS)) + + def setup(db, index_type="view", **kwargs): db.recreate() db.save_docs(copy.deepcopy(DOCS)) @@ -488,3 +493,34 @@ def add_text_indexes(db, kwargs): ] } ] + + +USERS_DOCS = [ + { + "_id": "org.couchdb.user:demo01", + "name": "demo01", + "username": "demo01", + "password": "apple01", + "roles": ["design"], + "order": 1, + "type": "user" + }, + { + "_id": "org.couchdb.user:demo02", + "name": "demo02", + "username": "demo02", + "password": "apple02", + "roles": ["reader"], + "order": 2, + "type": "user" + }, + { + "_id": "org.couchdb.user:demo03", + "name": "demo03", + "username": "demo03", + "password": "apple03", + "roles": ["reader", "writer"], + "order": 3, + "type": "user" + } +]