FAQ
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]).

Search Discussions

Discussion Posts

Previous

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 2 of 2 | next ›
Discussion Overview
groupcommits @
categoriescouchdb
postedFeb 16, '14 at 12:17a
activeFeb 16, '14 at 12:17a
posts2
users1
websitecouchdb.apache.org
irc#couchdb

1 user in discussion

Benoitc: 2 posts

People

Translate

site design / logo © 2021 Grokbase