forked from baron/baron-sso
- Added support for fixed UUIDs during bulk registration (Search-first + ExternalID mapping) - Implemented idempotency and visibility restoration for soft-deleted users - Enhanced bulk upload UI to show 'New/Updated/Unchanged' status and modified fields - Added logic to reclaim identifiers (login_id) from colliding records - Added frontend E2E and backend unit tests for UUID integrity and conflict handling - Fixed i18n, formatting, and mock tests to satisfy code-check - Applied 'go fix' for 'omitzero' tags and general Go standards
76 lines
2.1 KiB
Go
76 lines
2.1 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"baron-sso-backend/internal/domain"
|
|
"log/slog"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// SeedAdminIdentity creates the initial admin identity in the configured IDP.
|
|
// Returns the Kratos Identity ID and error.
|
|
func SeedAdminIdentity(idp domain.IdentityProvider) (string, error) {
|
|
if idp == nil {
|
|
return "", nil
|
|
}
|
|
|
|
adminEmail := strings.TrimSpace(os.Getenv("ADMIN_EMAIL"))
|
|
adminPassword := os.Getenv("ADMIN_PASSWORD")
|
|
if adminEmail == "" || adminPassword == "" {
|
|
slog.Warn("[Bootstrap] ADMIN_EMAIL or ADMIN_PASSWORD not set. Skipping admin identity seed.")
|
|
return "", nil
|
|
}
|
|
|
|
adminName := strings.TrimSpace(os.Getenv("ADMIN_NAME"))
|
|
if adminName == "" {
|
|
adminName = "System Admin"
|
|
}
|
|
|
|
user := &domain.BrokerUser{
|
|
Email: adminEmail,
|
|
Name: adminName,
|
|
PhoneNumber: "",
|
|
Attributes: map[string]any{
|
|
"department": "Admin",
|
|
"affiliationType": "internal",
|
|
"grade": "",
|
|
"role": "super_admin", // Explicitly set role for Kratos traits
|
|
},
|
|
}
|
|
|
|
// Retry logic for Kratos connection
|
|
maxRetries := 5
|
|
var err error
|
|
var identityID string
|
|
|
|
for i := range maxRetries {
|
|
identityID, err = idp.CreateUser(user, adminPassword)
|
|
if err == nil {
|
|
slog.Info("[Bootstrap] Admin identity created in IDP", "email", adminEmail, "idp", idp.Name(), "id", identityID)
|
|
return identityID, nil
|
|
}
|
|
|
|
if strings.Contains(err.Error(), "already exists") {
|
|
slog.Info("[Bootstrap] Admin identity already exists in IDP. Attempting to retrieve ID...", "email", adminEmail)
|
|
// Try to sign in to get the identity ID
|
|
authInfo, err := idp.SignIn(adminEmail, adminPassword)
|
|
if err == nil && authInfo != nil {
|
|
slog.Info("[Bootstrap] Retrieved existing admin identity ID", "id", authInfo.Subject)
|
|
return authInfo.Subject, nil
|
|
}
|
|
slog.Warn("[Bootstrap] Failed to retrieve existing admin identity ID via SignIn", "error", err)
|
|
return "", nil // Return nil error to avoid stopping bootstrap, but ID is missing
|
|
}
|
|
|
|
slog.Warn("[Bootstrap] Failed to seed admin identity (retrying...)",
|
|
"attempt", i+1,
|
|
"max_retries", maxRetries,
|
|
"error", err,
|
|
)
|
|
time.Sleep(2 * time.Second)
|
|
}
|
|
|
|
return "", err
|
|
}
|