From 0f8ebbdf0f0c12eb13435560e0ae9595363bb590 Mon Sep 17 00:00:00 2001 From: firest Date: Tue, 9 Aug 2022 15:17:39 +0800 Subject: [PATCH 1/3] feat(dashboard): add bootstrap files to initialize user accounts --- .../i18n/emqx_dashboard_i18n.conf | 10 +++ .../src/emqx_dashboard_admin.erl | 62 +++++++++++++++++-- .../emqx_dashboard/src/emqx_dashboard_app.erl | 1 + .../src/emqx_dashboard_schema.erl | 3 +- 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf b/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf index d6587c203..ad41b06a7 100644 --- a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf +++ b/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf @@ -197,4 +197,14 @@ its own from which a browser should permit loading resources.""" zh: "多语言支持" } } + bootstrap_user { + desc { + en: "Initialize users file." + zh: "初始化用户文件" + } + label { + en: "Initialize users file" + zh: "初始化用户文件" + } + } } diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 0650062f8..0df1e4e9e 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -50,7 +50,8 @@ -export([ add_default_user/0, - default_username/0 + default_username/0, + add_bootstrap_user/0 ]). -type emqx_admin() :: #?ADMIN{}. @@ -74,6 +75,28 @@ 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 -> + add_bootstrap_user(File); + _ -> + ok + end + end. + %%-------------------------------------------------------------------- %% API %%-------------------------------------------------------------------- @@ -272,11 +295,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 +308,35 @@ 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 + end, + load_bootstrap_user(Dev, MP); + eof -> + ok; + Error -> + Error + end. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_app.erl b/apps/emqx_dashboard/src/emqx_dashboard_app.erl index 08bfe1d21..4d9c1416a 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_app.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_app.erl @@ -31,6 +31,7 @@ start(_StartType, _StartArgs) -> case emqx_dashboard:start_listeners() of ok -> emqx_dashboard_cli:load(), + ok = emqx_dashboard_admin:add_bootstrap_user(), {ok, _} = emqx_dashboard_admin:add_default_user(), {ok, Sup}; {error, Reason} -> diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl index 55a1fd38c..4bb9fb6af 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl +++ b/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") -> [ From 463d255c0a5ddd024c18bd48ac56b84204346f5d Mon Sep 17 00:00:00 2001 From: firest Date: Tue, 9 Aug 2022 16:36:46 +0800 Subject: [PATCH 2/3] fix(dashboard): make dialyzer happy --- apps/emqx_dashboard/src/emqx_dashboard_admin.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 0df1e4e9e..3d7447dc5 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -310,7 +310,7 @@ add_default_user(Username, Password) -> end. add_bootstrap_user(File) -> - case file:open(File, read) of + case file:open(File, [read]) of {ok, Dev} -> {ok, MP} = re:compile(<<"(\.+):(\.+)">>), try @@ -330,7 +330,8 @@ load_bootstrap_user(Dev, MP) -> {ok, Line} -> case re:run(Line, MP, [global, {capture, all_but_first, binary}]) of {match, Captured} -> - [add_user(Username, Password, <<>>) || [Username, Password] <- Captured]; + _ = [add_user(Username, Password, <<>>) || [Username, Password] <- Captured], + ok; _ -> ok end, From d55c9341eb7f1a8d5109bf6912ceb070fbb0b6ef Mon Sep 17 00:00:00 2001 From: firest Date: Thu, 11 Aug 2022 17:42:22 +0800 Subject: [PATCH 3/3] fix(dashboard): fix nit codes --- apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf | 15 +++++++++++++-- apps/emqx_dashboard/src/emqx_dashboard_admin.erl | 2 ++ apps/emqx_dashboard/src/emqx_dashboard_app.erl | 10 +++++++--- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf b/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf index ad41b06a7..e404b54b4 100644 --- a/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf +++ b/apps/emqx_dashboard/i18n/emqx_dashboard_i18n.conf @@ -203,8 +203,19 @@ its own from which a browser should permit loading resources.""" zh: "初始化用户文件" } label { - en: "Initialize users file" - zh: "初始化用户文件" + 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 + ``` +""" } } } diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index 3d7447dc5..85f145595 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/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]}). @@ -91,6 +92,7 @@ add_bootstrap_user() -> File -> case mnesia:table_info(?ADMIN, size) of 0 -> + ?SLOG(debug, #{msg => "Add dashboard bootstrap users", file => File}), add_bootstrap_user(File); _ -> ok diff --git a/apps/emqx_dashboard/src/emqx_dashboard_app.erl b/apps/emqx_dashboard/src/emqx_dashboard_app.erl index 4d9c1416a..5084d76c4 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_app.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_app.erl @@ -31,9 +31,13 @@ start(_StartType, _StartArgs) -> case emqx_dashboard:start_listeners() of ok -> emqx_dashboard_cli:load(), - ok = emqx_dashboard_admin:add_bootstrap_user(), - {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.