瀏覽代碼

feat(cli): reset init user password

Jacky 2 月之前
父節點
當前提交
d1d13b620f
共有 5 個文件被更改,包括 113 次插入2 次删除
  1. 7 0
      api/user/user.go
  2. 3 1
      app/src/components/OTPInput/OTPInput.vue
  3. 0 1
      app/src/views/other/Login.vue
  4. 6 0
      internal/cmd/main.go
  5. 97 0
      internal/user/reset_password.go

+ 7 - 0
api/user/user.go

@@ -3,6 +3,7 @@ package user
 import (
 	"github.com/0xJacky/Nginx-UI/internal/user"
 	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/0xJacky/Nginx-UI/query"
 	"github.com/0xJacky/Nginx-UI/settings"
 	"github.com/gin-gonic/gin"
 	"github.com/uozi-tech/cosy"
@@ -40,6 +41,12 @@ func InitManageUserRouter(g *gin.RouterGroup) {
 			}
 		})
 		c.BeforeDecodeHook(encryptPassword)
+		c.ExecutedHook(func(ctx *cosy.Ctx[model.User]) {
+			if ctx.Payload["password"] != "" {
+				a := query.AuthToken
+				_, _ = a.Where(a.UserID.Eq(ctx.ID)).Delete()
+			}
+		})
 	})
 
 	c.DestroyHook(func(c *cosy.Ctx[model.User]) {

+ 3 - 1
app/src/components/OTPInput/OTPInput.vue

@@ -3,7 +3,9 @@ import VOtpInput from 'vue3-otp-input'
 
 const emit = defineEmits(['onComplete'])
 
-const data = defineModel<string>()
+const data = defineModel<string>({
+  default: '',
+})
 
 // eslint-disable-next-line vue/require-typed-ref
 const refOtp = ref()

+ 0 - 1
app/src/views/other/Login.vue

@@ -190,7 +190,6 @@ async function handlePasskeyLogin() {
               <AButton
                 v-if="has_casdoor"
                 block
-                html-type="submit"
                 :loading="loading"
                 class="mb-5"
                 @click="loginWithCasdoor"

+ 6 - 0
internal/cmd/main.go

@@ -5,6 +5,7 @@ import (
 	"log"
 	"os"
 
+	"github.com/0xJacky/Nginx-UI/internal/user"
 	"github.com/0xJacky/Nginx-UI/internal/version"
 	"github.com/urfave/cli/v3"
 )
@@ -24,6 +25,11 @@ func NewAppCmd() *cli.Command {
 					return nil
 				},
 			},
+			{
+				Name:  "reset-password",
+				Usage: "Reset the initial user password",
+				Action: user.ResetInitUserPassword,
+			},
 		},
 		Flags: []cli.Flag{
 			&cli.StringFlag{

+ 97 - 0
internal/user/reset_password.go

@@ -0,0 +1,97 @@
+package user
+
+import (
+	"context"
+	"crypto/rand"
+	"math/big"
+	"os"
+	"path"
+
+	"github.com/0xJacky/Nginx-UI/model"
+	"github.com/0xJacky/Nginx-UI/query"
+	"github.com/0xJacky/Nginx-UI/settings"
+	"github.com/gin-gonic/gin"
+	"github.com/pkg/errors"
+	"github.com/uozi-tech/cosy"
+	sqlite "github.com/uozi-tech/cosy-driver-sqlite"
+	"github.com/uozi-tech/cosy/logger"
+	cSettings "github.com/uozi-tech/cosy/settings"
+	"github.com/urfave/cli/v3"
+	"golang.org/x/crypto/bcrypt"
+)
+
+var (
+	ErrConfigNotFound    = errors.New("config not found")
+	ErrDBFileNotFound    = errors.New("db file not found")
+	ErrInitUserNotExists = errors.New("init user not exists")
+)
+
+func generateRandomPassword(length int) (string, error) {
+	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+"
+	password := make([]byte, length)
+	charsetLength := big.NewInt(int64(len(charset)))
+
+	for i := 0; i < length; i++ {
+		randomIndex, err := rand.Int(rand.Reader, charsetLength)
+		if err != nil {
+			return "", err
+		}
+		password[i] = charset[randomIndex.Int64()]
+	}
+	return string(password), nil
+}
+
+func ResetInitUserPassword(ctx context.Context, command *cli.Command) error {
+	confPath := command.String("config")
+	settings.Init(confPath)
+
+	cSettings.ServerSettings.RunMode = gin.ReleaseMode
+
+	logger.Init(cSettings.ServerSettings.RunMode)
+
+	logger.Infof("confPath: %s", confPath)
+
+	if _, err := os.Stat(confPath); os.IsNotExist(err) {
+		return ErrConfigNotFound
+	}
+
+	dbPath := path.Join(path.Dir(confPath), settings.DatabaseSettings.Name+".db")
+	logger.Infof("dbPath: %s", dbPath)
+	// check if db file exists
+	if _, err := os.Stat(dbPath); os.IsNotExist(err) {
+		return ErrDBFileNotFound
+	}
+
+	db := cosy.InitDB(sqlite.Open(path.Dir(cSettings.ConfPath), settings.DatabaseSettings))
+	model.Use(db)
+	query.Init(db)
+
+	u := query.User
+	user, err := u.FirstByID(1)
+	if err != nil {
+		return ErrInitUserNotExists
+	}
+
+	pwd, err := generateRandomPassword(12)
+	if err != nil {
+		return err
+	}
+
+	pwdBytes, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
+	if err != nil {
+		return err
+	}
+
+	_, err = u.Where(u.ID.Eq(1)).Updates(&model.User{
+		Password: string(pwdBytes),
+	})
+	if err != nil {
+		return err
+	}
+
+	a := query.AuthToken
+	_, _ = a.Where(a.UserID.Eq(1)).Delete()
+
+	logger.Infof("User: %s, Password: %s", user.Name, pwd)
+	return nil
+}