From 4c74bc86195d33c479da332219523377974e2cae Mon Sep 17 00:00:00 2001 From: Jacky Date: Mon, 6 May 2024 22:55:05 +0800 Subject: [PATCH] feat: use env to predefine admin user #214 --- Dockerfile | 2 +- api/system/install.go | 2 +- api/system/settings.go | 2 - app.example.ini | 1 + internal/kernal/boot.go | 13 ++---- internal/kernal/skip_install.go | 74 +++++++++++++++++++++++++++++++++ resources/docker/nginx-ui.run | 3 +- settings/settings.go | 10 ++--- settings/settings_test.go | 2 + settings/user.go | 8 ---- 10 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 internal/kernal/skip_install.go delete mode 100644 settings/user.go diff --git a/Dockerfile b/Dockerfile index 5ccbf9dd..43367519 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ COPY nginx-ui-$TARGETOS-$TARGETARCH$TARGETVARIANT/nginx-ui /usr/local/bin/nginx- # remove default nginx config RUN rm -f /etc/nginx/conf.d/default.conf \ - && rm -f /usr/etc/nginx/conf.d/default.conf + && rm -f /usr/local/etc/nginx/conf.d/default.conf # recreate access.log and error.log RUN rm -f /var/log/nginx/access.log && \ diff --git a/api/system/install.go b/api/system/install.go index 9130ef3f..49340fd5 100644 --- a/api/system/install.go +++ b/api/system/install.go @@ -49,7 +49,6 @@ func InstallNginxUI(c *gin.Context) { if "" != json.Database { settings.ServerSettings.Database = json.Database } - settings.ReflectFrom() err := settings.Save() if err != nil { @@ -72,6 +71,7 @@ func InstallNginxUI(c *gin.Context) { api.ErrHandler(c, err) return } + c.JSON(http.StatusOK, gin.H{ "message": "ok", }) diff --git a/api/system/settings.go b/api/system/settings.go index 5e18dff9..b09bc3c3 100644 --- a/api/system/settings.go +++ b/api/system/settings.go @@ -40,8 +40,6 @@ func SaveSettings(c *gin.Context) { fillSettings(&settings.OpenAISettings, &json.Openai) fillSettings(&settings.LogrotateSettings, &json.Logrotate) - settings.ReflectFrom() - err := settings.Save() if err != nil { api.ErrHandler(c, err) diff --git a/app.example.ini b/app.example.ini index ae9c8270..f0e97bcf 100644 --- a/app.example.ini +++ b/app.example.ini @@ -14,6 +14,7 @@ PageSize = 10 HttpHost = 0.0.0.0 CertRenewalInterval = 7 RecursiveNameservers = +SkipInstallation = false [nginx] AccessLogPath = /var/log/nginx/access.log diff --git a/internal/kernal/boot.go b/internal/kernal/boot.go index 5f331188..ec2baa41 100644 --- a/internal/kernal/boot.go +++ b/internal/kernal/boot.go @@ -41,6 +41,7 @@ func Boot() { func InitAfterDatabase() { syncs := []func(){ + registerPredefinedUser, cert.InitRegister, InitCronJobs, analytic.RetrieveNodesStatus, @@ -60,14 +61,9 @@ func recovery() { } func InitDatabase() { - - // Skip installation - if settings.ServerSettings.SkipInstallation && settings.ServerSettings.JwtSecret == "" { - settings.ServerSettings.JwtSecret = uuid.New().String() - err := settings.Save() - if err != nil { - logger.Error(err) - } + // Skip install + if settings.ServerSettings.SkipInstallation { + skipInstall() } if "" != settings.ServerSettings.JwtSecret { @@ -82,7 +78,6 @@ func InitNodeSecret() { if "" == settings.ServerSettings.NodeSecret { logger.Warn("NodeSecret is empty, generating...") settings.ServerSettings.NodeSecret = uuid.New().String() - settings.ReflectFrom() err := settings.Save() if err != nil { diff --git a/internal/kernal/skip_install.go b/internal/kernal/skip_install.go new file mode 100644 index 00000000..ad2e0326 --- /dev/null +++ b/internal/kernal/skip_install.go @@ -0,0 +1,74 @@ +package kernal + +import ( + "github.com/0xJacky/Nginx-UI/internal/logger" + "github.com/0xJacky/Nginx-UI/model" + "github.com/0xJacky/Nginx-UI/query" + "github.com/0xJacky/Nginx-UI/settings" + "github.com/caarlos0/env/v11" + "github.com/google/uuid" + "github.com/pkg/errors" + "golang.org/x/crypto/bcrypt" + "gorm.io/gorm" +) + +type predefinedUser struct { + Name string `json:"name"` + Password string `json:"password"` +} + +func skipInstall() { + logger.Info("Skip installation mode enabled") + + if settings.ServerSettings.JwtSecret == "" { + settings.ServerSettings.JwtSecret = uuid.New().String() + } + + if settings.ServerSettings.NodeSecret == "" { + settings.ServerSettings.NodeSecret = uuid.New().String() + logger.Infof("NodeSecret: %s", settings.ServerSettings.NodeSecret) + } + + err := settings.Save() + if err != nil { + logger.Fatal(err) + } +} + +func registerPredefinedUser() { + // when skip installation mode is enabled, the predefined user will be created + if !settings.ServerSettings.SkipInstallation { + return + } + pUser := &predefinedUser{} + + err := env.ParseWithOptions(pUser, env.Options{ + Prefix: "NGINX_UI_PREDEFINED_USER_", + UseFieldNameByDefault: true, + }) + + if err != nil { + logger.Fatal(err) + } + + u := query.Auth + + _, err = u.First() + + // Only effect when there is no user in the database + if !errors.Is(err, gorm.ErrRecordNotFound) || pUser.Name == "" || pUser.Password == "" { + return + } + + // Create a new user with the predefined name and password + pwd, _ := bcrypt.GenerateFromPassword([]byte(pUser.Password), bcrypt.DefaultCost) + + err = u.Create(&model.Auth{ + Name: pUser.Name, + Password: string(pwd), + }) + + if err != nil { + logger.Error(err) + } +} diff --git a/resources/docker/nginx-ui.run b/resources/docker/nginx-ui.run index 835988ce..43470252 100644 --- a/resources/docker/nginx-ui.run +++ b/resources/docker/nginx-ui.run @@ -1,2 +1,3 @@ -#!/bin/sh +#!/command/with-contenv sh +env nginx-ui --config /etc/nginx-ui/app.ini diff --git a/settings/settings.go b/settings/settings.go index 544d3aeb..0ae436a5 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -69,12 +69,6 @@ func MapTo() { } } -func ReflectFrom() { - for k, v := range sections { - reflectFrom(k, v) - } -} - func mapTo(section string, v interface{}) { err := Conf.Section(section).MapTo(v) if err != nil { @@ -90,6 +84,10 @@ func reflectFrom(section string, v interface{}) { } func Save() (err error) { + for k, v := range sections { + reflectFrom(k, v) + } + err = Conf.SaveTo(ConfPath) if err != nil { return diff --git a/settings/settings_test.go b/settings/settings_test.go index b50f3730..93f815f1 100644 --- a/settings/settings_test.go +++ b/settings/settings_test.go @@ -52,6 +52,7 @@ func TestSetup(t *testing.T) { _ = os.Setenv("NGINX_UI_LOGROTATE_CMD", "logrotate /custom/logrotate.conf") _ = os.Setenv("NGINX_UI_LOGROTATE_INTERVAL", "60") + ConfPath = "app.testing.ini" Setup() assert.Equal(t, "8080", ServerSettings.HttpPort) @@ -96,4 +97,5 @@ func TestSetup(t *testing.T) { assert.Equal(t, 60, LogrotateSettings.Interval) os.Clearenv() + _ = os.Remove("app.testing.ini") } diff --git a/settings/user.go b/settings/user.go deleted file mode 100644 index 1cf99137..00000000 --- a/settings/user.go +++ /dev/null @@ -1,8 +0,0 @@ -package settings - -type PredefinedUser struct { - User string `json:"user"` - Password string `json:"password"` -} - -var PredefinedUserSettings = &PredefinedUser{}