feat(authn http api): add test case and improve http api spec
This commit is contained in:
parent
327ff8636f
commit
7febcb852a
|
@ -1,11 +1,11 @@
|
|||
emqx_authn: {
|
||||
enable: false
|
||||
authenticators: [
|
||||
{
|
||||
name: "authenticator1"
|
||||
mechanism: password-based
|
||||
server_type: built-in-database
|
||||
user_id_type: clientid
|
||||
}
|
||||
# {
|
||||
# name: "authenticator1"
|
||||
# mechanism: password-based
|
||||
# server_type: built-in-database
|
||||
# user_id_type: clientid
|
||||
# }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
, provider :: module()
|
||||
, config :: map()
|
||||
, state :: map()
|
||||
, version :: binary()
|
||||
}).
|
||||
|
||||
-record(chain,
|
||||
|
|
|
@ -194,6 +194,10 @@ do_update_authenticator(ChainID, AuthenticatorID, #{name := NewName} = Config, C
|
|||
false ->
|
||||
case CreateWhenNotFound of
|
||||
true ->
|
||||
case lists:keymember(NewName, 2, Authenticators) of
|
||||
true ->
|
||||
{error, name_has_be_used};
|
||||
false ->
|
||||
case do_create_authenticator(ChainID, AuthenticatorID, Config) of
|
||||
{ok, Authenticator} ->
|
||||
NAuthenticators = Authenticators ++ [{AuthenticatorID, NewName, Authenticator}],
|
||||
|
@ -201,13 +205,14 @@ do_update_authenticator(ChainID, AuthenticatorID, #{name := NewName} = Config, C
|
|||
{ok, serialize_authenticator(Authenticator)};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end
|
||||
end;
|
||||
false ->
|
||||
{error, {not_found, {authenticator, AuthenticatorID}}}
|
||||
end;
|
||||
{value,
|
||||
{_, _, #authenticator{provider = Provider,
|
||||
state = #{version := Version} = State}},
|
||||
state = #{version := Version} = State} = Authenticator},
|
||||
Others} ->
|
||||
case lists:keymember(NewName, 2, Others) of
|
||||
true ->
|
||||
|
@ -215,10 +220,10 @@ do_update_authenticator(ChainID, AuthenticatorID, #{name := NewName} = Config, C
|
|||
false ->
|
||||
case (NewProvider = authenticator_provider(Config)) =:= Provider of
|
||||
true ->
|
||||
Unique = {ChainID, AuthenticatorID, Version},
|
||||
Unique = <<ChainID/binary, "/", AuthenticatorID/binary, ":", Version/binary>>,
|
||||
case Provider:update(Config#{'_unique' => Unique}, State) of
|
||||
{ok, NewState} ->
|
||||
NewAuthenticator = #authenticator{name = NewName,
|
||||
NewAuthenticator = Authenticator#authenticator{name = NewName,
|
||||
config = Config,
|
||||
state = switch_version(NewState)},
|
||||
NewAuthenticators = replace_authenticator(AuthenticatorID, NewAuthenticator, Authenticators),
|
||||
|
@ -228,9 +233,10 @@ do_update_authenticator(ChainID, AuthenticatorID, #{name := NewName} = Config, C
|
|||
{error, Reason}
|
||||
end;
|
||||
false ->
|
||||
case NewProvider:create(Config#{'_unique' => {ChainID, AuthenticatorID, Version}}) of
|
||||
Unique = <<ChainID/binary, "/", AuthenticatorID/binary, ":", Version/binary>>,
|
||||
case NewProvider:create(Config#{'_unique' => Unique}) of
|
||||
{ok, NewState} ->
|
||||
NewAuthenticator = #authenticator{name = NewName,
|
||||
NewAuthenticator = Authenticator#authenticator{name = NewName,
|
||||
provider = NewProvider,
|
||||
config = Config,
|
||||
state = switch_version(NewState)},
|
||||
|
|
|
@ -29,6 +29,56 @@
|
|||
, users2/2
|
||||
]).
|
||||
|
||||
-define(EXAMPLE_1, #{name => <<"example 1">>,
|
||||
mechanism => <<"password-based">>,
|
||||
server_type => <<"built-in-example">>,
|
||||
user_id_type => <<"username">>,
|
||||
password_hash_algorithm => #{
|
||||
name => <<"sha256">>
|
||||
}}).
|
||||
|
||||
-define(EXAMPLE_2, #{name => <<"example 2">>,
|
||||
mechanism => <<"password-based">>,
|
||||
server_type => <<"http-server">>,
|
||||
method => <<"post">>,
|
||||
url => <<"http://localhost:80/login">>,
|
||||
headers => #{
|
||||
<<"content-type">> => <<"application/json">>
|
||||
},
|
||||
form_data => #{
|
||||
<<"username">> => <<"${mqtt-username}">>,
|
||||
<<"password">> => <<"${mqtt-password}">>
|
||||
}}).
|
||||
|
||||
-define(EXAMPLE_3, #{name => <<"example 3">>,
|
||||
mechanism => <<"jwt">>,
|
||||
use_jwks => false,
|
||||
algorithm => <<"hmac-based">>,
|
||||
secret => <<"mysecret">>,
|
||||
secret_base64_encoded => false,
|
||||
verify_claims => #{
|
||||
<<"username">> => <<"${mqtt-username}">>
|
||||
}}).
|
||||
|
||||
-define(ERR_RESPONSE(Desc), #{description => Desc,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>),
|
||||
examples => #{
|
||||
example1 => #{
|
||||
summary => <<"Not Found">>,
|
||||
value => #{code => <<"NOT_FOUND">>, message => <<"Authenticator '67e4c9d3' does not exist">>}
|
||||
},
|
||||
example2 => #{
|
||||
summary => <<"Conflict">>,
|
||||
value => #{code => <<"ALREADY_EXISTS">>, message => <<"Name has be used">>}
|
||||
},
|
||||
example3 => #{
|
||||
summary => <<"Bad Request 1">>,
|
||||
value => #{code => <<"OUT_OF_RANGE">>, message => <<"Out of range">>}
|
||||
}
|
||||
}}}}).
|
||||
|
||||
api_spec() ->
|
||||
{[ authenticators_api()
|
||||
, authenticators_api2()
|
||||
|
@ -39,40 +89,6 @@ api_spec() ->
|
|||
], definitions()}.
|
||||
|
||||
authenticators_api() ->
|
||||
Example1 = #{name => <<"example">>,
|
||||
mechanism => <<"password-based">>,
|
||||
config => #{
|
||||
server_type => <<"built-in-example">>,
|
||||
user_id_type => <<"username">>,
|
||||
password_hash_algorithm => #{
|
||||
name => <<"sha256">>
|
||||
}
|
||||
}},
|
||||
Example2 = #{name => <<"example">>,
|
||||
mechanism => <<"password-based">>,
|
||||
config => #{
|
||||
server_type => <<"http-server">>,
|
||||
method => <<"post">>,
|
||||
url => <<"http://localhost:80/login">>,
|
||||
headers => #{
|
||||
<<"content-type">> => <<"application/json">>
|
||||
},
|
||||
form_data => #{
|
||||
<<"username">> => <<"${mqtt-username}">>,
|
||||
<<"password">> => <<"${mqtt-password}">>
|
||||
}
|
||||
}},
|
||||
Example3 = #{name => <<"example">>,
|
||||
mechanism => <<"jwt">>,
|
||||
config => #{
|
||||
use_jwks => false,
|
||||
algorithm => <<"hmac-based">>,
|
||||
secret => <<"mysecret">>,
|
||||
secret_base64_encoded => false,
|
||||
verify_claims => #{
|
||||
<<"username">> => <<"${mqtt-username}">>
|
||||
}
|
||||
}},
|
||||
Metadata = #{
|
||||
post => #{
|
||||
description => "Create authenticator",
|
||||
|
@ -83,15 +99,15 @@ authenticators_api() ->
|
|||
examples => #{
|
||||
default => #{
|
||||
summary => <<"Default">>,
|
||||
value => emqx_json:encode(Example1)
|
||||
value => emqx_json:encode(?EXAMPLE_1)
|
||||
},
|
||||
http => #{
|
||||
summary => <<"Authentication provided by HTTP Server">>,
|
||||
value => emqx_json:encode(Example2)
|
||||
value => emqx_json:encode(?EXAMPLE_2)
|
||||
},
|
||||
jwt => #{
|
||||
summary => <<"JWT Authentication">>,
|
||||
value => emqx_json:encode(Example3)
|
||||
value => emqx_json:encode(?EXAMPLE_3)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,12 +118,28 @@ authenticators_api() ->
|
|||
description => <<"Created">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"returned_authenticator">>)
|
||||
schema => minirest:ref(<<"returned_authenticator">>),
|
||||
examples => #{
|
||||
example1 => #{
|
||||
summary => <<"Example 1">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 1">>, ?EXAMPLE_1))
|
||||
},
|
||||
example2 => #{
|
||||
summary => <<"Example 2">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 2">>, ?EXAMPLE_2))
|
||||
},
|
||||
example3 => #{
|
||||
summary => <<"Example 3">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 3">>, ?EXAMPLE_3))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
<<"400">> => ?ERR_RESPONSE(<<"Bad Request">>),
|
||||
<<"409">> => ?ERR_RESPONSE(<<"Conflict">>)
|
||||
}
|
||||
},
|
||||
get => #{
|
||||
description => "List authenticators",
|
||||
responses => #{
|
||||
|
@ -118,6 +150,15 @@ authenticators_api() ->
|
|||
schema => #{
|
||||
type => array,
|
||||
items => minirest:ref(<<"returned_authenticator">>)
|
||||
},
|
||||
examples => #{
|
||||
example1 => #{
|
||||
summary => <<"Example 1">>,
|
||||
value => emqx_json:encode([ maps:put(id, <<"example 1">>, ?EXAMPLE_1)
|
||||
, maps:put(id, <<"example 2">>, ?EXAMPLE_2)
|
||||
, maps:put(id, <<"example 3">>, ?EXAMPLE_3)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,18 +187,25 @@ authenticators_api2() ->
|
|||
description => <<"OK">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"returned_authenticator">>)
|
||||
schema => minirest:ref(<<"returned_authenticator">>),
|
||||
examples => #{
|
||||
example1 => #{
|
||||
summary => <<"Example 1">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 1">>, ?EXAMPLE_1))
|
||||
},
|
||||
example2 => #{
|
||||
summary => <<"Example 2">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 2">>, ?EXAMPLE_2))
|
||||
},
|
||||
example3 => #{
|
||||
summary => <<"Example 3">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 3">>, ?EXAMPLE_3))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
},
|
||||
put => #{
|
||||
|
@ -180,6 +228,16 @@ authenticators_api2() ->
|
|||
, minirest:ref(<<"jwt">>)
|
||||
, minirest:ref(<<"scram">>)
|
||||
]
|
||||
},
|
||||
examples => #{
|
||||
example1 => #{
|
||||
summary => <<"Example 1">>,
|
||||
value => emqx_json:encode(?EXAMPLE_1)
|
||||
},
|
||||
example2 => #{
|
||||
summary => <<"Example 2">>,
|
||||
value => emqx_json:encode(?EXAMPLE_2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,18 +247,27 @@ authenticators_api2() ->
|
|||
description => <<"OK">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"returned_authenticator">>)
|
||||
schema => minirest:ref(<<"returned_authenticator">>),
|
||||
examples => #{
|
||||
example1 => #{
|
||||
summary => <<"Example 1">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 1">>, ?EXAMPLE_1))
|
||||
},
|
||||
example2 => #{
|
||||
summary => <<"Example 2">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 2">>, ?EXAMPLE_2))
|
||||
},
|
||||
example3 => #{
|
||||
summary => <<"Example 3">>,
|
||||
value => emqx_json:encode(maps:put(id, <<"example 3">>, ?EXAMPLE_3))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"400">> => ?ERR_RESPONSE(<<"Bad Request">>),
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>),
|
||||
<<"409">> => ?ERR_RESPONSE(<<"Conflict">>)
|
||||
}
|
||||
},
|
||||
delete => #{
|
||||
|
@ -219,14 +286,7 @@ authenticators_api2() ->
|
|||
<<"204">> => #{
|
||||
description => <<"No Content">>
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -266,14 +326,8 @@ position_api() ->
|
|||
<<"204">> => #{
|
||||
description => <<"No Content">>
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"400">> => ?ERR_RESPONSE(<<"Bad Request">>),
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -312,22 +366,8 @@ import_users_api() ->
|
|||
<<"204">> => #{
|
||||
description => <<"No Content">>
|
||||
},
|
||||
<<"400">> => #{
|
||||
description => <<"Bad Request">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"400">> => ?ERR_RESPONSE(<<"Bad Request">>),
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -382,14 +422,8 @@ users_api() ->
|
|||
}
|
||||
}
|
||||
},
|
||||
<<"400">> => #{
|
||||
description => <<"Bad Request">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"400">> => ?ERR_RESPONSE(<<"Bad Request">>),
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
},
|
||||
get => #{
|
||||
|
@ -423,7 +457,8 @@ users_api() ->
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -486,14 +521,8 @@ users2_api() ->
|
|||
}
|
||||
}
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"400">> => ?ERR_RESPONSE(<<"Bad Request">>),
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
},
|
||||
get => #{
|
||||
|
@ -536,14 +565,7 @@ users2_api() ->
|
|||
}
|
||||
}
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
},
|
||||
delete => #{
|
||||
|
@ -570,14 +592,7 @@ users2_api() ->
|
|||
<<"204">> => #{
|
||||
description => <<"No Content">>
|
||||
},
|
||||
<<"404">> => #{
|
||||
description => <<"Not Found">>,
|
||||
content => #{
|
||||
'application/json' => #{
|
||||
schema => minirest:ref(<<"error">>)
|
||||
}
|
||||
}
|
||||
}
|
||||
<<"404">> => ?ERR_RESPONSE(<<"Not Found">>)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1007,48 +1022,44 @@ authenticators2(delete, Request) ->
|
|||
position(post, Request) ->
|
||||
AuthenticatorID = cowboy_req:binding(id, Request),
|
||||
{ok, Body, _} = cowboy_req:read_body(Request),
|
||||
case emqx_json:decode(Body, [return_maps]) of
|
||||
#{<<"position">> := Position} when is_integer(Position) ->
|
||||
NBody = emqx_json:decode(Body, [return_maps]),
|
||||
Config = hocon_schema:check_plain(emqx_authn_other_schema, #{<<"position">> => NBody},
|
||||
#{nullable => true}, ["position"]),
|
||||
#{position := #{position := Position}} = emqx_map_lib:unsafe_atom_key_map(Config),
|
||||
case emqx_authn:move_authenticator_to_the_nth(?CHAIN, AuthenticatorID, Position) of
|
||||
ok ->
|
||||
{204};
|
||||
{error, Reason} ->
|
||||
serialize_error(Reason)
|
||||
end;
|
||||
_ ->
|
||||
serialize_error({missing_parameter, position})
|
||||
end.
|
||||
|
||||
import_users(post, Request) ->
|
||||
AuthenticatorID = cowboy_req:binding(id, Request),
|
||||
{ok, Body, _} = cowboy_req:read_body(Request),
|
||||
case emqx_json:decode(Body, [return_maps]) of
|
||||
#{<<"filename">> := Filename} when is_binary(Filename) ->
|
||||
NBody = emqx_json:decode(Body, [return_maps]),
|
||||
Config = hocon_schema:check_plain(emqx_authn_other_schema, #{<<"filename">> => NBody},
|
||||
#{nullable => true}, ["filename"]),
|
||||
#{filename := #{filename := Filename}} = emqx_map_lib:unsafe_atom_key_map(Config),
|
||||
case emqx_authn:import_users(?CHAIN, AuthenticatorID, Filename) of
|
||||
ok ->
|
||||
{204};
|
||||
{error, Reason} ->
|
||||
serialize_error(Reason)
|
||||
end;
|
||||
_ ->
|
||||
serialize_error({missing_parameter, filename})
|
||||
end.
|
||||
|
||||
users(post, Request) ->
|
||||
AuthenticatorID = cowboy_req:binding(id, Request),
|
||||
{ok, Body, _} = cowboy_req:read_body(Request),
|
||||
case emqx_json:decode(Body, [return_maps]) of
|
||||
#{<<"user_id">> := _,
|
||||
<<"password">> := _} = UserInfo ->
|
||||
NBody = emqx_json:decode(Body, [return_maps]),
|
||||
Config = hocon_schema:check_plain(emqx_authn_other_schema, #{<<"user_info">> => NBody},
|
||||
#{nullable => true}, ["user_info"]),
|
||||
#{user_info := UserInfo} = emqx_map_lib:unsafe_atom_key_map(Config),
|
||||
case emqx_authn:add_user(?CHAIN, AuthenticatorID, UserInfo) of
|
||||
{ok, User} ->
|
||||
{201, User};
|
||||
{error, Reason} ->
|
||||
serialize_error(Reason)
|
||||
end;
|
||||
_ ->
|
||||
serialize_error({missing_parameter, user_id})
|
||||
end;
|
||||
users(get, Request) ->
|
||||
AuthenticatorID = cowboy_req:binding(id, Request),
|
||||
case emqx_authn:list_users(?CHAIN, AuthenticatorID) of
|
||||
|
@ -1062,17 +1073,16 @@ users2(patch, Request) ->
|
|||
AuthenticatorID = cowboy_req:binding(id, Request),
|
||||
UserID = cowboy_req:binding(user_id, Request),
|
||||
{ok, Body, _} = cowboy_req:read_body(Request),
|
||||
case emqx_json:decode(Body, [return_maps]) of
|
||||
#{<<"password">> := _} = UserInfo ->
|
||||
case emqx_authn:add_user(?CHAIN, AuthenticatorID, UserID, UserInfo) of
|
||||
NBody = emqx_json:decode(Body, [return_maps]),
|
||||
Config = hocon_schema:check_plain(emqx_authn_other_schema, #{<<"new_user_info">> => NBody},
|
||||
#{nullable => true}, ["new_user_info"]),
|
||||
#{new_user_info := NewUserInfo} = emqx_map_lib:unsafe_atom_key_map(Config),
|
||||
case emqx_authn:update_user(?CHAIN, AuthenticatorID, UserID, NewUserInfo) of
|
||||
{ok, User} ->
|
||||
{200, User};
|
||||
{error, Reason} ->
|
||||
serialize_error(Reason)
|
||||
end;
|
||||
_ ->
|
||||
serialize_error({missing_parameter, password})
|
||||
end;
|
||||
users2(get, Request) ->
|
||||
AuthenticatorID = cowboy_req:binding(id, Request),
|
||||
UserID = cowboy_req:binding(user_id, Request),
|
||||
|
@ -1106,6 +1116,6 @@ serialize_error({missing_parameter, Name}) ->
|
|||
message => list_to_binary(
|
||||
io_lib:format("The input parameter '~p' that is mandatory for processing this request is not supplied", [Name])
|
||||
)}};
|
||||
serialize_error(_) ->
|
||||
serialize_error(Reason) ->
|
||||
{400, #{code => <<"BAD_REQUEST">>,
|
||||
message => <<"Todo">>}}.
|
||||
message => list_to_binary(io_lib:format("Todo: ~p", [Reason]))}}.
|
|
@ -133,8 +133,8 @@ destroy(#{user_group := UserGroup}) ->
|
|||
end).
|
||||
|
||||
%% TODO: binary to atom
|
||||
add_user(#{<<"user_id">> := UserID,
|
||||
<<"password">> := Password}, #{user_group := UserGroup} = State) ->
|
||||
add_user(#{user_id := UserID,
|
||||
password := Password}, #{user_group := UserGroup} = State) ->
|
||||
trans(
|
||||
fun() ->
|
||||
case mnesia:read(?TAB, {UserGroup, UserID}, write) of
|
||||
|
@ -157,7 +157,7 @@ delete_user(UserID, #{user_group := UserGroup}) ->
|
|||
end
|
||||
end).
|
||||
|
||||
update_user(UserID, #{<<"password">> := Password},
|
||||
update_user(UserID, #{password := Password},
|
||||
#{user_group := UserGroup} = State) ->
|
||||
trans(
|
||||
fun() ->
|
||||
|
|
|
@ -178,8 +178,8 @@ import_users(Filename0, State) ->
|
|||
{error, {unsupported_file_format, Extension}}
|
||||
end.
|
||||
|
||||
add_user(#{<<"user_id">> := UserID,
|
||||
<<"password">> := Password},
|
||||
add_user(#{user_id := UserID,
|
||||
password := Password},
|
||||
#{user_group := UserGroup} = State) ->
|
||||
trans(
|
||||
fun() ->
|
||||
|
@ -203,7 +203,7 @@ delete_user(UserID, #{user_group := UserGroup}) ->
|
|||
end
|
||||
end).
|
||||
|
||||
update_user(UserID, #{<<"password">> := Password},
|
||||
update_user(UserID, #{password := Password},
|
||||
#{user_group := UserGroup} = State) ->
|
||||
trans(
|
||||
fun() ->
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_authn_other_schema).
|
||||
|
||||
-include("emqx_authn.hrl").
|
||||
-include_lib("typerefl/include/types.hrl").
|
||||
|
||||
-behaviour(hocon_schema).
|
||||
|
||||
-export([ structs/0
|
||||
, fields/1
|
||||
]).
|
||||
|
||||
structs() -> [ "filename", "position", "user_info", "new_user_info"].
|
||||
|
||||
fields("filename") ->
|
||||
[ {filename, fun filename/1} ];
|
||||
fields("position") ->
|
||||
[ {position, fun position/1} ];
|
||||
fields("user_info") ->
|
||||
[ {user_id, fun user_id/1}
|
||||
, {password, fun password/1}
|
||||
];
|
||||
fields("new_user_info") ->
|
||||
[ {password, fun password/1}
|
||||
].
|
||||
|
||||
filename(type) -> string();
|
||||
filename(nullable) -> false;
|
||||
filename(_) -> undefined.
|
||||
|
||||
position(type) -> integer();
|
||||
position(validate) -> [fun (Position) -> Position > 0 end];
|
||||
position(nullable) -> false;
|
||||
position(_) -> undefined.
|
||||
|
||||
user_id(type) -> binary();
|
||||
user_id(nullable) -> false;
|
||||
user_id(_) -> undefined.
|
||||
|
||||
password(type) -> binary();
|
||||
password(nullable) -> false;
|
||||
password(_) -> undefined.
|
||||
|
|
@ -54,34 +54,44 @@ t_authenticator(_) ->
|
|||
AuthenticatorName1 = <<"myauthenticator1">>,
|
||||
AuthenticatorConfig1 = #{name => AuthenticatorName1,
|
||||
mechanism => 'password-based',
|
||||
config => #{
|
||||
server_type => 'built-in-database',
|
||||
user_id_type => username,
|
||||
password_hash_algorithm => #{
|
||||
name => sha256
|
||||
}}},
|
||||
?assertEqual({ok, AuthenticatorConfig1}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig1)),
|
||||
?assertEqual({ok, AuthenticatorConfig1}, ?AUTH:lookup_authenticator(?CHAIN, AuthenticatorName1)),
|
||||
?assertEqual({ok, [AuthenticatorConfig1]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
?assertEqual({error, {already_exists, {authenticator, AuthenticatorName1}}}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig1)),
|
||||
}},
|
||||
{ok, #{name := AuthenticatorName1, id := ID1}} = ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig1),
|
||||
?assertMatch({ok, #{name := AuthenticatorName1}}, ?AUTH:lookup_authenticator(?CHAIN, ID1)),
|
||||
?assertMatch({ok, [#{name := AuthenticatorName1}]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
?assertEqual({error, name_has_be_used}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig1)),
|
||||
|
||||
AuthenticatorConfig2 = #{name => AuthenticatorName1,
|
||||
mechanism => jwt,
|
||||
use_jwks => false,
|
||||
algorithm => 'hmac-based',
|
||||
secret => <<"abcdef">>,
|
||||
secret_base64_encoded => false,
|
||||
verify_claims => []},
|
||||
{ok, #{name := AuthenticatorName1, id := ID1, mechanism := jwt}} = ?AUTH:update_authenticator(?CHAIN, ID1, AuthenticatorConfig2),
|
||||
|
||||
ID2 = <<"random">>,
|
||||
?assertEqual({error, {not_found, {authenticator, ID2}}}, ?AUTH:update_authenticator(?CHAIN, ID2, AuthenticatorConfig2)),
|
||||
?assertEqual({error, name_has_be_used}, ?AUTH:update_or_create_authenticator(?CHAIN, ID2, AuthenticatorConfig2)),
|
||||
|
||||
AuthenticatorName2 = <<"myauthenticator2">>,
|
||||
AuthenticatorConfig2 = AuthenticatorConfig1#{name => AuthenticatorName2},
|
||||
?assertEqual({ok, AuthenticatorConfig2}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig2)),
|
||||
?assertMatch({ok, #{id := ?CHAIN, authenticators := [AuthenticatorConfig1, AuthenticatorConfig2]}}, ?AUTH:lookup_chain(?CHAIN)),
|
||||
?assertEqual({ok, AuthenticatorConfig2}, ?AUTH:lookup_authenticator(?CHAIN, AuthenticatorName2)),
|
||||
?assertEqual({ok, [AuthenticatorConfig1, AuthenticatorConfig2]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
AuthenticatorConfig3 = AuthenticatorConfig2#{name => AuthenticatorName2},
|
||||
{ok, #{name := AuthenticatorName2, id := ID2, secret := <<"abcdef">>}} = ?AUTH:update_or_create_authenticator(?CHAIN, ID2, AuthenticatorConfig3),
|
||||
?assertMatch({ok, #{name := AuthenticatorName2}}, ?AUTH:lookup_authenticator(?CHAIN, ID2)),
|
||||
{ok, #{name := AuthenticatorName2, id := ID2, secret := <<"fedcba">>}} = ?AUTH:update_or_create_authenticator(?CHAIN, ID2, AuthenticatorConfig3#{secret := <<"fedcba">>}),
|
||||
|
||||
?assertEqual(ok, ?AUTH:move_authenticator_to_the_front(?CHAIN, AuthenticatorName2)),
|
||||
?assertEqual({ok, [AuthenticatorConfig2, AuthenticatorConfig1]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
?assertEqual(ok, ?AUTH:move_authenticator_to_the_end(?CHAIN, AuthenticatorName2)),
|
||||
?assertEqual({ok, [AuthenticatorConfig1, AuthenticatorConfig2]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
?assertEqual(ok, ?AUTH:move_authenticator_to_the_nth(?CHAIN, AuthenticatorName2, 1)),
|
||||
?assertEqual({ok, [AuthenticatorConfig2, AuthenticatorConfig1]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
?assertEqual({error, out_of_range}, ?AUTH:move_authenticator_to_the_nth(?CHAIN, AuthenticatorName2, 3)),
|
||||
?assertEqual({error, out_of_range}, ?AUTH:move_authenticator_to_the_nth(?CHAIN, AuthenticatorName2, 0)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName1)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName2)),
|
||||
?assertMatch({ok, #{id := ?CHAIN, authenticators := [#{name := AuthenticatorName1}, #{name := AuthenticatorName2}]}}, ?AUTH:lookup_chain(?CHAIN)),
|
||||
?assertMatch({ok, [#{name := AuthenticatorName1}, #{name := AuthenticatorName2}]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
|
||||
?assertEqual(ok, ?AUTH:move_authenticator_to_the_nth(?CHAIN, ID2, 1)),
|
||||
?assertMatch({ok, [#{name := AuthenticatorName2}, #{name := AuthenticatorName1}]}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
?assertEqual({error, out_of_range}, ?AUTH:move_authenticator_to_the_nth(?CHAIN, ID2, 3)),
|
||||
?assertEqual({error, out_of_range}, ?AUTH:move_authenticator_to_the_nth(?CHAIN, ID2, 0)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID1)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID2)),
|
||||
?assertEqual({ok, []}, ?AUTH:list_authenticators(?CHAIN)),
|
||||
ok.
|
||||
|
||||
|
|
|
@ -39,15 +39,14 @@ end_per_suite(_) ->
|
|||
|
||||
t_jwt_authenticator(_) ->
|
||||
AuthenticatorName = <<"myauthenticator">>,
|
||||
Config = #{use_jwks => false,
|
||||
Config = #{name => AuthenticatorName,
|
||||
mechanism => jwt,
|
||||
use_jwks => false,
|
||||
algorithm => 'hmac-based',
|
||||
secret => <<"abcdef">>,
|
||||
secret_base64_encoded => false,
|
||||
verify_claims => []},
|
||||
AuthenticatorConfig = #{name => AuthenticatorName,
|
||||
mechanism => jwt,
|
||||
config => Config},
|
||||
?assertEqual({ok, AuthenticatorConfig}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig)),
|
||||
{ok, #{name := AuthenticatorName, id := ID}} = ?AUTH:create_authenticator(?CHAIN, Config),
|
||||
|
||||
Payload = #{<<"username">> => <<"myuser">>},
|
||||
JWS = generate_jws('hmac-based', Payload, <<"abcdef">>),
|
||||
|
@ -62,11 +61,11 @@ t_jwt_authenticator(_) ->
|
|||
%% secret_base64_encoded
|
||||
Config2 = Config#{secret => base64:encode(<<"abcdef">>),
|
||||
secret_base64_encoded => true},
|
||||
?assertMatch({ok, _}, ?AUTH:update_authenticator(?CHAIN, AuthenticatorName, Config2)),
|
||||
?assertMatch({ok, _}, ?AUTH:update_authenticator(?CHAIN, ID, Config2)),
|
||||
?assertEqual({stop, ok}, ?AUTH:authenticate(ClientInfo, ok)),
|
||||
|
||||
Config3 = Config#{verify_claims => [{<<"username">>, <<"${mqtt-username}">>}]},
|
||||
?assertMatch({ok, _}, ?AUTH:update_authenticator(?CHAIN, AuthenticatorName, Config3)),
|
||||
?assertMatch({ok, _}, ?AUTH:update_authenticator(?CHAIN, ID, Config3)),
|
||||
?assertEqual({stop, ok}, ?AUTH:authenticate(ClientInfo, ok)),
|
||||
?assertEqual({stop, {error, bad_username_or_password}}, ?AUTH:authenticate(ClientInfo#{username => <<"otheruser">>}, ok)),
|
||||
|
||||
|
@ -109,7 +108,7 @@ t_jwt_authenticator(_) ->
|
|||
ClientInfo8 = ClientInfo#{password => JWS8},
|
||||
?assertEqual({stop, {error, bad_username_or_password}}, ?AUTH:authenticate(ClientInfo8, ok)),
|
||||
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID)),
|
||||
ok.
|
||||
|
||||
t_jwt_authenticator2(_) ->
|
||||
|
@ -117,14 +116,13 @@ t_jwt_authenticator2(_) ->
|
|||
PublicKey = list_to_binary(filename:join([Dir, "data/public_key.pem"])),
|
||||
PrivateKey = list_to_binary(filename:join([Dir, "data/private_key.pem"])),
|
||||
AuthenticatorName = <<"myauthenticator">>,
|
||||
Config = #{use_jwks => false,
|
||||
Config = #{name => AuthenticatorName,
|
||||
mechanism => jwt,
|
||||
use_jwks => false,
|
||||
algorithm => 'public-key',
|
||||
certificate => PublicKey,
|
||||
verify_claims => []},
|
||||
AuthenticatorConfig = #{name => AuthenticatorName,
|
||||
mechanism => jwt,
|
||||
config => Config},
|
||||
?assertEqual({ok, AuthenticatorConfig}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig)),
|
||||
{ok, #{name := AuthenticatorName, id := ID}} = ?AUTH:create_authenticator(?CHAIN, Config),
|
||||
|
||||
Payload = #{<<"username">> => <<"myuser">>},
|
||||
JWS = generate_jws('public-key', Payload, PrivateKey),
|
||||
|
@ -133,7 +131,7 @@ t_jwt_authenticator2(_) ->
|
|||
?assertEqual({stop, ok}, ?AUTH:authenticate(ClientInfo, ok)),
|
||||
?assertEqual({stop, {error, not_authorized}}, ?AUTH:authenticate(ClientInfo#{password => <<"badpassword">>}, ok)),
|
||||
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID)),
|
||||
ok.
|
||||
|
||||
generate_jws('hmac-based', Payload, Secret) ->
|
||||
|
|
|
@ -41,18 +41,17 @@ t_mnesia_authenticator(_) ->
|
|||
AuthenticatorName = <<"myauthenticator">>,
|
||||
AuthenticatorConfig = #{name => AuthenticatorName,
|
||||
mechanism => 'password-based',
|
||||
config => #{
|
||||
server_type => 'built-in-database',
|
||||
user_id_type => username,
|
||||
password_hash_algorithm => #{
|
||||
name => sha256
|
||||
}}},
|
||||
?assertEqual({ok, AuthenticatorConfig}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig)),
|
||||
}},
|
||||
{ok, #{name := AuthenticatorName, id := ID}} = ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig),
|
||||
|
||||
UserInfo = #{<<"user_id">> => <<"myuser">>,
|
||||
<<"password">> => <<"mypass">>},
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:add_user(?CHAIN, AuthenticatorName, UserInfo)),
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:lookup_user(?CHAIN, AuthenticatorName, <<"myuser">>)),
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:add_user(?CHAIN, ID, UserInfo)),
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:lookup_user(?CHAIN, ID, <<"myuser">>)),
|
||||
|
||||
ClientInfo = #{zone => external,
|
||||
username => <<"myuser">>,
|
||||
|
@ -70,39 +69,38 @@ t_mnesia_authenticator(_) ->
|
|||
?assertEqual({error, bad_username_or_password}, emqx_access_control:authenticate(ClientInfo3)),
|
||||
|
||||
UserInfo2 = UserInfo#{<<"password">> => <<"mypass2">>},
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:update_user(?CHAIN, AuthenticatorName, <<"myuser">>, UserInfo2)),
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:update_user(?CHAIN, ID, <<"myuser">>, UserInfo2)),
|
||||
ClientInfo4 = ClientInfo#{password => <<"mypass2">>},
|
||||
?assertEqual({stop, ok}, ?AUTH:authenticate(ClientInfo4, ok)),
|
||||
|
||||
?assertEqual(ok, ?AUTH:delete_user(?CHAIN, AuthenticatorName, <<"myuser">>)),
|
||||
?assertEqual({error, not_found}, ?AUTH:lookup_user(?CHAIN, AuthenticatorName, <<"myuser">>)),
|
||||
?assertEqual(ok, ?AUTH:delete_user(?CHAIN, ID, <<"myuser">>)),
|
||||
?assertEqual({error, not_found}, ?AUTH:lookup_user(?CHAIN, ID, <<"myuser">>)),
|
||||
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:add_user(?CHAIN, AuthenticatorName, UserInfo)),
|
||||
?assertMatch({ok, #{user_id := <<"myuser">>}}, ?AUTH:lookup_user(?CHAIN, AuthenticatorName, <<"myuser">>)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName)),
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}}, ?AUTH:add_user(?CHAIN, ID, UserInfo)),
|
||||
?assertMatch({ok, #{user_id := <<"myuser">>}}, ?AUTH:lookup_user(?CHAIN, ID, <<"myuser">>)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID)),
|
||||
|
||||
?assertEqual({ok, AuthenticatorConfig}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig)),
|
||||
?assertMatch({error, not_found}, ?AUTH:lookup_user(?CHAIN, AuthenticatorName, <<"myuser">>)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName)),
|
||||
{ok, #{name := AuthenticatorName, id := ID1}} = ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig),
|
||||
?assertMatch({error, not_found}, ?AUTH:lookup_user(?CHAIN, ID1, <<"myuser">>)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID1)),
|
||||
ok.
|
||||
|
||||
t_import(_) ->
|
||||
AuthenticatorName = <<"myauthenticator">>,
|
||||
AuthenticatorConfig = #{name => AuthenticatorName,
|
||||
mechanism => 'password-based',
|
||||
config => #{
|
||||
server_type => 'built-in-database',
|
||||
user_id_type => username,
|
||||
password_hash_algorithm => #{
|
||||
name => sha256
|
||||
}}},
|
||||
?assertEqual({ok, AuthenticatorConfig}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig)),
|
||||
}},
|
||||
{ok, #{name := AuthenticatorName, id := ID}} = ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig),
|
||||
|
||||
Dir = code:lib_dir(emqx_authn, test),
|
||||
?assertEqual(ok, ?AUTH:import_users(?CHAIN, AuthenticatorName, filename:join([Dir, "data/user-credentials.json"]))),
|
||||
?assertEqual(ok, ?AUTH:import_users(?CHAIN, AuthenticatorName, filename:join([Dir, "data/user-credentials.csv"]))),
|
||||
?assertMatch({ok, #{user_id := <<"myuser1">>}}, ?AUTH:lookup_user(?CHAIN, AuthenticatorName, <<"myuser1">>)),
|
||||
?assertMatch({ok, #{user_id := <<"myuser3">>}}, ?AUTH:lookup_user(?CHAIN, AuthenticatorName, <<"myuser3">>)),
|
||||
?assertEqual(ok, ?AUTH:import_users(?CHAIN, ID, filename:join([Dir, "data/user-credentials.json"]))),
|
||||
?assertEqual(ok, ?AUTH:import_users(?CHAIN, ID, filename:join([Dir, "data/user-credentials.csv"]))),
|
||||
?assertMatch({ok, #{user_id := <<"myuser1">>}}, ?AUTH:lookup_user(?CHAIN, ID, <<"myuser1">>)),
|
||||
?assertMatch({ok, #{user_id := <<"myuser3">>}}, ?AUTH:lookup_user(?CHAIN, ID, <<"myuser3">>)),
|
||||
|
||||
ClientInfo1 = #{username => <<"myuser1">>,
|
||||
password => <<"mypassword1">>},
|
||||
|
@ -110,37 +108,35 @@ t_import(_) ->
|
|||
ClientInfo2 = ClientInfo1#{username => <<"myuser3">>,
|
||||
password => <<"mypassword3">>},
|
||||
?assertEqual({stop, ok}, ?AUTH:authenticate(ClientInfo2, ok)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID)),
|
||||
ok.
|
||||
|
||||
t_multi_mnesia_authenticator(_) ->
|
||||
AuthenticatorName1 = <<"myauthenticator1">>,
|
||||
AuthenticatorConfig1 = #{name => AuthenticatorName1,
|
||||
mechanism => 'password-based',
|
||||
config => #{
|
||||
server_type => 'built-in-database',
|
||||
user_id_type => username,
|
||||
password_hash_algorithm => #{
|
||||
name => sha256
|
||||
}}},
|
||||
}},
|
||||
AuthenticatorName2 = <<"myauthenticator2">>,
|
||||
AuthenticatorConfig2 = #{name => AuthenticatorName2,
|
||||
mechanism => 'password-based',
|
||||
config => #{
|
||||
server_type => 'built-in-database',
|
||||
user_id_type => clientid,
|
||||
password_hash_algorithm => #{
|
||||
name => sha256
|
||||
}}},
|
||||
?assertEqual({ok, AuthenticatorConfig1}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig1)),
|
||||
?assertEqual({ok, AuthenticatorConfig2}, ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig2)),
|
||||
}},
|
||||
{ok, #{name := AuthenticatorName1, id := ID1}} = ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig1),
|
||||
{ok, #{name := AuthenticatorName2, id := ID2}} = ?AUTH:create_authenticator(?CHAIN, AuthenticatorConfig2),
|
||||
|
||||
?assertEqual({ok, #{user_id => <<"myuser">>}},
|
||||
?AUTH:add_user(?CHAIN, AuthenticatorName1,
|
||||
?AUTH:add_user(?CHAIN, ID1,
|
||||
#{<<"user_id">> => <<"myuser">>,
|
||||
<<"password">> => <<"mypass1">>})),
|
||||
?assertEqual({ok, #{user_id => <<"myclient">>}},
|
||||
?AUTH:add_user(?CHAIN, AuthenticatorName2,
|
||||
?AUTH:add_user(?CHAIN, ID2,
|
||||
#{<<"user_id">> => <<"myclient">>,
|
||||
<<"password">> => <<"mypass2">>})),
|
||||
|
||||
|
@ -148,12 +144,12 @@ t_multi_mnesia_authenticator(_) ->
|
|||
clientid => <<"myclient">>,
|
||||
password => <<"mypass1">>},
|
||||
?assertEqual({stop, ok}, ?AUTH:authenticate(ClientInfo1, ok)),
|
||||
?assertEqual(ok, ?AUTH:move_authenticator_to_the_front(?CHAIN, AuthenticatorName2)),
|
||||
?assertEqual(ok, ?AUTH:move_authenticator_to_the_nth(?CHAIN, ID2, 1)),
|
||||
|
||||
?assertEqual({stop, {error, bad_username_or_password}}, ?AUTH:authenticate(ClientInfo1, ok)),
|
||||
ClientInfo2 = ClientInfo1#{password => <<"mypass2">>},
|
||||
?assertEqual({stop, ok}, ?AUTH:authenticate(ClientInfo2, ok)),
|
||||
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName1)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, AuthenticatorName2)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID1)),
|
||||
?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID2)),
|
||||
ok.
|
||||
|
|
Loading…
Reference in New Issue