Documentation
¶
Overview ¶
Package middleware provides HTTP middleware for authentication and authorization.
Package middleware provides HTTP middleware for GoatFlow.
Package middleware provides HTTP middleware for authentication and authorization.
Index ¶
- Constants
- func APITokenAuthMiddleware() gin.HandlerFunc
- func AuthenticateAPIToken(c *gin.Context, token string)
- func ClearLanguageCookie(c *gin.Context)
- func CustomerCaptiveRedirect(jwtManager *auth.JWTManager) gin.HandlerFunc
- func CustomerPortalGate(jwtManager *auth.JWTManager) gin.HandlerFunc
- func DatabaseHealthCheck() gin.HandlerFunc
- func DemoGuard() gin.HandlerFunc
- func DemoMode() gin.HandlerFunc
- func ExtractToken(c *gin.Context) string
- func GetCurrentUser(c *gin.Context) (uint, string, string, bool)
- func GetLanguage(c *gin.Context) string
- func IsAPIToken(token string) bool
- func IsCustomerPrincipal(c *gin.Context) bool
- func MaintenanceNotification(db *sql.DB) gin.HandlerFunc
- func OptionalAuth(jwtManager *auth.JWTManager) gin.HandlerFunc
- func RequestID() gin.HandlerFunc
- func RequireAdminAccess(rbac *auth.RBAC) gin.HandlerFunc
- func RequireAdminGroup() gin.HandlerFunc
- func RequireAgent() gin.HandlerFunc
- func RequireAgentAccess(rbac *auth.RBAC) gin.HandlerFunc
- func RequireAnyPermission(rbac *auth.RBAC, permissions ...auth.Permission) gin.HandlerFunc
- func RequireAnyQueueAccess(permType string) gin.HandlerFunc
- func RequireCustomer() gin.HandlerFunc
- func RequireCustomerOrAnyQueueAccess(permType string) gin.HandlerFunc
- func RequirePermission(rbac *auth.RBAC, permission auth.Permission) gin.HandlerFunc
- func RequireQueueAccess(permType string) gin.HandlerFunc
- func RequireQueueAccessFromTicket(permType string) gin.HandlerFunc
- func RequireRole(roles ...string) gin.HandlerFunc
- func RequireScope(scope string) gin.HandlerFunc
- func RequireTicketAccess(rbac *auth.RBAC) gin.HandlerFunc
- func RequireTicketReadOrCustomerOwner() gin.HandlerFunc
- func ResolveTenantFromHost(host string) uint
- func SecurityHeaders() gin.HandlerFunc
- func SetAPITokenVerifier(v APITokenVerifier)
- func SetCaptivePluginLandingResolver(r CaptivePluginLandingResolver)
- func SetLanguageCookie(c *gin.Context, lang string)
- func SetMaintenanceCheckerFactory(f func(*sql.DB) MaintenanceChecker)
- func SetQueueAccessCheckerFactory(f func(*sql.DB) QueueAccessChecker)
- func SetSessionServiceFactory(f func(*sql.DB) SessionChecker)
- func SetTicketQueueResolverFactory(f func() TicketQueueResolver)
- func T(c *gin.Context, key string, args ...interface{}) string
- func TranslateError(c *gin.Context, key string, args ...interface{}) string
- func TranslateSuccess(c *gin.Context, key string, args ...interface{}) string
- func TranslateValidation(c *gin.Context, key string, args ...interface{}) string
- func UnifiedAuthMiddleware(jwtManager interface{ ... }) gin.HandlerFunc
- func VerifySession(c *gin.Context, claims *auth.Claims) bool
- type APITokenVerifier
- type AuthMiddleware
- func (m *AuthMiddleware) CanAccessTicket(c *gin.Context, ticketOwnerID uint) bool
- func (m *AuthMiddleware) GetUserID(c *gin.Context) (uint, bool)
- func (m *AuthMiddleware) GetUserRole(c *gin.Context) (string, bool)
- func (m *AuthMiddleware) IsAuthenticated(c *gin.Context) bool
- func (m *AuthMiddleware) OptionalAuth() gin.HandlerFunc
- func (m *AuthMiddleware) RequireAuth() gin.HandlerFunc
- func (m *AuthMiddleware) RequirePermission(permission auth.Permission) gin.HandlerFunc
- func (m *AuthMiddleware) RequireRole(roles ...string) gin.HandlerFunc
- type CaptivePluginLandingResolver
- type I18nMiddleware
- type MaintenanceChecker
- type QueueAccessChecker
- type RateLimiter
- type ResolvedTicket
- type SessionChecker
- type TicketQueueResolver
Constants ¶
const ( // LanguageContextKey is the key for storing language in context. LanguageContextKey = "language" // DefaultLanguage is the default language. DefaultLanguage = "en" )
Variables ¶
This section is empty.
Functions ¶
func APITokenAuthMiddleware ¶
func APITokenAuthMiddleware() gin.HandlerFunc
APITokenAuthMiddleware authenticates requests using GoatKit API tokens (gf_*). Sets user context similar to JWT auth for compatibility with existing handlers.
func AuthenticateAPIToken ¶
AuthenticateAPIToken handles gf_* token authentication. Exported so that other auth middlewares (e.g. SessionOrJWTAuth) can delegate to it when they detect an API token.
func ClearLanguageCookie ¶
ClearLanguageCookie clears the language preference cookie.
func CustomerCaptiveRedirect ¶
func CustomerCaptiveRedirect(jwtManager *auth.JWTManager) gin.HandlerFunc
CustomerCaptiveRedirect redirects customers whose org is captive to a plugin. Must run before CustomerPortalGate: that gate invokes OptionalAuth inline which writes the response body via c.Next(), after which a later redirect is silently dropped.
Capture only fires when the customer also has plugin access via gk_org_plugin_access — captive_plugin alone would lock a user out of the portal entirely.
func CustomerPortalGate ¶
func CustomerPortalGate(jwtManager *auth.JWTManager) gin.HandlerFunc
CustomerPortalGate loads portal config, enforces enable/disable, and applies optional login rules. A signed-in customer gets their company's settings (per-company overrides on top of the global values); anonymous visitors get the global settings.
func DatabaseHealthCheck ¶
func DatabaseHealthCheck() gin.HandlerFunc
and returns a friendly error page if the database is down.
func DemoGuard ¶
func DemoGuard() gin.HandlerFunc
DemoGuard blocks non-admin users from modifying account security settings (password, MFA) when demo mode is active. Returns 403 with a friendly message.
func DemoMode ¶
func DemoMode() gin.HandlerFunc
DemoMode sets is_demo=true on every request when app.demo_mode is enabled. This allows templates and handlers to check for demo mode globally.
func ExtractToken ¶
ExtractToken extracts an auth token from the request. It checks the Authorization header first (Bearer JWT or raw API token), then falls back to cookies. On /customer paths customer-specific cookies are checked before agent cookies to avoid session conflicts in the same browser. The query parameter "token" is only accepted for browser transports that cannot reliably set headers: WebSocket upgrades and known same-origin SSE endpoints.
func GetCurrentUser ¶
GetCurrentUser retrieves the current user from context.
func GetLanguage ¶
GetLanguage gets the current language from context. Falls back to cookie detection if not set in context.
func IsAPIToken ¶
IsAPIToken checks if a token string is a GoatKit API token (gf_ prefix)
func IsCustomerPrincipal ¶ added in v0.10.0
IsCustomerPrincipal reports whether the authenticated caller is a customer: a customer JWT (role "Customer") or a customer API token. Customer ids live in customer_user, whose id space overlaps users.id, so a customer must never be treated as an agent with the same numeric id.
func MaintenanceNotification ¶
func MaintenanceNotification(db *sql.DB) gin.HandlerFunc
MaintenanceNotification middleware checks for active/upcoming maintenance and adds notification data to the context for templates.
func OptionalAuth ¶
func OptionalAuth(jwtManager *auth.JWTManager) gin.HandlerFunc
OptionalAuth is middleware that validates tokens if present but doesn't require them.
func RequestID ¶
func RequestID() gin.HandlerFunc
RequestID adds a unique request ID to each request.
func RequireAdminAccess ¶
func RequireAdminAccess(rbac *auth.RBAC) gin.HandlerFunc
RequireAdminAccess is a convenience function for admin-only routes.
func RequireAdminGroup ¶
func RequireAdminGroup() gin.HandlerFunc
RequireAdminGroup checks if the user is in the admin group.
func RequireAgent ¶ added in v0.10.0
func RequireAgent() gin.HandlerFunc
RequireAgent admits authenticated agents (agent JWTs and agent API tokens) and refuses customers and anonymous callers.
func RequireAgentAccess ¶
func RequireAgentAccess(rbac *auth.RBAC) gin.HandlerFunc
RequireAgentAccess allows both admins and agents.
func RequireAnyPermission ¶
func RequireAnyPermission(rbac *auth.RBAC, permissions ...auth.Permission) gin.HandlerFunc
RequireAnyPermission checks if the user has any of the required permissions.
func RequireAnyQueueAccess ¶
func RequireAnyQueueAccess(permType string) gin.HandlerFunc
RequireAnyQueueAccess checks if the user has the specified permission for at least one queue. This is useful for routes where access to any queue is sufficient (like ticket list pages).
func RequireCustomer ¶ added in v0.10.0
func RequireCustomer() gin.HandlerFunc
RequireCustomer admits authenticated customers (customer JWTs and customer API tokens) and refuses agents and anonymous callers.
func RequireCustomerOrAnyQueueAccess ¶ added in v0.10.0
func RequireCustomerOrAnyQueueAccess(permType string) gin.HandlerFunc
RequireCustomerOrAnyQueueAccess is RequireAnyQueueAccess for routes that customers may also call: customers pass through and the handler must limit them to their own tickets; agents need permType on at least one queue.
func RequirePermission ¶
func RequirePermission(rbac *auth.RBAC, permission auth.Permission) gin.HandlerFunc
RequirePermission checks if the user has the required permission.
func RequireQueueAccess ¶
func RequireQueueAccess(permType string) gin.HandlerFunc
RequireQueueAccess checks if the user has the specified permission for the queue. The queue ID is extracted from the URL parameter "queue_id" or query parameter "queue_id". Permission types: ro, rw, create, move_into, note, owner, priority
func RequireQueueAccessFromTicket ¶
func RequireQueueAccessFromTicket(permType string) gin.HandlerFunc
RequireQueueAccessFromTicket checks if the user has the specified permission for the queue that the ticket belongs to. The ticket ID is extracted from the URL parameter "ticket_id" or "id".
func RequireRole ¶
func RequireRole(roles ...string) gin.HandlerFunc
RequireRole checks if the user has the required role.
func RequireScope ¶
func RequireScope(scope string) gin.HandlerFunc
RequireScope middleware checks that the API token has the required scope. It also enforces AgentOnly and RequireRole restrictions from the scope definition.
func RequireTicketAccess ¶
func RequireTicketAccess(rbac *auth.RBAC) gin.HandlerFunc
RequireTicketAccess checks if the user can access a specific ticket.
func RequireTicketReadOrCustomerOwner ¶ added in v0.10.0
func RequireTicketReadOrCustomerOwner() gin.HandlerFunc
RequireTicketReadOrCustomerOwner admits agents with "ro" on the queue of the ticket in the path (as RequireQueueAccessFromTicket("ro")) and customers whose login is the ticket's customer_user_id. Other customers get 404, so the existence of foreign tickets is not revealed. The handler must still hide agent-only content (internal articles) from customers.
func ResolveTenantFromHost ¶
ResolveTenantFromHost maps the request host to a tenant ID using GOATFLOW_CUSTOMER_HOSTMAP. Format: "host1=1,host2=2". Unknown hosts return 0.
func SecurityHeaders ¶
func SecurityHeaders() gin.HandlerFunc
SecurityHeaders adds HTTP security headers to all responses.
CSP Note: GoatFlow uses Alpine.js (requires unsafe-eval for x-data/x-bind expression evaluation) and HTMX (injects inline scripts from AJAX responses). These frameworks are fundamentally incompatible with strict script-src CSP. XSS protection is provided by server-side HTML sanitisation (bluemonday), not by CSP script restrictions. CSP still protects against clickjacking, content sniffing, form hijacking, and framing attacks.
func SetAPITokenVerifier ¶
func SetAPITokenVerifier(v APITokenVerifier)
SetAPITokenVerifier sets the global token verifier
func SetCaptivePluginLandingResolver ¶
func SetCaptivePluginLandingResolver(r CaptivePluginLandingResolver)
SetCaptivePluginLandingResolver installs the landing-path lookup used by the captive redirect inside CustomerPortalGate.
func SetLanguageCookie ¶
SetLanguageCookie sets the language preference cookie.
func SetMaintenanceCheckerFactory ¶
func SetMaintenanceCheckerFactory(f func(*sql.DB) MaintenanceChecker)
SetMaintenanceCheckerFactory injects a maintenance checker factory from product code.
func SetQueueAccessCheckerFactory ¶
func SetQueueAccessCheckerFactory(f func(*sql.DB) QueueAccessChecker)
SetQueueAccessCheckerFactory injects a queue access checker factory from product code.
func SetSessionServiceFactory ¶
func SetSessionServiceFactory(f func(*sql.DB) SessionChecker)
func SetTicketQueueResolverFactory ¶
func SetTicketQueueResolverFactory(f func() TicketQueueResolver)
SetTicketQueueResolverFactory injects a ticket queue resolver factory from product code.
func TranslateError ¶
TranslateError translates an error message.
func TranslateSuccess ¶
TranslateSuccess translates a success message.
func TranslateValidation ¶
TranslateValidation translates a validation message.
func UnifiedAuthMiddleware ¶
func UnifiedAuthMiddleware(jwtManager interface {
ValidateToken(string) (*auth.Claims, error)
}) gin.HandlerFunc
UnifiedAuthMiddleware handles both JWT tokens and API tokens (gf_*).
func VerifySession ¶ added in v0.10.0
VerifySession reports whether the session an access token names still exists, touching its last-request time when it does. Every auth middleware that accepts a JWT must call it: a killed session revokes the token regardless of which cookies or headers the client sends. Without a session checker nothing can vouch for the token, so the answer is no.
Types ¶
type APITokenVerifier ¶
type APITokenVerifier interface {
VerifyToken(ctx context.Context, rawToken string) (*platformmodels.APIToken, error)
UpdateLastUsed(ctx context.Context, tokenID int64, ip string) error
}
APITokenVerifier is the interface for verifying API tokens. This breaks the import cycle between api and middleware packages.
type AuthMiddleware ¶
type AuthMiddleware struct {
// contains filtered or unexported fields
}
func NewAuthMiddleware ¶
func NewAuthMiddleware(jwtManager *auth.JWTManager) *AuthMiddleware
func (*AuthMiddleware) CanAccessTicket ¶
func (m *AuthMiddleware) CanAccessTicket(c *gin.Context, ticketOwnerID uint) bool
func (*AuthMiddleware) GetUserRole ¶
func (m *AuthMiddleware) GetUserRole(c *gin.Context) (string, bool)
func (*AuthMiddleware) IsAuthenticated ¶
func (m *AuthMiddleware) IsAuthenticated(c *gin.Context) bool
func (*AuthMiddleware) OptionalAuth ¶
func (m *AuthMiddleware) OptionalAuth() gin.HandlerFunc
func (*AuthMiddleware) RequireAuth ¶
func (m *AuthMiddleware) RequireAuth() gin.HandlerFunc
func (*AuthMiddleware) RequirePermission ¶
func (m *AuthMiddleware) RequirePermission(permission auth.Permission) gin.HandlerFunc
func (*AuthMiddleware) RequireRole ¶
func (m *AuthMiddleware) RequireRole(roles ...string) gin.HandlerFunc
type CaptivePluginLandingResolver ¶
CaptivePluginLandingResolver maps a plugin name to its declared landing path. Supplied by the api package at startup to avoid an import cycle (middleware → api → middleware). When nil, captive redirects degrade to no-op — the customer sees the normal portal rather than getting stuck at a blank page.
type I18nMiddleware ¶
type I18nMiddleware struct {
// contains filtered or unexported fields
}
I18nMiddleware handles language detection and sets it in context.
func NewI18nMiddleware ¶
func NewI18nMiddleware() *I18nMiddleware
NewI18nMiddleware creates a new i18n middleware.
func (*I18nMiddleware) Handle ¶
func (m *I18nMiddleware) Handle() gin.HandlerFunc
Handle returns the middleware handler function.
type MaintenanceChecker ¶
type MaintenanceChecker interface {
IsActive() (*platformmodels.SystemMaintenance, error)
IsComing(withinMinutes int) (*platformmodels.SystemMaintenance, error)
}
MaintenanceChecker checks for active system maintenance.
func NewMaintenanceChecker ¶
func NewMaintenanceChecker(db *sql.DB) MaintenanceChecker
NewMaintenanceChecker creates a MaintenanceChecker from the injected factory. Returns nil if no factory is set.
type QueueAccessChecker ¶
type QueueAccessChecker interface {
IsAdmin(ctx context.Context, userID uint) (bool, error)
HasQueueAccess(ctx context.Context, userID uint, queueID uint, permType string) (bool, error)
GetAccessibleQueueIDs(ctx context.Context, userID uint, permType string) ([]uint, error)
}
QueueAccessChecker checks queue permissions (subset of service.QueueAccessService).
func NewQueueAccessChecker ¶ added in v0.10.0
func NewQueueAccessChecker(db *sql.DB) QueueAccessChecker
NewQueueAccessChecker creates a QueueAccessChecker from the injected factory. Returns nil if no factory is set.
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter implements a token bucket rate limiter
func GlobalRateLimiter ¶
func GlobalRateLimiter() *RateLimiter
GlobalRateLimiter returns the shared rate limiter instance.
func (*RateLimiter) Allow ¶
func (rl *RateLimiter) Allow(key string, limit int) bool
Allow checks if a request is allowed and consumes a token from a bucket of limit requests per hour.
func (*RateLimiter) AllowPer ¶ added in v0.10.0
AllowPer checks if a request is allowed and consumes a token from a bucket of limit requests per window. A bucket whose limit or window changed (e.g. a reconfigured plugin UI) adopts the new values.
func (*RateLimiter) Remaining ¶
func (rl *RateLimiter) Remaining(key string) int
Remaining returns remaining tokens for a key
type ResolvedTicket ¶ added in v0.10.0
ResolvedTicket is a ticket a path identifier names, with its queue.
type SessionChecker ¶
type SessionChecker interface {
GetSession(sessionID string) (*platformmodels.Session, error)
TouchSession(sessionID string) error
}
SessionChecker checks session validity (subset of service.SessionService).
type TicketQueueResolver ¶
type TicketQueueResolver interface {
ResolveTickets(db *sql.DB, ticketIDStr string) ([]ResolvedTicket, error)
}
TicketQueueResolver resolves a ticket identifier (tn or id) to the tickets it can name. Product code injects a concrete implementation via SetTicketQueueResolverFactory. It returns sql.ErrNoRows when none exists.