package admin_test import ( "context" "database/sql" "net/http" "net/http/cookiejar" "net/http/httptest" "path/filepath" "testing" "git.asio.asia/nixevol/NixMsg/internal/admin" "git.asio.asia/nixevol/NixMsg/internal/auth" "git.asio.asia/nixevol/NixMsg/internal/store" ) func TestPasswordWrongOldLocksAfterTen(t *testing.T) { _, srv, client, _ := setup(t) login(t, client, srv.URL) base := srv.URL var last *http.Response var env envelope for i := 0; i < 10; i++ { last = postJSON(t, client, base+"/api/admin/password", `{"old_password":"not-the-password","new_password":"new-password-12"}`, map[string]string{"X-Nixmsg-Request": "1"}) env = decodeEnv(t, last) } if last.StatusCode != http.StatusTooManyRequests { t.Fatalf("want 429 after 10 wrong old passwords, got %d %+v", last.StatusCode, env) } if env.Error == nil || env.Error.Code != "rate_limited" { t.Fatalf("want rate_limited got %+v", env.Error) } } func TestLoginDeletesExpiredAdminSessions(t *testing.T) { dir := t.TempDir() db, err := store.Open(filepath.Join(dir, "data"), "FULL") if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = db.Close() }) hash := auth.NewStubHashPool() if seedErr := admin.SeedAdminPassword(context.Background(), db, hash, testPassword); seedErr != nil { t.Fatal(seedErr) } h := admin.New(admin.Deps{ DB: db, Hash: hash, Tokens: admin.NewRandomAPITokens(), Locks: admin.NewMemoryLoginLocks(), }) srv := httptest.NewServer(h) t.Cleanup(srv.Close) if qerr := db.Queue.Do(context.Background(), func(tx *sql.Tx) error { _, e := tx.Exec(`INSERT INTO admin_sessions(token_hash, created_at, expires_at) VALUES ('expired-hash', 1, 1)`) return e }); qerr != nil { t.Fatal(qerr) } jar, err := cookiejar.New(nil) if err != nil { t.Fatal(err) } client := &http.Client{Jar: jar} login(t, client, srv.URL) var n int if err := db.Read.QueryRow(`SELECT COUNT(*) FROM admin_sessions WHERE token_hash = 'expired-hash'`).Scan(&n); err != nil { t.Fatal(err) } if n != 0 { t.Fatalf("expired session still present, count=%d", n) } }