From 1b5b2b9d1abca868c819c0b18bbb0cfb5ea60a3c Mon Sep 17 00:00:00 2001 From: kyy Date: Fri, 13 Feb 2026 10:10:50 +0900 Subject: [PATCH] =?UTF-8?q?Kratos=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=EA=B3=84=EC=A0=95=EC=9D=98=20=EB=A1=9C=EC=BB=AC=20DB=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/bootstrap/sync_admin.go | 77 ++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 backend/internal/bootstrap/sync_admin.go diff --git a/backend/internal/bootstrap/sync_admin.go b/backend/internal/bootstrap/sync_admin.go new file mode 100644 index 00000000..129f91f5 --- /dev/null +++ b/backend/internal/bootstrap/sync_admin.go @@ -0,0 +1,77 @@ +package bootstrap + +import ( + "baron-sso-backend/internal/domain" + "log/slog" + "os" + "strings" + "time" + + "gorm.io/gorm" +) + +// SyncAdminRole updates the role of the admin user in the local DB. +// It ensures the admin user exists in the local DB with the correct Kratos ID. +func SyncAdminRole(db *gorm.DB, kratosID string) error { + adminEmail := strings.TrimSpace(os.Getenv("ADMIN_EMAIL")) + if adminEmail == "" { + slog.Warn("[Bootstrap] ADMIN_EMAIL not set. Skipping admin role sync.") + return nil + } + + adminName := strings.TrimSpace(os.Getenv("ADMIN_NAME")) + if adminName == "" { + adminName = "System Admin" + } + + // Find user by email + var user domain.User + if err := db.Where("email = ?", adminEmail).First(&user).Error; err != nil { + if err == gorm.ErrRecordNotFound { + if kratosID == "" { + slog.Warn("[Bootstrap] Admin user not found in local DB and Kratos ID is missing. Cannot create local user.", "email", adminEmail) + return nil + } + + // Create new admin user in local DB + newUser := domain.User{ + ID: kratosID, + Email: adminEmail, + Name: adminName, + Role: domain.RoleSuperAdmin, + Status: "active", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + Metadata: domain.JSONMap{"source": "bootstrap_seed"}, + } + if err := db.Create(&newUser).Error; err != nil { + return err + } + slog.Info("[Bootstrap] Created admin user in local DB", "email", adminEmail, "id", kratosID) + return nil + } + return err + } + + // Update role if needed + updates := map[string]interface{}{} + if user.Role != domain.RoleSuperAdmin { + updates["role"] = domain.RoleSuperAdmin + } + // Also ensure ID matches if it was somehow different (though changing PK is hard, at least log it) + if kratosID != "" && user.ID != kratosID { + slog.Warn("[Bootstrap] Admin user exists but ID mismatch with Kratos", "local_id", user.ID, "kratos_id", kratosID) + // We generally don't change UUID PKs, just warn. + } + + if len(updates) > 0 { + if err := db.Model(&user).Updates(updates).Error; err != nil { + return err + } + slog.Info("[Bootstrap] Updated admin user role to super_admin", "email", adminEmail) + } else { + slog.Info("[Bootstrap] Admin user already has super_admin role", "email", adminEmail) + } + + return nil +}