Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 671A11861F for ; Wed, 12 Aug 2015 15:54:25 +0000 (UTC) Received: (qmail 63755 invoked by uid 500); 12 Aug 2015 15:54:25 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 63684 invoked by uid 500); 12 Aug 2015 15:54:25 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 63655 invoked by uid 99); 12 Aug 2015 15:54:25 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 12 Aug 2015 15:54:25 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 1670DDFF41; Wed, 12 Aug 2015 15:54:25 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: rnewson@apache.org To: commits@couchdb.apache.org Date: Wed, 12 Aug 2015 15:54:25 -0000 Message-Id: <4f5debe8615249bda39bc823d0718dfd@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [01/11] chttpd commit: updated refs/heads/master to 238b8c4 Repository: couchdb-chttpd Updated Branches: refs/heads/master a66b901e6 -> 238b8c482 Introduce `chttpd_auth:authenticate` hook Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/90f1aa75 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/90f1aa75 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/90f1aa75 Branch: refs/heads/master Commit: 90f1aa751147f35f823cb33bb53495788c497e05 Parents: a66b901 Author: ILYA Khlopotov Authored: Wed Jul 29 09:40:23 2015 -0700 Committer: ILYA Khlopotov Committed: Tue Aug 11 08:27:51 2015 -0700 ---------------------------------------------------------------------- src/chttpd.erl | 44 +++++++++++++++++++++-------------------- src/chttpd_auth.erl | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ src/chttpd_sup.erl | 10 +++++++++- 3 files changed, 83 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/90f1aa75/src/chttpd.erl ---------------------------------------------------------------------- diff --git a/src/chttpd.erl b/src/chttpd.erl index 22d0656..b6b30de 100644 --- a/src/chttpd.erl +++ b/src/chttpd.erl @@ -27,6 +27,8 @@ send_method_not_allowed/2, send_error/2, send_error/4, send_redirect/2, send_chunked_error/2, send_json/2,send_json/3,send_json/4]). +-export([authenticate_request/3]). + -export([start_delayed_json_response/2, start_delayed_json_response/3, start_delayed_json_response/4, start_delayed_chunked_response/3, start_delayed_chunked_response/4, @@ -143,11 +145,6 @@ handle_request_int(MochiReq) -> ok = mochiweb_socket:setopts(MochiReq:get(socket), SocketOpts) end, - AuthenticationFuns = [ - fun chttpd_auth:cookie_authentication_handler/1, - fun chttpd_auth:default_authentication_handler/1 - ], - % for the path, use the raw path with the query string and fragment % removed, but URL quoting left intact RawUri = MochiReq:get(raw_path), @@ -215,7 +212,7 @@ handle_request_int(MochiReq) -> check_request_uri_length(RawUri), case chttpd_cors:maybe_handle_preflight_request(HttpReq) of not_preflight -> - case authenticate_request(HttpReq, AuthenticationFuns) of + case chttpd_auth:authenticate(HttpReq, fun authenticate_request/1) of #httpd{} = Req -> HandlerFun = chttpd_handlers:url_handler( HandlerKey, fun chttpd_db:handle_request/1), @@ -346,28 +343,33 @@ make_uri(Req, Raw) -> {[{<<"url">>,Url}, {<<"headers">>,{Headers}}]}. %%% end hack +authenticate_request(Req) -> + AuthenticationFuns = [ + {<<"cookie">>, fun chttpd_auth:cookie_authentication_handler/1}, + {<<"default">>, fun chttpd_auth:default_authentication_handler/1}, + {<<"local">>, fun chttpd_auth:party_mode_handler/1} %% should be last + ], + authenticate_request(Req, chttpd_auth_cache, AuthenticationFuns). + +authenticate_request(#httpd{} = Req0, AuthModule, AuthFuns) -> + Req = Req0#httpd{ + auth_module = AuthModule, + authentication_handlers = AuthFuns}, + authenticate_request(Req, AuthFuns). % Try authentication handlers in order until one returns a result authenticate_request(#httpd{user_ctx=#user_ctx{}} = Req, _AuthFuns) -> Req; -authenticate_request(#httpd{} = Req, [AuthFun|Rest]) -> - authenticate_request(AuthFun(Req), Rest); -authenticate_request(#httpd{} = Req, []) -> - case config:get("chttpd", "require_valid_user", "false") of - "true" -> - throw({unauthorized, <<"Authentication required.">>}); - "false" -> - case config:get("admins") of - [] -> - Ctx = #user_ctx{roles=[<<"_reader">>, <<"_writer">>, <<"_admin">>]}, - Req#httpd{user_ctx = Ctx}; - _ -> - Req#httpd{user_ctx=#user_ctx{}} - end - end; +authenticate_request(#httpd{} = Req, [{Name, AuthFun}|Rest]) -> + authenticate_request(maybe_set_handler(AuthFun(Req), Name), Rest); authenticate_request(Response, _AuthFuns) -> Response. +maybe_set_handler(#httpd{user_ctx=#user_ctx{} = UserCtx} = Req, Name) -> + Req#httpd{user_ctx = UserCtx#user_ctx{handler = Name}}; +maybe_set_handler(Else, _) -> + Else. + increment_method_stats(Method) -> couch_stats:increment_counter([couchdb, httpd_request_methods, Method]). http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/90f1aa75/src/chttpd_auth.erl ---------------------------------------------------------------------- diff --git a/src/chttpd_auth.erl b/src/chttpd_auth.erl index 1046538..7a45399 100644 --- a/src/chttpd_auth.erl +++ b/src/chttpd_auth.erl @@ -12,15 +12,66 @@ -module(chttpd_auth). +-export([authenticate/2]). + -export([default_authentication_handler/1]). -export([cookie_authentication_handler/1]). +-export([party_mode_handler/1]). + -export([handle_session_req/1]). +-include_lib("couch/include/couch_db.hrl"). + +-define(SERVICE_ID, chttpd_auth). + + +%% ------------------------------------------------------------------ +%% API Function Definitions +%% ------------------------------------------------------------------ + +authenticate(HttpReq, Default) -> + maybe_handle(authenticate, [HttpReq], Default). + + +%% ------------------------------------------------------------------ +%% Default callbacks +%% ------------------------------------------------------------------ + default_authentication_handler(Req) -> couch_httpd_auth:default_authentication_handler(Req, chttpd_auth_cache). cookie_authentication_handler(Req) -> couch_httpd_auth:cookie_authentication_handler(Req, chttpd_auth_cache). +party_mode_handler(Req) -> + case config:get("chttpd", "require_valid_user", "false") of + "true" -> + throw({unauthorized, <<"Authentication required.">>}); + "false" -> + case config:get("admins") of + [] -> + Ctx = #user_ctx{roles=[<<"_reader">>, <<"_writer">>, <<"_admin">>]}, + Req#httpd{user_ctx = Ctx}; + _ -> + Req#httpd{user_ctx=#user_ctx{}} + end + end. + handle_session_req(Req) -> couch_httpd_auth:handle_session_req(Req, chttpd_auth_cache). + + +%% ------------------------------------------------------------------ +%% Internal Function Definitions +%% ------------------------------------------------------------------ + +maybe_handle(Func, Args, Default) -> + Handle = couch_epi:get_handle(?SERVICE_ID), + case couch_epi:apply(Handle, ?SERVICE_ID, Func, Args, [ignore_providers]) of + [] when is_function(Default) -> + apply(Default, Args); + [] -> + Default; + [Result] -> + Result + end. http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/90f1aa75/src/chttpd_sup.erl ---------------------------------------------------------------------- diff --git a/src/chttpd_sup.erl b/src/chttpd_sup.erl index a4851e2..62d00eb 100644 --- a/src/chttpd_sup.erl +++ b/src/chttpd_sup.erl @@ -26,7 +26,7 @@ init([]) -> chttpd_config_listener:subscribe(), {ok, {{one_for_one, 3, 10}, [ ?CHILD(chttpd, worker), - ?CHILD(chttpd_auth_cache, worker), + ?CHILD(auth_cache_handler(), worker), chttpd_handlers:provider(chttpd, chttpd_httpd_handlers), {chttpd_auth_cache_lru, {ets_lru, start_link, [chttpd_auth_cache_lru, lru_opts()]}, @@ -52,3 +52,11 @@ lru_opts() -> _ -> [] end. + +auth_cache_handler() -> + case application:get_env(chttpd, auth_cache) of + {ok, Module} -> + Module; + _ -> + chttpd_auth_cache + end.