Documentation
¶
Overview ¶
Package tenant provides stable tenant scoping middleware.
Use the middleware to place a tenant identifier in request context before authorization, idempotency, repositories, or audit logging need tenant-aware behavior. Invalid or missing tenant data should fail at the application edge according to the service's routing policy. Set Options.RequireAllSources when request-carried tenant identifiers must match an authenticated tenant scope or route parameter before the handler runs.
Purpose: See the package summary above. Import: `github.com/aatuh/api-toolkit/v4/middleware/auth/tenant`. Example: See docs/api-reference.md for package example links and docs/cookbook.md for task recipes. Errors: Constructors, parsers, and handlers return or write documented errors according to their signatures; packages with plain data types do not add hidden error channels. Concurrency: Treat configured middleware and helpers as immutable after construction; request and response values remain request-scoped unless a type documents stronger guarantees. Stability: Stable core API under VERSIONING.md and scripts/apicheck.sh. When not to use: Prefer net/http, application-owned types, or narrower helpers when this package contract is not needed.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ErrorHandler ¶
type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error)
ErrorHandler handles authorization errors from the tenant middleware.
type Middleware ¶
type Middleware struct {
// contains filtered or unexported fields
}
Middleware enforces tenant scoping and stores the tenant in context.
func New ¶
func New(opts Options) (*Middleware, error)
New creates a tenant scoping middleware.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"github.com/aatuh/api-toolkit/v4/authorization"
"github.com/aatuh/api-toolkit/v4/middleware/auth/tenant"
)
func main() {
mw, err := tenant.New(tenant.Options{HeaderName: "X-Tenant-ID"})
if err != nil {
panic(err)
}
handler := mw.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
scope, _ := authorization.ScopeFromContext(r.Context())
fmt.Fprint(w, scope.TenantID)
}))
req := httptest.NewRequestWithContext(context.Background(), http.MethodGet, "/widgets", nil)
req.Header.Set("X-Tenant-ID", "tenant-1")
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, req)
fmt.Println(recorder.Body.String())
}
Output: tenant-1
type Options ¶
type Options struct {
Optional bool
HeaderName string
URLParam string
URLParamExtractor URLParamExtractor
TenantFromContext TenantFromContext
// RequireAllSources requires every configured tenant source to be present
// and to agree. Use it when a route must prove the request tenant matches
// the authenticated tenant scope.
RequireAllSources bool
ErrorHandler ErrorHandler
}
Options configures tenant scoping.
type TenantFromContext ¶
TenantFromContext extracts a tenant identifier from context.