Sfoglia il codice sorgente

Merge pull request #5679 from tigercl/chore/authn

chore(authn): update apis for user
tigercl 4 anni fa
parent
commit
f75778b037

+ 1 - 1
apps/emqx/include/emqx.hrl

@@ -147,6 +147,6 @@
         }).
 
 -record(chain,
-        { name :: binary()
+        { name :: atom()
         , authenticators :: [#authenticator{}]
         }).

+ 2 - 2
apps/emqx/src/emqx_access_control.erl

@@ -29,9 +29,9 @@
 -spec(authenticate(emqx_types:clientinfo()) ->
     {ok, map()} | {ok, map(), binary()} | {continue, map()} | {continue, binary(), map()} | {error, term()}).
 authenticate(Credential) ->
-    case run_hooks('client.authenticate', [Credential], {ok, #{superuser => false}}) of
+    case run_hooks('client.authenticate', [Credential], {ok, #{is_superuser => false}}) of
         ok ->
-            {ok, #{superuser => false}};
+            {ok, #{is_superuser => false}};
         Other ->
             Other
     end.

+ 13 - 9
apps/emqx/src/emqx_authentication.erl

@@ -80,7 +80,7 @@
 
 -type config() :: #{atom() => term()}.
 -type state() :: #{atom() => term()}.
--type extra() :: #{superuser := boolean(),
+-type extra() :: #{is_superuser := boolean(),
                    atom() => term()}.
 -type user_info() :: #{user_id := binary(),
                        atom() => term()}.
@@ -473,7 +473,7 @@ handle_call({update_authenticator, ChainName, AuthenticatorID, Config}, _From, S
                                state    = #{version := Version} = ST} = Authenticator ->
                     case AuthenticatorID =:= generate_id(Config) of
                         true ->
-                            Unique = <<ChainName/binary, "/", AuthenticatorID/binary, ":", Version/binary>>,
+                            Unique = unique(ChainName, AuthenticatorID, Version),
                             case Provider:update(Config#{'_unique' => Unique}, ST) of
                                 {ok, NewST} ->
                                     NewAuthenticator = Authenticator#authenticator{state = switch_version(NewST)},
@@ -575,17 +575,17 @@ split_by_id(ID, AuthenticatorsConfig) ->
     end.
 
 global_chain(mqtt) ->
-    <<"mqtt:global">>;
+    'mqtt:global';
 global_chain('mqtt-sn') ->
-    <<"mqtt-sn:global">>;
+    'mqtt-sn:global';
 global_chain(coap) ->
-    <<"coap:global">>;
+    'coap:global';
 global_chain(lwm2m) ->
-    <<"lwm2m:global">>;
+    'lwm2m:global';
 global_chain(stomp) ->
-    <<"stomp:global">>;
+    'stomp:global';
 global_chain(_) ->
-    <<"unknown:global">>.
+    'unknown:global'.
 
 may_hook(#{hooked := false} = State) ->
     case lists:any(fun(#chain{authenticators = []}) -> false;
@@ -618,7 +618,7 @@ do_create_authenticator(ChainName, AuthenticatorID, #{enable := Enable} = Config
         undefined ->
             {error, no_available_provider};
         Provider ->
-            Unique = <<ChainName/binary, "/", AuthenticatorID/binary, ":", ?VER_1/binary>>,
+            Unique = unique(ChainName, AuthenticatorID, ?VER_1),
             case Provider:create(Config#{'_unique' => Unique}) of
                 {ok, State} ->
                     Authenticator = #authenticator{id = AuthenticatorID,
@@ -704,6 +704,10 @@ serialize_authenticator(#authenticator{id = ID,
      , state => State
      }.
 
+unique(ChainName, AuthenticatorID, Version) ->
+    NChainName = atom_to_binary(ChainName),
+    <<NChainName/binary, "/", AuthenticatorID/binary, ":", Version/binary>>.
+
 switch_version(State = #{version := ?VER_1}) ->
     State#{version := ?VER_2};
 switch_version(State = #{version := ?VER_2}) ->

+ 8 - 8
apps/emqx/src/emqx_channel.erl

@@ -214,7 +214,7 @@ init(ConnInfo = #{peername := {PeerHost, _Port},
     ClientInfo = set_peercert_infos(
                    Peercert,
                    #{zone         => Zone,
-                     listener     => Listener,
+                     listener     => emqx_listeners:listener_id(Type, Listener),
                      protocol     => Protocol,
                      peerhost     => PeerHost,
                      sockport     => SockPort,
@@ -223,7 +223,7 @@ init(ConnInfo = #{peername := {PeerHost, _Port},
                      mountpoint   => MountPoint,
                      is_bridge    => false,
                      is_superuser => false
-                    }, Zone, Listener),
+                    }, Zone),
     {NClientInfo, NConnInfo} = take_ws_cookie(ClientInfo, ConnInfo),
     #channel{conninfo   = NConnInfo,
              clientinfo = NClientInfo,
@@ -244,12 +244,12 @@ quota_policy(RawPolicy) ->
              erlang:trunc(hocon_postprocess:duration(StrWind) / 1000)}}
      || {Name, [StrCount, StrWind]} <- maps:to_list(RawPolicy)].
 
-set_peercert_infos(NoSSL, ClientInfo, _, _)
+set_peercert_infos(NoSSL, ClientInfo, _)
   when NoSSL =:= nossl;
        NoSSL =:= undefined ->
     ClientInfo#{username => undefined};
 
-set_peercert_infos(Peercert, ClientInfo, Zone, _Listener) ->
+set_peercert_infos(Peercert, ClientInfo, Zone) ->
     {DN, CN} = {esockd_peercert:subject(Peercert),
                 esockd_peercert:common_name(Peercert)},
     PeercetAs = fun(Key) ->
@@ -1303,11 +1303,11 @@ do_authenticate(#{auth_method := AuthMethod} = Credential, #channel{clientinfo =
     case emqx_access_control:authenticate(Credential) of
         {ok, Result} ->
             {ok, Properties,
-             Channel#channel{clientinfo = ClientInfo#{is_superuser => maps:get(superuser, Result, false)},
+             Channel#channel{clientinfo = ClientInfo#{is_superuser => maps:get(is_superuser, Result, false)},
                              auth_cache = #{}}};
         {ok, Result, AuthData} ->
             {ok, Properties#{'Authentication-Data' => AuthData},
-             Channel#channel{clientinfo = ClientInfo#{is_superuser => maps:get(superuser, Result, false)},
+             Channel#channel{clientinfo = ClientInfo#{is_superuser => maps:get(is_superuser, Result, false)},
                              auth_cache = #{}}};
         {continue, AuthCache} ->
             {continue, Properties, Channel#channel{auth_cache = AuthCache}};
@@ -1320,8 +1320,8 @@ do_authenticate(#{auth_method := AuthMethod} = Credential, #channel{clientinfo =
 
 do_authenticate(Credential, #channel{clientinfo = ClientInfo} = Channel) ->
     case emqx_access_control:authenticate(Credential) of
-        {ok, #{superuser := Superuser}} ->
-            {ok, #{}, Channel#channel{clientinfo = ClientInfo#{is_superuser => Superuser}}};
+        {ok, #{is_superuser := IsSuperuser}} ->
+            {ok, #{}, Channel#channel{clientinfo = ClientInfo#{is_superuser => IsSuperuser}}};
         {error, Reason} ->
             {error, emqx_reason_codes:connack_error(Reason)}
     end.

+ 8 - 8
apps/emqx/test/emqx_authentication_SUITE.erl

@@ -73,7 +73,7 @@ update(_Config, _State) ->
     {ok, #{mark => 2}}.
 
 authenticate(#{username := <<"good">>}, _State) ->
-    {ok, #{superuser => true}};
+    {ok, #{is_superuser => true}};
 authenticate(#{username := _}, _State) ->
     {error, bad_username_or_password}.
 
@@ -94,7 +94,7 @@ end_per_suite(_) ->
 
 t_chain(_) ->
     % CRUD of authentication chain
-    ChainName = <<"test">>,
+    ChainName = 'test',
     ?assertMatch({ok, []}, ?AUTHN:list_chains()),
     ?assertMatch({ok, #{name := ChainName, authenticators := []}}, ?AUTHN:create_chain(ChainName)),
     ?assertEqual({error, {already_exists, {chain, ChainName}}}, ?AUTHN:create_chain(ChainName)),
@@ -105,7 +105,7 @@ t_chain(_) ->
     ok.
 
 t_authenticator(_) ->
-    ChainName = <<"test">>,
+    ChainName = 'test',
     AuthenticatorConfig1 = #{mechanism => 'password-based',
                              backend => 'built-in-database',
                              enable => true},
@@ -155,13 +155,13 @@ t_authenticator(_) ->
     ok.
 
 t_authenticate(_) ->
-    ListenerID = <<"tcp:default">>,
+    ListenerID = 'tcp:default',
     ClientInfo = #{zone => default,
                    listener => ListenerID,
                    protocol => mqtt,
                    username => <<"good">>,
 			       password => <<"any">>},
-    ?assertEqual({ok, #{superuser => false}}, emqx_access_control:authenticate(ClientInfo)),
+    ?assertEqual({ok, #{is_superuser => false}}, emqx_access_control:authenticate(ClientInfo)),
 
     AuthNType = {'password-based', 'built-in-database'},
     ?AUTHN:add_provider(AuthNType, ?MODULE),
@@ -171,7 +171,7 @@ t_authenticate(_) ->
                             enable => true},
     ?AUTHN:create_chain(ListenerID),
     ?assertMatch({ok, _}, ?AUTHN:create_authenticator(ListenerID, AuthenticatorConfig)),
-    ?assertEqual({ok, #{superuser => true}}, emqx_access_control:authenticate(ClientInfo)),
+    ?assertEqual({ok, #{is_superuser => true}}, emqx_access_control:authenticate(ClientInfo)),
     ?assertEqual({error, bad_username_or_password}, emqx_access_control:authenticate(ClientInfo#{username => <<"bad">>})),
 
     ?AUTHN:delete_chain(ListenerID),
@@ -186,7 +186,7 @@ t_update_config(_) ->
     ?AUTHN:add_provider(AuthNType1, ?MODULE),
     ?AUTHN:add_provider(AuthNType2, ?MODULE),
 
-    Global = <<"mqtt:global">>,
+    Global = 'mqtt:global',
     AuthenticatorConfig1 = #{mechanism => 'password-based',
                              backend => 'built-in-database',
                              enable => true},
@@ -212,7 +212,7 @@ t_update_config(_) ->
     ?assertMatch({ok, _}, update_config([authentication], {delete_authenticator, Global, ID1})),
     ?assertEqual({error, {not_found, {authenticator, ID1}}}, ?AUTHN:lookup_authenticator(Global, ID1)),
 
-    ListenerID = <<"tcp:default">>,
+    ListenerID = 'tcp:default',
     ConfKeyPath = [listeners, tcp, default, authentication],
     ?assertMatch({ok, _}, update_config(ConfKeyPath, {create_authenticator, ListenerID, AuthenticatorConfig1})),
     ?assertMatch({ok, #{id := ID1, state := #{mark := 1}}}, ?AUTHN:lookup_authenticator(ListenerID, ID1)),

+ 1 - 1
apps/emqx/test/emqx_channel_SUITE.erl

@@ -144,7 +144,7 @@ init_per_suite(Config) ->
     %% Access Control Meck
     ok = meck:new(emqx_access_control, [passthrough, no_history, no_link]),
     ok = meck:expect(emqx_access_control, authenticate,
-                     fun(_) -> {ok, #{superuser => false}} end),
+                     fun(_) -> {ok, #{is_superuser => false}} end),
     ok = meck:expect(emqx_access_control, authorize, fun(_, _, _) -> allow end),
     %% Broker Meck
     ok = meck:new(emqx_broker, [passthrough, no_history, no_link]),

+ 1 - 1
apps/emqx_authn/data/user-credentials.csv

@@ -1,3 +1,3 @@
-user_id,password_hash,salt,superuser
+user_id,password_hash,salt,is_superuser
 myuser3,b6c743545a7817ae8c8f624371d5f5f0373234bb0ff36b8ffbf19bce0e06ab75,de1024f462fb83910fd13151bd4bd235,true
 myuser4,ee68c985a69208b6eda8c6c9b4c7c2d2b15ee2352cdd64a903171710a99182e8,ad773b5be9dd0613fe6c2f4d8c403139,false

+ 2 - 2
apps/emqx_authn/data/user-credentials.json

@@ -3,12 +3,12 @@
         "user_id":"myuser1",
         "password_hash":"c5e46903df45e5dc096dc74657610dbee8deaacae656df88a1788f1847390242",
         "salt": "e378187547bf2d6f0545a3f441aa4d8a",
-        "superuser": true
+        "is_superuser": true
     },
     {
         "user_id":"myuser2",
         "password_hash":"f4d17f300b11e522fd33f497c11b126ef1ea5149c74d2220f9a16dc876d4567b",
         "salt": "6d3f9bd5b54d94b98adbcfe10b6d181f",
-        "superuser": false
+        "is_superuser": false
     }
 ]

+ 1 - 1
apps/emqx_authn/include/emqx_authn.hrl

@@ -18,7 +18,7 @@
 
 -define(AUTHN, emqx_authentication).
 
--define(GLOBAL, <<"mqtt:global">>).
+-define(GLOBAL, 'mqtt:global').
 
 -define(RE_PLACEHOLDER, "\\$\\{[a-z0-9\\-]+\\}").
 

File diff suppressed because it is too large
+ 584 - 302
apps/emqx_authn/src/emqx_authn_api.erl


+ 1 - 1
apps/emqx_authn/src/emqx_authn_app.erl

@@ -53,7 +53,7 @@ remove_providers() ->
 initialize() ->
     ?AUTHN:initialize_authentication(?GLOBAL, emqx:get_raw_config([authentication], [])),
     lists:foreach(fun({ListenerID, ListenerConfig}) ->
-                      ?AUTHN:initialize_authentication(atom_to_binary(ListenerID), maps:get(authentication, ListenerConfig, []))
+                      ?AUTHN:initialize_authentication(ListenerID, maps:get(authentication, ListenerConfig, []))
                   end, emqx_listeners:list()),
     ok.
 

+ 21 - 21
apps/emqx_authn/src/enhanced_authn/emqx_enhanced_authn_scram_mnesia.erl

@@ -53,7 +53,7 @@
         , stored_key
         , server_key
         , salt
-        , superuser
+        , is_superuser
         }).
 
 %%------------------------------------------------------------------------------
@@ -147,9 +147,9 @@ add_user(#{user_id := UserID,
         fun() ->
             case mnesia:read(?TAB, {UserGroup, UserID}, write) of
                 [] ->
-                    Superuser = maps:get(superuser, UserInfo, false),
-                    add_user(UserID, Password, Superuser, State),
-                    {ok, #{user_id => UserID, superuser => Superuser}};
+                    IsSuperuser = maps:get(is_superuser, UserInfo, false),
+                    add_user(UserID, Password, IsSuperuser, State),
+                    {ok, #{user_id => UserID, is_superuser => IsSuperuser}};
                 [_] ->
                     {error, already_exist}
             end
@@ -173,8 +173,8 @@ update_user(UserID, User,
             case mnesia:read(?TAB, {UserGroup, UserID}, write) of
                 [] ->
                     {error, not_found};
-                [#user_info{superuser = Superuser} = UserInfo] ->
-                    UserInfo1 = UserInfo#user_info{superuser = maps:get(superuser, User, Superuser)},
+                [#user_info{is_superuser = IsSuperuser} = UserInfo] ->
+                    UserInfo1 = UserInfo#user_info{is_superuser = maps:get(is_superuser, User, IsSuperuser)},
                     UserInfo2 = case maps:get(password, User, undefined) of
                                     undefined ->
                                         UserInfo1;
@@ -229,36 +229,36 @@ check_client_first_message(Bin, _Cache, #{iteration_count := IterationCount} = S
             {error, not_authorized}
     end.
 
-check_client_final_message(Bin, #{superuser := Superuser} = Cache, #{algorithm := Alg}) ->
+check_client_final_message(Bin, #{is_superuser := IsSuperuser} = Cache, #{algorithm := Alg}) ->
     case esasl_scram:check_client_final_message(
              Bin,
              Cache#{algorithm => Alg}
          ) of
         {ok, ServerFinalMessage} ->
-            {ok, #{superuser => Superuser}, ServerFinalMessage};
+            {ok, #{is_superuser => IsSuperuser}, ServerFinalMessage};
         {error, _Reason} ->
             {error, not_authorized}
     end.
 
-add_user(UserID, Password, Superuser, State) ->
+add_user(UserID, Password, IsSuperuser, State) ->
     {StoredKey, ServerKey, Salt} = esasl_scram:generate_authentication_info(Password, State),
-    UserInfo = #user_info{user_id    = UserID,
-                          stored_key = StoredKey,
-                          server_key = ServerKey,
-                          salt       = Salt,
-                          superuser  = Superuser},
+    UserInfo = #user_info{user_id      = UserID,
+                          stored_key   = StoredKey,
+                          server_key   = ServerKey,
+                          salt         = Salt,
+                          is_superuser = IsSuperuser},
     mnesia:write(?TAB, UserInfo, write).
 
 retrieve(UserID, #{user_group := UserGroup}) ->
     case mnesia:dirty_read(?TAB, {UserGroup, UserID}) of
-        [#user_info{stored_key = StoredKey,
-                    server_key = ServerKey,
-                    salt       = Salt,
-                    superuser  = Superuser}] ->
+        [#user_info{stored_key   = StoredKey,
+                    server_key   = ServerKey,
+                    salt         = Salt,
+                    is_superuser = IsSuperuser}] ->
             {ok, #{stored_key => StoredKey,
                    server_key => ServerKey,
                    salt => Salt,
-                   superuser => Superuser}};
+                   is_superuser => IsSuperuser}};
         [] ->
             {error, not_found}
     end.
@@ -273,5 +273,5 @@ trans(Fun, Args) ->
         {aborted, Reason} -> {error, Reason}
     end.
 
-serialize_user_info(#user_info{user_id = {_, UserID}, superuser = Superuser}) ->
-    #{user_id => UserID, superuser => Superuser}.
+serialize_user_info(#user_info{user_id = {_, UserID}, is_superuser = IsSuperuser}) ->
+    #{user_id => UserID, is_superuser => IsSuperuser}.

+ 3 - 3
apps/emqx_authn/src/simple_authn/emqx_authn_http.erl

@@ -161,16 +161,16 @@ authenticate(Credential, #{'_unique' := Unique,
     try
         Request = generate_request(Credential, State),
         case emqx_resource:query(Unique, {Method, Request, RequestTimeout}) of
-            {ok, 204, _Headers} -> {ok, #{superuser => false}};
+            {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, #{superuser => maps:get(<<"superuser">>, NBody, false),
+                        {ok, #{is_superuser => maps:get(<<"is_superuser">>, NBody, false),
                                user_property => NBody}};
                     {error, _Reason} ->
-                        {ok, #{superuser => false}}
+                        {ok, #{is_superuser => false}}
                 end;
             {error, _Reason} ->
                 ignore

+ 1 - 1
apps/emqx_authn/src/simple_authn/emqx_authn_jwt.erl

@@ -249,7 +249,7 @@ verify(JWS, [JWK | More], VerifyClaims) ->
             Claims = emqx_json:decode(Payload, [return_maps]),
             case verify_claims(Claims, VerifyClaims) of
                 ok ->
-                    {ok, #{superuser => maps:get(<<"superuser">>, Claims, false)}};
+                    {ok, #{is_superuser => maps:get(<<"is_superuser">>, Claims, false)}};
                 {error, Reason} ->
                     {error, Reason}
             end;

+ 21 - 21
apps/emqx_authn/src/simple_authn/emqx_authn_mnesia.erl

@@ -51,7 +51,7 @@
         { user_id :: {user_group(), user_id()}
         , password_hash :: binary()
         , salt :: binary()
-        , superuser :: boolean()
+        , is_superuser :: boolean()
         }).
 
 -reflect_type([ user_id_type/0 ]).
@@ -158,13 +158,13 @@ authenticate(#{password := Password} = Credential,
     case mnesia:dirty_read(?TAB, {UserGroup, UserID}) of
         [] ->
             ignore;
-        [#user_info{password_hash = PasswordHash, salt = Salt0, superuser = Superuser}] ->
+        [#user_info{password_hash = PasswordHash, salt = Salt0, is_superuser = IsSuperuser}] ->
             Salt = case Algorithm of
                        bcrypt -> PasswordHash;
                        _ -> Salt0
                    end,
             case PasswordHash =:= hash(Algorithm, Password, Salt) of
-                true -> {ok, #{superuser => Superuser}};
+                true -> {ok, #{is_superuser => IsSuperuser}};
                 false -> {error, bad_username_or_password}
             end
     end.
@@ -197,9 +197,9 @@ add_user(#{user_id := UserID,
             case mnesia:read(?TAB, {UserGroup, UserID}, write) of
                 [] ->
                     {PasswordHash, Salt} = hash(Password, State),
-                    Superuser = maps:get(superuser, UserInfo, false),
-                    insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser),
-                    {ok, #{user_id => UserID, superuser => Superuser}};
+                    IsSuperuser = maps:get(is_superuser, UserInfo, false),
+                    insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser),
+                    {ok, #{user_id => UserID, is_superuser => IsSuperuser}};
                 [_] ->
                     {error, already_exist}
             end
@@ -225,8 +225,8 @@ update_user(UserID, UserInfo,
                     {error, not_found};
                 [#user_info{ password_hash = PasswordHash
                            , salt = Salt
-                           , superuser = Superuser}] ->
-                    NSuperuser = maps:get(superuser, UserInfo, Superuser),
+                           , is_superuser = IsSuperuser}] ->
+                    NSuperuser = maps:get(is_superuser, UserInfo, IsSuperuser),
                     {NPasswordHash, NSalt} = case maps:get(password, UserInfo, undefined) of
                                                  undefined ->
                                                      {PasswordHash, Salt};
@@ -234,7 +234,7 @@ update_user(UserID, UserInfo,
                                                      hash(Password, State)
                                              end,
                     insert_user(UserGroup, UserID, NPasswordHash, NSalt, NSuperuser),
-                    {ok, #{user_id => UserID, superuser => NSuperuser}}
+                    {ok, #{user_id => UserID, is_superuser => NSuperuser}}
             end
         end).
 
@@ -290,8 +290,8 @@ import(UserGroup, [#{<<"user_id">> := UserID,
                      <<"password_hash">> := PasswordHash} = UserInfo | More])
   when is_binary(UserID) andalso is_binary(PasswordHash) ->
     Salt = maps:get(<<"salt">>, UserInfo, <<>>),
-    Superuser = maps:get(<<"superuser">>, UserInfo, false),
-    insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser),
+    IsSuperuser = maps:get(<<"is_superuser">>, UserInfo, false),
+    insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser),
     import(UserGroup, More);
 import(_UserGroup, [_ | _More]) ->
     {error, bad_format}.
@@ -305,8 +305,8 @@ import(UserGroup, File, Seq) ->
                 {ok, #{user_id := UserID,
                        password_hash := PasswordHash} = UserInfo} ->
                     Salt = maps:get(salt, UserInfo, <<>>),
-                    Superuser = maps:get(superuser, UserInfo, false),
-                    insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser),
+                    IsSuperuser = maps:get(is_superuser, UserInfo, false),
+                    insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser),
                     import(UserGroup, File, Seq);
                 {error, Reason} ->
                     {error, Reason}
@@ -341,10 +341,10 @@ get_user_info_by_seq([PasswordHash | More1], [<<"password_hash">> | More2], Acc)
     get_user_info_by_seq(More1, More2, Acc#{password_hash => PasswordHash});
 get_user_info_by_seq([Salt | More1], [<<"salt">> | More2], Acc) ->
     get_user_info_by_seq(More1, More2, Acc#{salt => Salt});
-get_user_info_by_seq([<<"true">> | More1], [<<"superuser">> | More2], Acc) ->
-    get_user_info_by_seq(More1, More2, Acc#{superuser => true});
-get_user_info_by_seq([<<"false">> | More1], [<<"superuser">> | More2], Acc) ->
-    get_user_info_by_seq(More1, More2, Acc#{superuser => false});
+get_user_info_by_seq([<<"true">> | More1], [<<"is_superuser">> | More2], Acc) ->
+    get_user_info_by_seq(More1, More2, Acc#{is_superuser => true});
+get_user_info_by_seq([<<"false">> | More1], [<<"is_superuser">> | More2], Acc) ->
+    get_user_info_by_seq(More1, More2, Acc#{is_superuser => false});
 get_user_info_by_seq(_, _, _) ->
     {error, bad_format}.
 
@@ -368,11 +368,11 @@ hash(Password, #{password_hash_algorithm := Algorithm} = State) ->
     PasswordHash = hash(Algorithm, Password, Salt),
     {PasswordHash, Salt}.
 
-insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser) ->
+insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser) ->
      UserInfo = #user_info{user_id = {UserGroup, UserID},
                            password_hash = PasswordHash,
                            salt = Salt,
-                           superuser = Superuser},
+                           is_superuser = IsSuperuser},
     mnesia:write(?TAB, UserInfo, write).
 
 delete_user2(UserInfo) ->
@@ -400,5 +400,5 @@ to_binary(B) when is_binary(B) ->
 to_binary(L) when is_list(L) ->
     iolist_to_binary(L).
 
-serialize_user_info(#user_info{user_id = {_, UserID}, superuser = Superuser}) ->
-    #{user_id => UserID, superuser => Superuser}.
+serialize_user_info(#user_info{user_id = {_, UserID}, is_superuser = IsSuperuser}) ->
+    #{user_id => UserID, is_superuser => IsSuperuser}.

+ 10 - 4
apps/emqx_authn/src/simple_authn/emqx_authn_mongodb.erl

@@ -64,6 +64,7 @@ common_fields() ->
     , {selector,                fun selector/1}
     , {password_hash_field,     fun password_hash_field/1}
     , {salt_field,              fun salt_field/1}
+    , {is_superuser_field,      fun is_superuser_field/1}
     , {password_hash_algorithm, fun password_hash_algorithm/1}
     , {salt_position,           fun salt_position/1}
     ] ++ emqx_authn_schema:common_fields().
@@ -84,6 +85,10 @@ salt_field(type) -> binary();
 salt_field(nullable) -> true;
 salt_field(_) -> undefined.
 
+is_superuser_field(type) -> binary();
+is_superuser_field(nullable) -> true;
+is_superuser_field(_) -> undefined.
+
 password_hash_algorithm(type) -> {enum, [plain, md5, sha, sha256, sha512, bcrypt]};
 password_hash_algorithm(default) -> sha256;
 password_hash_algorithm(_) -> undefined.
@@ -109,6 +114,7 @@ create(#{ selector := Selector
     State = maps:with([ collection
                       , password_hash_field
                       , salt_field
+                      , is_superuser_field
                       , password_hash_algorithm
                       , salt_position
                       , '_unique'], Config),
@@ -149,7 +155,7 @@ authenticate(#{password := Password} = Credential,
             Doc ->
                 case check_password(Password, Doc, State) of
                     ok ->
-                        {ok, #{superuser => superuser(Doc, State)}};
+                        {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};
@@ -230,9 +236,9 @@ check_password(Password,
             end
     end.
 
-superuser(Doc, #{superuser_field := SuperuserField}) ->
-    maps:get(SuperuserField, Doc, false);
-superuser(_, _) ->
+is_superuser(Doc, #{is_superuser_field := IsSuperuserField}) ->
+    maps:get(IsSuperuserField, Doc, false);
+is_superuser(_, _) ->
     false.
 
 hash(Algorithm, Password, Salt, prefix) ->

+ 1 - 1
apps/emqx_authn/src/simple_authn/emqx_authn_mysql.erl

@@ -123,7 +123,7 @@ authenticate(#{password := Password} = Credential,
                 Selected = maps:from_list(lists:zip(Columns, Rows)),
                 case check_password(Password, Selected, State) of
                     ok ->
-                        {ok, #{superuser => maps:get(<<"superuser">>, Selected, false)}};
+                        {ok, #{is_superuser => maps:get(<<"is_superuser">>, Selected, false)}};
                     {error, Reason} ->
                         {error, Reason}
                 end;

+ 1 - 1
apps/emqx_authn/src/simple_authn/emqx_authn_pgsql.erl

@@ -113,7 +113,7 @@ authenticate(#{password := Password} = Credential,
                 Selected = maps:from_list(lists:zip(NColumns, Rows)),
                 case check_password(Password, Selected, State) of
                     ok ->
-                        {ok, #{superuser => maps:get(<<"superuser">>, Selected, false)}};
+                        {ok, #{is_superuser => maps:get(<<"is_superuser">>, Selected, false)}};
                     {error, Reason} ->
                         {error, Reason}
                 end;

+ 2 - 2
apps/emqx_authn/src/simple_authn/emqx_authn_redis.erl

@@ -135,7 +135,7 @@ authenticate(#{password := Password} = Credential,
                 Selected = merge(Fields, Values),
                 case check_password(Password, Selected, State) of
                    ok ->
-                       {ok, #{superuser => maps:get("superuser", Selected, false)}};
+                       {ok, #{is_superuser => maps:get("is_superuser", Selected, false)}};
                    {error, Reason} ->
                        {error, Reason}
                 end;
@@ -180,7 +180,7 @@ check_fields(["password_hash" | More], false) ->
     check_fields(More, true);
 check_fields(["salt" | More], HasPassHash) ->
     check_fields(More, HasPassHash);
-check_fields(["superuser" | More], HasPassHash) ->
+check_fields(["is_superuser" | More], HasPassHash) ->
     check_fields(More, HasPassHash);
 check_fields([Field | _], _) ->
     error({unsupported_field, Field}).

+ 1 - 1
apps/emqx_authn/test/data/user-credentials.csv

@@ -1,3 +1,3 @@
-user_id,password_hash,salt,superuser
+user_id,password_hash,salt,is_superuser
 myuser3,b6c743545a7817ae8c8f624371d5f5f0373234bb0ff36b8ffbf19bce0e06ab75,de1024f462fb83910fd13151bd4bd235,true
 myuser4,ee68c985a69208b6eda8c6c9b4c7c2d2b15ee2352cdd64a903171710a99182e8,ad773b5be9dd0613fe6c2f4d8c403139,false

+ 2 - 2
apps/emqx_authn/test/data/user-credentials.json

@@ -3,12 +3,12 @@
         "user_id":"myuser1",
         "password_hash":"c5e46903df45e5dc096dc74657610dbee8deaacae656df88a1788f1847390242",
         "salt": "e378187547bf2d6f0545a3f441aa4d8a",
-        "superuser": true
+        "is_superuser": true
     },
     {
         "user_id":"myuser2",
         "password_hash":"f4d17f300b11e522fd33f497c11b126ef1ea5149c74d2220f9a16dc876d4567b",
         "salt": "6d3f9bd5b54d94b98adbcfe10b6d181f",
-        "superuser": false
+        "is_superuser": false
     }
 ]

+ 9 - 9
apps/emqx_authn/test/emqx_authn_jwt_SUITE.erl

@@ -52,13 +52,13 @@ all() ->
 %     JWS = generate_jws('hmac-based', Payload, <<"abcdef">>),
 %     ClientInfo = #{username => <<"myuser">>,
 % 			       password => JWS},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
 
-%     Payload1 = #{<<"username">> => <<"myuser">>, <<"superuser">> => true},
+%     Payload1 = #{<<"username">> => <<"myuser">>, <<"is_superuser">> => true},
 %     JWS1 = generate_jws('hmac-based', Payload1, <<"abcdef">>),
 %     ClientInfo1 = #{username => <<"myuser">>,
 % 			        password => JWS1},
-%     ?assertEqual({stop, {ok, #{superuser => true}}}, ?AUTH:authenticate(ClientInfo1, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => true}}}, ?AUTH:authenticate(ClientInfo1, ignored)),
 
 %     BadJWS = generate_jws('hmac-based', Payload, <<"bad_secret">>),
 %     ClientInfo2 = ClientInfo#{password => BadJWS},
@@ -68,11 +68,11 @@ all() ->
 %     Config2 = Config#{secret => base64:encode(<<"abcdef">>),
 %                       secret_base64_encoded => true},
 %     ?assertMatch({ok, _}, ?AUTH:update_authenticator(?CHAIN, ID, Config2)),
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
 
 %     Config3 = Config#{verify_claims => [{<<"username">>, <<"${mqtt-username}">>}]},
 %     ?assertMatch({ok, _}, ?AUTH:update_authenticator(?CHAIN, ID, Config3)),
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
 %     ?assertEqual({stop, {error, bad_username_or_password}}, ?AUTH:authenticate(ClientInfo#{username => <<"otheruser">>}, ok)),
 
 %     %% Expiration
@@ -86,14 +86,14 @@ all() ->
 %                 , <<"exp">> => erlang:system_time(second) + 60},
 %     JWS4 = generate_jws('hmac-based', Payload4, <<"abcdef">>),
 %     ClientInfo4 = ClientInfo#{password => JWS4},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo4, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo4, ignored)),
 
 %     %% Issued At
 %     Payload5 = #{ <<"username">> => <<"myuser">>
 %                 , <<"iat">> => erlang:system_time(second) - 60},
 %     JWS5 = generate_jws('hmac-based', Payload5, <<"abcdef">>),
 %     ClientInfo5 = ClientInfo#{password => JWS5},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo5, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo5, ignored)),
 
 %     Payload6 = #{ <<"username">> => <<"myuser">>
 %                 , <<"iat">> => erlang:system_time(second) + 60},
@@ -106,7 +106,7 @@ all() ->
 %                 , <<"nbf">> => erlang:system_time(second) - 60},
 %     JWS7 = generate_jws('hmac-based', Payload7, <<"abcdef">>),
 %     ClientInfo7 = ClientInfo#{password => JWS7},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo7, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo7, ignored)),
 
 %     Payload8 = #{ <<"username">> => <<"myuser">>
 %                 , <<"nbf">> => erlang:system_time(second) + 60},
@@ -134,7 +134,7 @@ all() ->
 %     JWS = generate_jws('public-key', Payload, PrivateKey),
 %     ClientInfo = #{username => <<"myuser">>,
 % 			       password => JWS},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
 %     ?assertEqual({stop, {error, not_authorized}}, ?AUTH:authenticate(ClientInfo#{password => <<"badpassword">>}, ignored)),
 
 %     ?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID)),

+ 10 - 10
apps/emqx_authn/test/emqx_authn_mnesia_SUITE.erl

@@ -56,9 +56,9 @@ all() ->
 %     ClientInfo = #{zone => external,
 %                    username => <<"myuser">>,
 % 			       password => <<"mypass">>},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo, ignored)),
 %     ?AUTH:enable(),
-%     ?assertEqual({ok, #{superuser => false}}, emqx_access_control:authenticate(ClientInfo)),
+%     ?assertEqual({ok, #{is_superuser => false}}, emqx_access_control:authenticate(ClientInfo)),
 
 %     ClientInfo2 = ClientInfo#{username => <<"baduser">>},
 %     ?assertEqual({stop, {error, not_authorized}}, ?AUTH:authenticate(ClientInfo2, ignored)),
@@ -71,10 +71,10 @@ all() ->
 %     UserInfo2 = UserInfo#{password => <<"mypass2">>},
 %     ?assertMatch({ok, #{user_id := <<"myuser">>}}, ?AUTH:update_user(?CHAIN, ID, <<"myuser">>, UserInfo2)),
 %     ClientInfo4 = ClientInfo#{password => <<"mypass2">>},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo4, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo4, ignored)),
 
-%     ?assertMatch({ok, #{user_id := <<"myuser">>}}, ?AUTH:update_user(?CHAIN, ID, <<"myuser">>, #{superuser => true})),
-%     ?assertEqual({stop, {ok, #{superuser => true}}}, ?AUTH:authenticate(ClientInfo4, ignored)),
+%     ?assertMatch({ok, #{user_id := <<"myuser">>}}, ?AUTH:update_user(?CHAIN, ID, <<"myuser">>, #{is_superuser => true})),
+%     ?assertEqual({stop, {ok, #{is_superuser => true}}}, ?AUTH:authenticate(ClientInfo4, ignored)),
 
 %     ?assertEqual(ok, ?AUTH:delete_user(?CHAIN, ID, <<"myuser">>)),
 %     ?assertEqual({error, not_found}, ?AUTH:lookup_user(?CHAIN, ID, <<"myuser">>)),
@@ -107,15 +107,15 @@ all() ->
 
 %     ClientInfo1 = #{username => <<"myuser1">>,
 % 			        password => <<"mypassword1">>},
-%     ?assertEqual({stop, {ok, #{superuser => true}}}, ?AUTH:authenticate(ClientInfo1, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => true}}}, ?AUTH:authenticate(ClientInfo1, ignored)),
 
 %     ClientInfo2 = ClientInfo1#{username => <<"myuser2">>,
 %                                password => <<"mypassword2">>},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo2, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo2, ignored)),
 
 %     ClientInfo3 = ClientInfo1#{username => <<"myuser3">>,
 %                                password => <<"mypassword3">>},
-%     ?assertEqual({stop, {ok, #{superuser => true}}}, ?AUTH:authenticate(ClientInfo3, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => true}}}, ?AUTH:authenticate(ClientInfo3, ignored)),
 
 %     ?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID)),
 %     ok.
@@ -152,12 +152,12 @@ all() ->
 %     ClientInfo1 = #{username => <<"myuser">>,
 %                     clientid => <<"myclient">>,
 % 			        password => <<"mypass1">>},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo1, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo1, ignored)),
 %     ?assertEqual(ok, ?AUTH:move_authenticator(?CHAIN, ID2, top)),
 
 %     ?assertEqual({stop, {error, bad_username_or_password}}, ?AUTH:authenticate(ClientInfo1, ignored)),
 %     ClientInfo2 = ClientInfo1#{password => <<"mypass2">>},
-%     ?assertEqual({stop, {ok, #{superuser => false}}}, ?AUTH:authenticate(ClientInfo2, ignored)),
+%     ?assertEqual({stop, {ok, #{is_superuser => false}}}, ?AUTH:authenticate(ClientInfo2, ignored)),
 
 %     ?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID1)),
 %     ?assertEqual(ok, ?AUTH:delete_authenticator(?CHAIN, ID2)),