package mock import ( "os" "path/filepath" "testing" "time" "tera-clone/services/tera-api/internal/security/password" ) type startupCountingKDF struct { password.PrototypeSHA256 hashes int } func (k *startupCountingKDF) Hash(value, salt string) (password.Record, error) { k.hashes++ return k.PrototypeSHA256.Hash(value, salt) } func TestStartupReusesPersistedAuthWithoutBootstrapHashes(t *testing.T) { path := filepath.Join(t.TempDir(), "auth.json") kdf := &startupCountingKDF{} stages := map[string]bool{} options := StoreOptions{AuthPath: path, PasswordKDF: kdf, RemoveLegacyAuthUsers: true, StartupTiming: func(stage string, elapsed time.Duration, err error) { stages[stage] = true if elapsed < 0 || err != nil { t.Errorf("stage %s: elapsed=%v err=%v", stage, elapsed, err) } }, } first, err := NewStoreWithOptions(time.Now, options) if err != nil { t.Fatal(err) } if kdf.hashes != 1 { t.Fatalf("factory boot hashes=%d, want 1", kdf.hashes) } first.Close() before, err := os.ReadFile(path) if err != nil { t.Fatal(err) } kdf.hashes = 0 second, err := NewStoreWithOptions(time.Now, options) if err != nil { t.Fatal(err) } defer second.Close() if kdf.hashes != 0 { t.Fatalf("restart hashes=%d, want 0", kdf.hashes) } after, err := os.ReadFile(path) if err != nil { t.Fatal(err) } if string(before) != string(after) { t.Fatal("restart changed persisted credentials") } for _, stage := range []string{"auth.load", "auth.persist", "store.total"} { if !stages[stage] { t.Errorf("missing stage %s", stage) } } } func TestStartupDoesNotRestoreDeletedAccounts(t *testing.T) { path := filepath.Join(t.TempDir(), "auth.json") if err := os.WriteFile(path, []byte(`{"users":{},"address_filters":{"mode":"blacklist","rules":[]}}`), 0600); err != nil { t.Fatal(err) } kdf := &startupCountingKDF{} s, err := NewStoreWithOptions(time.Now, StoreOptions{AuthPath: path, PasswordKDF: kdf, RemoveLegacyAuthUsers: true}) if err != nil { t.Fatal(err) } defer s.Close() if kdf.hashes != 0 || len(s.authUsers) != 0 { t.Fatal("persisted empty inventory was bootstrapped") } } func TestStartupReportsInvalidAuthStore(t *testing.T) { path := filepath.Join(t.TempDir(), "auth.json") if err := os.WriteFile(path, []byte(`{invalid`), 0600); err != nil { t.Fatal(err) } failed := map[string]bool{} _, err := NewStoreWithOptions(time.Now, StoreOptions{AuthPath: path, StartupTiming: func(stage string, _ time.Duration, err error) { failed[stage] = err != nil }}) if err == nil || !failed["auth.load"] || !failed["store.total"] { t.Fatalf("missing startup failure: %v %v", err, failed) } }