You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

95 lines
2.6 KiB

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)
}
}