package server import ( "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" ) // TestSameOriginGuard checks the admin console's CSRF defence: safe methods pass, // a state-changing request needs an Origin/Referer host matching the request Host. func TestSameOriginGuard(t *testing.T) { gin.SetMode(gin.TestMode) e := gin.New() g := e.Group("/_gm") g.Use(requireSameOrigin()) g.POST("/act", func(c *gin.Context) { c.Status(http.StatusOK) }) g.GET("/page", func(c *gin.Context) { c.Status(http.StatusOK) }) cases := []struct { name string method string path string origin string referer string want int }{ {"get is safe", http.MethodGet, "/_gm/page", "", "", http.StatusOK}, {"post without origin rejected", http.MethodPost, "/_gm/act", "", "", http.StatusForbidden}, {"post matching origin ok", http.MethodPost, "/_gm/act", "http://example.com", "", http.StatusOK}, {"post foreign origin rejected", http.MethodPost, "/_gm/act", "http://evil.test", "", http.StatusForbidden}, {"post matching referer ok", http.MethodPost, "/_gm/act", "", "http://example.com/_gm/x", http.StatusOK}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { req := httptest.NewRequest(tc.method, "http://example.com"+tc.path, nil) if tc.origin != "" { req.Header.Set("Origin", tc.origin) } if tc.referer != "" { req.Header.Set("Referer", tc.referer) } rec := httptest.NewRecorder() e.ServeHTTP(rec, req) if rec.Code != tc.want { t.Errorf("status = %d, want %d", rec.Code, tc.want) } }) } }