46 lines
1.5 KiB
Go
46 lines
1.5 KiB
Go
// Package actor stores the calling user (tenant_id + uid) on a request
|
|
// context so middleware can inject it once and any downstream layer
|
|
// (handler / logic / usecase / repository) can read it without
|
|
// re-parsing the JWT.
|
|
//
|
|
// The package lives under internal/library because it is depended on
|
|
// by BOTH internal/middleware AND internal/logic/*. Defining the
|
|
// context key here is the only way to keep a single key value across
|
|
// packages (Go context.Value keys are typed by package, so each
|
|
// package would otherwise get its own isolated slot).
|
|
package actor
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
type contextKey struct{}
|
|
|
|
// Actor identifies the calling tenant member, injected by the AuthJWT
|
|
// middleware after a successful Bearer token parse.
|
|
type Actor struct {
|
|
TenantID string
|
|
UID string
|
|
}
|
|
|
|
// WithActor stores tenant/uid on ctx. Returns the original ctx
|
|
// unchanged when either field is empty.
|
|
func WithActor(ctx context.Context, tenantID, uid string) context.Context {
|
|
if tenantID == "" || uid == "" {
|
|
return ctx
|
|
}
|
|
return context.WithValue(ctx, contextKey{}, Actor{TenantID: tenantID, UID: uid})
|
|
}
|
|
|
|
// ActorFromContext returns the actor injected by AuthJWT. The error is
|
|
// a plain error (no biz code) so callers can wrap it with their own
|
|
// scope-specific Builder when needed.
|
|
func ActorFromContext(ctx context.Context) (Actor, error) {
|
|
v, ok := ctx.Value(contextKey{}).(Actor)
|
|
if !ok || v.TenantID == "" || v.UID == "" {
|
|
return Actor{}, fmt.Errorf("missing bearer token or X-Tenant-ID/X-UID headers")
|
|
}
|
|
return v, nil
|
|
}
|