diff options
Diffstat (limited to 'src/chttpd/src/chttpd_auth_cache.erl')
-rw-r--r-- | src/chttpd/src/chttpd_auth_cache.erl | 140 |
1 files changed, 82 insertions, 58 deletions
diff --git a/src/chttpd/src/chttpd_auth_cache.erl b/src/chttpd/src/chttpd_auth_cache.erl index 17a31bf55..2173eca95 100644 --- a/src/chttpd/src/chttpd_auth_cache.erl +++ b/src/chttpd/src/chttpd_auth_cache.erl @@ -14,8 +14,14 @@ -behaviour(gen_server). -export([start_link/0, get_user_creds/2, update_user_creds/3, dbname/0]). --export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, - code_change/3]). +-export([ + init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3 +]). -export([listen_for_changes/1, changes_callback/2]). -include_lib("couch/include/couch_db.hrl"). @@ -25,7 +31,7 @@ -record(state, { changes_pid, - last_seq="0" + last_seq = "0" }). %% public functions @@ -36,18 +42,21 @@ start_link() -> get_user_creds(Req, UserName) when is_list(UserName) -> get_user_creds(Req, ?l2b(UserName)); get_user_creds(_Req, UserName) when is_binary(UserName) -> - Resp = case couch_auth_cache:get_admin(UserName) of - nil -> - get_from_cache(UserName); - Props -> - case get_from_cache(UserName) of - nil -> - Props; - UserProps when is_list(UserProps) -> - couch_auth_cache:add_roles(Props, - couch_util:get_value(<<"roles">>, UserProps)) - end - end, + Resp = + case couch_auth_cache:get_admin(UserName) of + nil -> + get_from_cache(UserName); + Props -> + case get_from_cache(UserName) of + nil -> + Props; + UserProps when is_list(UserProps) -> + couch_auth_cache:add_roles( + Props, + couch_util:get_value(<<"roles">>, UserProps) + ) + end + end, maybe_validate_user_creds(Resp). update_user_creds(_Req, UserDoc, _Ctx) -> @@ -109,19 +118,23 @@ handle_call(_Call, _From, State) -> handle_cast(_Msg, State) -> {noreply, State}. -handle_info({'DOWN', _, _, Pid, Reason}, #state{changes_pid=Pid} = State) -> - Seq = case Reason of - {seq, EndSeq} -> - EndSeq; - {database_does_not_exist, _} -> - couch_log:notice("~p changes listener died because the _users database does not exist. Create the database to silence this notice.", [?MODULE]), - 0; - _ -> - couch_log:notice("~p changes listener died ~r", [?MODULE, Reason]), - 0 - end, +handle_info({'DOWN', _, _, Pid, Reason}, #state{changes_pid = Pid} = State) -> + Seq = + case Reason of + {seq, EndSeq} -> + EndSeq; + {database_does_not_exist, _} -> + couch_log:notice( + "~p changes listener died because the _users database does not exist. Create the database to silence this notice.", + [?MODULE] + ), + 0; + _ -> + couch_log:notice("~p changes listener died ~r", [?MODULE, Reason]), + 0 + end, erlang:send_after(5000, self(), {start_listener, Seq}), - {noreply, State#state{last_seq=Seq}}; + {noreply, State#state{last_seq = Seq}}; handle_info({start_listener, Seq}, State) -> {noreply, State#state{changes_pid = spawn_changes(Seq)}}; handle_info(_Msg, State) -> @@ -132,7 +145,7 @@ terminate(_Reason, #state{changes_pid = Pid}) when is_pid(Pid) -> terminate(_Reason, _State) -> ok. -code_change(_OldVsn, #state{}=State, _Extra) -> +code_change(_OldVsn, #state{} = State, _Extra) -> {ok, State}. %% private functions @@ -175,14 +188,15 @@ changes_callback({error, _}, EndSeq) -> load_user_from_db(UserName) -> try fabric:open_doc(dbname(), docid(UserName), [?ADMIN_CTX, ejson_body, conflicts]) of - {ok, Doc} -> - {Props} = couch_doc:to_json_obj(Doc, []), - Props; - _Else -> - couch_log:debug("no record of user ~s", [UserName]), - nil - catch error:database_does_not_exist -> - nil + {ok, Doc} -> + {Props} = couch_doc:to_json_obj(Doc, []), + Props; + _Else -> + couch_log:debug("no record of user ~s", [UserName]), + nil + catch + error:database_does_not_exist -> + nil end. dbname() -> @@ -196,23 +210,30 @@ username(<<"org.couchdb.user:", UserName/binary>>) -> ensure_auth_ddoc_exists(DbName, DDocId) -> case fabric:open_doc(DbName, DDocId, [?ADMIN_CTX, ejson_body]) of - {not_found, _Reason} -> - {ok, AuthDesign} = couch_auth_cache:auth_design_doc(DDocId), - update_doc_ignoring_conflict(DbName, AuthDesign, [?ADMIN_CTX]); - {ok, Doc} -> - {Props} = couch_doc:to_json_obj(Doc, []), - case couch_util:get_value(<<"validate_doc_update">>, Props, []) of - ?AUTH_DB_DOC_VALIDATE_FUNCTION -> - ok; - _ -> - Props1 = lists:keyreplace(<<"validate_doc_update">>, 1, Props, - {<<"validate_doc_update">>, - ?AUTH_DB_DOC_VALIDATE_FUNCTION}), - update_doc_ignoring_conflict(DbName, couch_doc:from_json_obj({Props1}), [?ADMIN_CTX]) - end; - {error, Reason} -> - couch_log:notice("Failed to ensure auth ddoc ~s/~s exists for reason: ~p", [DbName, DDocId, Reason]), - ok + {not_found, _Reason} -> + {ok, AuthDesign} = couch_auth_cache:auth_design_doc(DDocId), + update_doc_ignoring_conflict(DbName, AuthDesign, [?ADMIN_CTX]); + {ok, Doc} -> + {Props} = couch_doc:to_json_obj(Doc, []), + case couch_util:get_value(<<"validate_doc_update">>, Props, []) of + ?AUTH_DB_DOC_VALIDATE_FUNCTION -> + ok; + _ -> + Props1 = lists:keyreplace( + <<"validate_doc_update">>, + 1, + Props, + {<<"validate_doc_update">>, ?AUTH_DB_DOC_VALIDATE_FUNCTION} + ), + update_doc_ignoring_conflict(DbName, couch_doc:from_json_obj({Props1}), [ + ?ADMIN_CTX + ]) + end; + {error, Reason} -> + couch_log:notice("Failed to ensure auth ddoc ~s/~s exists for reason: ~p", [ + DbName, DDocId, Reason + ]), + ok end, ok. @@ -229,15 +250,18 @@ maybe_validate_user_creds(nil) -> % throws if UserCreds includes a _conflicts member % returns UserCreds otherwise maybe_validate_user_creds(UserCreds) -> - AllowConflictedUserDocs = config:get_boolean("chttpd_auth", "allow_conflicted_user_docs", false), + AllowConflictedUserDocs = config:get_boolean( + "chttpd_auth", "allow_conflicted_user_docs", false + ), case {couch_util:get_value(<<"_conflicts">>, UserCreds), AllowConflictedUserDocs} of {undefined, _} -> {ok, UserCreds, nil}; {_, true} -> {ok, UserCreds, nil}; {_ConflictList, false} -> - throw({unauthorized, - <<"User document conflicts must be resolved before the document", - " is used for authentication purposes.">> - }) + throw( + {unauthorized, + <<"User document conflicts must be resolved before the document", + " is used for authentication purposes.">>} + ) end. |