Browse Source

feat: use env to predefine admin user #214

Jacky 1 year ago
parent
commit
4c74bc8619

+ 1 - 1
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 && \

+ 1 - 1
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",
 	})

+ 0 - 2
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)

+ 1 - 0
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

+ 4 - 9
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 {

+ 74 - 0
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)
+	}
+}

+ 2 - 1
resources/docker/nginx-ui.run

@@ -1,2 +1,3 @@
-#!/bin/sh
+#!/command/with-contenv sh
+env
 nginx-ui --config /etc/nginx-ui/app.ini

+ 4 - 6
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

+ 2 - 0
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")
 }

+ 0 - 8
settings/user.go

@@ -1,8 +0,0 @@
-package settings
-
-type PredefinedUser struct {
-	User     string `json:"user"`
-	Password string `json:"password"`
-}
-
-var PredefinedUserSettings = &PredefinedUser{}