package bootstrap import ( "FileRelay/internal/config" "FileRelay/internal/model" "FileRelay/internal/storage" "context" "crypto/rand" "fmt" "log" "math/big" "github.com/glebarez/sqlite" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) var DB *gorm.DB func InitDB() { var err error dbPath := config.GlobalConfig.Database.Path if dbPath == "" { dbPath = "file_relay.db" } DB, err = gorm.Open(sqlite.Open(dbPath), &gorm.Config{}) if err != nil { log.Fatalf("Failed to connect to database: %v", err) } // 自动迁移 err = DB.AutoMigrate( &model.FileBatch{}, &model.FileItem{}, &model.APIToken{}, &model.Admin{}, ) if err != nil { log.Fatalf("Failed to migrate database: %v", err) } fmt.Println("Database initialized and migrated.") // 初始化存储 if err := ReloadStorage(); err != nil { log.Fatalf("Failed to initialize storage: %v", err) } // 初始化管理员 (如果不存在) initAdmin() } func ReloadStorage() error { storageType := config.GlobalConfig.Storage.Type switch storageType { case "local": storage.GlobalStorage = storage.NewLocalStorage(config.GlobalConfig.Storage.Local.Path) case "webdav": cfg := config.GlobalConfig.Storage.WebDAV storage.GlobalStorage = storage.NewWebDAVStorage(cfg.URL, cfg.Username, cfg.Password, cfg.Root) case "s3": cfg := config.GlobalConfig.Storage.S3 s3Storage, err := storage.NewS3Storage(context.Background(), cfg.Endpoint, cfg.Region, cfg.AccessKey, cfg.SecretKey, cfg.Bucket, cfg.UseSSL) if err != nil { return err } storage.GlobalStorage = s3Storage default: return fmt.Errorf("unsupported storage type: %s", storageType) } fmt.Printf("Storage initialized with type: %s\n", storageType) return nil } func initAdmin() { var count int64 DB.Model(&model.Admin{}).Count(&count) if count == 0 { passwordHash := config.GlobalConfig.Security.AdminPasswordHash if passwordHash == "" { // 生成随机密码 password := generateRandomPassword(12) hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { log.Fatalf("Failed to generate password hash: %v", err) } passwordHash = string(hash) fmt.Printf("**************************************************\n") fmt.Printf("NO ADMIN PASSWORD CONFIGURED. GENERATED RANDOM PASSWORD:\n") fmt.Printf("Password: %s\n", password) fmt.Printf("Please save this password or configure admin_password_hash in config.yaml\n") fmt.Printf("**************************************************\n") } admin := &model.Admin{ PasswordHash: passwordHash, } DB.Create(admin) fmt.Println("Admin account initialized.") } } func generateRandomPassword(length int) string { const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*" b := make([]byte, length) for i := range b { num, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) if err != nil { return "admin123" // 退路 } b[i] = charset[num.Int64()] } return string(b) }