package lkgateway import ( "os" "path/filepath" "testing" ) // H1: пустой/битый users.json на настроенной системе НЕ должен открывать админку. func TestAuthFailClosed(t *testing.T) { dir := t.TempDir() oldUsers, oldMarker, oldStore, oldFailed := usersFile, configuredMarker, globalUsers, usersLoadFailed t.Cleanup(func() { usersFile, configuredMarker, globalUsers, usersLoadFailed = oldUsers, oldMarker, oldStore, oldFailed }) usersFile = filepath.Join(dir, "users.json") configuredMarker = filepath.Join(dir, "configured") reload := func() { usersLoadFailed = false globalUsers = loadUsers() } // 1) свежая система: файла нет, маркера нет → открыто для первичной настройки reload() if !authOpen() || authLockedOut() { t.Fatalf("свежая система: ожидали open, got open=%v locked=%v", authOpen(), authLockedOut()) } // 2) корректный стор с админом → не открыто, не заблокировано, маркер создан if err := os.WriteFile(usersFile, []byte(`[{"login":"admin","role":"admin","active":true}]`), 0o600); err != nil { t.Fatal(err) } reload() if authOpen() || authLockedOut() { t.Fatalf("настроенная система: open=%v locked=%v", authOpen(), authLockedOut()) } if !isConfigured() { t.Fatal("маркер настройки не создан при загрузке валидного стора") } // 3) файл ПОВРЕЖДЁН (битый JSON) → fail-closed if err := os.WriteFile(usersFile, []byte(`{ не json`), 0o600); err != nil { t.Fatal(err) } reload() if authOpen() { t.Error("битый users.json открыл админку без входа — fail-open!") } if !authLockedOut() { t.Error("битый users.json должен блокировать админку") } // 4) файл ПРОПАЛ, но система была настроена (маркер есть) → fail-closed os.Remove(usersFile) reload() if authOpen() { t.Error("пропавший users.json на настроенной системе открыл админку — fail-open!") } if !authLockedOut() { t.Error("пропавший стор на настроенной системе должен блокировать админку") } }