mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
Add auth to mod_http_fileserver
This commit is contained in:
parent
1c90b19d74
commit
995c97671d
@ -56,7 +56,7 @@
|
||||
-record(state,
|
||||
{host, docroot, accesslog, accesslogfd,
|
||||
directory_indices, custom_headers, default_content_type,
|
||||
content_types = []}).
|
||||
content_types = [], user_access = none}).
|
||||
|
||||
-define(PROCNAME, ejabberd_mod_http_fileserver).
|
||||
|
||||
@ -133,7 +133,8 @@ start_link(Host, Opts) ->
|
||||
init([Host, Opts]) ->
|
||||
try initialize(Host, Opts) of
|
||||
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
|
||||
CustomHeaders, DefaultContentType, ContentTypes} ->
|
||||
CustomHeaders, DefaultContentType, ContentTypes,
|
||||
UserAccess} ->
|
||||
{ok, #state{host = Host,
|
||||
accesslog = AccessLog,
|
||||
accesslogfd = AccessLogFD,
|
||||
@ -141,7 +142,8 @@ init([Host, Opts]) ->
|
||||
directory_indices = DirectoryIndices,
|
||||
custom_headers = CustomHeaders,
|
||||
default_content_type = DefaultContentType,
|
||||
content_types = ContentTypes}}
|
||||
content_types = ContentTypes,
|
||||
user_access = UserAccess}}
|
||||
catch
|
||||
throw:Reason ->
|
||||
{stop, Reason}
|
||||
@ -165,7 +167,15 @@ initialize(Host, Opts) ->
|
||||
[]),
|
||||
DefaultContentType = gen_mod:get_opt(default_content_type, Opts,
|
||||
fun iolist_to_binary/1,
|
||||
?DEFAULT_CONTENT_TYPE),
|
||||
?DEFAULT_CONTENT_TYPE),
|
||||
UserAccess0 = gen_mod:get_opt(must_authenticate_with, Opts,
|
||||
mod_opt_type(must_authenticate_with),
|
||||
[]),
|
||||
UserAccess = case UserAccess0 of
|
||||
[] -> none;
|
||||
_ ->
|
||||
dict:from_list(UserAccess0)
|
||||
end,
|
||||
ContentTypes = build_list_content_types(
|
||||
gen_mod:get_opt(content_types, Opts,
|
||||
fun(L) when is_list(L) ->
|
||||
@ -180,7 +190,7 @@ initialize(Host, Opts) ->
|
||||
[str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes],
|
||||
<<", ">>)]),
|
||||
{DocRoot, AccessLog, AccessLogFD, DirectoryIndices,
|
||||
CustomHeaders, DefaultContentType, ContentTypes}.
|
||||
CustomHeaders, DefaultContentType, ContentTypes, UserAccess}.
|
||||
|
||||
|
||||
%% @spec (AdminCTs::[CT], Default::[CT]) -> [CT]
|
||||
@ -246,10 +256,11 @@ try_open_log(FN, Host) ->
|
||||
%% {stop, Reason, State}
|
||||
%% Description: Handling call messages
|
||||
%%--------------------------------------------------------------------
|
||||
handle_call({serve, LocalPath}, _From, State) ->
|
||||
Reply = serve(LocalPath, State#state.docroot, State#state.directory_indices,
|
||||
handle_call({serve, LocalPath, Auth}, _From, State) ->
|
||||
Reply = serve(LocalPath, Auth, State#state.docroot, State#state.directory_indices,
|
||||
State#state.custom_headers,
|
||||
State#state.default_content_type, State#state.content_types),
|
||||
State#state.default_content_type, State#state.content_types,
|
||||
State#state.user_access),
|
||||
{reply, Reply, State};
|
||||
handle_call(_Request, _From, State) ->
|
||||
{reply, ok, State}.
|
||||
@ -305,9 +316,9 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%% @doc Handle an HTTP request.
|
||||
%% LocalPath is the part of the requested URL path that is "local to the module".
|
||||
%% Returns the page to be sent back to the client and/or HTTP status code.
|
||||
process(LocalPath, Request) ->
|
||||
process(LocalPath, #request{host = Host, auth = Auth} = Request) ->
|
||||
?DEBUG("Requested ~p", [LocalPath]),
|
||||
try gen_server:call(get_proc_name(Request#request.host), {serve, LocalPath}) of
|
||||
try gen_server:call(get_proc_name(Host), {serve, LocalPath, Auth}) of
|
||||
{FileSize, Code, Headers, Contents} ->
|
||||
add_to_log(FileSize, Code, Request),
|
||||
{Code, Headers, Contents}
|
||||
@ -318,21 +329,38 @@ process(LocalPath, Request) ->
|
||||
ejabberd_web:error(not_found)
|
||||
end.
|
||||
|
||||
serve(LocalPath, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes) ->
|
||||
FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
|
||||
case file:read_file_info(FileName) of
|
||||
{error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND;
|
||||
{error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND;
|
||||
{error, eacces} -> ?HTTP_ERR_FORBIDDEN;
|
||||
{ok, #file_info{type = directory}} -> serve_index(FileName,
|
||||
DirectoryIndices,
|
||||
CustomHeaders,
|
||||
DefaultContentType,
|
||||
ContentTypes);
|
||||
{ok, FileInfo} -> serve_file(FileInfo, FileName,
|
||||
CustomHeaders,
|
||||
DefaultContentType,
|
||||
ContentTypes)
|
||||
|
||||
serve(LocalPath, Auth, DocRoot, DirectoryIndices, CustomHeaders, DefaultContentType,
|
||||
ContentTypes, UserAccess) ->
|
||||
CanProceed = case {UserAccess, Auth} of
|
||||
{none, _} -> true;
|
||||
{_, {User, Pass}} ->
|
||||
case dict:find(User, UserAccess) of
|
||||
{ok, Pass} -> true;
|
||||
_ -> false
|
||||
end;
|
||||
_ ->
|
||||
false
|
||||
end,
|
||||
case CanProceed of
|
||||
true ->
|
||||
FileName = filename:join(filename:split(DocRoot) ++ LocalPath),
|
||||
case file:read_file_info(FileName) of
|
||||
{error, enoent} -> ?HTTP_ERR_FILE_NOT_FOUND;
|
||||
{error, enotdir} -> ?HTTP_ERR_FILE_NOT_FOUND;
|
||||
{error, eacces} -> ?HTTP_ERR_FORBIDDEN;
|
||||
{ok, #file_info{type = directory}} -> serve_index(FileName,
|
||||
DirectoryIndices,
|
||||
CustomHeaders,
|
||||
DefaultContentType,
|
||||
ContentTypes);
|
||||
{ok, FileInfo} -> serve_file(FileInfo, FileName,
|
||||
CustomHeaders,
|
||||
DefaultContentType,
|
||||
ContentTypes)
|
||||
end;
|
||||
_ ->
|
||||
?HTTP_ERR_FORBIDDEN
|
||||
end.
|
||||
|
||||
%% Troll through the directory indices attempting to find one which
|
||||
@ -466,6 +494,14 @@ mod_opt_type(default_content_type) ->
|
||||
mod_opt_type(directory_indices) ->
|
||||
fun (L) when is_list(L) -> L end;
|
||||
mod_opt_type(docroot) -> fun (A) -> A end;
|
||||
mod_opt_type(must_authenticate_with) ->
|
||||
fun (L) when is_list(L) ->
|
||||
lists:map(fun(UP) when is_binary(UP) ->
|
||||
[K, V] = binary:split(UP, <<":">>),
|
||||
{K, V}
|
||||
end, L)
|
||||
end;
|
||||
mod_opt_type(_) ->
|
||||
[accesslog, content_types, custom_headers,
|
||||
default_content_type, directory_indices, docroot].
|
||||
default_content_type, directory_indices, docroot,
|
||||
must_authenticate_with].
|
||||
|
Loading…
Reference in New Issue
Block a user