package application import ( "context" "errors" "testing" "git.nianxx.cn/wangxuming/NianAIGC/backend/internal/administration" "git.nianxx.cn/wangxuming/NianAIGC/backend/internal/postgres" ) // bootstrapFakeStore is a minimal in-memory administration.Store for // bootstrap tests. Only ListAccounts and CreateAccount carry behavior; the // remaining methods exist to satisfy the interface. type bootstrapFakeStore struct { accounts map[string]administration.Account } func newBootstrapFakeStore() *bootstrapFakeStore { return &bootstrapFakeStore{accounts: map[string]administration.Account{}} } func (s *bootstrapFakeStore) ListAccounts(_ context.Context, filters administration.AccountFilters) ([]administration.Account, error) { out := []administration.Account{} for _, account := range s.accounts { if filters.OrganizationID != "" && account.OrganizationID != filters.OrganizationID { continue } if filters.Role != "" && account.Role != filters.Role { continue } if !filters.IncludeDisabled && account.Status != administration.StatusActive { continue } out = append(out, account) } return out, nil } func (s *bootstrapFakeStore) GetAccount(_ context.Context, id string) (administration.Account, bool, error) { account, ok := s.accounts[id] return account, ok, nil } func (s *bootstrapFakeStore) CreateAccount(_ context.Context, account administration.Account) (administration.Account, error) { if _, exists := s.accounts[account.ID]; exists { return administration.Account{}, errors.New("account already exists") } s.accounts[account.ID] = account return account, nil } func (s *bootstrapFakeStore) UpdateAccount(_ context.Context, account administration.Account) (administration.Account, error) { s.accounts[account.ID] = account return account, nil } func (s *bootstrapFakeStore) DeleteAccount(_ context.Context, id, _ string) error { delete(s.accounts, id) return nil } func (s *bootstrapFakeStore) ListOrganizations(context.Context, bool) ([]administration.Organization, error) { return nil, nil } func (s *bootstrapFakeStore) GetOrganization(context.Context, string) (administration.Organization, bool, error) { return administration.Organization{}, false, nil } func (s *bootstrapFakeStore) CreateOrganization(_ context.Context, organization administration.Organization) (administration.Organization, error) { return organization, nil } func (s *bootstrapFakeStore) UpdateOrganization(_ context.Context, organization administration.Organization) (administration.Organization, error) { return organization, nil } func (s *bootstrapFakeStore) DeleteOrganization(context.Context, string) error { return nil } func (s *bootstrapFakeStore) CountOrganizationMembers(context.Context, string) (int, error) { return 0, nil } func configuredBootstrap() BootstrapAdminConfig { return BootstrapAdminConfig{Phone: "13800138000", Password: "change-me-now", DisplayName: "平台超级管理员"} } func TestParseBootstrapAdminConfig(t *testing.T) { env := map[string]string{ "ZHINIAN_BOOTSTRAP_ADMIN_PHONE": " 13800138000 ", "ZHINIAN_BOOTSTRAP_ADMIN_PASSWORD": "change-me-now", "ZHINIAN_BOOTSTRAP_ADMIN_NAME": " 平台超级管理员 ", } config := ParseBootstrapAdminConfig(func(name string) string { return env[name] }) if config.Phone != "13800138000" || config.Password != "change-me-now" || config.DisplayName != "平台超级管理员" { t.Fatalf("unexpected parsed config: %+v", config) } if !config.Configured() { t.Fatalf("expected parsed config to be complete") } defaulted := ParseBootstrapAdminConfig(func(name string) string { if name == "ZHINIAN_BOOTSTRAP_ADMIN_NAME" { return "" } return env[name] }) if defaulted.DisplayName != "平台超级管理员" { t.Fatalf("expected default display name, got %q", defaulted.DisplayName) } if config := ParseBootstrapAdminConfig(nil); config.Configured() { t.Fatalf("nil getenv must produce an incomplete config") } } func TestBootstrapSuperAdminNoopWithoutConfig(t *testing.T) { store := newBootstrapFakeStore() service := administration.NewService(store) created, err := BootstrapSuperAdmin(context.Background(), postgres.BackendPostgres, service, BootstrapAdminConfig{}) if err != nil || created { t.Fatalf("expected no-op without config, got created=%v err=%v", created, err) } if len(store.accounts) != 0 { t.Fatalf("expected no accounts, got %d", len(store.accounts)) } } func TestBootstrapSuperAdminNoopOnLocalBackend(t *testing.T) { store := newBootstrapFakeStore() service := administration.NewService(store) created, err := BootstrapSuperAdmin(context.Background(), postgres.BackendLocal, service, configuredBootstrap()) if err != nil || created { t.Fatalf("expected no-op on local backend, got created=%v err=%v", created, err) } if len(store.accounts) != 0 { t.Fatalf("expected no accounts, got %d", len(store.accounts)) } } func TestBootstrapSuperAdminCreatesOnce(t *testing.T) { store := newBootstrapFakeStore() service := administration.NewService(store) created, err := BootstrapSuperAdmin(context.Background(), postgres.BackendPostgres, service, configuredBootstrap()) if err != nil || !created { t.Fatalf("expected first bootstrap to create, got created=%v err=%v", created, err) } if len(store.accounts) != 1 { t.Fatalf("expected exactly one account, got %d", len(store.accounts)) } for _, account := range store.accounts { if account.Role != administration.RoleSuperAdmin || account.Status != administration.StatusActive { t.Fatalf("unexpected bootstrapped account: %+v", account) } if account.PasswordHash == "change-me-now" || account.PasswordHash == "" { t.Fatalf("password must be hashed, got %q", account.PasswordHash) } } created, err = BootstrapSuperAdmin(context.Background(), postgres.BackendPostgres, service, configuredBootstrap()) if err != nil || created { t.Fatalf("expected second bootstrap to skip, got created=%v err=%v", created, err) } if len(store.accounts) != 1 { t.Fatalf("expected still exactly one account, got %d", len(store.accounts)) } } func TestBootstrapSuperAdminSkipsDisabledSuperAdmin(t *testing.T) { store := newBootstrapFakeStore() existing := administration.Account{ ID: "user-existing", Phone: "13900139000", DisplayName: "已有超管", Role: administration.RoleSuperAdmin, Status: administration.StatusDisabled, SessionVersion: 1, } store.accounts[existing.ID] = existing service := administration.NewService(store) created, err := BootstrapSuperAdmin(context.Background(), postgres.BackendPostgres, service, configuredBootstrap()) if err != nil || created { t.Fatalf("expected skip with existing disabled super admin, got created=%v err=%v", created, err) } if len(store.accounts) != 1 { t.Fatalf("expected no new account, got %d", len(store.accounts)) } } func TestBootstrapSuperAdminRejectsShortPassword(t *testing.T) { store := newBootstrapFakeStore() service := administration.NewService(store) config := configuredBootstrap() config.Password = "short" created, err := BootstrapSuperAdmin(context.Background(), postgres.BackendPostgres, service, config) if err == nil { t.Fatalf("expected short password to fail") } if created { t.Fatalf("expected no account on failed bootstrap") } if len(store.accounts) != 0 { t.Fatalf("expected no accounts, got %d", len(store.accounts)) } }