couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From beno...@apache.org
Subject [2/2] couch commit: updated refs/heads/1994-merge-rcouch to f9e3095
Date Sun, 16 Feb 2014 00:17:18 GMT
Add validate_doc_read property to a design document.

Like validate_doc_update, this function validate if the document can be
read by the curreny user.

ex:

    function(doc, userCtx) {
        if ((typeof doc.name !== 'undefined') && (doc.name !=
userCtx.name)) {
            throw({unauthorized: doc.name + ' cannnot read ' +
doc._id});
        }
    }

will allow the current user to only read the documents where the
properties name is the name of the user.

Note: admins can always read the documents.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/f9e30951
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/f9e30951
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/f9e30951

Branch: refs/heads/1994-merge-rcouch
Commit: f9e3095195dd31fc55334e675d48f5e395d67b55
Parents: bfd6cbb
Author: benoitc <bchesneau@gmail.com>
Authored: Sun Feb 16 01:16:08 2014 +0100
Committer: benoitc <bchesneau@gmail.com>
Committed: Sun Feb 16 01:16:08 2014 +0100

----------------------------------------------------------------------
 include/couch_db.hrl        |  1 +
 src/couch_db.erl            | 32 +++++++++++++++++++++++++++++++-
 src/couch_db_updater.erl    | 27 +++++++++++++++++----------
 src/couch_doc.erl           | 15 ++++++++++++++-
 src/couch_query_servers.erl | 14 +++++++++++++-
 5 files changed, 76 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f9e30951/include/couch_db.hrl
----------------------------------------------------------------------
diff --git a/include/couch_db.hrl b/include/couch_db.hrl
index e0a1c82..539dd4a 100644
--- a/include/couch_db.hrl
+++ b/include/couch_db.hrl
@@ -190,6 +190,7 @@
     name,
     filepath,
     validate_doc_funs = [],
+    validate_doc_read_funs = [],
     security = [],
     security_ptr = nil,
     user_ctx = #user_ctx{},

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f9e30951/src/couch_db.erl
----------------------------------------------------------------------
diff --git a/src/couch_db.erl b/src/couch_db.erl
index 11ea0fd..a852cae 100644
--- a/src/couch_db.erl
+++ b/src/couch_db.erl
@@ -1321,7 +1321,9 @@ make_doc(#db{updater_fd = Fd} = Db, Id, Deleted, Bp, RevisionPath) ->
         atts = Atts,
         deleted = Deleted
     },
