Przeglądaj źródła

Merge pull request #8667 from lafirest/feat/bootstrap_user

feat(dashboard): add bootstrap files to initialize user accounts
lafirest 3 lat temu
rodzic
commit
c7f6517aee

+ 21 - 0
apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf

@@ -197,4 +197,25 @@ its own from which a browser should permit loading resources."""
       zh: "多语言支持"
     }
   }
+  bootstrap_user {
+    desc {
+      en: "Initialize users file."
+      zh: "初始化用户文件"
+    }
+    label {
+      en: """Is used to add an administrative user to Dashboard when emqx is first launched,
+      the format is:
+       ```
+       username1:password1
+       username2:password2
+       ```
+"""
+      zh: """用于在首次启动 emqx 时,为 Dashboard 添加管理用户,其格式为:
+      ```
+      username1:password1
+      username2:password2
+      ```
+"""
+    }
+  }
 }

+ 59 - 6
apps/emqx_dashboard/src/emqx_dashboard_admin.erl

@@ -19,6 +19,7 @@
 -module(emqx_dashboard_admin).
 
 -include("emqx_dashboard.hrl").
+-include_lib("emqx/include/logger.hrl").
 -include_lib("stdlib/include/ms_transform.hrl").
 
 -boot_mnesia({mnesia, [boot]}).
@@ -50,7 +51,8 @@
 
 -export([
     add_default_user/0,
-    default_username/0
+    default_username/0,
+    add_bootstrap_user/0
 ]).
 
 -type emqx_admin() :: #?ADMIN{}.
@@ -74,6 +76,29 @@ mnesia(boot) ->
         ]}
     ]).
 
+%%--------------------------------------------------------------------
+%% bootstrap API
+%%--------------------------------------------------------------------
+
+-spec add_default_user() -> {ok, map() | empty | default_user_exists} | {error, any()}.
+add_default_user() ->
+    add_default_user(binenv(default_username), binenv(default_password)).
+
+-spec add_bootstrap_user() -> ok | {error, _}.
+add_bootstrap_user() ->
+    case emqx:get_config([dashboard, bootstrap_user], undefined) of
+        undefined ->
+            ok;
+        File ->
+            case mnesia:table_info(?ADMIN, size) of
+                0 ->
+                    ?SLOG(debug, #{msg => "Add dashboard bootstrap users", file => File}),
+                    add_bootstrap_user(File);
+                _ ->
+                    ok
+            end
+    end.
+
 %%--------------------------------------------------------------------
 %% API
 %%--------------------------------------------------------------------
@@ -272,11 +297,6 @@ destroy_token_by_username(Username, Token) ->
 %%--------------------------------------------------------------------
 %% Internal functions
 %%--------------------------------------------------------------------
-
--spec add_default_user() -> {ok, map() | empty | default_user_exists} | {error, any()}.
-add_default_user() ->
-    add_default_user(binenv(default_username), binenv(default_password)).
-
 default_username() ->
     binenv(default_username).
 
@@ -290,3 +310,36 @@ add_default_user(Username, Password) ->
         [] -> add_user(Username, Password, <<"administrator">>);
         _ -> {ok, default_user_exists}
     end.
+
+add_bootstrap_user(File) ->
+    case file:open(File, [read]) of
+        {ok, Dev} ->
+            {ok, MP} = re:compile(<<"(\.+):(\.+)">>),
+            try
+                load_bootstrap_user(Dev, MP)
+            catch
+                Type:Reason ->
+                    {error, {Type, Reason}}
+            after
+                file:close(Dev)
+            end;
+        Error ->
+            Error
+    end.
+
+load_bootstrap_user(Dev, MP) ->
+    case file:read_line(Dev) of
+        {ok, Line} ->
+            case re:run(Line, MP, [global, {capture, all_but_first, binary}]) of
+                {match, Captured} ->
+                    _ = [add_user(Username, Password, <<>>) || [Username, Password] <- Captured],
+                    ok;
+                _ ->
+                    ok
+            end,
+            load_bootstrap_user(Dev, MP);
+        eof ->
+            ok;
+        Error ->
+            Error
+    end.

+ 7 - 2
apps/emqx_dashboard/src/emqx_dashboard_app.erl

@@ -31,8 +31,13 @@ start(_StartType, _StartArgs) ->
     case emqx_dashboard:start_listeners() of
         ok ->
             emqx_dashboard_cli:load(),
-            {ok, _} = emqx_dashboard_admin:add_default_user(),
-            {ok, Sup};
+            case emqx_dashboard_admin:add_bootstrap_user() of
+                ok ->
+                    {ok, _} = emqx_dashboard_admin:add_default_user(),
+                    {ok, Sup};
+                Error ->
+                    Error
+            end;
         {error, Reason} ->
             {error, Reason}
     end.

+ 2 - 1
apps/emqx_dashboard/src/emqx_dashboard_schema.erl

@@ -54,7 +54,8 @@ fields("dashboard") ->
                 }
             )},
         {cors, fun cors/1},
-        {i18n_lang, fun i18n_lang/1}
+        {i18n_lang, fun i18n_lang/1},
+        {bootstrap_user, ?HOCON(binary(), #{desc => ?DESC(bootstrap_user), required => false})}
     ];
 fields("listeners") ->
     [