Files
NetworkAuth/database/migrate.go
2025-10-26 00:08:55 +08:00

173 lines
5.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package database
import (
"fmt"
"networkDev/models"
"strings"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
// AutoMigrate 自动迁移数据库模型
// - 会确保必要的数据表结构存在
// - 不会破坏已有数据
func AutoMigrate() error {
db, err := GetDB()
if err != nil {
return err
}
if err := db.AutoMigrate(&models.User{}, &models.Settings{}, &models.App{}, &models.API{}, &models.Variable{}); err != nil {
logrus.WithError(err).Error("AutoMigrate 执行失败")
return err
}
// 兼容迁移:如果 users.password_salt 列长度 < 64则扩大到 64
if err := ensureUserPasswordSaltLength(db); err != nil {
logrus.WithError(err).Error("调整 users.password_salt 列长度失败")
return err
}
// 兼容迁移:确保 tasks.verification_code 字段类型为 LONGTEXT 以支持大图片数据
if err := ensureVerificationCodeType(db); err != nil {
logrus.WithError(err).Error("调整 tasks.verification_code 字段类型失败")
return err
}
logrus.Info("AutoMigrate 执行完成")
return nil
}
// ensureVerificationCodeType 确保tasks.verification_code字段类型为LONGTEXT以支持大图片数据
// 中文注释检查并修改verification_code字段类型支持Base64编码的大图片数据存储
func ensureVerificationCodeType(db *gorm.DB) error {
// 获取数据库方言类型
dialector := db.Dialector.Name()
// 根据不同数据库类型执行不同的检查逻辑
switch dialector {
case "mysql":
// MySQL/MariaDB使用INFORMATION_SCHEMA
var result struct {
ColumnName string `gorm:"column:COLUMN_NAME"`
ColumnType string `gorm:"column:COLUMN_TYPE"`
}
err := db.Raw("SELECT COLUMN_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND COLUMN_NAME = ? LIMIT 1",
"tasks", "verification_code").Scan(&result).Error
if err != nil {
return nil // 查询失败则跳过
}
// 检查列类型如果不是LONGTEXT则修改
if !strings.Contains(strings.ToLower(result.ColumnType), "longtext") {
alterSQL := "ALTER TABLE tasks MODIFY COLUMN verification_code LONGTEXT"
if err := db.Exec(alterSQL).Error; err != nil {
return fmt.Errorf("修改verification_code字段类型失败: %v", err)
}
logrus.Info("verification_code字段类型已更新为LONGTEXT")
}
case "sqlite":
// SQLite使用pragma_table_info检查列信息
var columns []struct {
CID int `gorm:"column:cid"`
Name string `gorm:"column:name"`
Type string `gorm:"column:type"`
NotNull int `gorm:"column:notnull"`
DfltValue *string `gorm:"column:dflt_value"`
PK int `gorm:"column:pk"`
}
err := db.Raw("PRAGMA table_info(tasks)").Scan(&columns).Error
if err != nil {
return nil // 查询失败则跳过
}
// 查找verification_code列
for _, col := range columns {
if col.Name == "verification_code" {
// SQLite中如果列类型不是TEXT需要重建表
if !strings.Contains(strings.ToLower(col.Type), "text") {
// SQLite不支持直接修改列类型但GORM的AutoMigrate会处理这种情况
logrus.Info("SQLite检测到verification_code字段类型需要更新依赖GORM AutoMigrate处理")
}
break
}
}
default:
// 其他数据库类型暂不处理
logrus.Infof("数据库类型 %s 暂不支持verification_code字段类型检查", dialector)
}
return nil
}
// ensureUserPasswordSaltLength 确保users.password_salt列长度至少为64
// 中文注释检查并修改password_salt列长度兼容32字节64十六进制字符的盐值
func ensureUserPasswordSaltLength(db *gorm.DB) error {
// 获取数据库方言类型
dialector := db.Dialector.Name()
// 根据不同数据库类型执行不同的检查逻辑
switch dialector {
case "mysql":
// MySQL/MariaDB使用INFORMATION_SCHEMA
var result struct {
ColumnName string `gorm:"column:COLUMN_NAME"`
ColumnType string `gorm:"column:COLUMN_TYPE"`
}
err := db.Raw("SELECT COLUMN_NAME, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND COLUMN_NAME = ? LIMIT 1",
"users", "password_salt").Scan(&result).Error
if err != nil {
return nil // 查询失败则跳过
}
// 检查列类型如果长度小于64则修改
if strings.Contains(strings.ToLower(result.ColumnType), "varchar") {
if strings.Contains(result.ColumnType, "(32)") || strings.Contains(result.ColumnType, "(16)") {
alterSQL := "ALTER TABLE users MODIFY COLUMN password_salt VARCHAR(64)"
if err := db.Exec(alterSQL).Error; err != nil {
return fmt.Errorf("修改password_salt列长度失败: %v", err)
}
logrus.Info("password_salt列长度已更新为64")
}
}
case "sqlite":
// SQLite使用pragma_table_info检查列信息
var columns []struct {
CID int `gorm:"column:cid"`
Name string `gorm:"column:name"`
Type string `gorm:"column:type"`
NotNull int `gorm:"column:notnull"`
DfltValue *string `gorm:"column:dflt_value"`
PK int `gorm:"column:pk"`
}
err := db.Raw("PRAGMA table_info(users)").Scan(&columns).Error
if err != nil {
return nil // 查询失败则跳过
}
// 查找password_salt列
for _, col := range columns {
if col.Name == "password_salt" {
// SQLite中如果列类型包含长度限制且小于64需要重建表
if strings.Contains(strings.ToLower(col.Type), "varchar(32)") ||
strings.Contains(strings.ToLower(col.Type), "varchar(16)") {
// SQLite不支持直接修改列类型但GORM的AutoMigrate会处理这种情况
logrus.Info("SQLite检测到password_salt列长度需要更新依赖GORM AutoMigrate处理")
}
break
}
}
default:
// 其他数据库类型暂不处理
logrus.Infof("数据库类型 %s 暂不支持password_salt列长度检查", dialector)
}
return nil
}