diff --git a/apps/emqx_authn/i18n/emqx_authn_api_i18n.conf b/apps/emqx_authn/i18n/emqx_authn_api_i18n.conf index 1878662ea..777a1df00 100644 --- a/apps/emqx_authn/i18n/emqx_authn_api_i18n.conf +++ b/apps/emqx_authn/i18n/emqx_authn_api_i18n.conf @@ -225,4 +225,12 @@ emqx_authn_api { zh: """模糊用户名""" } } + + is_superuser { + desc { + en: """Is superuser""" + zh: """是否是超级用户""" + } + } + } diff --git a/apps/emqx_authn/src/emqx_authn_api.erl b/apps/emqx_authn/src/emqx_authn_api.erl index 9974d66de..0e7f03ce7 100644 --- a/apps/emqx_authn/src/emqx_authn_api.erl +++ b/apps/emqx_authn/src/emqx_authn_api.erl @@ -440,6 +440,12 @@ schema("/authentication/:id/users") -> in => query, desc => ?DESC(like_clientid), required => false + })}, + {is_superuser, + mk(boolean(), #{ + in => query, + desc => ?DESC(is_superuser), + required => false })} ], responses => #{ @@ -478,7 +484,13 @@ schema("/listeners/:listener_id/authentication/:id/users") -> param_listener_id(), param_auth_id(), ref(emqx_dashboard_swagger, page), - ref(emqx_dashboard_swagger, limit) + ref(emqx_dashboard_swagger, limit), + {is_superuser, + mk(boolean(), #{ + in => query, + desc => ?DESC(is_superuser), + required => false + })} ], responses => #{ 200 => emqx_dashboard_swagger:schema_with_example( diff --git a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl index b3bb91ff7..ef9d154d1 100644 --- a/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl +++ b/apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl @@ -74,7 +74,8 @@ -define(AUTHN_QSCHEMA, [ {<<"like_username">>, binary}, {<<"like_clientid">>, binary}, - {<<"user_group">>, binary} + {<<"user_group">>, binary}, + {<<"is_superuser">>, atom} ]). -define(QUERY_FUN, {?MODULE, query}). @@ -469,21 +470,26 @@ format_user_info(#user_info{user_id = {_, UserID}, is_superuser = IsSuperuser}) #{user_id => UserID, is_superuser => IsSuperuser}. ms_from_qstring(QString) -> - [Ms] = lists:foldl( - fun - ({user_group, '=:=', UserGroup}, AccIn) -> - [group_match_spec(UserGroup) | AccIn]; - (_, AccIn) -> - AccIn - end, - [], - QString - ), - Ms. + case lists:keytake(user_group, 1, QString) of + {value, {user_group, '=:=', UserGroup}, QString2} -> + group_match_spec(UserGroup, QString2); + _ -> + [] + end. group_match_spec(UserGroup) -> - ets:fun2ms( - fun(#user_info{user_id = {Group, _}} = User) when Group =:= UserGroup -> - User - end - ). + group_match_spec(UserGroup, []). + +group_match_spec(UserGroup, QString) -> + case lists:keyfind(is_superuser, 1, QString) of + false -> + ets:fun2ms(fun(#user_info{user_id = {Group, _}} = User) when Group =:= UserGroup -> + User + end); + {is_superuser, '=:=', Value} -> + ets:fun2ms(fun(#user_info{user_id = {Group, _}, is_superuser = IsSuper} = User) when + Group =:= UserGroup, IsSuper =:= Value + -> + User + end) + end. diff --git a/apps/emqx_authn/test/emqx_authn_api_SUITE.erl b/apps/emqx_authn/test/emqx_authn_api_SUITE.erl index 21b53bb1f..e082c93b4 100644 --- a/apps/emqx_authn/test/emqx_authn_api_SUITE.erl +++ b/apps/emqx_authn/test/emqx_authn_api_SUITE.erl @@ -356,7 +356,43 @@ test_authenticator_users(PathPrefix) -> ?assertEqual( [<<"u1">>, <<"u2">>, <<"u3">>], lists:usort([UserId || #{<<"user_id">> := UserId} <- Page1Users ++ Page2Users]) - ). + ), + + {ok, 200, Super1Data} = request(get, UsersUri ++ "?page=1&limit=3&is_superuser=true"), + + #{ + <<"data">> := Super1Users, + <<"meta">> := + #{ + <<"page">> := 1, + <<"limit">> := 3, + <<"count">> := 1 + } + } = jiffy:decode(Super1Data, [return_maps]), + + ?assertEqual( + [<<"u2">>], + lists:usort([UserId || #{<<"user_id">> := UserId} <- Super1Users]) + ), + + {ok, 200, Super2Data} = request(get, UsersUri ++ "?page=1&limit=3&is_superuser=false"), + + #{ + <<"data">> := Super2Users, + <<"meta">> := + #{ + <<"page">> := 1, + <<"limit">> := 3, + <<"count">> := 2 + } + } = jiffy:decode(Super2Data, [return_maps]), + + ?assertEqual( + [<<"u1">>, <<"u3">>], + lists:usort([UserId || #{<<"user_id">> := UserId} <- Super2Users]) + ), + + ok. test_authenticator_user(PathPrefix) -> UsersUri = uri(PathPrefix ++ [?CONF_NS, "password_based:built_in_database", "users"]),