Documentation
¶
Index ¶
- Constants
- func AuditLog(exporter enterprise.AuditExporter) gin.HandlerFunc
- func BodySizeLimit(maxBytes int64) gin.HandlerFunc
- func CORS() gin.HandlerFunc
- func GetLocalUser(c *gin.Context) *models.User
- func GetSAMLSession(c *gin.Context) samlsp.Session
- func InjectSAMLSession(samlMiddleware *samlsp.Middleware, la services.LocalAuthService) gin.HandlerFunc
- func IsSecure() bool
- func Logger() gin.HandlerFunc
- func RateLimit(tier string, limit int, windowSecs int) gin.HandlerFunc
- func RateLimitAPI() gin.HandlerFunc
- func RateLimitAuth() gin.HandlerFunc
- func RateLimitWebhooks() gin.HandlerFunc
- func Recovery() gin.HandlerFunc
- func RequestID() gin.HandlerFunc
- func RequireAdmin() gin.HandlerFunc
- func RequireAuth(samlMiddleware *samlsp.Middleware, localAuth ...services.LocalAuthService) gin.HandlerFunc
- func RequirePro() gin.HandlerFunc
- func SecurityHeaders() gin.HandlerFunc
- func SlackSignatureVerification() gin.HandlerFunc
- func TeamsAuth(appID string) gin.HandlerFunc
Constants ¶
const ( // DefaultMaxBodySize is 10MB for general API requests DefaultMaxBodySize int64 = 10 * 1024 * 1024 // WebhookMaxBodySize is 1MB for webhook endpoints // Webhooks should be small - large payloads indicate a problem WebhookMaxBodySize int64 = 1 * 1024 * 1024 )
const ( // SlackMaxTimestampAge is the maximum age of a request timestamp (5 minutes) // This prevents replay attacks SlackMaxTimestampAge = 5 * time.Minute // SlackSignatureVersion is the version prefix for Slack signatures SlackSignatureVersion = "v0" )
Variables ¶
This section is empty.
Functions ¶
func AuditLog ¶
func AuditLog(exporter enterprise.AuditExporter) gin.HandlerFunc
AuditLog returns a Gin middleware that calls exporter.Export after each request completes. In the OSS build the exporter is the no-op stub, so this middleware adds zero overhead beyond the function call.
The middleware captures the HTTP layer only (method, path, status, actor). Fine-grained domain events (e.g. "incident.resolved") are emitted by the enterprise service layer implementations in the enterprise repo.
func BodySizeLimit ¶
func BodySizeLimit(maxBytes int64) gin.HandlerFunc
BodySizeLimit returns a middleware that limits the request body size
This helps prevent: - Denial of service attacks via large payloads - Memory exhaustion from unbounded inputs - Accidental large payloads indicating misconfiguration
Usage:
webhooks.Use(middleware.BodySizeLimit(WebhookMaxBodySize))
func CORS ¶
func CORS() gin.HandlerFunc
CORS returns a middleware that enforces an origin allowlist.
Allowed origins are read from the CORS_ALLOWED_ORIGINS environment variable (comma-separated).
In development (APP_ENV=development or unset) all http://localhost:* origins are automatically allowed — no configuration needed when running `npm run dev` on any port.
In production (APP_ENV=production) only explicitly listed origins are permitted. When the embedded frontend is used (same-origin deployment) the browser sends no Origin header at all, so CORS headers are never needed.
Security properties:
- Only allowlisted origins receive Access-Control-Allow-Origin.
- Access-Control-Allow-Credentials: true is only sent for allowlisted origins.
- Requests from unknown origins are served without CORS headers, causing the browser to block the cross-origin response.
func GetLocalUser ¶
GetLocalUser retrieves the locally-authenticated user from context.
func InjectSAMLSession ¶
func InjectSAMLSession(samlMiddleware *samlsp.Middleware, la services.LocalAuthService) gin.HandlerFunc
InjectSAMLSession reads the SAML session cookie (if present) and sets it in the Gin context without aborting when no session exists. Use on routes that must be accessible without auth but should still identify SAML users (e.g. GET /auth/me). When la is provided, also resolves the DB user into contextKeyLocalUser so handlers see a unified identity regardless of auth path.
func IsSecure ¶
func IsSecure() bool
IsSecure returns true if the Secure flag should be set on cookies. Always secure except in local development to allow plain HTTP. Single definition used by both middleware and handler packages.
func Logger ¶
func Logger() gin.HandlerFunc
Logger returns a Gin middleware for structured JSON logging with slog
func RateLimit ¶
func RateLimit(tier string, limit int, windowSecs int) gin.HandlerFunc
RateLimit returns a Gin middleware that allows at most limit requests per windowSecs seconds per client IP. tier is used in the Redis key and log fields.
func RateLimitAPI ¶
func RateLimitAPI() gin.HandlerFunc
RateLimitAPI limits authenticated requests by user-ID (600 req/min) and falls back to IP-based limiting (120 req/min) for unauthenticated requests.
The higher authenticated limit prevents false positives when the UI fires many parallel requests (e.g. Gantt calendar loading one timeline per schedule). IP-based limits are insufficient for multi-user teams sharing an office NAT, and unnecessary once the user is already authenticated.
func RateLimitAuth ¶
func RateLimitAuth() gin.HandlerFunc
RateLimitAuth allows 10 requests per minute per IP. Applied to login endpoints to prevent brute-force attacks.
func RateLimitWebhooks ¶
func RateLimitWebhooks() gin.HandlerFunc
RateLimitWebhooks allows 300 requests per minute per IP. Sized for Prometheus Alertmanager bursts (many alerts firing simultaneously).
func Recovery ¶
func Recovery() gin.HandlerFunc
Recovery returns a middleware that recovers from panics
func RequestID ¶
func RequestID() gin.HandlerFunc
RequestID adds a unique request ID to each request for tracing Supports X-Request-ID header from load balancers/proxies
func RequireAdmin ¶
func RequireAdmin() gin.HandlerFunc
RequireAdmin aborts with 403 if the local user is not an admin. No-op in SAML/open mode.
func RequireAuth ¶
func RequireAuth(samlMiddleware *samlsp.Middleware, localAuth ...services.LocalAuthService) gin.HandlerFunc
RequireAuth enforces authentication on a route group.
Priority order:
- Local session cookie (oi_session) — checked first
- SAML session — checked if no local session
- Neither configured → open mode pass-through
func RequirePro ¶
func RequirePro() gin.HandlerFunc
RequirePro aborts with 402 Payment Required if no valid Pro licence is active. Apply to route groups that contain Pro-only endpoints.
func SecurityHeaders ¶
func SecurityHeaders() gin.HandlerFunc
SecurityHeaders returns a middleware that sets standard security headers on all responses.
Headers set:
- X-Content-Type-Options: nosniff (prevents MIME type sniffing)
- X-Frame-Options: DENY (legacy clickjacking protection for older browsers)
- Content-Security-Policy: tightened policy — see inline comment
- Referrer-Policy: strict-origin-when-cross-origin
- Strict-Transport-Security: max-age=63072000; includeSubDomains (2 years; HTTPS only)
- X-Permitted-Cross-Domain-Policies: none (blocks Flash/PDF cross-domain policy files)
X-XSS-Protection is intentionally omitted: it is deprecated, removed from modern browsers, and can introduce vulnerabilities in older IE/Edge versions.
func SlackSignatureVerification ¶
func SlackSignatureVerification() gin.HandlerFunc
SlackSignatureVerification returns a middleware that verifies Slack request signatures
This implements Slack's signature verification algorithm: https://api.slack.com/authentication/verifying-requests-from-slack
The middleware: 1. Checks that the request timestamp is within 5 minutes (prevents replay attacks) 2. Computes HMAC-SHA256 signature of "v0:timestamp:body" 3. Compares computed signature with X-Slack-Signature header 4. Rejects requests with invalid or missing signatures
Usage:
slackRoutes.Use(middleware.SlackSignatureVerification())
func TeamsAuth ¶
func TeamsAuth(appID string) gin.HandlerFunc
TeamsAuth validates the Bot Framework JWT Bearer token sent by Microsoft.
Bot Framework sends tokens signed by Microsoft's identity platform. The token's "aud" claim must match the bot's App ID, and the signature is verified against public keys from Microsoft's Bot Framework OIDC discovery doc.
Types ¶
This section is empty.