Files
NianAIGC/backend/internal/application/bootstrap_admin.go

68 lines
2.7 KiB
Go

package application
import (
"context"
"strings"
"git.nianxx.cn/wangxuming/NianAIGC/backend/internal/administration"
"git.nianxx.cn/wangxuming/NianAIGC/backend/internal/postgres"
)
// BootstrapAdminConfig describes the config-driven first super administrator.
// When every field is present and the process runs against PostgreSQL,
// application startup creates this account exactly once and skips the
// bootstrap when a super administrator already exists.
type BootstrapAdminConfig struct {
Phone string
Password string
DisplayName string
}
// Configured reports whether every bootstrap field is present.
func (c BootstrapAdminConfig) Configured() bool {
return c.Phone != "" && c.Password != "" && c.DisplayName != ""
}
// ParseBootstrapAdminConfig reads ZHINIAN_BOOTSTRAP_ADMIN_PHONE,
// ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD, and ZHINIAN_BOOTSTRAP_ADMIN_NAME. The
// variable names mirror the previous scripts/bootstrap-admin.mjs contract;
// the display name defaults to 平台超级管理员.
func ParseBootstrapAdminConfig(getenv func(string) string) BootstrapAdminConfig {
if getenv == nil {
return BootstrapAdminConfig{}
}
return BootstrapAdminConfig{
Phone: strings.TrimSpace(getenv("ZHINIAN_BOOTSTRAP_ADMIN_PHONE")),
Password: getenv("ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD"),
DisplayName: firstNonEmpty(strings.TrimSpace(getenv("ZHINIAN_BOOTSTRAP_ADMIN_NAME")), "平台超级管理员"),
}
}
// BootstrapSuperAdmin creates the configured first super administrator once.
// It is a no-op when the backend is not PostgreSQL, when the configuration is
// incomplete, or when a super administrator already exists (including
// disabled ones, so a retired administrator cannot trigger a duplicate).
// Failures are returned to the caller and fail application startup, so a
// misconfigured bootstrap is visible instead of silently missing.
func BootstrapSuperAdmin(ctx context.Context, backend postgres.Backend, service *administration.Service, config BootstrapAdminConfig) (bool, error) {
if backend != postgres.BackendPostgres || !config.Configured() {
return false, nil
}
existing, err := service.ListAccounts(ctx, administration.Actor{Role: administration.RoleSuperAdmin}, administration.AccountFilters{Role: administration.RoleSuperAdmin, IncludeDisabled: true})
if err != nil {
return false, err
}
if len(existing) > 0 {
return false, nil
}
if _, err := service.CreateAccount(ctx, administration.Actor{Role: administration.RoleSuperAdmin}, administration.CreateAccountInput{
Phone: config.Phone,
DisplayName: config.DisplayName,
Password: config.Password,
Role: administration.RoleSuperAdmin,
}); err != nil {
return false, err
}
return true, nil
}