All checks were successful
Check / check (pull_request) Successful in 3m22s
Bump golangci-lint from v2.10.1 to v2.12.2 in the Dockerfile lint stage (tag+digest pin) and script/bootstrap release-archive pins (linux amd64/arm64 sha256s). Replace .golangci.yml with the canonical v2-layout config so linter settings (lll 88, funlen 80/50, cyclop 15, dupl 100) actually apply. Fix all findings surfaced by the new linter and config: - noctx: use httptest.NewRequestWithContext in all tests - gosec G710/G703: route app redirects through a path-escaping redirectToApp helper; annotate internal log path usage - goconst: introduce shared constants for template/JSON keys and repeated test literals - lll: wrap lines to the 88-column limit - dupl: extract shared helpers (generic findAllByAppID in models, deleteAppResource in handlers, parsePush in webhook payloads, table-driven/helper-based test dedup) - nolintlint: drop nolint directives made obsolete by the new limits Record the change in TODO.md; make check is green.
80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package middleware //nolint:testpackage // tests internal CORS behavior
|
|
|
|
import (
|
|
"log/slog"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"sneak.berlin/go/upaas/internal/config"
|
|
)
|
|
|
|
//nolint:gosec // test credentials
|
|
func newCORSTestMiddleware(corsOrigins string) *Middleware {
|
|
return &Middleware{
|
|
log: slog.Default(),
|
|
params: &Params{
|
|
Config: &config.Config{
|
|
CORSOrigins: corsOrigins,
|
|
SessionSecret: "test-secret-32-bytes-long-enough",
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// assertNoCORSHeaders runs a request with the given Origin header through
|
|
// CORS middleware configured with corsOrigins and asserts that no
|
|
// Access-Control-Allow-Origin header is set.
|
|
func assertNoCORSHeaders(t *testing.T, corsOrigins, origin, msg string) {
|
|
t.Helper()
|
|
|
|
m := newCORSTestMiddleware(corsOrigins)
|
|
handler := m.CORS()(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
|
|
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil)
|
|
req.Header.Set("Origin", origin)
|
|
|
|
rec := httptest.NewRecorder()
|
|
handler.ServeHTTP(rec, req)
|
|
|
|
assert.Empty(t, rec.Header().Get("Access-Control-Allow-Origin"), msg)
|
|
}
|
|
|
|
func TestCORS_NoOriginsConfigured_NoCORSHeaders(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
assertNoCORSHeaders(t, "", "https://evil.com",
|
|
"expected no CORS headers when no origins configured")
|
|
}
|
|
|
|
func TestCORS_OriginsConfigured_AllowsMatchingOrigin(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := newCORSTestMiddleware("https://app.example.com,https://other.example.com")
|
|
handler := m.CORS()(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
|
|
req := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil)
|
|
req.Header.Set("Origin", "https://app.example.com")
|
|
|
|
rec := httptest.NewRecorder()
|
|
handler.ServeHTTP(rec, req)
|
|
|
|
assert.Equal(t, "https://app.example.com",
|
|
rec.Header().Get("Access-Control-Allow-Origin"))
|
|
assert.Equal(t, "true",
|
|
rec.Header().Get("Access-Control-Allow-Credentials"))
|
|
}
|
|
|
|
func TestCORS_OriginsConfigured_RejectsNonMatchingOrigin(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
assertNoCORSHeaders(t, "https://app.example.com", "https://evil.com",
|
|
"expected no CORS headers for non-matching origin")
|
|
}
|