mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-05-22 16:49:34 +08:00
feat: add community enhancements — password reset, audit logs, multi-source backup
Three community-requested features: 1. CLI password reset: `backupx reset-password --username admin --password xxx` Docker users can run via `docker exec`. No full app init needed. 2. Audit logging: async fire-and-forget audit trail for all key operations (login, CRUD on tasks/targets/records, settings changes). New UI page at /audit with category filter and pagination. 3. Multi-source path backup: file backup tasks now support multiple source directories packed into a single tar archive. Backward compatible with existing single sourcePath field.
This commit is contained in:
@@ -10,11 +10,21 @@ import (
|
||||
|
||||
"backupx/server/internal/app"
|
||||
"backupx/server/internal/config"
|
||||
"backupx/server/internal/security"
|
||||
"github.com/glebarez/sqlite"
|
||||
"gorm.io/gorm"
|
||||
gormlogger "gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
var version = "dev"
|
||||
|
||||
func main() {
|
||||
// 子命令分发:reset-password
|
||||
if len(os.Args) > 1 && os.Args[1] == "reset-password" {
|
||||
runResetPassword(os.Args[2:])
|
||||
return
|
||||
}
|
||||
|
||||
var configPath string
|
||||
var showVersion bool
|
||||
|
||||
@@ -48,3 +58,58 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// runResetPassword 通过 CLI 直接操作 SQLite 重置用户密码,无需完整 app 初始化。
|
||||
// 用法:backupx reset-password --username admin --password newpass123 [--config path]
|
||||
func runResetPassword(args []string) {
|
||||
fs := flag.NewFlagSet("reset-password", flag.ExitOnError)
|
||||
username := fs.String("username", "admin", "要重置密码的用户名")
|
||||
password := fs.String("password", "", "新密码(至少 8 个字符)")
|
||||
configPath := fs.String("config", "", "配置文件路径")
|
||||
if err := fs.Parse(args); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *password == "" {
|
||||
fmt.Fprintln(os.Stderr, "错误:--password 参数为必填项")
|
||||
fs.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
if len(*password) < 8 {
|
||||
fmt.Fprintln(os.Stderr, "错误:密码长度至少 8 个字符")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cfg, err := config.Load(*configPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "加载配置失败:%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
db, err := gorm.Open(sqlite.Open(cfg.Database.Path), &gorm.Config{Logger: gormlogger.Default.LogMode(gormlogger.Silent)})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "打开数据库失败:%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var count int64
|
||||
db.Table("users").Where("username = ?", *username).Count(&count)
|
||||
if count == 0 {
|
||||
fmt.Fprintf(os.Stderr, "错误:用户 %q 不存在\n", *username)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
hash, err := security.HashPassword(*password)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "密码哈希失败:%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
result := db.Table("users").Where("username = ?", *username).Update("password_hash", hash)
|
||||
if result.Error != nil {
|
||||
fmt.Fprintf(os.Stderr, "密码更新失败:%v\n", result.Error)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("用户 %q 密码已重置成功\n", *username)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user