25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-02 16:37:52 +01:00

feat: support loading Elixir modules for auth

Allow to specify an Elixir module name in `auth_method`.

If the referenced module, `M`,  cannot be loaded as `ejabberd_auth_M`,
try to load it as `Elixir.M`.
This commit is contained in:
Marcos de Vera Piquero 2024-11-22 08:30:55 +01:00
parent 715b5b64c6
commit 17b5b34e3c
4 changed files with 58 additions and 5 deletions

View File

@ -0,0 +1,39 @@
defmodule ModAuthExample do
@moduledoc """
This is a dummy auth module to demonstrate the usage of Elixir to
create Ejabberd Auth modules.
"""
import Ejabberd.Logger
@behaviour :ejabberd_auth
@impl true
def start(host) do
info("Using mod_auth_example to authenticate #{host} users")
nil
end
@impl true
def stop(host) do
info("Stop using mod_auth_example to authenticate #{host} users")
nil
end
@impl true
def check_password("alice", _authz_id, _host, "secret"), do: {:nocache, true}
def check_password(_username, _authz_id, _host, _secret), do: {:nocache, false}
@impl true
def user_exists("alice", _host), do: {:nocache, true}
def user_exists(_username, _host), do: {:nocache, false}
@impl true
def plain_password_required(_binary), do: true
@impl true
def store_type(_host), do: :external
@impl true
def use_cache(_host), do: false
end

View File

@ -505,10 +505,15 @@ db_type(M) ->
and_then( and_then(
atom(), atom(),
fun(T) -> fun(T) ->
case code:ensure_loaded(db_module(M, T)) of case code:ensure_loaded(db_module(M, T)) of
{module, _} -> T; {module, _} -> T;
{error, _} -> fail({bad_db_type, M, T}) {error, _} ->
end ElixirModule = "Elixir." ++ atom_to_list(T),
case code:ensure_loaded(list_to_atom(ElixirModule)) of
{module, _} -> list_to_atom(ElixirModule);
{error, _} -> fail({bad_db_type, M, T})
end
end
end). end).
-spec queue_type() -> yconf:validator(ram | file). -spec queue_type() -> yconf:validator(ram | file).

View File

@ -177,6 +177,15 @@ module_name([Dir, _, <<H,_/binary>> | _] = Mod) when H >= 65, H =< 90 ->
Lib -> <<"Elixir.Ejabberd.", Lib/binary, ".">> Lib -> <<"Elixir.Ejabberd.", Lib/binary, ".">>
end, end,
misc:binary_to_atom(<<Prefix/binary, Module/binary>>); misc:binary_to_atom(<<Prefix/binary, Module/binary>>);
module_name([<<"auth">> | T] = Mod) ->
case hd(T) of
%% T already starts with "Elixir" if an Elixir module is
%% loaded with that name, as per `econf:db_type/1`
<<"Elixir", _/binary>> -> misc:binary_to_atom(hd(T));
_ -> module_name([<<"ejabberd">>] ++ Mod)
end;
module_name([<<"ejabberd">> | _] = Mod) -> module_name([<<"ejabberd">> | _] = Mod) ->
Module = str:join([erlang_name(M) || M<-Mod], $_), Module = str:join([erlang_name(M) || M<-Mod], $_),
misc:binary_to_atom(Module); misc:binary_to_atom(Module);

View File

@ -893,7 +893,7 @@ auth_modules() ->
auth_modules(Server) -> auth_modules(Server) ->
LServer = jid:nameprep(Server), LServer = jid:nameprep(Server),
Methods = ejabberd_option:auth_method(LServer), Methods = ejabberd_option:auth_method(LServer),
[ejabberd:module_name([<<"ejabberd">>, <<"auth">>, [ejabberd:module_name([<<"auth">>,
misc:atom_to_binary(M)]) misc:atom_to_binary(M)])
|| M <- Methods]. || M <- Methods].