aboutsummaryrefslogtreecommitdiffstats
path: root/web/login_test.go
diff options
context:
space:
mode:
authorAdam Mathes <adam@adammathes.com>2026-02-16 08:00:53 -0800
committerAdam Mathes <adam@adammathes.com>2026-02-16 08:00:53 -0800
commit12eaaf186fce84d069556e11fea85e0be42c1a8b (patch)
tree9480a885cecc783897e9f3cb345b5ec1cc0ecd99 /web/login_test.go
parente7516c4124d033332922db91a3dc0e8dc417c2aa (diff)
downloadneko-12eaaf186fce84d069556e11fea85e0be42c1a8b.tar.gz
neko-12eaaf186fce84d069556e11fea85e0be42c1a8b.tar.bz2
neko-12eaaf186fce84d069556e11fea85e0be42c1a8b.zip
Fix restricted login access and modernize login page
- Close NK-oqd24q: Fix login access for v3/api - Update web.go to exclude /login/ from CSRF check during initial submission - Modernize web/static/login.html with new CSS and structure - Add web/login_test.go to verify CSRF exclusion - Created NK-ngokc3 for further CSRF enhancements
Diffstat (limited to 'web/login_test.go')
-rw-r--r--web/login_test.go68
1 files changed, 68 insertions, 0 deletions
diff --git a/web/login_test.go b/web/login_test.go
new file mode 100644
index 0000000..b48e7bc
--- /dev/null
+++ b/web/login_test.go
@@ -0,0 +1,68 @@
+package web
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+
+ "golang.org/x/crypto/bcrypt"
+
+ "adammathes.com/neko/config"
+)
+
+func TestCSRFLoginExclusion(t *testing.T) {
+ // Setup password
+ pw := "secret"
+ hashed, _ := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost)
+ // We need to set the global config since loginHandler uses it
+ config.Config.DigestPassword = string(hashed) // wait, config stores the hashed password?
+ // let's check web.go loginHandler:
+ // if password == config.Config.DigestPassword {
+ // v, _ := bcrypt.GenerateFromPassword([]byte(password), 0)
+
+ // Ah, it compares PLAIN TEXT password with config.Config.DigestPassword.
+ // wait, line 113: if password == config.Config.DigestPassword {
+ // So config stores the PLAIN TEXT password? That's... odd, but okay for this test.
+ originalPw := config.Config.DigestPassword
+ defer func() { config.Config.DigestPassword = originalPw }()
+ config.Config.DigestPassword = pw
+
+ // Create a mux with login handler
+ mux := http.NewServeMux()
+ mux.HandleFunc("/login/", loginHandler)
+ mux.HandleFunc("/other", func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ })
+
+ // Wrap with CSRF middleware
+ // We need to pass a pointer to Settings
+ handler := CSRFMiddleware(&config.Config, mux)
+
+ // Test 1: POST /login/ without CSRF token
+ // Should NOT return 403 Forbidden.
+ // Since we provide correct password, it should redirect (307)
+ req := httptest.NewRequest("POST", "/login/", strings.NewReader("password="+pw))
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ rr := httptest.NewRecorder()
+
+ handler.ServeHTTP(rr, req)
+
+ if rr.Code == http.StatusForbidden {
+ t.Errorf("Expected /login/ POST to be allowed without CSRF token, got 403 Forbidden")
+ }
+ if rr.Code != http.StatusTemporaryRedirect {
+ t.Errorf("Expected 307 Redirect on successful login, got %d", rr.Code)
+ }
+
+ // Test 2: POST /other without CSRF token
+ // Should fail with 403 Forbidden
+ req2 := httptest.NewRequest("POST", "/other", nil)
+ rr2 := httptest.NewRecorder()
+
+ handler.ServeHTTP(rr2, req2)
+
+ if rr2.Code != http.StatusForbidden {
+ t.Errorf("Expected 403 Forbidden for POST /other, got %d", rr2.Code)
+ }
+}