Merge pull request #9569 from sstrigler/EMQX-8372-5-0-refactor-delete-authorization-sources-built-in-database-purge-all
refactor: move to /authorization/sources/built_in_database/rules
This commit is contained in:
commit
f54f238556
|
@ -92,7 +92,7 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: emqx/emqx-fvt
|
||||
ref: broker-autotest-v2
|
||||
ref: broker-autotest-v3
|
||||
path: scripts
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
|
@ -191,7 +191,7 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: emqx/emqx-fvt
|
||||
ref: broker-autotest-v2
|
||||
ref: broker-autotest-v3
|
||||
path: scripts
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
|
@ -297,7 +297,7 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: emqx/emqx-fvt
|
||||
ref: broker-autotest-v2
|
||||
ref: broker-autotest-v3
|
||||
path: scripts
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
|
@ -396,7 +396,7 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: emqx/emqx-fvt
|
||||
ref: broker-autotest-v2
|
||||
ref: broker-autotest-v3
|
||||
path: scripts
|
||||
- name: run jwks_server
|
||||
timeout-minutes: 10
|
||||
|
@ -496,7 +496,7 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: emqx/emqx-fvt
|
||||
ref: broker-autotest-v2
|
||||
ref: broker-autotest-v3
|
||||
path: scripts
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
emqx_authz_api_mnesia {
|
||||
users_username_get {
|
||||
desc {
|
||||
en: """Show the list of record for username"""
|
||||
en: """Show the list of rules for users"""
|
||||
zh: """获取内置数据库中所有用户名类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
users_username_post {
|
||||
desc {
|
||||
en: """Add new records for username"""
|
||||
en: """Add new rule for 'username'"""
|
||||
zh: """添加内置数据库中用户名类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
users_clientid_get {
|
||||
desc {
|
||||
en: """Show the list of record for clientid"""
|
||||
en: """Show the list of rules for clients"""
|
||||
zh: """获取内置数据库中所有客户端标识符类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
users_clientid_post {
|
||||
desc {
|
||||
en: """Add new records for clientid"""
|
||||
en: """Add new rule for 'clientid'"""
|
||||
zh: """添加内置数据库中客户端标识符类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
@ -30,71 +30,71 @@ emqx_authz_api_mnesia {
|
|||
|
||||
user_username_get {
|
||||
desc {
|
||||
en: """Get record info for username"""
|
||||
en: """Get rule for 'username'"""
|
||||
zh: """获取内置数据库中指定用户名类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
user_username_put {
|
||||
desc {
|
||||
en: """Set record for username"""
|
||||
en: """Set rule for 'username'"""
|
||||
zh: """更新内置数据库中指定用户名类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
user_username_delete {
|
||||
desc {
|
||||
en: """Delete one record for username"""
|
||||
en: """Delete rule for 'username'"""
|
||||
zh: """删除内置数据库中指定用户名类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
user_clientid_get {
|
||||
desc {
|
||||
en: """Get record info for clientid"""
|
||||
en: """Get rule for 'clientid'"""
|
||||
zh: """获取内置数据库中指定客户端标识符类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
user_clientid_put {
|
||||
desc {
|
||||
en: """Set record for clientid"""
|
||||
en: """Set rule for 'clientid'"""
|
||||
zh: """更新内置数据库中指定客户端标识符类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
user_clientid_delete {
|
||||
desc {
|
||||
en: """Delete one record for clientid"""
|
||||
en: """Delete rule for 'clientid'"""
|
||||
zh: """删除内置数据库中指定客户端标识符类型的规则记录"""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rules_for_all_get {
|
||||
rules_all_get {
|
||||
desc {
|
||||
en: """Show the list of rules for all"""
|
||||
en: """Show the list of rules for 'all'"""
|
||||
zh: """列出为所有客户端启用的规则列表"""
|
||||
}
|
||||
}
|
||||
|
||||
rules_for_all_post {
|
||||
rules_all_post {
|
||||
desc {
|
||||
en: """
|
||||
Create/Update the list of rules for all.
|
||||
Set a empty list to clean up rules
|
||||
"""
|
||||
zh: """
|
||||
创建/更新 为所有客户端启用的规则列表。
|
||||
设为空列表以清楚所有规则
|
||||
"""
|
||||
en: """Create/Update the list of rules for 'all'."""
|
||||
zh: """创建/更新 为所有客户端启用的规则列表。"""
|
||||
}
|
||||
}
|
||||
|
||||
purge_all_delete {
|
||||
rules_all_delete {
|
||||
desc {
|
||||
en: """Purge all records for username/clientid/all"""
|
||||
zh: """清除所有内置数据库中的规则, 用户名/客户端标识符/所有"""
|
||||
en: """Delete rules for 'all'"""
|
||||
zh: """删除 `all` 规则"""
|
||||
}
|
||||
}
|
||||
|
||||
rules_delete {
|
||||
desc {
|
||||
en: """Delete all rules for all 'users', 'clients' and 'all'"""
|
||||
zh: """清除内置数据库中的所有类型('users' 、'clients' 、'all')的所有规则"""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%% -*- mode: erlang -*-
|
||||
{application, emqx_authz, [
|
||||
{description, "An OTP application"},
|
||||
{vsn, "0.1.10"},
|
||||
{vsn, "0.1.11"},
|
||||
{registered, []},
|
||||
{mod, {emqx_authz_app, []}},
|
||||
{applications, [
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
user/2,
|
||||
client/2,
|
||||
all/2,
|
||||
purge/2
|
||||
rules/2
|
||||
]).
|
||||
|
||||
%% query funs
|
||||
|
@ -70,19 +70,19 @@ api_spec() ->
|
|||
|
||||
paths() ->
|
||||
[
|
||||
"/authorization/sources/built_in_database/username",
|
||||
"/authorization/sources/built_in_database/clientid",
|
||||
"/authorization/sources/built_in_database/username/:username",
|
||||
"/authorization/sources/built_in_database/clientid/:clientid",
|
||||
"/authorization/sources/built_in_database/all",
|
||||
"/authorization/sources/built_in_database/purge-all"
|
||||
"/authorization/sources/built_in_database/rules/users",
|
||||
"/authorization/sources/built_in_database/rules/clients",
|
||||
"/authorization/sources/built_in_database/rules/users/:username",
|
||||
"/authorization/sources/built_in_database/rules/clients/:clientid",
|
||||
"/authorization/sources/built_in_database/rules/all",
|
||||
"/authorization/sources/built_in_database/rules"
|
||||
].
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Schema for each URI
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
schema("/authorization/sources/built_in_database/username") ->
|
||||
schema("/authorization/sources/built_in_database/rules/users") ->
|
||||
#{
|
||||
'operationId' => users,
|
||||
get =>
|
||||
|
@ -128,7 +128,7 @@ schema("/authorization/sources/built_in_database/username") ->
|
|||
}
|
||||
}
|
||||
};
|
||||
schema("/authorization/sources/built_in_database/clientid") ->
|
||||
schema("/authorization/sources/built_in_database/rules/clients") ->
|
||||
#{
|
||||
'operationId' => clients,
|
||||
get =>
|
||||
|
@ -174,7 +174,7 @@ schema("/authorization/sources/built_in_database/clientid") ->
|
|||
}
|
||||
}
|
||||
};
|
||||
schema("/authorization/sources/built_in_database/username/:username") ->
|
||||
schema("/authorization/sources/built_in_database/rules/users/:username") ->
|
||||
#{
|
||||
'operationId' => user,
|
||||
get =>
|
||||
|
@ -227,7 +227,7 @@ schema("/authorization/sources/built_in_database/username/:username") ->
|
|||
}
|
||||
}
|
||||
};
|
||||
schema("/authorization/sources/built_in_database/clientid/:clientid") ->
|
||||
schema("/authorization/sources/built_in_database/rules/clients/:clientid") ->
|
||||
#{
|
||||
'operationId' => client,
|
||||
get =>
|
||||
|
@ -280,20 +280,20 @@ schema("/authorization/sources/built_in_database/clientid/:clientid") ->
|
|||
}
|
||||
}
|
||||
};
|
||||
schema("/authorization/sources/built_in_database/all") ->
|
||||
schema("/authorization/sources/built_in_database/rules/all") ->
|
||||
#{
|
||||
'operationId' => all,
|
||||
get =>
|
||||
#{
|
||||
tags => [<<"authorization">>],
|
||||
description => ?DESC(rules_for_all_get),
|
||||
description => ?DESC(rules_all_get),
|
||||
responses =>
|
||||
#{200 => swagger_with_example({rules, ?TYPE_REF}, {all, ?PUT_MAP_EXAMPLE})}
|
||||
},
|
||||
post =>
|
||||
#{
|
||||
tags => [<<"authorization">>],
|
||||
description => ?DESC(rules_for_all_post),
|
||||
description => ?DESC(rules_all_post),
|
||||
'requestBody' =>
|
||||
swagger_with_example({rules, ?TYPE_REF}, {all, ?PUT_MAP_EXAMPLE}),
|
||||
responses =>
|
||||
|
@ -303,15 +303,24 @@ schema("/authorization/sources/built_in_database/all") ->
|
|||
[?BAD_REQUEST], <<"Bad rule schema">>
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
schema("/authorization/sources/built_in_database/purge-all") ->
|
||||
#{
|
||||
'operationId' => purge,
|
||||
},
|
||||
delete =>
|
||||
#{
|
||||
tags => [<<"authorization">>],
|
||||
description => ?DESC(purge_all_delete),
|
||||
description => ?DESC(rules_all_delete),
|
||||
responses =>
|
||||
#{
|
||||
204 => <<"Deleted">>
|
||||
}
|
||||
}
|
||||
};
|
||||
schema("/authorization/sources/built_in_database/rules") ->
|
||||
#{
|
||||
'operationId' => rules,
|
||||
delete =>
|
||||
#{
|
||||
tags => [<<"authorization">>],
|
||||
description => ?DESC(rules_delete),
|
||||
responses =>
|
||||
#{
|
||||
204 => <<"Deleted">>,
|
||||
|
@ -555,9 +564,12 @@ all(get, _) ->
|
|||
end;
|
||||
all(post, #{body := #{<<"rules">> := Rules}}) ->
|
||||
emqx_authz_mnesia:store_rules(all, format_rules(Rules)),
|
||||
{204};
|
||||
all(delete, _) ->
|
||||
emqx_authz_mnesia:store_rules(all, []),
|
||||
{204}.
|
||||
|
||||
purge(delete, _) ->
|
||||
rules(delete, _) ->
|
||||
case emqx_authz_api_sources:get_raw_source(<<"built_in_database">>) of
|
||||
[#{<<"enable">> := false}] ->
|
||||
ok = emqx_authz_mnesia:purge_rules(),
|
||||
|
|
|
@ -70,21 +70,21 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "username"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users"]),
|
||||
[?USERNAME_RULES_EXAMPLE]
|
||||
),
|
||||
|
||||
{ok, 409, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "username"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users"]),
|
||||
[?USERNAME_RULES_EXAMPLE]
|
||||
),
|
||||
|
||||
{ok, 200, Request1} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "username"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users"]),
|
||||
[]
|
||||
),
|
||||
#{
|
||||
|
@ -104,7 +104,8 @@ t_api(_) ->
|
|||
"authorization",
|
||||
"sources",
|
||||
"built_in_database",
|
||||
"username?page=1&limit=20&like_username=noexist"
|
||||
"rules",
|
||||
"users?page=1&limit=20&like_username=noexist"
|
||||
]),
|
||||
[]
|
||||
),
|
||||
|
@ -120,7 +121,7 @@ t_api(_) ->
|
|||
{ok, 200, Request2} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "username", "user1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users", "user1"]),
|
||||
[]
|
||||
),
|
||||
#{<<"username">> := <<"user1">>, <<"rules">> := Rules1} = jsx:decode(Request2),
|
||||
|
@ -128,13 +129,13 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
put,
|
||||
uri(["authorization", "sources", "built_in_database", "username", "user1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users", "user1"]),
|
||||
?USERNAME_RULES_EXAMPLE#{rules => []}
|
||||
),
|
||||
{ok, 200, Request3} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "username", "user1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users", "user1"]),
|
||||
[]
|
||||
),
|
||||
#{<<"username">> := <<"user1">>, <<"rules">> := Rules2} = jsx:decode(Request3),
|
||||
|
@ -143,46 +144,46 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
delete,
|
||||
uri(["authorization", "sources", "built_in_database", "username", "user1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users", "user1"]),
|
||||
[]
|
||||
),
|
||||
{ok, 404, _} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "username", "user1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users", "user1"]),
|
||||
[]
|
||||
),
|
||||
{ok, 404, _} =
|
||||
request(
|
||||
delete,
|
||||
uri(["authorization", "sources", "built_in_database", "username", "user1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users", "user1"]),
|
||||
[]
|
||||
),
|
||||
|
||||
{ok, 204, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients"]),
|
||||
[?CLIENTID_RULES_EXAMPLE]
|
||||
),
|
||||
|
||||
{ok, 409, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients"]),
|
||||
[?CLIENTID_RULES_EXAMPLE]
|
||||
),
|
||||
|
||||
{ok, 200, Request4} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients"]),
|
||||
[]
|
||||
),
|
||||
{ok, 200, Request5} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid", "client1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients", "client1"]),
|
||||
[]
|
||||
),
|
||||
#{
|
||||
|
@ -196,13 +197,13 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
put,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid", "client1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients", "client1"]),
|
||||
?CLIENTID_RULES_EXAMPLE#{rules => []}
|
||||
),
|
||||
{ok, 200, Request6} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid", "client1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients", "client1"]),
|
||||
[]
|
||||
),
|
||||
#{<<"clientid">> := <<"client1">>, <<"rules">> := Rules4} = jsx:decode(Request6),
|
||||
|
@ -211,32 +212,32 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
delete,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid", "client1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients", "client1"]),
|
||||
[]
|
||||
),
|
||||
{ok, 404, _} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid", "client1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients", "client1"]),
|
||||
[]
|
||||
),
|
||||
{ok, 404, _} =
|
||||
request(
|
||||
delete,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid", "client1"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients", "client1"]),
|
||||
[]
|
||||
),
|
||||
|
||||
{ok, 204, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "all"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "all"]),
|
||||
?ALL_RULES_EXAMPLE
|
||||
),
|
||||
{ok, 200, Request7} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "all"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "all"]),
|
||||
[]
|
||||
),
|
||||
#{<<"rules">> := Rules5} = jsx:decode(Request7),
|
||||
|
@ -244,15 +245,14 @@ t_api(_) ->
|
|||
|
||||
{ok, 204, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "all"]),
|
||||
|
||||
?ALL_RULES_EXAMPLE#{rules => []}
|
||||
delete,
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "all"]),
|
||||
[]
|
||||
),
|
||||
{ok, 200, Request8} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "all"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "all"]),
|
||||
[]
|
||||
),
|
||||
#{<<"rules">> := Rules6} = jsx:decode(Request8),
|
||||
|
@ -261,7 +261,7 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "username"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users"]),
|
||||
[
|
||||
#{username => erlang:integer_to_binary(N), rules => []}
|
||||
|| N <- lists:seq(1, 20)
|
||||
|
@ -270,7 +270,7 @@ t_api(_) ->
|
|||
{ok, 200, Request9} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "username?page=2&limit=5"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "users?page=2&limit=5"]),
|
||||
[]
|
||||
),
|
||||
#{<<"data">> := Data1} = jsx:decode(Request9),
|
||||
|
@ -279,7 +279,7 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
post,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients"]),
|
||||
[
|
||||
#{clientid => erlang:integer_to_binary(N), rules => []}
|
||||
|| N <- lists:seq(1, 20)
|
||||
|
@ -288,7 +288,7 @@ t_api(_) ->
|
|||
{ok, 200, Request10} =
|
||||
request(
|
||||
get,
|
||||
uri(["authorization", "sources", "built_in_database", "clientid?limit=5"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules", "clients?limit=5"]),
|
||||
[]
|
||||
),
|
||||
#{<<"data">> := Data2} = jsx:decode(Request10),
|
||||
|
@ -297,7 +297,7 @@ t_api(_) ->
|
|||
{ok, 400, Msg1} =
|
||||
request(
|
||||
delete,
|
||||
uri(["authorization", "sources", "built_in_database", "purge-all"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules"]),
|
||||
[]
|
||||
),
|
||||
?assertMatch({match, _}, re:run(Msg1, "must\sbe\sdisabled\sbefore")),
|
||||
|
@ -323,7 +323,7 @@ t_api(_) ->
|
|||
{ok, 204, _} =
|
||||
request(
|
||||
delete,
|
||||
uri(["authorization", "sources", "built_in_database", "purge-all"]),
|
||||
uri(["authorization", "sources", "built_in_database", "rules"]),
|
||||
[]
|
||||
),
|
||||
?assertEqual(0, emqx_authz_mnesia:record_count()),
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
- `/bridges_probe` API endpoint to test params for creating a new data bridge [#9585](https://github.com/emqx/emqx/pull/9585).
|
||||
|
||||
- Refactor `/authorization/sources/built_in_database/` by adding `rules/` to the path [#9569](https://github.com/emqx/emqx/pull/9569).
|
||||
|
||||
## Bug fixes
|
||||
|
||||
- Trigger `message.dropped` hook when QoS2 message is resend by client with a same packet id, or 'awaiting_rel' queue is full [#9487](https://github.com/emqx/emqx/pull/9487).
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
- 确保黑名单的默认超期时间足够长 [#9599](https://github.com/emqx/emqx/pull/9599/)。
|
||||
|
||||
- [FIXME] `/bridges_probe` API 端点用于测试创建新数据桥的参数 [#9585](https://github.com/emqx/emqx/pull/9585)。
|
||||
- 添加新 API 接口 `/bridges_probe` 用于测试创建桥接的参数是否可用 [#9585](https://github.com/emqx/emqx/pull/9585)。
|
||||
|
||||
- 重构 `/authorization/sources/built_in_database/` 接口,将 `rules/` 添加到了其路径中 [#9569](https://github.com/emqx/emqx/pull/9569)。
|
||||
|
||||
## 修复
|
||||
|
||||
|
|
Loading…
Reference in New Issue