package initialize import ( "bytes" "context" "encoding/json" "testing" "time" "kra/internal/biz/system" "kra/internal/config" "gorm.io/gorm" ) type configurationBackend struct { value *config.Config persisted *config.Config } func (b *configurationBackend) IsInitialized(context.Context) (bool, error) { return true, nil } func (b *configurationBackend) InitializeDatabase(context.Context, *system.DatabaseConfig, func(context.Context, *gorm.DB) error) error { return nil } func (b *configurationBackend) PersistConfig(context.Context) error { return nil } func (b *configurationBackend) PersistRuntimeConfig(_ context.Context, value *config.Config) error { b.persisted = config.Clone(value) return nil } func (b *configurationBackend) ReloadConfig(context.Context) error { return nil } func (b *configurationBackend) Config() *config.Config { return config.Clone(b.value) } func TestConfigurationJSONMasksSecretsWithoutMutatingConfig(t *testing.T) { backend := &configurationBackend{value: &config.Config{ Data: &config.Data{Database: &config.Database{Password: "database-secret", Source: "dsn"}, Redis: &config.Redis{Password: "redis-secret"}}, Admin: &config.Admin{JWT: &config.JWT{SigningKey: "jwt-secret", ExpiresTime: 24 * time.Hour}, Email: &config.Email{Secret: "email-secret"}, Storage: &config.Storage{Qiniu: &config.Qiniu{SecretKey: "storage-secret"}}}, }} raw, err := (&Repo{backend: backend}).ConfigurationJSON() if err != nil { t.Fatal(err) } if !json.Valid(raw) { t.Fatalf("invalid response: %s", raw) } for _, secret := range []string{"database-secret", "redis-secret", "jwt-secret", "email-secret", "storage-secret", "dsn"} { if bytes.Contains(raw, []byte(secret)) { t.Fatalf("configuration response exposed %q: %s", secret, raw) } } if backend.value.Data.Database.Password != "database-secret" || backend.value.Admin.JWT.SigningKey != "jwt-secret" { t.Fatal("ConfigurationJSON mutated the live configuration") } } func TestSaveConfigurationJSONMergesPartialValuesAndPreservesSecrets(t *testing.T) { backend := &configurationBackend{value: &config.Config{ Data: &config.Data{Database: &config.Database{Driver: "mysql", Host: "old", Password: "database-secret", Source: "old-dsn"}, Redis: &config.Redis{Name: "main", Password: "redis-secret", ReadTimeout: time.Second}}, Admin: &config.Admin{ConfigPath: "config.yaml", JWT: &config.JWT{SigningKey: "jwt-secret", Issuer: "old", ExpiresTime: time.Hour}, Captcha: &config.Captcha{StoreExpiration: time.Minute}, Email: &config.Email{Host: "old.smtp", Secret: "email-secret", IsSSL: true}}, }} raw := json.RawMessage(`{"data":{"database":{"host":"new","password":"******"},"redis":{"read_timeout":"250ms"}},"admin":{"jwt":{"issuer":"new","signingKey":"******","expiresTime":"48h"},"captcha":{"storeExpiration":"5m"}},"email":{"host":"new.smtp","secret":"******","is-ssl":false}}`) if err := (&Repo{backend: backend}).SaveConfigurationJSON(context.Background(), raw); err != nil { t.Fatal(err) } got := backend.persisted if got == nil || got.Data.Database.Host != "new" || got.Admin.JWT.Issuer != "new" || got.Admin.Email.Host != "new.smtp" { t.Fatalf("partial update was not applied: %#v", got) } if got.Data.Database.Password != "database-secret" || got.Admin.JWT.SigningKey != "jwt-secret" || got.Admin.Email.Secret != "email-secret" { t.Fatal("masked secrets were not preserved") } if got.Data.Redis.ReadTimeout != 250*time.Millisecond || got.Admin.JWT.ExpiresTime != 48*time.Hour || got.Admin.Captcha.StoreExpiration != 5*time.Minute || got.Admin.Email.IsSSL { t.Fatalf("management values were not decoded: redis=%s jwt=%s captcha=%s ssl=%t", got.Data.Redis.ReadTimeout, got.Admin.JWT.ExpiresTime, got.Admin.Captcha.StoreExpiration, got.Admin.Email.IsSSL) } if got.Admin.ConfigPath != "config.yaml" { t.Fatalf("config path = %q", got.Admin.ConfigPath) } } func TestSaveConfigurationJSONPreservesStandaloneDSN(t *testing.T) { backend := &configurationBackend{value: &config.Config{ Data: &config.Data{Database: &config.Database{Driver: "mysql", Source: "user:secret@tcp(database.example:3306)/kra"}}, Admin: &config.Admin{}, }} if err := (&Repo{backend: backend}).SaveConfigurationJSON(context.Background(), json.RawMessage(`{"admin":{"routerPrefix":"/api"}}`)); err != nil { t.Fatal(err) } if got := backend.persisted.Data.Database.Source; got != "user:secret@tcp(database.example:3306)/kra" { t.Fatalf("standalone DSN = %q", got) } }