aboutsummaryrefslogtreecommitdiffstats
path: root/web/login_test.go
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-02-16 23:31:54 +0000
committerClaude <noreply@anthropic.com>2026-02-16 23:31:54 +0000
commit5f5f8be8c6ca78f5d61372544bb24d692d9597f0 (patch)
tree7c864522e7c5aff3552d493136a692f6c167c528 /web/login_test.go
parented1b953e1336aeda282b46acd1c5e21529fa0950 (diff)
downloadneko-5f5f8be8c6ca78f5d61372544bb24d692d9597f0.tar.gz
neko-5f5f8be8c6ca78f5d61372544bb24d692d9597f0.tar.bz2
neko-5f5f8be8c6ca78f5d61372544bb24d692d9597f0.zip
Add tests for CSRF exclusions, Filter includeContent, multi-feed, and routing
- CSRF: test excluded paths (/api/login, /api/logout), PUT/DELETE methods - Item model: test Filter includeContent flag, ItemById returns content, multiple feed_ids filtering - API: test read_filter=all param, feed_ids comma-separated filter, full_content exclusion from stream - Routing: add v3 frontend route test https://claude.ai/code/session_019Z4VJxzY7tcAuNkPAkvry9
Diffstat (limited to 'web/login_test.go')
-rw-r--r--web/login_test.go86
1 files changed, 86 insertions, 0 deletions
diff --git a/web/login_test.go b/web/login_test.go
index f4931b2..9d78396 100644
--- a/web/login_test.go
+++ b/web/login_test.go
@@ -85,3 +85,89 @@ func TestCSRFLoginWithFormToken(t *testing.T) {
t.Errorf("Expected POST /other with valid CSRF header to succeed, got 403")
}
}
+
+func TestCSRFExcludedPaths(t *testing.T) {
+ originalPw := config.Config.DigestPassword
+ defer func() { config.Config.DigestPassword = originalPw }()
+ config.Config.DigestPassword = "secret"
+
+ mux := http.NewServeMux()
+ mux.HandleFunc("/api/login", apiLoginHandler)
+ mux.HandleFunc("/api/logout", apiLogoutHandler)
+ handler := CSRFMiddleware(&config.Config, mux)
+
+ // POST /api/login without CSRF token should succeed (excluded path)
+ req := httptest.NewRequest("POST", "/api/login", strings.NewReader("password=secret"))
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ rr := httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ if rr.Code == http.StatusForbidden {
+ t.Error("POST /api/login should be excluded from CSRF protection")
+ }
+
+ // POST /api/logout without CSRF token should succeed (excluded path)
+ req = httptest.NewRequest("POST", "/api/logout", nil)
+ rr = httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ if rr.Code == http.StatusForbidden {
+ t.Error("POST /api/logout should be excluded from CSRF protection")
+ }
+}
+
+func TestCSRFPutAndDeleteMethods(t *testing.T) {
+ cfg := &config.Settings{SecureCookies: false}
+ inner := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ })
+ handler := CSRFMiddleware(cfg, inner)
+
+ // GET to get a token
+ getReq := httptest.NewRequest("GET", "/", nil)
+ getRR := httptest.NewRecorder()
+ handler.ServeHTTP(getRR, getReq)
+
+ var csrfToken string
+ for _, c := range getRR.Result().Cookies() {
+ if c.Name == "csrf_token" {
+ csrfToken = c.Value
+ }
+ }
+
+ // PUT without token should fail
+ req := httptest.NewRequest("PUT", "/item/1", nil)
+ req.AddCookie(&http.Cookie{Name: "csrf_token", Value: csrfToken})
+ rr := httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ if rr.Code != http.StatusForbidden {
+ t.Errorf("PUT without CSRF token should return 403, got %d", rr.Code)
+ }
+
+ // DELETE without token should fail
+ req = httptest.NewRequest("DELETE", "/feed/1", nil)
+ req.AddCookie(&http.Cookie{Name: "csrf_token", Value: csrfToken})
+ rr = httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ if rr.Code != http.StatusForbidden {
+ t.Errorf("DELETE without CSRF token should return 403, got %d", rr.Code)
+ }
+
+ // PUT with valid token should succeed
+ req = httptest.NewRequest("PUT", "/item/1", nil)
+ req.AddCookie(&http.Cookie{Name: "csrf_token", Value: csrfToken})
+ req.Header.Set("X-CSRF-Token", csrfToken)
+ rr = httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ if rr.Code != http.StatusOK {
+ t.Errorf("PUT with valid CSRF token should succeed, got %d", rr.Code)
+ }
+
+ // DELETE with valid token should succeed
+ req = httptest.NewRequest("DELETE", "/feed/1", nil)
+ req.AddCookie(&http.Cookie{Name: "csrf_token", Value: csrfToken})
+ req.Header.Set("X-CSRF-Token", csrfToken)
+ rr = httptest.NewRecorder()
+ handler.ServeHTTP(rr, req)
+ if rr.Code != http.StatusOK {
+ t.Errorf("DELETE with valid CSRF token should succeed, got %d", rr.Code)
+ }
+}