docs(httpauth-firebase): fix rbac tier reference from 1 to 0
rbac is a Tier 0 module (no micro-lib dependencies). The dependency line incorrectly cited it as Tier 1. The module's own tier (4) is unchanged — it remains the auth layer above the transport infrastructure.
This commit is contained in:
66
enrichment.go
Normal file
66
enrichment.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package httpauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"code.nochebuena.dev/go/rbac"
|
||||
)
|
||||
|
||||
// IdentityEnricher builds an rbac.Identity from verified token claims.
|
||||
// The application provides the implementation — typically reads from a user store.
|
||||
type IdentityEnricher interface {
|
||||
Enrich(ctx context.Context, uid string, claims map[string]any) (rbac.Identity, error)
|
||||
}
|
||||
|
||||
// EnrichOpt configures EnrichmentMiddleware.
|
||||
type EnrichOpt func(*enrichConfig)
|
||||
|
||||
type enrichConfig struct {
|
||||
tenantHeader string
|
||||
}
|
||||
|
||||
// WithTenantHeader configures the request header from which TenantID is read.
|
||||
// If the header is absent on a request, TenantID remains "" — no error is returned.
|
||||
func WithTenantHeader(header string) EnrichOpt {
|
||||
return func(c *enrichConfig) {
|
||||
c.tenantHeader = header
|
||||
}
|
||||
}
|
||||
|
||||
// EnrichmentMiddleware reads uid + claims injected by AuthMiddleware, calls
|
||||
// enricher.Enrich to build a full rbac.Identity, and stores it in the context.
|
||||
// Returns 401 if no uid is present (AuthMiddleware was not in the chain).
|
||||
// Returns 500 if the enricher fails.
|
||||
func EnrichmentMiddleware(enricher IdentityEnricher, opts ...EnrichOpt) func(http.Handler) http.Handler {
|
||||
cfg := &enrichConfig{}
|
||||
for _, o := range opts {
|
||||
o(cfg)
|
||||
}
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
uid, ok := getUID(r.Context())
|
||||
if !ok {
|
||||
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
claims, _ := getClaims(r.Context())
|
||||
|
||||
identity, err := enricher.Enrich(r.Context(), uid, claims)
|
||||
if err != nil {
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.tenantHeader != "" {
|
||||
if tenantID := r.Header.Get(cfg.tenantHeader); tenantID != "" {
|
||||
identity = identity.WithTenant(tenantID)
|
||||
}
|
||||
}
|
||||
|
||||
ctx := rbac.SetInContext(r.Context(), identity)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user