diff options
-rw-r--r-- | share/www/script/test/reader_acl.js | 16 | ||||
-rw-r--r-- | src/couchdb/couch_db.erl | 9 | ||||
-rw-r--r-- | src/couchdb/couch_rep.erl | 6 | ||||
-rw-r--r-- | src/couchdb/couch_view_group.erl | 16 |
4 files changed, 35 insertions, 12 deletions
diff --git a/share/www/script/test/reader_acl.js b/share/www/script/test/reader_acl.js index 6f834bfb..a42e9bea 100644 --- a/share/www/script/test/reader_acl.js +++ b/share/www/script/test/reader_acl.js @@ -90,10 +90,26 @@ couchTests.reader_acl = function(debug) { // server _admin can always read T(secretDb.open("baz").foo == "bar"); + // and run temp views + TEquals(secretDb.query(function(doc) { + emit(null, null) + }).total_rows, 1); + + T(secretDb.save({ + "_id" : "_design/foo", + views : { + bar : { + map : "function(doc){emit(null, null)}" + } + } + }).ok) + // now top-secret users can read too T(CouchDB.login("jchris@apache.org", "funnybone").ok); T(CouchDB.session().userCtx.roles.indexOf("_admin") == -1); T(secretDb.open("baz").foo == "bar"); + // readers can query stored views + T(secretDb.view("foo/bar").total_rows == 1); CouchDB.logout(); diff --git a/src/couchdb/couch_db.erl b/src/couchdb/couch_db.erl index 6d5da15b..e5635f55 100644 --- a/src/couchdb/couch_db.erl +++ b/src/couchdb/couch_db.erl @@ -13,7 +13,7 @@ -module(couch_db). -behaviour(gen_server). --export([open/2,close/1,create/2,start_compact/1,get_db_info/1,get_design_docs/1]). +-export([open/2,open_int/2,close/1,create/2,start_compact/1,get_db_info/1,get_design_docs/1]). -export([open_ref_counted/2,is_idle/1,monitor/1,count_changes_since/2]). -export([update_doc/3,update_doc/4,update_docs/4,update_docs/2,update_docs/3,delete_doc/3]). -export([get_doc_info/2,open_doc/2,open_doc/3,open_doc_revs/4]). @@ -64,6 +64,13 @@ open_db_file(Filepath, Options) -> create(DbName, Options) -> couch_server:create(DbName, Options). +% this is for opening a database for internal purposes like the replicator +% or the view indexer. it never throws a reader error. +open_int(DbName, Options) -> + couch_server:open(DbName, Options). + +% this should be called anytime an http request opens the database. +% it ensures that the http userCtx is a valid reader open(DbName, Options) -> case couch_server:open(DbName, Options) of {ok, Db} -> diff --git a/src/couchdb/couch_rep.erl b/src/couchdb/couch_rep.erl index 82716809..4bad4a9f 100644 --- a/src/couchdb/couch_rep.erl +++ b/src/couchdb/couch_rep.erl @@ -646,7 +646,7 @@ ensure_full_commit(#http_db{} = Target) -> true = proplists:get_value(<<"ok">>, ResultProps), proplists:get_value(<<"instance_start_time">>, ResultProps); ensure_full_commit(Target) -> - {ok, NewDb} = couch_db:open(Target#db.name, []), + {ok, NewDb} = couch_db:open_int(Target#db.name, []), UpdateSeq = couch_db:get_update_seq(Target), CommitSeq = couch_db:get_committed_update_seq(NewDb), InstanceStartTime = NewDb#db.instance_start_time, @@ -674,7 +674,7 @@ ensure_full_commit(#http_db{} = Source, RequiredSeq) -> proplists:get_value(<<"instance_start_time">>, ResultProps); undefined -> nil end; ensure_full_commit(Source, RequiredSeq) -> - {ok, NewDb} = couch_db:open(Source#db.name, []), + {ok, NewDb} = couch_db:open_int(Source#db.name, []), CommitSeq = couch_db:get_committed_update_seq(NewDb), InstanceStartTime = NewDb#db.instance_start_time, couch_db:close(NewDb), @@ -705,7 +705,7 @@ update_local_doc(Db, Doc) -> up_to_date(#http_db{}, _Seq) -> true; up_to_date(Source, Seq) -> - {ok, NewDb} = couch_db:open(Source#db.name, []), + {ok, NewDb} = couch_db:open_int(Source#db.name, []), T = NewDb#db.update_seq == Seq, couch_db:close(NewDb), T. diff --git a/src/couchdb/couch_view_group.erl b/src/couchdb/couch_view_group.erl index 8439304d..bb4102c2 100644 --- a/src/couchdb/couch_view_group.erl +++ b/src/couchdb/couch_view_group.erl @@ -125,7 +125,7 @@ handle_call({request_group, RequestSeq}, From, updater_pid=nil, waiting_list=WaitList }=State) when RequestSeq > Seq -> - {ok, Db} = couch_db:open(DbName, []), + {ok, Db} = couch_db:open_int(DbName, []), Group2 = Group#group{db=Db}, Owner = self(), Pid = spawn_link(fun()-> couch_view_updater:update(Owner, Group2) end), @@ -164,7 +164,7 @@ handle_cast({start_compact, CompactFun}, #group_state{compactor_pid=nil} init_args = {RootDir, DbName, _} } = State, ?LOG_INFO("View index compaction starting for ~s ~s", [DbName, GroupId]), - {ok, Db} = couch_db:open(DbName, []), + {ok, Db} = couch_db:open_int(DbName, []), {ok, Fd} = open_index_file(compact, RootDir, DbName, GroupSig), NewGroup = reset_file(Db, Fd, DbName, Group), Pid = spawn_link(fun() -> CompactFun(Group, NewGroup) end), @@ -224,7 +224,7 @@ handle_cast({compact_done, NewGroup}, State) -> ?LOG_INFO("View index compaction still behind for ~s ~s -- current: ~p " ++ "compact: ~p", [DbName, GroupId, CurrentSeq, NewGroup#group.current_seq]), couch_db:close(NewGroup#group.db), - {ok, Db} = couch_db:open(DbName, []), + {ok, Db} = couch_db:open_int(DbName, []), Pid = spawn_link(fun() -> {_,Ref} = erlang:spawn_monitor(fun() -> couch_view_updater:update(nil, NewGroup#group{db = Db}) @@ -257,7 +257,7 @@ handle_cast({partial_update, _, _}, State) -> {noreply, State}. handle_info(delayed_commit, #group_state{db_name=DbName,group=Group}=State) -> - {ok, Db} = couch_db:open(DbName, []), + {ok, Db} = couch_db:open_int(DbName, []), CommittedSeq = couch_db:get_committed_update_seq(Db), couch_db:close(Db), if CommittedSeq >= Group#group.current_seq -> @@ -292,7 +292,7 @@ handle_info({'EXIT', FromPid, {new_group, #group{db=Db}=Group}}, group=Group#group{db=nil}, updater_pid=nil}}; StillWaiting -> % we still have some waiters, reopen the database and reupdate the index - {ok, Db2} = couch_db:open(DbName, []), + {ok, Db2} = couch_db:open_int(DbName, []), Group2 = Group#group{db=Db2}, Owner = self(), Pid = spawn_link(fun() -> couch_view_updater:update(Owner, Group2) end), @@ -372,7 +372,7 @@ reply_all(#group_state{waiting_list=WaitList}=State, Reply) -> State#group_state{waiting_list=[]}. prepare_group({RootDir, DbName, #group{sig=Sig}=Group}, ForceReset)-> - case couch_db:open(DbName, []) of + case couch_db:open_int(DbName, []) of {ok, Db} -> case open_index_file(RootDir, DbName, Sig) of {ok, Fd} -> @@ -437,7 +437,7 @@ open_index_file(compact, RootDir, DbName, GroupSig) -> end. open_temp_group(DbName, Language, DesignOptions, MapSrc, RedSrc) -> - case couch_db:open(DbName, []) of + case couch_db:open_int(DbName, []) of {ok, Db} -> View = #view{map_names=[<<"_temp">>], id_num=0, @@ -459,7 +459,7 @@ set_view_sig(#group{ G#group{sig=erlang:md5(term_to_binary({Views, Language, DesignOptions}))}. open_db_group(DbName, GroupId) -> - case couch_db:open(DbName, []) of + case couch_db:open_int(DbName, []) of {ok, Db} -> case couch_db:open_doc(Db, GroupId) of {ok, Doc} -> |