fix(authn): add timeout option for mysql connector
This commit is contained in:
parent
e737f18548
commit
e31840d943
|
@ -303,8 +303,8 @@ authenticate(#{listener := Listener, protocol := Protocol} = Credential, _AuthRe
|
|||
|
||||
do_authenticate([], _) ->
|
||||
{stop, {error, not_authorized}};
|
||||
do_authenticate([#authenticator{provider = Provider, state = State} | More], Credential) ->
|
||||
case Provider:authenticate(Credential, State) of
|
||||
do_authenticate([#authenticator{provider = Provider, state = #{'_unique' := Unique} = State} | More], Credential) ->
|
||||
try Provider:authenticate(Credential, State) of
|
||||
ignore ->
|
||||
do_authenticate(More, Credential);
|
||||
Result ->
|
||||
|
@ -314,6 +314,10 @@ do_authenticate([#authenticator{provider = Provider, state = State} | More], Cre
|
|||
%% {continue, AuthData, AuthCache}
|
||||
%% {error, Reason}
|
||||
{stop, Result}
|
||||
catch
|
||||
error:Reason:Stacktrace ->
|
||||
?LOG(warning, "The following error occurred in '~s' during authentication: ~p", [Unique, {Reason, Stacktrace}]),
|
||||
do_authenticate(More, Credential)
|
||||
end.
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
|
|
|
@ -156,26 +156,20 @@ authenticate(#{auth_method := _}, _) ->
|
|||
authenticate(Credential, #{'_unique' := Unique,
|
||||
method := Method,
|
||||
request_timeout := RequestTimeout} = State) ->
|
||||
try
|
||||
Request = generate_request(Credential, State),
|
||||
case emqx_resource:query(Unique, {Method, Request, RequestTimeout}) of
|
||||
{ok, 204, _Headers} -> {ok, #{is_superuser => false}};
|
||||
{ok, 200, Headers, Body} ->
|
||||
ContentType = proplists:get_value(<<"content-type">>, Headers, <<"application/json">>),
|
||||
case safely_parse_body(ContentType, Body) of
|
||||
{ok, NBody} ->
|
||||
%% TODO: Return by user property
|
||||
{ok, #{is_superuser => maps:get(<<"is_superuser">>, NBody, false),
|
||||
user_property => NBody}};
|
||||
{error, _Reason} ->
|
||||
{ok, #{is_superuser => false}}
|
||||
end;
|
||||
{error, _Reason} ->
|
||||
ignore
|
||||
end
|
||||
catch
|
||||
error:Reason ->
|
||||
?LOG(warning, "The following error occurred in '~s' during authentication: ~p", [Unique, Reason]),
|
||||
Request = generate_request(Credential, State),
|
||||
case emqx_resource:query(Unique, {Method, Request, RequestTimeout}) of
|
||||
{ok, 204, _Headers} -> {ok, #{is_superuser => false}};
|
||||
{ok, 200, Headers, Body} ->
|
||||
ContentType = proplists:get_value(<<"content-type">>, Headers, <<"application/json">>),
|
||||
case safely_parse_body(ContentType, Body) of
|
||||
{ok, NBody} ->
|
||||
%% TODO: Return by user property
|
||||
{ok, #{is_superuser => maps:get(<<"is_superuser">>, NBody, false),
|
||||
user_property => NBody}};
|
||||
{error, _Reason} ->
|
||||
{ok, #{is_superuser => false}}
|
||||
end;
|
||||
{error, _Reason} ->
|
||||
ignore
|
||||
end.
|
||||
|
||||
|
|
|
@ -141,29 +141,23 @@ authenticate(#{password := Password} = Credential,
|
|||
, selector := Selector0
|
||||
, '_unique' := Unique
|
||||
} = State) ->
|
||||
try
|
||||
Selector1 = replace_placeholders(Selector0, Credential),
|
||||
Selector2 = normalize_selector(Selector1),
|
||||
case emqx_resource:query(Unique, {find_one, Collection, Selector2, #{}}) of
|
||||
undefined -> ignore;
|
||||
{error, Reason} ->
|
||||
?LOG(error, "['~s'] Query failed: ~p", [Unique, Reason]),
|
||||
ignore;
|
||||
Doc ->
|
||||
case check_password(Password, Doc, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => is_superuser(Doc, State)}};
|
||||
{error, {cannot_find_password_hash_field, PasswordHashField}} ->
|
||||
?LOG(error, "['~s'] Can't find password hash field: ~s", [Unique, PasswordHashField]),
|
||||
{error, bad_username_or_password};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end
|
||||
end
|
||||
catch
|
||||
error:Error ->
|
||||
?LOG(warning, "The following error occurred in '~s' during authentication: ~p", [Unique, Error]),
|
||||
ignore
|
||||
Selector1 = replace_placeholders(Selector0, Credential),
|
||||
Selector2 = normalize_selector(Selector1),
|
||||
case emqx_resource:query(Unique, {find_one, Collection, Selector2, #{}}) of
|
||||
undefined -> ignore;
|
||||
{error, Reason} ->
|
||||
?LOG(error, "['~s'] Query failed: ~p", [Unique, Reason]),
|
||||
ignore;
|
||||
Doc ->
|
||||
case check_password(Password, Doc, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => is_superuser(Doc, State)}};
|
||||
{error, {cannot_find_password_hash_field, PasswordHashField}} ->
|
||||
?LOG(error, "['~s'] Can't find password hash field: ~s", [Unique, PasswordHashField]),
|
||||
{error, bad_username_or_password};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end
|
||||
end.
|
||||
|
||||
destroy(#{'_unique' := Unique}) ->
|
||||
|
|
|
@ -114,24 +114,18 @@ authenticate(#{password := Password} = Credential,
|
|||
query := Query,
|
||||
query_timeout := Timeout,
|
||||
'_unique' := Unique} = State) ->
|
||||
try
|
||||
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
|
||||
case emqx_resource:query(Unique, {sql, Query, Params, Timeout}) of
|
||||
{ok, _Columns, []} -> ignore;
|
||||
{ok, Columns, Rows} ->
|
||||
Selected = maps:from_list(lists:zip(Columns, Rows)),
|
||||
case check_password(Password, Selected, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => maps:get(<<"is_superuser">>, Selected, false)}};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
{error, _Reason} ->
|
||||
ignore
|
||||
end
|
||||
catch
|
||||
error:Error ->
|
||||
?LOG(warning, "The following error occurred in '~s' during authentication: ~p", [Unique, Error]),
|
||||
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
|
||||
case emqx_resource:query(Unique, {sql, Query, Params, Timeout}) of
|
||||
{ok, _Columns, []} -> ignore;
|
||||
{ok, Columns, Rows} ->
|
||||
Selected = maps:from_list(lists:zip(Columns, Rows)),
|
||||
case check_password(Password, Selected, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => maps:get(<<"is_superuser">>, Selected, false)}};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
{error, _Reason} ->
|
||||
ignore
|
||||
end.
|
||||
|
||||
|
|
|
@ -103,25 +103,19 @@ authenticate(#{password := Password} = Credential,
|
|||
#{query := Query,
|
||||
placeholders := PlaceHolders,
|
||||
'_unique' := Unique} = State) ->
|
||||
try
|
||||
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
|
||||
case emqx_resource:query(Unique, {sql, Query, Params}) of
|
||||
{ok, _Columns, []} -> ignore;
|
||||
{ok, Columns, Rows} ->
|
||||
NColumns = [Name || #column{name = Name} <- Columns],
|
||||
Selected = maps:from_list(lists:zip(NColumns, Rows)),
|
||||
case check_password(Password, Selected, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => maps:get(<<"is_superuser">>, Selected, false)}};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
{error, _Reason} ->
|
||||
ignore
|
||||
end
|
||||
catch
|
||||
error:Error ->
|
||||
?LOG(warning, "The following error occurred in '~s' during authentication: ~p", [Unique, Error]),
|
||||
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
|
||||
case emqx_resource:query(Unique, {sql, Query, Params}) of
|
||||
{ok, _Columns, []} -> ignore;
|
||||
{ok, Columns, Rows} ->
|
||||
NColumns = [Name || #column{name = Name} <- Columns],
|
||||
Selected = maps:from_list(lists:zip(NColumns, Rows)),
|
||||
case check_password(Password, Selected, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => maps:get(<<"is_superuser">>, Selected, false)}};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
{error, _Reason} ->
|
||||
ignore
|
||||
end.
|
||||
|
||||
|
|
|
@ -127,24 +127,18 @@ authenticate(#{password := Password} = Credential,
|
|||
#{ query := {Command, Key, Fields}
|
||||
, '_unique' := Unique
|
||||
} = State) ->
|
||||
try
|
||||
NKey = binary_to_list(iolist_to_binary(replace_placeholders(Key, Credential))),
|
||||
case emqx_resource:query(Unique, {cmd, [Command, NKey | Fields]}) of
|
||||
{ok, Values} ->
|
||||
Selected = merge(Fields, Values),
|
||||
case check_password(Password, Selected, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => maps:get("is_superuser", Selected, false)}};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
{error, Reason} ->
|
||||
?LOG(error, "['~s'] Query failed: ~p", [Unique, Reason]),
|
||||
ignore
|
||||
end
|
||||
catch
|
||||
error:{cannot_get_variable, Placeholder} ->
|
||||
?LOG(warning, "The following error occurred in '~s' during authentication: ~p", [Unique, {cannot_get_variable, Placeholder}]),
|
||||
NKey = binary_to_list(iolist_to_binary(replace_placeholders(Key, Credential))),
|
||||
case emqx_resource:query(Unique, {cmd, [Command, NKey | Fields]}) of
|
||||
{ok, Values} ->
|
||||
Selected = merge(Fields, Values),
|
||||
case check_password(Password, Selected, State) of
|
||||
ok ->
|
||||
{ok, #{is_superuser => maps:get("is_superuser", Selected, false)}};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
{error, Reason} ->
|
||||
?LOG(error, "['~s'] Query failed: ~p", [Unique, Reason]),
|
||||
ignore
|
||||
end.
|
||||
|
||||
|
|
|
@ -76,11 +76,13 @@ on_stop(InstId, #{poolname := PoolName}) ->
|
|||
logger:info("stopping mysql connector: ~p", [InstId]),
|
||||
emqx_plugin_libs_pool:stop_pool(PoolName).
|
||||
|
||||
on_query(InstId, {sql, SQL}, AfterQuery, #{poolname := PoolName} = State) ->
|
||||
on_query(InstId, {sql, SQL, []}, AfterQuery, #{poolname := PoolName} = State);
|
||||
on_query(InstId, {sql, SQL, Params}, AfterQuery, #{poolname := PoolName} = State) ->
|
||||
on_query(InstId, {sql, SQL}, AfterQuery, #{poolname := _PoolName} = State) ->
|
||||
on_query(InstId, {sql, SQL, [], default_timeout}, AfterQuery, State);
|
||||
on_query(InstId, {sql, SQL, Params}, AfterQuery, #{poolname := _PoolName} = State) ->
|
||||
on_query(InstId, {sql, SQL, Params, default_timeout}, AfterQuery, State);
|
||||
on_query(InstId, {sql, SQL, Params, Timeout}, AfterQuery, #{poolname := PoolName} = State) ->
|
||||
logger:debug("mysql connector ~p received sql query: ~p, at state: ~p", [InstId, SQL, State]),
|
||||
case Result = ecpool:pick_and_do(PoolName, {mysql, query, [SQL, Params]}, no_handover) of
|
||||
case Result = ecpool:pick_and_do(PoolName, {mysql, query, [SQL, Params, Timeout]}, no_handover) of
|
||||
{error, Reason} ->
|
||||
logger:debug("mysql connector ~p do sql query failed, sql: ~p, reason: ~p", [InstId, SQL, Reason]),
|
||||
emqx_resource:query_failed(AfterQuery);
|
||||
|
|
|
@ -76,8 +76,8 @@ on_stop(InstId, #{poolname := PoolName}) ->
|
|||
logger:info("stopping postgresql connector: ~p", [InstId]),
|
||||
emqx_plugin_libs_pool:stop_pool(PoolName).
|
||||
|
||||
on_query(InstId, {sql, SQL}, AfterQuery, #{poolname := PoolName} = State) ->
|
||||
on_query(InstId, {sql, SQL, []}, AfterQuery, #{poolname := PoolName} = State);
|
||||
on_query(InstId, {sql, SQL}, AfterQuery, #{poolname := _PoolName} = State) ->
|
||||
on_query(InstId, {sql, SQL, []}, AfterQuery, State);
|
||||
on_query(InstId, {sql, SQL, Params}, AfterQuery, #{poolname := PoolName} = State) ->
|
||||
logger:debug("postgresql connector ~p received sql query: ~p, at state: ~p", [InstId, SQL, State]),
|
||||
case Result = ecpool:pick_and_do(PoolName, {?MODULE, query, [SQL, Params]}, no_handover) of
|
||||
|
|
Loading…
Reference in New Issue