This commit is contained in:
ryan
2026-05-13 10:53:14 +08:00
parent 856e3f46d2
commit e85df49962
31 changed files with 2504 additions and 645 deletions
+120 -1
View File
@@ -1216,6 +1216,108 @@ func migrateV9(db *gorm.DB, backend string) error {
return backfillProxyRouteDomainCertificateFields(db)
}
func ensureDefaultGitHubAuthSource(db *gorm.DB) error {
if db == nil || !db.Migrator().HasTable(&AuthSource{}) || !db.Migrator().HasTable(&ExternalAccount{}) {
return nil
}
var githubUserCount int64
if db.Migrator().HasColumn(&User{}, "github_id") {
if err := db.Model(&User{}).Where("github_id <> ''").Count(&githubUserCount).Error; err != nil {
return fmt.Errorf("count legacy github users failed: %w", err)
}
}
optionMap := map[string]string{}
if db.Migrator().HasTable(&Option{}) {
var options []Option
if err := db.Find(&options).Error; err != nil {
return fmt.Errorf("query options for github auth source migration failed: %w", err)
}
for _, option := range options {
optionMap[option.Key] = option.Value
}
}
clientID := strings.TrimSpace(optionMap["GitHubClientId"])
clientSecret := strings.TrimSpace(optionMap["GitHubClientSecret"])
enabled := optionMap["GitHubOAuthEnabled"] == "true" && clientID != "" && clientSecret != ""
if githubUserCount == 0 && clientID == "" && clientSecret == "" {
return nil
}
source := AuthSource{}
err := db.Where("type = ? AND name = ?", AuthSourceTypeGitHub, "GitHub").First(&source).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
source = AuthSource{
Name: "GitHub",
Type: AuthSourceTypeGitHub,
DisplayName: "GitHub",
IsActive: enabled,
ClientID: clientID,
ClientSecret: clientSecret,
Scopes: "user:email",
}
if err := db.Create(&source).Error; err != nil {
return fmt.Errorf("create default github auth source failed: %w", err)
}
} else if err != nil {
return fmt.Errorf("query default github auth source failed: %w", err)
} else {
updates := map[string]any{}
if source.ClientID == "" && clientID != "" {
updates["client_id"] = clientID
}
if source.ClientSecret == "" && clientSecret != "" {
updates["client_secret"] = clientSecret
}
if source.Scopes == "" {
updates["scopes"] = "user:email"
}
if enabled && !source.IsActive {
updates["is_active"] = true
}
if len(updates) > 0 {
if err := db.Model(&source).Updates(updates).Error; err != nil {
return fmt.Errorf("update default github auth source failed: %w", err)
}
}
}
if githubUserCount == 0 {
return nil
}
var users []User
if err := db.Select("id", "github_id", "username", "email").Where("github_id <> ''").Find(&users).Error; err != nil {
return fmt.Errorf("query legacy github users failed: %w", err)
}
for _, user := range users {
account := ExternalAccount{
AuthSourceID: source.ID,
UserID: user.Id,
ExternalID: user.GitHubId,
ExternalUsername: user.GitHubId,
Email: user.Email,
}
if err := db.Where(ExternalAccount{
AuthSourceID: source.ID,
ExternalID: user.GitHubId,
}).FirstOrCreate(&account).Error; err != nil {
return fmt.Errorf("migrate github external account for user %d failed: %w", user.Id, err)
}
}
return nil
}
// migrateV10 adds configurable auth sources and external account bindings.
func migrateV10(db *gorm.DB, backend string) error {
if err := applyCurrentSchema(db, backend); err != nil {
return err
}
return ensureDefaultGitHubAuthSource(db)
}
func validateDatabaseSchemaV9(db *gorm.DB, backend string) error {
if err := validateDatabaseSchemaV8(db, backend); err != nil {
return err
@@ -1229,6 +1331,19 @@ func validateDatabaseSchemaV9(db *gorm.DB, backend string) error {
return nil
}
func validateDatabaseSchemaV10(db *gorm.DB, backend string) error {
if err := validateDatabaseSchemaV9(db, backend); err != nil {
return err
}
if !db.Migrator().HasTable(&AuthSource{}) {
return fmt.Errorf("table auth_sources is missing")
}
if !db.Migrator().HasTable(&ExternalAccount{}) {
return fmt.Errorf("table external_accounts is missing")
}
return nil
}
func databaseSchemaMigrations() []databaseSchemaMigration {
return []databaseSchemaMigration{
{fromVersion: 1, toVersion: 2, migrate: migrateV2, validate: validateDatabaseSchemaV2},
@@ -1239,6 +1354,7 @@ func databaseSchemaMigrations() []databaseSchemaMigration {
{fromVersion: 6, toVersion: 7, migrate: migrateV7, validate: validateDatabaseSchemaV7},
{fromVersion: 7, toVersion: 8, migrate: migrateV8, validate: validateDatabaseSchemaV8},
{fromVersion: 8, toVersion: 9, migrate: migrateV9, validate: validateDatabaseSchemaV9},
{fromVersion: 9, toVersion: 10, migrate: migrateV10, validate: validateDatabaseSchemaV10},
}
}
@@ -1321,7 +1437,10 @@ func initializeFreshDatabaseSchema(db *gorm.DB, backend string) error {
if err := backfillProxyRouteDomainCertificateFields(db); err != nil {
return err
}
if err := validateDatabaseSchemaV9(db, backend); err != nil {
if err := ensureDefaultGitHubAuthSource(db); err != nil {
return err
}
if err := validateDatabaseSchemaV10(db, backend); err != nil {
return err
}
return saveDatabaseSchemaVersion(db, currentDatabaseSchemaVersion)