|
|
@@ -47,7 +47,6 @@
|
|
|
register_providers/1,
|
|
|
deregister_provider/1,
|
|
|
deregister_providers/1,
|
|
|
- create_chain/1,
|
|
|
delete_chain/1,
|
|
|
lookup_chain/1,
|
|
|
list_chains/0,
|
|
|
@@ -271,7 +270,6 @@ authenticator_id(Config) ->
|
|
|
initialize_authentication(_, []) ->
|
|
|
ok;
|
|
|
initialize_authentication(ChainName, AuthenticatorsConfig) ->
|
|
|
- _ = create_chain(ChainName),
|
|
|
CheckedConfig = to_list(AuthenticatorsConfig),
|
|
|
lists:foreach(
|
|
|
fun(AuthenticatorConfig) ->
|
|
|
@@ -322,10 +320,6 @@ deregister_providers(AuthNTypes) when is_list(AuthNTypes) ->
|
|
|
deregister_provider(AuthNType) ->
|
|
|
deregister_providers([AuthNType]).
|
|
|
|
|
|
--spec create_chain(chain_name()) -> {ok, chain()} | {error, term()}.
|
|
|
-create_chain(Name) ->
|
|
|
- call({create_chain, Name}).
|
|
|
-
|
|
|
-spec delete_chain(chain_name()) -> ok | {error, term()}.
|
|
|
delete_chain(Name) ->
|
|
|
call({delete_chain, Name}).
|
|
|
@@ -451,50 +445,36 @@ handle_call(
|
|
|
end;
|
|
|
handle_call({deregister_providers, AuthNTypes}, _From, #{providers := Providers} = State) ->
|
|
|
reply(ok, State#{providers := maps:without(AuthNTypes, Providers)});
|
|
|
-handle_call({create_chain, Name}, _From, State) ->
|
|
|
- case ets:member(?CHAINS_TAB, Name) of
|
|
|
- true ->
|
|
|
- reply({error, {already_exists, {chain, Name}}}, State);
|
|
|
- false ->
|
|
|
- Chain = #chain{
|
|
|
- name = Name,
|
|
|
- authenticators = []
|
|
|
- },
|
|
|
- true = ets:insert(?CHAINS_TAB, Chain),
|
|
|
- reply({ok, serialize_chain(Chain)}, State)
|
|
|
- end;
|
|
|
-handle_call({delete_chain, Name}, _From, State) ->
|
|
|
- case ets:lookup(?CHAINS_TAB, Name) of
|
|
|
- [] ->
|
|
|
- reply({error, {not_found, {chain, Name}}}, State);
|
|
|
- [#chain{} = Chain] ->
|
|
|
- _MatchedIDs = do_delete_authenticators(fun(_) -> true end, Chain),
|
|
|
- true = ets:delete(?CHAINS_TAB, Name),
|
|
|
- reply(ok, maybe_unhook(State))
|
|
|
- end;
|
|
|
+handle_call({delete_chain, ChainName}, _From, State) ->
|
|
|
+ UpdateFun = fun(Chain) ->
|
|
|
+ {_MatchedIDs, NewChain} = do_delete_authenticators(fun(_) -> true end, Chain),
|
|
|
+ {ok, ok, NewChain}
|
|
|
+ end,
|
|
|
+ Reply = with_chain(ChainName, UpdateFun),
|
|
|
+ reply(Reply, maybe_unhook(State));
|
|
|
handle_call({create_authenticator, ChainName, Config}, _From, #{providers := Providers} = State) ->
|
|
|
UpdateFun = fun(Chain) ->
|
|
|
handle_create_authenticator(Chain, Config, Providers)
|
|
|
end,
|
|
|
- Reply = update_chain(ChainName, UpdateFun),
|
|
|
+ Reply = with_new_chain(ChainName, UpdateFun),
|
|
|
reply(Reply, maybe_hook(State));
|
|
|
handle_call({delete_authenticator, ChainName, AuthenticatorID}, _From, State) ->
|
|
|
UpdateFun = fun(Chain) ->
|
|
|
handle_delete_authenticator(Chain, AuthenticatorID)
|
|
|
end,
|
|
|
- Reply = update_chain(ChainName, UpdateFun),
|
|
|
+ Reply = with_chain(ChainName, UpdateFun),
|
|
|
reply(Reply, maybe_unhook(State));
|
|
|
handle_call({update_authenticator, ChainName, AuthenticatorID, Config}, _From, State) ->
|
|
|
UpdateFun = fun(Chain) ->
|
|
|
handle_update_authenticator(Chain, AuthenticatorID, Config)
|
|
|
end,
|
|
|
- Reply = update_chain(ChainName, UpdateFun),
|
|
|
+ Reply = with_chain(ChainName, UpdateFun),
|
|
|
reply(Reply, State);
|
|
|
handle_call({move_authenticator, ChainName, AuthenticatorID, Position}, _From, State) ->
|
|
|
UpdateFun = fun(Chain) ->
|
|
|
handle_move_authenticator(Chain, AuthenticatorID, Position)
|
|
|
end,
|
|
|
- Reply = update_chain(ChainName, UpdateFun),
|
|
|
+ Reply = with_chain(ChainName, UpdateFun),
|
|
|
reply(Reply, State);
|
|
|
handle_call({import_users, ChainName, AuthenticatorID, Filename}, _From, State) ->
|
|
|
Reply = call_authenticator(ChainName, AuthenticatorID, import_users, [Filename]),
|
|
|
@@ -569,11 +549,9 @@ handle_update_authenticator(Chain, AuthenticatorID, Config) ->
|
|
|
NewAuthenticator,
|
|
|
Authenticators
|
|
|
),
|
|
|
- true = ets:insert(
|
|
|
- ?CHAINS_TAB,
|
|
|
- Chain#chain{authenticators = NewAuthenticators}
|
|
|
- ),
|
|
|
- {ok, serialize_authenticator(NewAuthenticator)};
|
|
|
+ NewChain = Chain#chain{authenticators = NewAuthenticators},
|
|
|
+ Result = {ok, serialize_authenticator(NewAuthenticator)},
|
|
|
+ {ok, Result, NewChain};
|
|
|
{error, Reason} ->
|
|
|
{error, Reason}
|
|
|
end;
|
|
|
@@ -587,18 +565,18 @@ handle_delete_authenticator(Chain, AuthenticatorID) ->
|
|
|
ID =:= AuthenticatorID
|
|
|
end,
|
|
|
case do_delete_authenticators(MatchFun, Chain) of
|
|
|
- [] ->
|
|
|
+ {[], _NewChain} ->
|
|
|
{error, {not_found, {authenticator, AuthenticatorID}}};
|
|
|
- [AuthenticatorID] ->
|
|
|
- ok
|
|
|
+ {[AuthenticatorID], NewChain} ->
|
|
|
+ {ok, ok, NewChain}
|
|
|
end.
|
|
|
|
|
|
handle_move_authenticator(Chain, AuthenticatorID, Position) ->
|
|
|
#chain{authenticators = Authenticators} = Chain,
|
|
|
case do_move_authenticator(AuthenticatorID, Authenticators, Position) of
|
|
|
{ok, NAuthenticators} ->
|
|
|
- true = ets:insert(?CHAINS_TAB, Chain#chain{authenticators = NAuthenticators}),
|
|
|
- ok;
|
|
|
+ NewChain = Chain#chain{authenticators = NAuthenticators},
|
|
|
+ {ok, ok, NewChain};
|
|
|
{error, Reason} ->
|
|
|
{error, Reason}
|
|
|
end.
|
|
|
@@ -616,18 +594,15 @@ handle_create_authenticator(Chain, Config, Providers) ->
|
|
|
NAuthenticators =
|
|
|
Authenticators ++
|
|
|
[Authenticator#authenticator{enable = maps:get(enable, Config)}],
|
|
|
- true = ets:insert(
|
|
|
- ?CHAINS_TAB,
|
|
|
- Chain#chain{authenticators = NAuthenticators}
|
|
|
- ),
|
|
|
-
|
|
|
ok = emqx_metrics_worker:create_metrics(
|
|
|
authn_metrics,
|
|
|
metrics_id(Name, AuthenticatorID),
|
|
|
[total, success, failed, nomatch],
|
|
|
[total]
|
|
|
),
|
|
|
- {ok, serialize_authenticator(Authenticator)};
|
|
|
+ NewChain = Chain#chain{authenticators = NAuthenticators},
|
|
|
+ Result = {ok, serialize_authenticator(Authenticator)},
|
|
|
+ {ok, Result, NewChain};
|
|
|
{error, Reason} ->
|
|
|
{error, Reason}
|
|
|
end
|
|
|
@@ -675,6 +650,14 @@ do_authenticate(
|
|
|
reply(Reply, State) ->
|
|
|
{reply, Reply, State}.
|
|
|
|
|
|
+save_chain(#chain{
|
|
|
+ name = Name,
|
|
|
+ authenticators = []
|
|
|
+}) ->
|
|
|
+ ets:delete(?CHAINS_TAB, Name);
|
|
|
+save_chain(#chain{} = Chain) ->
|
|
|
+ ets:insert(?CHAINS_TAB, Chain).
|
|
|
+
|
|
|
create_chain_table() ->
|
|
|
try
|
|
|
_ = ets:new(?CHAINS_TAB, [
|
|
|
@@ -774,14 +757,7 @@ do_delete_authenticators(MatchFun, #chain{name = Name, authenticators = Authenti
|
|
|
end,
|
|
|
Matching
|
|
|
),
|
|
|
- true =
|
|
|
- case Others of
|
|
|
- [] ->
|
|
|
- ets:delete(?CHAINS_TAB, Name);
|
|
|
- _ ->
|
|
|
- ets:insert(?CHAINS_TAB, Chain#chain{authenticators = Others})
|
|
|
- end,
|
|
|
- MatchingIDs.
|
|
|
+ {MatchingIDs, Chain#chain{authenticators = Others}}.
|
|
|
|
|
|
do_destroy_authenticator(#authenticator{provider = Provider, state = State}) ->
|
|
|
_ = Provider:destroy(State),
|
|
|
@@ -824,21 +800,41 @@ insert(
|
|
|
insert(Authenticator, [Authenticator0 | More], {Relative, RelatedID}, Acc) ->
|
|
|
insert(Authenticator, More, {Relative, RelatedID}, [Authenticator0 | Acc]).
|
|
|
|
|
|
-update_chain(ChainName, UpdateFun) ->
|
|
|
+with_new_chain(ChainName, Fun) ->
|
|
|
+ case ets:lookup(?CHAINS_TAB, ChainName) of
|
|
|
+ [] ->
|
|
|
+ Chain = #chain{name = ChainName, authenticators = []},
|
|
|
+ do_with_chain(Fun, Chain);
|
|
|
+ [Chain] ->
|
|
|
+ do_with_chain(Fun, Chain)
|
|
|
+ end.
|
|
|
+
|
|
|
+with_chain(ChainName, Fun) ->
|
|
|
case ets:lookup(?CHAINS_TAB, ChainName) of
|
|
|
[] ->
|
|
|
{error, {not_found, {chain, ChainName}}};
|
|
|
[Chain] ->
|
|
|
- try
|
|
|
- UpdateFun(Chain)
|
|
|
- catch
|
|
|
- Class:Reason:Stk ->
|
|
|
- {error, {exception, {Class, Reason, Stk}}}
|
|
|
- end
|
|
|
+ do_with_chain(Fun, Chain)
|
|
|
+ end.
|
|
|
+
|
|
|
+do_with_chain(Fun, Chain) ->
|
|
|
+ try
|
|
|
+ case Fun(Chain) of
|
|
|
+ {ok, Result} ->
|
|
|
+ Result;
|
|
|
+ {ok, Result, NewChain} ->
|
|
|
+ save_chain(NewChain),
|
|
|
+ Result;
|
|
|
+ {error, _} = Error ->
|
|
|
+ Error
|
|
|
+ end
|
|
|
+ catch
|
|
|
+ Class:Reason:Stk ->
|
|
|
+ {error, {exception, {Class, Reason, Stk}}}
|
|
|
end.
|
|
|
|
|
|
call_authenticator(ChainName, AuthenticatorID, Func, Args) ->
|
|
|
- UpdateFun =
|
|
|
+ Fun =
|
|
|
fun(#chain{authenticators = Authenticators}) ->
|
|
|
case lists:keyfind(AuthenticatorID, #authenticator.id, Authenticators) of
|
|
|
false ->
|
|
|
@@ -846,13 +842,13 @@ call_authenticator(ChainName, AuthenticatorID, Func, Args) ->
|
|
|
#authenticator{provider = Provider, state = State} ->
|
|
|
case erlang:function_exported(Provider, Func, length(Args) + 1) of
|
|
|
true ->
|
|
|
- erlang:apply(Provider, Func, Args ++ [State]);
|
|
|
+ {ok, erlang:apply(Provider, Func, Args ++ [State])};
|
|
|
false ->
|
|
|
{error, unsupported_operation}
|
|
|
end
|
|
|
end
|
|
|
end,
|
|
|
- update_chain(ChainName, UpdateFun).
|
|
|
+ with_chain(ChainName, Fun).
|
|
|
|
|
|
serialize_chain(#chain{
|
|
|
name = Name,
|