Zaiming Shi 5 лет назад
Родитель
Сommit
3a91ff8a7b
30 измененных файлов с 155 добавлено и 314 удалено
  1. 15 2
      apps/emqx_auth_http/src/emqx_auth_http_app.erl
  2. 0 10
      apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src
  3. 29 4
      apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl
  4. 0 9
      apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src
  5. 0 9
      apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src
  6. 2 0
      apps/emqx_auth_redis/.gitignore
  7. 0 10
      apps/emqx_auth_redis/src/emqx_auth_redis.appup.src
  8. 26 10
      apps/emqx_auth_redis/test/emqx_auth_redis_SUITE.erl
  9. 0 10
      apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src
  10. 0 8
      apps/emqx_dashboard/priv/www/static/js/0.7a09d1383e1319441399.js
  11. 0 8
      apps/emqx_dashboard/priv/www/static/js/2.71ffb214c95162432f13.js
  12. 0 1
      apps/emqx_dashboard/priv/www/static/js/20.308aa0fdf6653ef3299f.js
  13. 0 1
      apps/emqx_dashboard/priv/www/static/js/22.d968dc6f54a690adde18.js
  14. 0 1
      apps/emqx_dashboard/priv/www/static/js/3.25b49772270df4b9915d.js
  15. 0 1
      apps/emqx_dashboard/priv/www/static/js/5.8935139a413f40d70253.js
  16. 0 1
      apps/emqx_dashboard/priv/www/static/js/8.e86f6131cc8a9138368d.js
  17. 0 1
      apps/emqx_dashboard/priv/www/static/js/manifest.b28890b7e119092c6f70.js
  18. 0 24
      apps/emqx_exhook/src/emqx_exhook.app.src.script
  19. 0 9
      apps/emqx_exhook/src/emqx_exhook.appup.src
  20. 0 24
      apps/emqx_exproto/src/emqx_exproto.app.src.script
  21. 0 9
      apps/emqx_exproto/src/emqx_exproto.appup.src
  22. 16 1
      apps/emqx_management/src/emqx_mgmt.erl
  23. 9 6
      apps/emqx_management/src/emqx_mgmt_api_data.erl
  24. 4 2
      apps/emqx_management/src/emqx_mgmt_cli.erl
  25. 0 8
      apps/emqx_rule_engine/src/emqx_rule_engine.appup.src
  26. 45 75
      apps/emqx_rule_engine/src/emqx_rule_funcs.erl
  27. 4 57
      apps/emqx_rule_engine/test/emqx_rule_funcs_SUITE.erl
  28. 1 1
      apps/emqx_sasl/test/emqx_sasl_scram_SUITE.erl
  29. 0 9
      apps/emqx_web_hook/src/emqx_web_hook.appup.src
  30. 4 3
      sync-apps.sh

+ 15 - 2
apps/emqx_auth_http/src/emqx_auth_http_app.erl

@@ -119,7 +119,7 @@ translate_env() ->
                             #{host := Host0,
                             #{host := Host0,
                               port := Port,
                               port := Port,
                               path := Path} = uri_string:parse(list_to_binary(URL)),
                               path := Path} = uri_string:parse(list_to_binary(URL)),
-                            {ok, Host} = inet:parse_address(binary_to_list(Host0)),
+                            Host = get_addr(binary_to_list(Host0)),
                             [{Name, {Host, Port, binary_to_list(Path)}} | Acc]
                             [{Name, {Host, Port, binary_to_list(Path)}} | Acc]
                     end
                     end
                 end, [], [acl_req, auth_req, super_req]),
                 end, [], [acl_req, auth_req, super_req]),
@@ -144,4 +144,17 @@ same_host_and_port([{_, {Host, Port, _}}, {_, {Host, Port, _}}]) ->
 same_host_and_port([{_, {Host, Port, _}}, URL = {_, {Host, Port, _}} | Rest]) ->
 same_host_and_port([{_, {Host, Port, _}}, URL = {_, {Host, Port, _}} | Rest]) ->
     same_host_and_port([URL | Rest]);
     same_host_and_port([URL | Rest]);
 same_host_and_port(_) ->
 same_host_and_port(_) ->
-    false.
+    false.
+
+get_addr(Hostname) ->
+    case inet:parse_address(Hostname) of
+        {ok, {_,_,_,_} = Addr} -> Addr;
+        {ok, {_,_,_,_,_,_,_,_} = Addr} -> Addr;
+        {error, einval} ->
+            case inet:getaddr(Hostname, inet) of
+                 {error, _} ->
+                     {ok, Addr} = inet:getaddr(Hostname, inet6),
+                     Addr;
+                 {ok, Addr} -> Addr
+            end
+    end.

+ 0 - 10
apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src

@@ -1,10 +0,0 @@
-%% -*-: erlang -*-
-
-{VSN,
-  [
-    {<<".*">>, []}
-  ],
-  [
-    {<<".*">>, []}
-  ]
-}.

+ 29 - 4
apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl

