feat(tpl): use `emqx_connector_template` in `emqx_authn`, `emqx_authz`
This slightly changes semantics: now the attempt to create authenticator with illegal bindings in templates will fail, instead of treating them as literals. The runtime behaviour on the other hand should be the same.
This commit is contained in:
parent
35902dc72d
commit
0538a77700
|
@ -19,67 +19,79 @@
|
||||||
|
|
||||||
-define(PH_VAR_THIS, <<"$_THIS_">>).
|
-define(PH_VAR_THIS, <<"$_THIS_">>).
|
||||||
|
|
||||||
-define(PH(Type), <<"${", Type/binary, "}">>).
|
-define(PH(Var), <<"${" Var "}">>).
|
||||||
|
|
||||||
%% action: publish/subscribe
|
%% action: publish/subscribe
|
||||||
-define(PH_ACTION, <<"${action}">>).
|
-define(VAR_ACTION, "action").
|
||||||
|
-define(PH_ACTION, ?PH(?VAR_ACTION)).
|
||||||
|
|
||||||
%% cert
|
%% cert
|
||||||
-define(PH_CERT_SUBJECT, <<"${cert_subject}">>).
|
-define(VAR_CERT_SUBJECT, "cert_subject").
|
||||||
-define(PH_CERT_CN_NAME, <<"${cert_common_name}">>).
|
-define(VAR_CERT_CN_NAME, "cert_common_name").
|
||||||
|
-define(PH_CERT_SUBJECT, ?PH(?VAR_CERT_SUBJECT)).
|
||||||
|
-define(PH_CERT_CN_NAME, ?PH(?VAR_CERT_CN_NAME)).
|
||||||
|
|
||||||
%% MQTT
|
%% MQTT
|
||||||
-define(PH_PASSWORD, <<"${password}">>).
|
-define(VAR_PASSWORD, "password").
|
||||||
-define(PH_CLIENTID, <<"${clientid}">>).
|
-define(VAR_CLIENTID, "clientid").
|
||||||
-define(PH_FROM_CLIENTID, <<"${from_clientid}">>).
|
-define(VAR_USERNAME, "username").
|
||||||
-define(PH_USERNAME, <<"${username}">>).
|
-define(VAR_TOPIC, "topic").
|
||||||
-define(PH_FROM_USERNAME, <<"${from_username}">>).
|
-define(PH_PASSWORD, ?PH(?VAR_PASSWORD)).
|
||||||
-define(PH_TOPIC, <<"${topic}">>).
|
-define(PH_CLIENTID, ?PH(?VAR_CLIENTID)).
|
||||||
|
-define(PH_FROM_CLIENTID, ?PH("from_clientid")).
|
||||||
|
-define(PH_USERNAME, ?PH(?VAR_USERNAME)).
|
||||||
|
-define(PH_FROM_USERNAME, ?PH("from_username")).
|
||||||
|
-define(PH_TOPIC, ?PH(?VAR_TOPIC)).
|
||||||
%% MQTT payload
|
%% MQTT payload
|
||||||
-define(PH_PAYLOAD, <<"${payload}">>).
|
-define(PH_PAYLOAD, ?PH("payload")).
|
||||||
%% client IPAddress
|
%% client IPAddress
|
||||||
-define(PH_PEERHOST, <<"${peerhost}">>).
|
-define(VAR_PEERHOST, "peerhost").
|
||||||
|
-define(PH_PEERHOST, ?PH(?VAR_PEERHOST)).
|
||||||
%% ip & port
|
%% ip & port
|
||||||
-define(PH_HOST, <<"${host}">>).
|
-define(PH_HOST, ?PH("host")).
|
||||||
-define(PH_PORT, <<"${port}">>).
|
-define(PH_PORT, ?PH("port")).
|
||||||
%% Enumeration of message QoS 0,1,2
|
%% Enumeration of message QoS 0,1,2
|
||||||
-define(PH_QOS, <<"${qos}">>).
|
-define(VAR_QOS, "qos").
|
||||||
-define(PH_FLAGS, <<"${flags}">>).
|
-define(PH_QOS, ?PH(?VAR_QOS)).
|
||||||
|
-define(PH_FLAGS, ?PH("flags")).
|
||||||
%% Additional data related to process within the MQTT message
|
%% Additional data related to process within the MQTT message
|
||||||
-define(PH_HEADERS, <<"${headers}">>).
|
-define(PH_HEADERS, ?PH("headers")).
|
||||||
%% protocol name
|
%% protocol name
|
||||||
-define(PH_PROTONAME, <<"${proto_name}">>).
|
-define(VAR_PROTONAME, "proto_name").
|
||||||
|
-define(PH_PROTONAME, ?PH(?VAR_PROTONAME)).
|
||||||
%% protocol version
|
%% protocol version
|
||||||
-define(PH_PROTOVER, <<"${proto_ver}">>).
|
-define(PH_PROTOVER, ?PH("proto_ver")).
|
||||||
%% MQTT keepalive interval
|
%% MQTT keepalive interval
|
||||||
-define(PH_KEEPALIVE, <<"${keepalive}">>).
|
-define(PH_KEEPALIVE, ?PH("keepalive")).
|
||||||
%% MQTT clean_start
|
%% MQTT clean_start
|
||||||
-define(PH_CLEAR_START, <<"${clean_start}">>).
|
-define(PH_CLEAR_START, ?PH("clean_start")).
|
||||||
%% MQTT Session Expiration time
|
%% MQTT Session Expiration time
|
||||||
-define(PH_EXPIRY_INTERVAL, <<"${expiry_interval}">>).
|
-define(PH_EXPIRY_INTERVAL, ?PH("expiry_interval")).
|
||||||
|
|
||||||
%% Time when PUBLISH message reaches Broker (ms)
|
%% Time when PUBLISH message reaches Broker (ms)
|
||||||
-define(PH_PUBLISH_RECEIVED_AT, <<"${publish_received_at}">>).
|
-define(PH_PUBLISH_RECEIVED_AT, ?PH("publish_received_at")).
|
||||||
%% Mountpoint for bridging messages
|
%% Mountpoint for bridging messages
|
||||||
-define(PH_MOUNTPOINT, <<"${mountpoint}">>).
|
-define(VAR_MOUNTPOINT, "mountpoint").
|
||||||
|
-define(PH_MOUNTPOINT, ?PH(?VAR_MOUNTPOINT)).
|
||||||
%% IPAddress and Port of terminal
|
%% IPAddress and Port of terminal
|
||||||
-define(PH_PEERNAME, <<"${peername}">>).
|
-define(PH_PEERNAME, ?PH("peername")).
|
||||||
%% IPAddress and Port listened by emqx
|
%% IPAddress and Port listened by emqx
|
||||||
-define(PH_SOCKNAME, <<"${sockname}">>).
|
-define(PH_SOCKNAME, ?PH("sockname")).
|
||||||
%% whether it is MQTT bridge connection
|
%% whether it is MQTT bridge connection
|
||||||
-define(PH_IS_BRIDGE, <<"${is_bridge}">>).
|
-define(PH_IS_BRIDGE, ?PH("is_bridge")).
|
||||||
%% Terminal connection completion time (s)
|
%% Terminal connection completion time (s)
|
||||||
-define(PH_CONNECTED_AT, <<"${connected_at}">>).
|
-define(PH_CONNECTED_AT, ?PH("connected_at")).
|
||||||
%% Event trigger time(millisecond)
|
%% Event trigger time(millisecond)
|
||||||
-define(PH_TIMESTAMP, <<"${timestamp}">>).
|
-define(PH_TIMESTAMP, ?PH("timestamp")).
|
||||||
%% Terminal disconnection completion time (s)
|
%% Terminal disconnection completion time (s)
|
||||||
-define(PH_DISCONNECTED_AT, <<"${disconnected_at}">>).
|
-define(PH_DISCONNECTED_AT, ?PH("disconnected_at")).
|
||||||
|
|
||||||
-define(PH_NODE, <<"${node}">>).
|
-define(PH_NODE, ?PH("node")).
|
||||||
-define(PH_REASON, <<"${reason}">>).
|
-define(PH_REASON, ?PH("reason")).
|
||||||
|
|
||||||
-define(PH_ENDPOINT_NAME, <<"${endpoint_name}">>).
|
-define(PH_ENDPOINT_NAME, ?PH("endpoint_name")).
|
||||||
-define(PH_RETAIN, <<"${retain}">>).
|
-define(VAR_RETAIN, "retain").
|
||||||
|
-define(PH_RETAIN, ?PH(?VAR_RETAIN)).
|
||||||
|
|
||||||
%% sync change these place holder with binary def.
|
%% sync change these place holder with binary def.
|
||||||
-define(PH_S_ACTION, "${action}").
|
-define(PH_S_ACTION, "${action}").
|
||||||
|
|
|
@ -45,12 +45,12 @@
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(AUTHN_PLACEHOLDERS, [
|
-define(AUTHN_PLACEHOLDERS, [
|
||||||
?PH_USERNAME,
|
<<?VAR_USERNAME>>,
|
||||||
?PH_CLIENTID,
|
<<?VAR_CLIENTID>>,
|
||||||
?PH_PASSWORD,
|
<<?VAR_PASSWORD>>,
|
||||||
?PH_PEERHOST,
|
<<?VAR_PEERHOST>>,
|
||||||
?PH_CERT_SUBJECT,
|
<<?VAR_CERT_SUBJECT>>,
|
||||||
?PH_CERT_CN_NAME
|
<<?VAR_CERT_CN_NAME>>
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(DEFAULT_RESOURCE_OPTS, #{
|
-define(DEFAULT_RESOURCE_OPTS, #{
|
||||||
|
@ -107,48 +107,62 @@ check_password_from_selected_map(Algorithm, Selected, Password) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
parse_deep(Template) ->
|
parse_deep(Template) ->
|
||||||
emqx_placeholder:preproc_tmpl_deep(Template, #{placeholders => ?AUTHN_PLACEHOLDERS}).
|
Result = emqx_connector_template:parse_deep(Template),
|
||||||
|
ok = emqx_connector_template:validate(?AUTHN_PLACEHOLDERS, Result),
|
||||||
|
Result.
|
||||||
|
|
||||||
parse_str(Template) ->
|
parse_str(Template) ->
|
||||||
emqx_placeholder:preproc_tmpl(Template, #{placeholders => ?AUTHN_PLACEHOLDERS}).
|
Result = emqx_connector_template:parse(Template),
|
||||||
|
ok = emqx_connector_template:validate(?AUTHN_PLACEHOLDERS, Result),
|
||||||
|
Result.
|
||||||
|
|
||||||
parse_sql(Template, ReplaceWith) ->
|
parse_sql(Template, ReplaceWith) ->
|
||||||
emqx_placeholder:preproc_sql(
|
{Statement, Result} = emqx_connector_template_sql:parse_prepstmt(
|
||||||
Template,
|
Template,
|
||||||
#{
|
#{parameters => ReplaceWith, strip_double_quote => true}
|
||||||
replace_with => ReplaceWith,
|
),
|
||||||
placeholders => ?AUTHN_PLACEHOLDERS,
|
ok = emqx_connector_template:validate(?AUTHN_PLACEHOLDERS, Result),
|
||||||
strip_double_quote => true
|
{Statement, Result}.
|
||||||
}
|
|
||||||
).
|
|
||||||
|
|
||||||
render_deep(Template, Credential) ->
|
render_deep(Template, Credential) ->
|
||||||
emqx_placeholder:proc_tmpl_deep(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{Term, _Errors} = emqx_connector_template:render(
|
||||||
Template,
|
Template,
|
||||||
mapping_credential(Credential),
|
mapping_credential(Credential),
|
||||||
#{return => full_binary, var_trans => fun handle_var/2}
|
#{var_trans => fun handle_var/2}
|
||||||
).
|
),
|
||||||
|
Term.
|
||||||
|
|
||||||
render_str(Template, Credential) ->
|
render_str(Template, Credential) ->
|
||||||
emqx_placeholder:proc_tmpl(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{String, _Errors} = emqx_connector_template:render(
|
||||||
Template,
|
Template,
|
||||||
mapping_credential(Credential),
|
mapping_credential(Credential),
|
||||||
#{return => full_binary, var_trans => fun handle_var/2}
|
#{var_trans => fun handle_var/2}
|
||||||
).
|
),
|
||||||
|
unicode:characters_to_binary(String).
|
||||||
|
|
||||||
render_urlencoded_str(Template, Credential) ->
|
render_urlencoded_str(Template, Credential) ->
|
||||||
emqx_placeholder:proc_tmpl(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{String, _Errors} = emqx_connector_template:render(
|
||||||
Template,
|
Template,
|
||||||
mapping_credential(Credential),
|
mapping_credential(Credential),
|
||||||
#{return => full_binary, var_trans => fun urlencode_var/2}
|
#{var_trans => fun urlencode_var/2}
|
||||||
).
|
),
|
||||||
|
unicode:characters_to_binary(String).
|
||||||
|
|
||||||
render_sql_params(ParamList, Credential) ->
|
render_sql_params(ParamList, Credential) ->
|
||||||
emqx_placeholder:proc_tmpl(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{Row, _Errors} = emqx_connector_template:render(
|
||||||
ParamList,
|
ParamList,
|
||||||
mapping_credential(Credential),
|
mapping_credential(Credential),
|
||||||
#{return => rawlist, var_trans => fun handle_sql_var/2}
|
#{var_trans => fun handle_sql_var/2}
|
||||||
).
|
),
|
||||||
|
Row.
|
||||||
|
|
||||||
is_superuser(#{<<"is_superuser">> := Value}) ->
|
is_superuser(#{<<"is_superuser">> := Value}) ->
|
||||||
#{is_superuser => to_bool(Value)};
|
#{is_superuser => to_bool(Value)};
|
||||||
|
@ -272,19 +286,19 @@ without_password(Credential, [Name | Rest]) ->
|
||||||
urlencode_var(Var, Value) ->
|
urlencode_var(Var, Value) ->
|
||||||
emqx_http_lib:uri_encode(handle_var(Var, Value)).
|
emqx_http_lib:uri_encode(handle_var(Var, Value)).
|
||||||
|
|
||||||
handle_var(_Name, undefined) ->
|
handle_var(_, undefined) ->
|
||||||
<<>>;
|
<<>>;
|
||||||
handle_var([<<"peerhost">>], PeerHost) ->
|
handle_var([<<"peerhost">>], PeerHost) ->
|
||||||
emqx_placeholder:bin(inet:ntoa(PeerHost));
|
emqx_connector_template:to_string(inet:ntoa(PeerHost));
|
||||||
handle_var(_, Value) ->
|
handle_var(_, Value) ->
|
||||||
emqx_placeholder:bin(Value).
|
emqx_connector_template:to_string(Value).
|
||||||
|
|
||||||
handle_sql_var(_Name, undefined) ->
|
handle_sql_var(_, undefined) ->
|
||||||
<<>>;
|
<<>>;
|
||||||
handle_sql_var([<<"peerhost">>], PeerHost) ->
|
handle_sql_var([<<"peerhost">>], PeerHost) ->
|
||||||
emqx_placeholder:bin(inet:ntoa(PeerHost));
|
emqx_connector_sql:to_sql_value(inet:ntoa(PeerHost));
|
||||||
handle_sql_var(_, Value) ->
|
handle_sql_var(_, Value) ->
|
||||||
emqx_placeholder:sql_data(Value).
|
emqx_connector_sql:to_sql_value(Value).
|
||||||
|
|
||||||
mapping_credential(C = #{cn := CN, dn := DN}) ->
|
mapping_credential(C = #{cn := CN, dn := DN}) ->
|
||||||
C#{cert_common_name => CN, cert_subject => DN};
|
C#{cert_common_name => CN, cert_subject => DN};
|
||||||
|
|
|
@ -183,19 +183,15 @@ compile_topic(<<"eq ", Topic/binary>>) ->
|
||||||
compile_topic({eq, Topic}) ->
|
compile_topic({eq, Topic}) ->
|
||||||
{eq, emqx_topic:words(bin(Topic))};
|
{eq, emqx_topic:words(bin(Topic))};
|
||||||
compile_topic(Topic) ->
|
compile_topic(Topic) ->
|
||||||
TopicBin = bin(Topic),
|
Template = emqx_connector_template:parse(Topic),
|
||||||
case
|
ok = emqx_connector_template:validate([<<?VAR_USERNAME>>, <<?VAR_CLIENTID>>], Template),
|
||||||
emqx_placeholder:preproc_tmpl(
|
case emqx_connector_template:trivial(Template) of
|
||||||
TopicBin,
|
true -> emqx_topic:words(bin(Topic));
|
||||||
#{placeholders => [?PH_USERNAME, ?PH_CLIENTID]}
|
false -> {pattern, Template}
|
||||||
)
|
|
||||||
of
|
|
||||||
[{str, _}] -> emqx_topic:words(TopicBin);
|
|
||||||
Tokens -> {pattern, Tokens}
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
bin(L) when is_list(L) ->
|
bin(L) when is_list(L) ->
|
||||||
list_to_binary(L);
|
unicode:characters_to_binary(L);
|
||||||
bin(B) when is_binary(B) ->
|
bin(B) when is_binary(B) ->
|
||||||
B.
|
B.
|
||||||
|
|
||||||
|
@ -307,7 +303,7 @@ match_who(_, _) ->
|
||||||
match_topics(_ClientInfo, _Topic, []) ->
|
match_topics(_ClientInfo, _Topic, []) ->
|
||||||
false;
|
false;
|
||||||
match_topics(ClientInfo, Topic, [{pattern, PatternFilter} | Filters]) ->
|
match_topics(ClientInfo, Topic, [{pattern, PatternFilter} | Filters]) ->
|
||||||
TopicFilter = emqx_placeholder:proc_tmpl(PatternFilter, ClientInfo),
|
TopicFilter = bin(emqx_connector_template:render_strict(PatternFilter, ClientInfo)),
|
||||||
match_topic(emqx_topic:words(Topic), emqx_topic:words(TopicFilter)) orelse
|
match_topic(emqx_topic:words(Topic), emqx_topic:words(TopicFilter)) orelse
|
||||||
match_topics(ClientInfo, Topic, Filters);
|
match_topics(ClientInfo, Topic, Filters);
|
||||||
match_topics(ClientInfo, Topic, [TopicFilter | Filters]) ->
|
match_topics(ClientInfo, Topic, [TopicFilter | Filters]) ->
|
||||||
|
|
|
@ -108,48 +108,62 @@ update_config(Path, ConfigRequest) ->
|
||||||
}).
|
}).
|
||||||
|
|
||||||
parse_deep(Template, PlaceHolders) ->
|
parse_deep(Template, PlaceHolders) ->
|
||||||
emqx_placeholder:preproc_tmpl_deep(Template, #{placeholders => PlaceHolders}).
|
Result = emqx_connector_template:parse_deep(Template),
|
||||||
|
ok = emqx_connector_template:validate(PlaceHolders, Result),
|
||||||
|
Result.
|
||||||
|
|
||||||
parse_str(Template, PlaceHolders) ->
|
parse_str(Template, PlaceHolders) ->
|
||||||
emqx_placeholder:preproc_tmpl(Template, #{placeholders => PlaceHolders}).
|
Result = emqx_connector_template:parse(Template),
|
||||||
|
ok = emqx_connector_template:validate(PlaceHolders, Result),
|
||||||
|
Result.
|
||||||
|
|
||||||
parse_sql(Template, ReplaceWith, PlaceHolders) ->
|
parse_sql(Template, ReplaceWith, PlaceHolders) ->
|
||||||
emqx_placeholder:preproc_sql(
|
{Statement, Result} = emqx_connector_template_sql:parse_prepstmt(
|
||||||
Template,
|
Template,
|
||||||
#{
|
#{parameters => ReplaceWith, strip_double_quote => true}
|
||||||
replace_with => ReplaceWith,
|
),
|
||||||
placeholders => PlaceHolders,
|
ok = emqx_connector_template:validate(PlaceHolders, Result),
|
||||||
strip_double_quote => true
|
{Statement, Result}.
|
||||||
}
|
|
||||||
).
|
|
||||||
|
|
||||||
render_deep(Template, Values) ->
|
render_deep(Template, Values) ->
|
||||||
emqx_placeholder:proc_tmpl_deep(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{Term, _Errors} = emqx_connector_template:render(
|
||||||
Template,
|
Template,
|
||||||
client_vars(Values),
|
client_vars(Values),
|
||||||
#{return => full_binary, var_trans => fun handle_var/2}
|
#{var_trans => fun handle_var/2}
|
||||||
).
|
),
|
||||||
|
Term.
|
||||||
|
|
||||||
render_str(Template, Values) ->
|
render_str(Template, Values) ->
|
||||||
emqx_placeholder:proc_tmpl(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{String, _Errors} = emqx_connector_template:render(
|
||||||
Template,
|
Template,
|
||||||
client_vars(Values),
|
client_vars(Values),
|
||||||
#{return => full_binary, var_trans => fun handle_var/2}
|
#{var_trans => fun handle_var/2}
|
||||||
).
|
),
|
||||||
|
unicode:characters_to_binary(String).
|
||||||
|
|
||||||
render_urlencoded_str(Template, Values) ->
|
render_urlencoded_str(Template, Values) ->
|
||||||
emqx_placeholder:proc_tmpl(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{String, _Errors} = emqx_connector_template:render(
|
||||||
Template,
|
Template,
|
||||||
client_vars(Values),
|
client_vars(Values),
|
||||||
#{return => full_binary, var_trans => fun urlencode_var/2}
|
#{var_trans => fun urlencode_var/2}
|
||||||
).
|
),
|
||||||
|
unicode:characters_to_binary(String).
|
||||||
|
|
||||||
render_sql_params(ParamList, Values) ->
|
render_sql_params(ParamList, Values) ->
|
||||||
emqx_placeholder:proc_tmpl(
|
% NOTE
|
||||||
|
% Ignoring errors here, undefined bindings will be replaced with empty string.
|
||||||
|
{Row, _Errors} = emqx_connector_template:render(
|
||||||
ParamList,
|
ParamList,
|
||||||
client_vars(Values),
|
client_vars(Values),
|
||||||
#{return => rawlist, var_trans => fun handle_sql_var/2}
|
#{var_trans => fun handle_sql_var/2}
|
||||||
).
|
),
|
||||||
|
Row.
|
||||||
|
|
||||||
-spec parse_http_resp_body(binary(), binary()) -> allow | deny | ignore | error.
|
-spec parse_http_resp_body(binary(), binary()) -> allow | deny | ignore | error.
|
||||||
parse_http_resp_body(<<"application/x-www-form-urlencoded", _/binary>>, Body) ->
|
parse_http_resp_body(<<"application/x-www-form-urlencoded", _/binary>>, Body) ->
|
||||||
|
@ -218,19 +232,19 @@ convert_client_var(Other) -> Other.
|
||||||
urlencode_var(Var, Value) ->
|
urlencode_var(Var, Value) ->
|
||||||
emqx_http_lib:uri_encode(handle_var(Var, Value)).
|
emqx_http_lib:uri_encode(handle_var(Var, Value)).
|
||||||
|
|
||||||
handle_var(_Name, undefined) ->
|
handle_var(_, undefined) ->
|
||||||
<<>>;
|
<<>>;
|
||||||
handle_var([<<"peerhost">>], IpAddr) ->
|
handle_var([<<"peerhost">>], IpAddr) ->
|
||||||
inet_parse:ntoa(IpAddr);
|
inet_parse:ntoa(IpAddr);
|
||||||
handle_var(_Name, Value) ->
|
handle_var(_Name, Value) ->
|
||||||
emqx_placeholder:bin(Value).
|
emqx_connector_template:to_string(Value).
|
||||||
|
|
||||||
handle_sql_var(_Name, undefined) ->
|
handle_sql_var(_, undefined) ->
|
||||||
<<>>;
|
<<>>;
|
||||||
handle_sql_var([<<"peerhost">>], IpAddr) ->
|
handle_sql_var([<<"peerhost">>], IpAddr) ->
|
||||||
inet_parse:ntoa(IpAddr);
|
inet_parse:ntoa(IpAddr);
|
||||||
handle_sql_var(_Name, Value) ->
|
handle_sql_var(_Name, Value) ->
|
||||||
emqx_placeholder:sql_data(Value).
|
emqx_connector_sql:to_sql_value(Value).
|
||||||
|
|
||||||
bin(A) when is_atom(A) -> atom_to_binary(A, utf8);
|
bin(A) when is_atom(A) -> atom_to_binary(A, utf8);
|
||||||
bin(L) when is_list(L) -> list_to_binary(L);
|
bin(L) when is_list(L) -> list_to_binary(L);
|
||||||
|
|
|
@ -67,6 +67,10 @@ set_special_configs(_App) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
t_compile(_) ->
|
t_compile(_) ->
|
||||||
|
% NOTE
|
||||||
|
% Some of the following testcase are relying on the internal representation of
|
||||||
|
% `emqx_connector_template:t()`. If the internal representation is changed, these
|
||||||
|
% testcases may fail.
|
||||||
?assertEqual({deny, all, all, [['#']]}, emqx_authz_rule:compile({deny, all})),
|
?assertEqual({deny, all, all, [['#']]}, emqx_authz_rule:compile({deny, all})),
|
||||||
|
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
|
@ -116,7 +120,7 @@ t_compile(_) ->
|
||||||
|
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
{allow, {username, {eq, <<"test">>}}, publish, [
|
{allow, {username, {eq, <<"test">>}}, publish, [
|
||||||
{pattern, [{str, <<"t/foo">>}, {var, [<<"username">>]}, {str, <<"boo">>}]}
|
{pattern, [<<"t/foo">>, {var, [<<"username">>]}, <<"boo">>]}
|
||||||
]},
|
]},
|
||||||
emqx_authz_rule:compile({allow, {username, "test"}, publish, ["t/foo${username}boo"]})
|
emqx_authz_rule:compile({allow, {username, "test"}, publish, ["t/foo${username}boo"]})
|
||||||
),
|
),
|
||||||
|
|
|
@ -39,20 +39,20 @@
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-define(PLACEHOLDERS, [
|
-define(PLACEHOLDERS, [
|
||||||
?PH_USERNAME,
|
<<?VAR_USERNAME>>,
|
||||||
?PH_CLIENTID,
|
<<?VAR_CLIENTID>>,
|
||||||
?PH_PEERHOST,
|
<<?VAR_PEERHOST>>,
|
||||||
?PH_PROTONAME,
|
<<?VAR_PROTONAME>>,
|
||||||
?PH_MOUNTPOINT,
|
<<?VAR_MOUNTPOINT>>,
|
||||||
?PH_TOPIC,
|
<<?VAR_TOPIC>>,
|
||||||
?PH_ACTION,
|
<<?VAR_ACTION>>,
|
||||||
?PH_CERT_SUBJECT,
|
<<?VAR_CERT_SUBJECT>>,
|
||||||
?PH_CERT_CN_NAME
|
<<?VAR_CERT_CN_NAME>>
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(PLACEHOLDERS_FOR_RICH_ACTIONS, [
|
-define(PLACEHOLDERS_FOR_RICH_ACTIONS, [
|
||||||
?PH_QOS,
|
<<?VAR_QOS>>,
|
||||||
?PH_RETAIN
|
<<?VAR_RETAIN>>
|
||||||
]).
|
]).
|
||||||
|
|
||||||
description() ->
|
description() ->
|
||||||
|
|
|
@ -36,11 +36,11 @@
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-define(PLACEHOLDERS, [
|
-define(PLACEHOLDERS, [
|
||||||
?PH_USERNAME,
|
<<?VAR_USERNAME>>,
|
||||||
?PH_CLIENTID,
|
<<?VAR_CLIENTID>>,
|
||||||
?PH_PEERHOST,
|
<<?VAR_PEERHOST>>,
|
||||||
?PH_CERT_CN_NAME,
|
<<?VAR_CERT_CN_NAME>>,
|
||||||
?PH_CERT_SUBJECT
|
<<?VAR_CERT_SUBJECT>>
|
||||||
]).
|
]).
|
||||||
|
|
||||||
description() ->
|
description() ->
|
||||||
|
|
|
@ -38,11 +38,11 @@
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-define(PLACEHOLDERS, [
|
-define(PLACEHOLDERS, [
|
||||||
?PH_USERNAME,
|
<<?VAR_USERNAME>>,
|
||||||
?PH_CLIENTID,
|
<<?VAR_CLIENTID>>,
|
||||||
?PH_PEERHOST,
|
<<?VAR_PEERHOST>>,
|
||||||
?PH_CERT_CN_NAME,
|
<<?VAR_CERT_CN_NAME>>,
|
||||||
?PH_CERT_SUBJECT
|
<<?VAR_CERT_SUBJECT>>
|
||||||
]).
|
]).
|
||||||
|
|
||||||
description() ->
|
description() ->
|
||||||
|
|
|
@ -38,11 +38,11 @@
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-define(PLACEHOLDERS, [
|
-define(PLACEHOLDERS, [
|
||||||
?PH_USERNAME,
|
<<?VAR_USERNAME>>,
|
||||||
?PH_CLIENTID,
|
<<?VAR_CLIENTID>>,
|
||||||
?PH_PEERHOST,
|
<<?VAR_PEERHOST>>,
|
||||||
?PH_CERT_CN_NAME,
|
<<?VAR_CERT_CN_NAME>>,
|
||||||
?PH_CERT_SUBJECT
|
<<?VAR_CERT_SUBJECT>>
|
||||||
]).
|
]).
|
||||||
|
|
||||||
description() ->
|
description() ->
|
||||||
|
|
|
@ -36,11 +36,11 @@
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
-define(PLACEHOLDERS, [
|
-define(PLACEHOLDERS, [
|
||||||
?PH_CERT_CN_NAME,
|
<<?VAR_CERT_CN_NAME>>,
|
||||||
?PH_CERT_SUBJECT,
|
<<?VAR_CERT_SUBJECT>>,
|
||||||
?PH_PEERHOST,
|
<<?VAR_PEERHOST>>,
|
||||||
?PH_CLIENTID,
|
<<?VAR_CLIENTID>>,
|
||||||
?PH_USERNAME
|
<<?VAR_USERNAME>>
|
||||||
]).
|
]).
|
||||||
|
|
||||||
description() ->
|
description() ->
|
||||||
|
|
|
@ -153,7 +153,7 @@ trivial(Template) ->
|
||||||
unparse({'$tpl', Template}) ->
|
unparse({'$tpl', Template}) ->
|
||||||
unparse_deep(Template);
|
unparse_deep(Template);
|
||||||
unparse(Template) ->
|
unparse(Template) ->
|
||||||
lists:map(fun unparse_part/1, Template).
|
unicode:characters_to_list(lists:map(fun unparse_part/1, Template)).
|
||||||
|
|
||||||
unparse_part({var, Name}) ->
|
unparse_part({var, Name}) ->
|
||||||
render_placeholder(Name);
|
render_placeholder(Name);
|
||||||
|
@ -222,7 +222,7 @@ render_strict(Template, Bindings, Opts) ->
|
||||||
{String, []} ->
|
{String, []} ->
|
||||||
String;
|
String;
|
||||||
{_, Errors = [_ | _]} ->
|
{_, Errors = [_ | _]} ->
|
||||||
error(Errors, [unicode:characters_to_list(unparse(Template)), Bindings])
|
error(Errors, [unparse(Template), Bindings])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Parse an arbitrary Erlang term into a "deep" template.
|
%% @doc Parse an arbitrary Erlang term into a "deep" template.
|
||||||
|
@ -306,9 +306,7 @@ unparse_deep(Term) ->
|
||||||
|
|
||||||
-spec lookup_var(var(), bindings()) ->
|
-spec lookup_var(var(), bindings()) ->
|
||||||
{ok, binding()} | {error, undefined}.
|
{ok, binding()} | {error, undefined}.
|
||||||
lookup_var(?PH_VAR_THIS, Value) ->
|
lookup_var(Var, Value) when Var == ?PH_VAR_THIS orelse Var == [] ->
|
||||||
{ok, Value};
|
|
||||||
lookup_var([], Value) ->
|
|
||||||
{ok, Value};
|
{ok, Value};
|
||||||
lookup_var([Prop | Rest], Bindings) ->
|
lookup_var([Prop | Rest], Bindings) ->
|
||||||
case lookup(Prop, Bindings) of
|
case lookup(Prop, Bindings) of
|
||||||
|
|
Loading…
Reference in New Issue