-    after_doc_read(Db, Doc).
+    Doc1 = after_doc_read(Db, Doc),
+    ok = validate_doc_read(Db, Doc1),
+    Doc1.
 
 
 after_doc_read(#db{after_doc_read = nil}, Doc) ->
@@ -1330,6 +1332,34 @@ after_doc_read(#db{after_doc_read = Fun} = Db, Doc) ->
     Fun(couch_doc:with_ejson_body(Doc), Db).
 
 
+validate_doc_read(#db{validate_doc_read_funs=[]}, _Doc) ->
+    ok;
+validate_doc_read(_Db, #doc{id= <<"_local/",_/binary>>}) ->
+    ok;
+validate_doc_read(Db, Doc) ->
+    case catch(check_is_admin(Db)) of
+        ok ->
+            ok;
+        _ ->
+            JsonCtx = couch_util:json_user_ctx(Db),
+            SecObj = get_security(Db),
+            try [case Fun(Doc, JsonCtx, SecObj) of
+                    ok -> ok;
+                    Error -> throw(Error)
+                end || Fun <- Db#db.validate_doc_read_funs],
+                ok
+            catch
+                throw:{forbidden, _}=Error ->
+                    throw(Error);
+                throw:{unauthorized, _}=Error ->
+                    throw(Error);
+                throw:Error ->
+                    ?LOG_ERROR("Error while validating read: ~p~n", [Error]),
+                    ok
+            end
+    end.
+
+
 increment_stat(#db{options = Options}, Stat) ->
     case lists:member(sys_db, Options) of
     true ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f9e30951/src/couch_db_updater.erl
----------------------------------------------------------------------
diff --git a/src/couch_db_updater.erl b/src/couch_db_updater.erl
index 947669c..6a57c9b 100644
--- a/src/couch_db_updater.erl
+++ b/src/couch_db_updater.erl
@@ -503,16 +503,23 @@ close_db(#db{fd_ref_counter = RefCntr}) ->
 refresh_validate_doc_funs(Db0) ->
     Db = Db0#db{user_ctx = #user_ctx{roles=[<<"_admin">>]}},
     DesignDocs = couch_db:get_design_docs(Db),
-    ProcessDocFuns = lists:flatmap(
-        fun(DesignDocInfo) ->
-            {ok, DesignDoc} = couch_db:open_doc_int(
-                Db, DesignDocInfo, [ejson_body]),
-            case couch_doc:get_validate_doc_fun(DesignDoc) of
-            nil -> [];
-            Fun -> [Fun]
-            end
-        end, DesignDocs),
-    Db0#db{validate_doc_funs=ProcessDocFuns}.
+    {UpdateFuns, ReadFuns} = lists:foldl(
+            fun(DesignDocInfo, {UAcc, RAcc}) ->
+                    {ok, DesignDoc} = couch_db:open_doc_int(Db, DesignDocInfo,
+                                                            [ejson_body]),
+                    UAcc1 = case couch_doc:get_validate_doc_fun(DesignDoc) of
+                        nil -> UAcc;
+                        Fun -> [Fun|UAcc]
+                    end,
+                    RAcc1 = case couch_doc:get_validate_read_doc_fun(
+                            DesignDoc) of
+                        nil -> RAcc;
+                        Fun1 -> [Fun1|RAcc]
+                    end,
+                    {UAcc1, RAcc1}
+            end, {[], []}, DesignDocs),
+    Db0#db{validate_doc_funs=UpdateFuns, validate_doc_read_funs=ReadFuns}.
+
 
 % rev tree functions
 

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f9e30951/src/couch_doc.erl
----------------------------------------------------------------------
diff --git a/src/couch_doc.erl b/src/couch_doc.erl
index 4047370..efde8c1 100644
--- a/src/couch_doc.erl
+++ b/src/couch_doc.erl
@@ -13,7 +13,8 @@
 -module(couch_doc).
 
 -export([to_doc_info/1,to_doc_info_path/1,parse_rev/1,parse_revs/1,rev_to_str/1,revs_to_strs/1]).
--export([att_foldl/3,range_att_foldl/5,att_foldl_decode/3,get_validate_doc_fun/1]).
+-export([att_foldl/3,range_att_foldl/5,att_foldl_decode/3,
+         get_validate_doc_fun/1,get_validate_read_doc_fun/1]).
 -export([from_json_obj/1,to_json_obj/2,has_stubs/1, merge_stubs/2]).
 -export([validate_docid/1]).
 -export([doc_from_multi_part_stream/2]).
@@ -412,6 +413,18 @@ get_validate_doc_fun(#doc{body={Props}}=DDoc) ->
     end.
 
 
+get_validate_read_doc_fun(#doc{body={Props}}=DDoc) ->
+    case couch_util:get_value(<<"validate_doc_read">>, Props) of
+        undefined ->
+            nil;
+        _Else ->
+            fun(Doc, Ctx, SecObj) ->
+                    couch_query_servers:validate_doc_read(DDoc, Doc, Ctx,
+                                                          SecObj)
+            end
+    end.
+
+
 has_stubs(#doc{atts=Atts}) ->
     has_stubs(Atts);
 has_stubs([]) ->

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f9e30951/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 3b58cbe..148cdba 100644
--- a/src/couch_query_servers.erl
+++ b/src/couch_query_servers.erl
@@ -17,7 +17,7 @@
 
 -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2,code_change/3]).
 -export([start_doc_map/3, map_docs/2, map_doc_raw/2, stop_doc_map/1, raw_to_ejson/1]).
--export([reduce/3, rereduce/3,validate_doc_update/5]).
+-export([reduce/3, rereduce/3,validate_doc_update/5,validate_doc_read/4]).
 -export([filter_docs/5]).
 -export([filter_view/3]).
 
@@ -233,6 +233,18 @@ validate_doc_update(DDoc, EditDoc, DiskDoc, Ctx, SecObj) ->
             throw({unauthorized, Message})
     end.
 
+validate_doc_read(DDoc, Doc, Ctx, SecObj) ->
+    JsonDoc = couch_doc:to_json_obj(Doc, [revs]),
+    case ddoc_prompt(DDoc, [<<"validate_doc_read">>],
+                     [JsonDoc, Ctx, SecObj]) of
+        1 ->
+            ok;
+        {[{<<"forbidden">>, Message}]} ->
+            throw({forbidden, Message});
+        {[{<<"unauthorized">>, Message}]} ->
+            throw({unauthorized, Message})
+    end.
+
 json_doc(nil) -> null;
 json_doc(Doc) ->
     couch_doc:to_json_obj(Doc, [revs]).


Mime
View raw message