@@ -63,10 +63,8 @@ check(ClientInfo = #{ clientid := Clientid
             emqx_metrics:inc(?AUTH_METRICS(ignore)),
             emqx_metrics:inc(?AUTH_METRICS(ignore)),
             ok;
             ok;
         List ->
         List ->
-            case [ Hash  || <<Salt:4/binary, Hash/binary>> <- lists:sort(fun emqx_auth_mnesia_cli:comparing/2, List),
-                            Hash =:= hash(NPassword, Salt, HashType)
-                 ] of
-                [] ->
+            case match_password(NPassword, HashType, List)  of
+                false ->
                     ?LOG(error, "[Mnesia] Auth from mnesia failed: ~p", [ClientInfo]),
                     ?LOG(error, "[Mnesia] Auth from mnesia failed: ~p", [ClientInfo]),
                     emqx_metrics:inc(?AUTH_METRICS(failure)),
                     emqx_metrics:inc(?AUTH_METRICS(failure)),
                     {stop, AuthResult#{anonymous => false, auth_result => password_error}};
                     {stop, AuthResult#{anonymous => false, auth_result => password_error}};
@@ -78,7 +76,34 @@ check(ClientInfo = #{ clientid := Clientid
 
 
 description() -> "Authentication with Mnesia".
 description() -> "Authentication with Mnesia".
 
 
+match_password(Password, HashType, HashList) ->
+    lists:any(
+      fun(Secret) ->
+        case is_salt_hash(Secret, HashType) of
+            true ->
+                <<Salt:4/binary, Hash/binary>> = Secret,
+                Hash =:= hash(Password, Salt, HashType);
+            _ ->
+                Secret =:= hash(Password, HashType)
+        end
+      end, HashList).
+
+hash(undefined, HashType) ->
+    hash(<<>>, HashType);
+hash(Password, HashType) ->
+    emqx_passwd:hash(HashType, Password).
+
 hash(undefined, SaltBin, HashType) ->
 hash(undefined, SaltBin, HashType) ->
     hash(<<>>, SaltBin, HashType);
     hash(<<>>, SaltBin, HashType);
 hash(Password, SaltBin, HashType) ->
 hash(Password, SaltBin, HashType) ->
     emqx_passwd:hash(HashType, <<SaltBin/binary, Password/binary>>).
     emqx_passwd:hash(HashType, <<SaltBin/binary, Password/binary>>).
+
+is_salt_hash(_, plain) ->
+    true;
+is_salt_hash(Secret, HashType) ->
+    not (byte_size(Secret) == len(HashType)).
+
+len(md5) -> 32;
+len(sha) -> 40;
+len(sha256) -> 64;
+len(sha512) -> 128.

+ 0 - 9
apps/emqx_auth_mysql/src/emqx_auth_mysql.appup.src

@@ -1,9 +0,0 @@
-%% -*-: erlang -*-
-{VSN,
-   [
-     {<<".*">>, []}
-   ],
-   [
-     {<<".*">>, []}
-   ]
-}.

+ 0 - 9
apps/emqx_auth_pgsql/src/emqx_auth_pgsql.appup.src

@@ -1,9 +0,0 @@
-%% -*-: erlang -*-
-{VSN,
-   [
-     {<<".*">>, []}
-   ],
-   [
-     {<<".*">>, []}
-   ]
-}.

+ 2 - 0
apps/emqx_auth_redis/.gitignore

@@ -24,3 +24,5 @@ erlang.mk
 rebar.lock
 rebar.lock
 /.idea/
 /.idea/
 .DS_Store
 .DS_Store
+/.ci/redis/nodes.*.conf
+/.ci/redis/*.log

+ 0 - 10
apps/emqx_auth_redis/src/emqx_auth_redis.appup.src

@@ -1,10 +0,0 @@
-%% -*-: erlang -*-
-
-{VSN,
-   [
-     {<<".*">>, []}
-   ],
-   [
-     {<<".*">>, []}
-   ]
-}.

+ 26 - 10
apps/emqx_auth_redis/test/emqx_auth_redis_SUITE.erl

@@ -69,21 +69,18 @@ set_special_configs(_App) ->
     ok.
     ok.
 
 
 init_redis_rows() ->
 init_redis_rows() ->
-    {ok, Connection} = ?POOL(?APP),
     %% Users
     %% Users
-    [eredis:q(Connection, ["HMSET", Key|FiledValue]) || {Key, FiledValue} <- ?INIT_AUTH],
-
+    [q(["HMSET", Key|FiledValue]) || {Key, FiledValue} <- ?INIT_AUTH],
     %% ACLs
     %% ACLs
     emqx_modules:load_module(emqx_mod_acl_internal, false),
     emqx_modules:load_module(emqx_mod_acl_internal, false),
-    Result = [eredis:q(Connection, ["HSET", Key, Filed, Value]) || {Key, Filed, Value} <- ?INIT_ACL],
+    Result = [q(["HSET", Key, Filed, Value]) || {Key, Filed, Value} <- ?INIT_ACL],
     ct:pal("redis init result: ~p~n", [Result]).
     ct:pal("redis init result: ~p~n", [Result]).
 
 
 deinit_redis_rows() ->
 deinit_redis_rows() ->
-    {ok, Connection} = ?POOL(?APP),
     AuthKeys = [Key || {Key, _Filed, _Value} <- ?INIT_AUTH],
     AuthKeys = [Key || {Key, _Filed, _Value} <- ?INIT_AUTH],
     AclKeys = [Key || {Key, _Value} <- ?INIT_ACL],
     AclKeys = [Key || {Key, _Value} <- ?INIT_ACL],
-    eredis:q(Connection, ["DEL" | AuthKeys]),
-    eredis:q(Connection, ["DEL" | AclKeys]).
+    q(["DEL" | AuthKeys]),
+    q(["DEL" | AclKeys]).
 
 
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
 %% Cases
 %% Cases
@@ -121,9 +118,8 @@ t_check_auth(_) ->
     {error, _} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}).
     {error, _} = emqx_access_control:authenticate(Bcrypt#{password => <<"password">>}).
 
 
 t_check_auth_hget(_) ->
 t_check_auth_hget(_) ->
-    {ok, Connection} = ?POOL(?APP),
-    eredis:q(Connection, ["HSET", "mqtt_user:hset", "password", "hset"]),
-    eredis:q(Connection, ["HSET", "mqtt_user:hset", "is_superuser", "1"]),
+    q(["HSET", "mqtt_user:hset", "password", "hset"]),
+    q(["HSET", "mqtt_user:hset", "is_superuser", "1"]),
     reload([{password_hash, plain}, {auth_cmd, "HGET mqtt_user:%u password"}]),
     reload([{password_hash, plain}, {auth_cmd, "HGET mqtt_user:%u password"}]),
     Hset = #{clientid => <<"hset">>, username => <<"hset">>, zone => external},
     Hset = #{clientid => <<"hset">>, username => <<"hset">>, zone => external},
     {ok, #{is_superuser := true}} = emqx_access_control:authenticate(Hset#{password => <<"hset">>}).
     {ok, #{is_superuser := true}} = emqx_access_control:authenticate(Hset#{password => <<"hset">>}).
@@ -164,6 +160,16 @@ t_acl_super(_) ->
     end,
     end,
     emqtt:disconnect(C).
     emqtt:disconnect(C).
 
 
+t_check_cluster_connection(_) ->
+    ?assertMatch({error, _Reason}, reload([{server, [{type,cluster},
+                                           {pool_size,8},
+                                           {auto_reconnect,1},
+                                           {database,0},
+                                           {password,[]},
+                                           {sentinel,[]},
+                                           {servers,[{"wrong",6379},{"wrong",6380},{"wrong",6381}]}]}])).
+
+
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
 %% Internal funcs
 %% Internal funcs
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
@@ -172,3 +178,13 @@ reload(Config) when is_list(Config) ->
     application:stop(?APP),
     application:stop(?APP),
     [application:set_env(?APP, K, V) || {K, V} <- Config],
     [application:set_env(?APP, K, V) || {K, V} <- Config],
     application:start(?APP).
     application:start(?APP).
+
+q(Cmd) ->
+    {ok, Server} = application:get_env(?APP, server),
+    case proplists:get_value(type, Server) of
+        single ->
+            {ok, Connection} = ?POOL(?APP),
+            eredis:q(Connection, Cmd);
+        cluster ->
+            eredis_cluster:q(emqx_auth_redis, Cmd)
+    end.

+ 0 - 10
apps/emqx_bridge_mqtt/src/emqx_bridge_mqtt.appup.src

@@ -1,10 +0,0 @@
-%% -*-: erlang -*-
-
-{VSN,
-  [
-    {<<".*">>, []}
-  ],
-  [
-    {<<"*.">>, []}
-  ]
-}.

Разница между файлами не показана из-за своего большого размера
+ 0 - 8
apps/emqx_dashboard/priv/www/static/js/0.7a09d1383e1319441399.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 8
apps/emqx_dashboard/priv/www/static/js/2.71ffb214c95162432f13.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
apps/emqx_dashboard/priv/www/static/js/20.308aa0fdf6653ef3299f.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
apps/emqx_dashboard/priv/www/static/js/22.d968dc6f54a690adde18.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
apps/emqx_dashboard/priv/www/static/js/3.25b49772270df4b9915d.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
apps/emqx_dashboard/priv/www/static/js/5.8935139a413f40d70253.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
apps/emqx_dashboard/priv/www/static/js/8.e86f6131cc8a9138368d.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 1
apps/emqx_dashboard/priv/www/static/js/manifest.b28890b7e119092c6f70.js


+ 0 - 24
apps/emqx_exhook/src/emqx_exhook.app.src.script

@@ -1,24 +0,0 @@
-%%-*- mode: erlang -*-
-%% .app.src.script
-
-RemoveLeadingV =
-    fun(Tag) ->
-        case re:run(Tag, "^[v]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of
-            nomatch ->
-                re:replace(Tag, "/", "-", [{return ,list}]);
-            _ ->
-                %% if it is a version number prefixed by 'v' or 'e', then remove it
-                re:replace(Tag, "[v]", "", [{return ,list}])
-        end
-    end,
-
-case os:getenv("EMQX_DEPS_DEFAULT_VSN") of
-    false -> CONFIG; % env var not defined
-    []    -> CONFIG; % env var set to empty string
-    Tag ->
-       [begin
-           AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}),
-           {application, App, AppConf0}
-        end || Conf = {application, App, AppConf} <- CONFIG]
-end.
-

+ 0 - 9
apps/emqx_exhook/src/emqx_exhook.appup.src

@@ -1,9 +0,0 @@
-%% -*-: erlang -*-
-{VSN,
-  [
-    {<<".*">>, []}
-  ],
-  [
-    {<<".*">>, []}
-  ]
-}.

+ 0 - 24
apps/emqx_exproto/src/emqx_exproto.app.src.script

@@ -1,24 +0,0 @@
-%%-*- mode: erlang -*-
-%% .app.src.script
-
-RemoveLeadingV =
-    fun(Tag) ->
-        case re:run(Tag, "^[v]?[0-9]\.[0-9]\.([0-9]|(rc|beta|alpha)\.[0-9])", [{capture, none}]) of
-            nomatch ->
-                re:replace(Tag, "/", "-", [{return ,list}]);
-            _ ->
-                %% if it is a version number prefixed by 'v' or 'e', then remove it
-                re:replace(Tag, "[v]", "", [{return ,list}])
-        end
-    end,
-
-case os:getenv("EMQX_DEPS_DEFAULT_VSN") of
-    false -> CONFIG; % env var not defined
-    []    -> CONFIG; % env var set to empty string
-    Tag ->
-       [begin
-           AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}),
-           {application, App, AppConf0}
-        end || Conf = {application, App, AppConf} <- CONFIG]
-end.
-

+ 0 - 9
apps/emqx_exproto/src/emqx_exproto.appup.src

@@ -1,9 +0,0 @@
-%% -*-: erlang -*-
-{VSN,
-  [
-    {<<".*">>, []}
-  ],
-  [
-    {<<".*">>, []}
-  ]
-}.

+ 16 - 1
apps/emqx_management/src/emqx_mgmt.erl

@@ -128,6 +128,7 @@
         , export_auth_username/0
         , export_auth_username/0
         , export_auth_mnesia/0
         , export_auth_mnesia/0
         , export_acl_mnesia/0
         , export_acl_mnesia/0
+        , export_schemas/0
         , import_rules/1
         , import_rules/1
         , import_resources/1
         , import_resources/1
         , import_blacklist/1
         , import_blacklist/1
@@ -137,6 +138,7 @@
         , import_auth_username/1
         , import_auth_username/1
         , import_auth_mnesia/1
         , import_auth_mnesia/1
         , import_acl_mnesia/1
         , import_acl_mnesia/1
+        , import_schemas/1
         , to_version/1
         , to_version/1
         ]).
         ]).
 
 
@@ -677,6 +679,13 @@ export_acl_mnesia() ->
                         end, [], ets:tab2list(emqx_acl))
                         end, [], ets:tab2list(emqx_acl))
     end.
     end.
 
 
+export_schemas() ->
+    case ets:info(emqx_schema) of
+        undefined -> [];
+        _ ->
+            [emqx_schema_api:format_schema(Schema) || Schema <- emqx_schema_registry:get_all_schemas()]
+    end.
+
 import_rules(Rules) ->
 import_rules(Rules) ->
     lists:foreach(fun(#{<<"id">> := RuleId,
     lists:foreach(fun(#{<<"id">> := RuleId,
                         <<"rawsql">> := RawSQL,
                         <<"rawsql">> := RawSQL,
@@ -779,13 +788,19 @@ import_auth_mnesia(Auths) ->
 import_acl_mnesia(Acls) ->
 import_acl_mnesia(Acls) ->
     case ets:info(emqx_acl) of
     case ets:info(emqx_acl) of
         undefined -> ok;
         undefined -> ok;
-        _ ->
+        _ -> 
             [ mnesia:dirty_write({emqx_acl ,Login, Topic, Action, Allow}) || #{<<"login">> := Login, 
             [ mnesia:dirty_write({emqx_acl ,Login, Topic, Action, Allow}) || #{<<"login">> := Login, 
                                                                                <<"topic">> := Topic,
                                                                                <<"topic">> := Topic,
                                                                                <<"action">> := Action,
                                                                                <<"action">> := Action,
                                                                                <<"allow">> := Allow} <- Acls ]
                                                                                <<"allow">> := Allow} <- Acls ]
     end.
     end.
 
 
+import_schemas(Schemas) -> 
+    case ets:info(emqx_schema) of
+        undefined -> ok;
+        _ -> [emqx_schema_registry:add_schema(emqx_schema_api:make_schema_params(Schema)) || Schema <- Schemas]
+    end.
+
 any_to_atom(L) when is_list(L) -> list_to_atom(L);
 any_to_atom(L) when is_list(L) -> list_to_atom(L);
 any_to_atom(B) when is_binary(B) -> binary_to_atom(B, utf8);
 any_to_atom(B) when is_binary(B) -> binary_to_atom(B, utf8);
 any_to_atom(A) when is_atom(A) -> A.
 any_to_atom(A) when is_atom(A) -> A.

+ 9 - 6
apps/emqx_management/src/emqx_mgmt_api_data.erl

@@ -84,6 +84,7 @@ export(_Bindings, _Params) ->
     AuthUsername = emqx_mgmt:export_auth_username(),
     AuthUsername = emqx_mgmt:export_auth_username(),
     AuthMnesia = emqx_mgmt:export_auth_mnesia(),
     AuthMnesia = emqx_mgmt:export_auth_mnesia(),
     AclMnesia = emqx_mgmt:export_acl_mnesia(),
     AclMnesia = emqx_mgmt:export_acl_mnesia(),
+    Schemas = emqx_mgmt:export_schemas(),
     Seconds = erlang:system_time(second),
     Seconds = erlang:system_time(second),
     {{Y, M, D}, {H, MM, S}} = emqx_mgmt_util:datetime(Seconds),
     {{Y, M, D}, {H, MM, S}} = emqx_mgmt_util:datetime(Seconds),
     Filename = io_lib:format("emqx-export-~p-~p-~p-~p-~p-~p.json", [Y, M, D, H, MM, S]),
     Filename = io_lib:format("emqx-export-~p-~p-~p-~p-~p-~p.json", [Y, M, D, H, MM, S]),
@@ -99,7 +100,8 @@ export(_Bindings, _Params) ->
             {auth_clientid, AuthClientid},
             {auth_clientid, AuthClientid},
             {auth_username, AuthUsername},
             {auth_username, AuthUsername},
             {auth_mnesia, AuthMnesia},
             {auth_mnesia, AuthMnesia},
-            {acl_mnesia, AclMnesia}
+            {acl_mnesia, AclMnesia},
+            {schemas, Schemas}
            ],
            ],
 
 
     Bin = emqx_json:encode(Data),
     Bin = emqx_json:encode(Data),
@@ -178,19 +180,20 @@ do_import(Filename) ->
             case lists:member(Version, ?VERSIONS) of
             case lists:member(Version, ?VERSIONS) of
                 true  ->
                 true  ->
                     try
                     try
-                        %emqx_mgmt:import_confs(maps:get(<<"configs">>, Data, []), maps:get(<<"listeners_state">>, Data, [])),
+                        emqx_mgmt:import_confs(maps:get(<<"configs">>, Data, []), maps:get(<<"listeners_state">>, Data, [])),
                         emqx_mgmt:import_resources(maps:get(<<"resources">>, Data, [])),
                         emqx_mgmt:import_resources(maps:get(<<"resources">>, Data, [])),
                         emqx_mgmt:import_rules(maps:get(<<"rules">>, Data, [])),
                         emqx_mgmt:import_rules(maps:get(<<"rules">>, Data, [])),
                         emqx_mgmt:import_blacklist(maps:get(<<"blacklist">>, Data, [])),
                         emqx_mgmt:import_blacklist(maps:get(<<"blacklist">>, Data, [])),
                         emqx_mgmt:import_applications(maps:get(<<"apps">>, Data, [])),
                         emqx_mgmt:import_applications(maps:get(<<"apps">>, Data, [])),
                         emqx_mgmt:import_users(maps:get(<<"users">>, Data, [])),
                         emqx_mgmt:import_users(maps:get(<<"users">>, Data, [])),
-                        %emqx_mgmt:import_modules(maps:get(<<"modules">>, Data, [])),
+                        emqx_mgmt:import_modules(maps:get(<<"modules">>, Data, [])),
                         emqx_mgmt:import_auth_clientid(maps:get(<<"auth_clientid">>, Data, [])),
                         emqx_mgmt:import_auth_clientid(maps:get(<<"auth_clientid">>, Data, [])),
                         emqx_mgmt:import_auth_username(maps:get(<<"auth_username">>, Data, [])),
                         emqx_mgmt:import_auth_username(maps:get(<<"auth_username">>, Data, [])),
-                        %emqx_mgmt:import_auth_mnesia(maps:get(<<"auth_mnesia">>, Data, []), Version),
-                        %emqx_mgmt:import_acl_mnesia(maps:get(<<"acl_mnesia">>, Data, []), Version),
+                        emqx_mgmt:import_auth_mnesia(maps:get(<<"auth_mnesia">>, Data, []), Version),
+                        emqx_mgmt:import_acl_mnesia(maps:get(<<"acl_mnesia">>, Data, []), Version),
+                        emqx_mgmt:import_schemas(maps:get(<<"schemas">>, Data, [])),
                         logger:debug("The emqx data has been imported successfully"),
                         logger:debug("The emqx data has been imported successfully"),
-                        error({not_implemented, [import_confs,import_modules,import_auth_mnesia,import_acl_mnesia]})
+                        ok
                     catch Class:Reason:Stack ->
                     catch Class:Reason:Stack ->
                         logger:error("The emqx data import failed: ~0p", [{Class,Reason,Stack}]),
                         logger:error("The emqx data import failed: ~0p", [{Class,Reason,Stack}]),
                         {error, import_failed}
                         {error, import_failed}

+ 4 - 2
apps/emqx_management/src/emqx_mgmt_cli.erl

@@ -567,6 +567,7 @@ data(["export"]) ->
     AuthUsername = emqx_mgmt:export_auth_username(),
     AuthUsername = emqx_mgmt:export_auth_username(),
     AuthMnesia = emqx_mgmt:export_auth_mnesia(),
     AuthMnesia = emqx_mgmt:export_auth_mnesia(),
     AclMnesia = emqx_mgmt:export_acl_mnesia(),
     AclMnesia = emqx_mgmt:export_acl_mnesia(),
+    Schemas = emqx_mgmt:export_schemas(),
     Seconds = erlang:system_time(second),
     Seconds = erlang:system_time(second),
     {{Y, M, D}, {H, MM, S}} = emqx_mgmt_util:datetime(Seconds),
     {{Y, M, D}, {H, MM, S}} = emqx_mgmt_util:datetime(Seconds),
     Filename = io_lib:format("emqx-export-~p-~p-~p-~p-~p-~p.json", [Y, M, D, H, MM, S]),
     Filename = io_lib:format("emqx-export-~p-~p-~p-~p-~p-~p.json", [Y, M, D, H, MM, S]),
@@ -582,8 +583,8 @@ data(["export"]) ->
             {auth_clientid, AuthClientID},
             {auth_clientid, AuthClientID},
             {auth_username, AuthUsername},
             {auth_username, AuthUsername},
             {auth_mnesia, AuthMnesia},
             {auth_mnesia, AuthMnesia},
-            {acl_mnesia, AclMnesia}
-            ],
+            {acl_mnesia, AclMnesia},
+            {schemas, Schemas}],
     ok = filelib:ensure_dir(NFilename),
     ok = filelib:ensure_dir(NFilename),
     case file:write_file(NFilename, emqx_json:encode(Data)) of
     case file:write_file(NFilename, emqx_json:encode(Data)) of
         ok ->
         ok ->
@@ -609,6 +610,7 @@ data(["import", Filename]) ->
                         emqx_mgmt:import_auth_username(maps:get(<<"auth_username">>, Data, [])),
                         emqx_mgmt:import_auth_username(maps:get(<<"auth_username">>, Data, [])),
                         emqx_mgmt:import_auth_mnesia(maps:get(<<"auth_mnesia">>, Data, [])),
                         emqx_mgmt:import_auth_mnesia(maps:get(<<"auth_mnesia">>, Data, [])),
                         emqx_mgmt:import_acl_mnesia(maps:get(<<"acl_mnesia">>, Data, [])),
                         emqx_mgmt:import_acl_mnesia(maps:get(<<"acl_mnesia">>, Data, [])),
+                        emqx_mgmt:import_schemas(maps:get(<<"schemas">>, Data, [])),
                         emqx_ctl:print("The emqx data has been imported successfully.~n")
                         emqx_ctl:print("The emqx data has been imported successfully.~n")
                     catch Class:Reason:Stack ->
                     catch Class:Reason:Stack ->
                         emqx_ctl:print("The emqx data import failed due: ~0p~n", [{Class,Reason,Stack}])
                         emqx_ctl:print("The emqx data import failed due: ~0p~n", [{Class,Reason,Stack}])

+ 0 - 8
apps/emqx_rule_engine/src/emqx_rule_engine.appup.src

@@ -1,8 +0,0 @@
-{VSN,
-  [
-    {<<".*">>, []}
-  ],
-  [
-    {<<".*">>, []}
-  ]
-}.

+ 45 - 75
apps/emqx_rule_engine/src/emqx_rule_funcs.erl

@@ -78,10 +78,6 @@
         , bitxor/2
         , bitxor/2
         , bitsl/2
         , bitsl/2
         , bitsr/2
         , bitsr/2
-        , bitsize/1
-        , subbits/2
-        , subbits/3
-        , subbits/6
         ]).
         ]).
 
 
 %% Data Type Convertion
 %% Data Type Convertion
@@ -237,7 +233,7 @@ payload() ->
 
 
 payload(Path) ->
 payload(Path) ->
     fun(#{payload := Payload}) when erlang:is_map(Payload) ->
     fun(#{payload := Payload}) when erlang:is_map(Payload) ->
-            map_get(Path, Payload);
+            emqx_rule_maps:nested_get(map_path(Path), Payload);
        (_) -> undefined
        (_) -> undefined
     end.
     end.
 
 
@@ -405,74 +401,6 @@ bitsl(X, I) when is_integer(X), is_integer(I) ->
 bitsr(X, I) when is_integer(X), is_integer(I) ->
 bitsr(X, I) when is_integer(X), is_integer(I) ->
     X bsr I.
     X bsr I.
 
 
-bitsize(Bits) when is_bitstring(Bits) ->
-    bit_size(Bits).
-
-subbits(Bits, Len) when is_integer(Len), is_bitstring(Bits) ->
-    subbits(Bits, 1, Len).
-
-subbits(Bits, Start, Len) when is_integer(Start), is_integer(Len), is_bitstring(Bits) ->
-    get_subbits(Bits, Start, Len, <<"integer">>, <<"unsigned">>, <<"big">>).
-
-subbits(Bits, Start, Len, Type, Signedness, Endianness) when is_integer(Start), is_integer(Len), is_bitstring(Bits) ->
-    get_subbits(Bits, Start, Len, Type, Signedness, Endianness).
-
-get_subbits(Bits, Start, Len, Type, Signedness, Endianness) ->
-    Begin = Start - 1,
-    case Bits of
-        <<_:Begin, Rem/bits>> when Rem =/= <<>> ->
-            Sz = bit_size(Rem),
-            do_get_subbits(Rem, Sz, Len, Type, Signedness, Endianness);
-        _ -> undefined
-    end.
-
--define(match_bits(Bits0, Pattern, ElesePattern),
-    case Bits0 of
-        Pattern ->
-            SubBits;
-        ElesePattern ->
-            SubBits
-    end).
-do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"unsigned">>, <<"big">>) ->
-    ?match_bits(Bits, <<SubBits:Len/integer-unsigned-big-unit:1, _/bits>>,
-                      <<SubBits:Sz/integer-unsigned-big-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"float">>, <<"unsigned">>, <<"big">>) ->
-    ?match_bits(Bits, <<SubBits:Len/float-unsigned-big-unit:1, _/bits>>,
-                      <<SubBits:Sz/float-unsigned-big-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"unsigned">>, <<"big">>) ->
-    ?match_bits(Bits, <<SubBits:Len/bits-unsigned-big-unit:1, _/bits>>,
-                      <<SubBits:Sz/bits-unsigned-big-unit:1>>);
-
-do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"signed">>, <<"big">>) ->
-    ?match_bits(Bits, <<SubBits:Len/integer-signed-big-unit:1, _/bits>>,
-                      <<SubBits:Sz/integer-signed-big-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"float">>, <<"signed">>, <<"big">>) ->
-    ?match_bits(Bits, <<SubBits:Len/float-signed-big-unit:1, _/bits>>,
-                      <<SubBits:Sz/float-signed-big-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"signed">>, <<"big">>) ->
-    ?match_bits(Bits, <<SubBits:Len/bits-signed-big-unit:1, _/bits>>,
-                      <<SubBits:Sz/bits-signed-big-unit:1>>);
-
-do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"unsigned">>, <<"little">>) ->
-    ?match_bits(Bits, <<SubBits:Len/integer-unsigned-little-unit:1, _/bits>>,
-                      <<SubBits:Sz/integer-unsigned-little-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"float">>, <<"unsigned">>, <<"little">>) ->
-    ?match_bits(Bits, <<SubBits:Len/float-unsigned-little-unit:1, _/bits>>,
-                      <<SubBits:Sz/float-unsigned-little-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"unsigned">>, <<"little">>) ->
-    ?match_bits(Bits, <<SubBits:Len/bits-unsigned-little-unit:1, _/bits>>,
-                      <<SubBits:Sz/bits-unsigned-little-unit:1>>);
-
-do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"signed">>, <<"little">>) ->
-    ?match_bits(Bits, <<SubBits:Len/integer-signed-little-unit:1, _/bits>>,
-                      <<SubBits:Sz/integer-signed-little-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"float">>, <<"signed">>, <<"little">>) ->
-    ?match_bits(Bits, <<SubBits:Len/float-signed-little-unit:1, _/bits>>,
-                      <<SubBits:Sz/float-signed-little-unit:1>>);
-do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"signed">>, <<"little">>) ->
-    ?match_bits(Bits, <<SubBits:Len/bits-signed-little-unit:1, _/bits>>,
-                      <<SubBits:Sz/bits-signed-little-unit:1>>).
-
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
 %% Data Type Convertion Funcs
 %% Data Type Convertion Funcs
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
@@ -679,10 +607,52 @@ map_get(Key, Map) ->
     map_get(Key, Map, undefined).
     map_get(Key, Map, undefined).
 
 
 map_get(Key, Map, Default) ->
 map_get(Key, Map, Default) ->
-    emqx_rule_maps:nested_get(map_path(Key), Map, Default).
+    case maps:find(Key, Map) of
+        {ok, Val} -> Val;
+        error when is_atom(Key) ->
+            %% the map may have an equivalent binary-form key
+            BinKey = emqx_rule_utils:bin(Key),
+            case maps:find(BinKey, Map) of
+                {ok, Val} -> Val;
+                error -> Default
+            end;
+        error when is_binary(Key) ->
+            try %% the map may have an equivalent atom-form key
+                AtomKey = list_to_existing_atom(binary_to_list(Key)),
+                case maps:find(AtomKey, Map) of
+                    {ok, Val} -> Val;
+                    error -> Default
+                end
+            catch error:badarg ->
+                Default
+            end;
+        error ->
+            Default
+    end.
 
 
 map_put(Key, Val, Map) ->
 map_put(Key, Val, Map) ->
-    emqx_rule_maps:nested_put(map_path(Key), Val, Map).
+    case maps:find(Key, Map) of
+        {ok, _} -> maps:put(Key, Val, Map);
+        error when is_atom(Key) ->
+            %% the map may have an equivalent binary-form key
+            BinKey = emqx_rule_utils:bin(Key),
+            case maps:find(BinKey, Map) of
+                {ok, _} -> maps:put(BinKey, Val, Map);
+                error -> maps:put(Key, Val, Map)
+            end;
+        error when is_binary(Key) ->
+            try %% the map may have an equivalent atom-form key
+                AtomKey = list_to_existing_atom(binary_to_list(Key)),
+                case maps:find(AtomKey, Map) of
+                    {ok, _} -> maps:put(AtomKey, Val, Map);
+                    error -> maps:put(Key, Val, Map)
+                end
+            catch error:badarg ->
+                maps:put(Key, Val, Map)
+            end;
+        error ->
+            maps:put(Key, Val, Map)
+    end.
 
 
 mget(Key, Map) ->
 mget(Key, Map) ->
     mget(Key, Map, undefined).
     mget(Key, Map, undefined).

+ 4 - 57
apps/emqx_rule_engine/test/emqx_rule_funcs_SUITE.erl

@@ -489,75 +489,22 @@ t_contains(_) ->
 
 
 t_map_get(_) ->
 t_map_get(_) ->
     ?assertEqual(1, apply_func(map_get, [<<"a">>, #{a => 1}])),
     ?assertEqual(1, apply_func(map_get, [<<"a">>, #{a => 1}])),
-    ?assertEqual(undefined, apply_func(map_get, [<<"a">>, #{}])),
-    ?assertEqual(1, apply_func(map_get, [<<"a.b">>, #{a => #{b => 1}}])),
-    ?assertEqual(undefined, apply_func(map_get, [<<"a.c">>, #{a => #{b => 1}}])).
+    ?assertEqual(undefined, apply_func(map_get, [<<"a">>, #{}])).
 
 
 t_map_put(_) ->
 t_map_put(_) ->
     ?assertEqual(#{<<"a">> => 1}, apply_func(map_put, [<<"a">>, 1, #{}])),
     ?assertEqual(#{<<"a">> => 1}, apply_func(map_put, [<<"a">>, 1, #{}])),
-    ?assertEqual(#{a => 2}, apply_func(map_put, [<<"a">>, 2, #{a => 1}])),
-    ?assertEqual(#{<<"a">> => #{<<"b">> => 1}}, apply_func(map_put, [<<"a.b">>, 1, #{}])),
-    ?assertEqual(#{a => #{b => 1, <<"c">> => 1}}, apply_func(map_put, [<<"a.c">>, 1, #{a => #{b => 1}}])).
+    ?assertEqual(#{a => 2}, apply_func(map_put, [<<"a">>, 2, #{a => 1}])).
 
 
-t_mget(_) ->
+ t_mget(_) ->
     ?assertEqual(1, apply_func(map_get, [<<"a">>, #{a => 1}])),
     ?assertEqual(1, apply_func(map_get, [<<"a">>, #{a => 1}])),
     ?assertEqual(1, apply_func(map_get, [<<"a">>, #{<<"a">> => 1}])),
     ?assertEqual(1, apply_func(map_get, [<<"a">>, #{<<"a">> => 1}])),
     ?assertEqual(undefined, apply_func(map_get, [<<"a">>, #{}])).
     ?assertEqual(undefined, apply_func(map_get, [<<"a">>, #{}])).
 
 
-t_mput(_) ->
+ t_mput(_) ->
     ?assertEqual(#{<<"a">> => 1}, apply_func(map_put, [<<"a">>, 1, #{}])),
     ?assertEqual(#{<<"a">> => 1}, apply_func(map_put, [<<"a">>, 1, #{}])),
     ?assertEqual(#{<<"a">> => 2}, apply_func(map_put, [<<"a">>, 2, #{<<"a">> => 1}])),
     ?assertEqual(#{<<"a">> => 2}, apply_func(map_put, [<<"a">>, 2, #{<<"a">> => 1}])),
     ?assertEqual(#{a => 2}, apply_func(map_put, [<<"a">>, 2, #{a => 1}])).
     ?assertEqual(#{a => 2}, apply_func(map_put, [<<"a">>, 2, #{a => 1}])).
 
 
-t_bitsize(_) ->
-    ?assertEqual(8, apply_func(bitsize, [<<"a">>])),
-    ?assertEqual(4, apply_func(bitsize, [<<15:4>>])).
-
-t_subbits(_) ->
-    ?assertEqual(1, apply_func(subbits, [<<255:8>>, 1])),
-    ?assertEqual(3, apply_func(subbits, [<<255:8>>, 2])),
-    ?assertEqual(7, apply_func(subbits, [<<255:8>>, 3])),
-    ?assertEqual(15, apply_func(subbits, [<<255:8>>, 4])),
-    ?assertEqual(31, apply_func(subbits, [<<255:8>>, 5])),
-    ?assertEqual(63, apply_func(subbits, [<<255:8>>, 6])),
-    ?assertEqual(127, apply_func(subbits, [<<255:8>>, 7])),
-    ?assertEqual(255, apply_func(subbits, [<<255:8>>, 8])).
-
-t_subbits2(_) ->
-    ?assertEqual(1, apply_func(subbits, [<<255:8>>, 1, 1])),
-    ?assertEqual(3, apply_func(subbits, [<<255:8>>, 1, 2])),
-    ?assertEqual(7, apply_func(subbits, [<<255:8>>, 1, 3])),
-    ?assertEqual(15, apply_func(subbits, [<<255:8>>, 1, 4])),
-    ?assertEqual(31, apply_func(subbits, [<<255:8>>, 1, 5])),
-    ?assertEqual(63, apply_func(subbits, [<<255:8>>, 1, 6])),
-    ?assertEqual(127, apply_func(subbits, [<<255:8>>, 1, 7])),
-    ?assertEqual(255, apply_func(subbits, [<<255:8>>, 1, 8])).
-
-t_subbits2_1(_) ->
-    ?assertEqual(1, apply_func(subbits, [<<255:8>>, 2, 1])),
-    ?assertEqual(3, apply_func(subbits, [<<255:8>>, 2, 2])),
-    ?assertEqual(7, apply_func(subbits, [<<255:8>>, 2, 3])),
-    ?assertEqual(15, apply_func(subbits, [<<255:8>>, 2, 4])),
-    ?assertEqual(31, apply_func(subbits, [<<255:8>>, 2, 5])),
-    ?assertEqual(63, apply_func(subbits, [<<255:8>>, 2, 6])),
-    ?assertEqual(127, apply_func(subbits, [<<255:8>>, 2, 7])),
-    ?assertEqual(127, apply_func(subbits, [<<255:8>>, 2, 8])).
-
-t_subbits2_integer(_) ->
-    ?assertEqual(456, apply_func(subbits, [<<456:32/integer>>, 1, 32, <<"integer">>, <<"signed">>, <<"big">>])),
-    ?assertEqual(-456, apply_func(subbits, [<<-456:32/integer>>, 1, 32, <<"integer">>, <<"signed">>, <<"big">>])).
-
-t_subbits2_float(_) ->
-    R = apply_func(subbits, [<<5.3:64/float>>, 1, 64, <<"float">>, <<"unsigned">>, <<"big">>]),
-    RL = (5.3 - R),
-    ct:pal(";;;;~p", [R]),
-    ?assert( (RL >= 0 andalso RL < 0.0001) orelse (RL =< 0 andalso RL > -0.0001)),
-
-    R2 = apply_func(subbits, [<<-5.3:64/float>>, 1, 64, <<"float">>, <<"signed">>, <<"big">>]),
-
-    RL2 = (5.3 + R2),
-    ct:pal(";;;;~p", [R2]),
-    ?assert( (RL2 >= 0 andalso RL2 < 0.0001) orelse (RL2 =< 0 andalso RL2 > -0.0001)).
 
 
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
 %% Test cases for Hash funcs
 %% Test cases for Hash funcs

+ 1 - 1
apps/emqx_sasl/test/emqx_sasl_scram_SUITE.erl

@@ -137,4 +137,4 @@ receive_msg() ->
             ct:print("==========+~p~n", [Msg]), 
             ct:print("==========+~p~n", [Msg]), 
             receive_msg()
             receive_msg()
     after 200 -> ok
     after 200 -> ok
-    end.
+    end.

+ 0 - 9
apps/emqx_web_hook/src/emqx_web_hook.appup.src

@@ -1,9 +0,0 @@
-%% -*-: erlang -*-
-{VSN,
-  [
-    {<<".*">>, []}
-  ],
-  [
-    {<<".*">>, []}
-  ]
-}.

+ 4 - 3
sync-apps.sh

@@ -85,10 +85,11 @@ done
 cleanup_app(){
 cleanup_app(){
     local app="$1"
     local app="$1"
     pushd "apps/$app"
     pushd "apps/$app"
-    rm -f Makefile rebar.config.script
+    rm -f Makefile rebar.config.script LICENSE src/*.app.src.script src/*.appup.src
     rm -rf ".github" ".ci"
     rm -rf ".github" ".ci"
-    rm -rf src/*.app.src.script
-    rm -rf src/*.appup.src
+    # restore rebar.config and app.src
+    git checkout rebar.config
+    git checkout src/*.app.src
     popd
     popd
 }
 }