diff --git a/auth/auth.go b/auth/auth.go index e5bd6535..cd6ee096 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -31,29 +31,12 @@ package auth import ( - "errors" "fmt" "net/http" "golang.org/x/net/context" ) -// Common errors used with this package. -var ( - ErrNoRequestContext = errors.New("no http request in context") - ErrNoAuthUserInfo = errors.New("no auth user info in context") -) - -// RequestFromContext returns the http request in the given context. -// Returns ErrNoRequestContext if the context does not have an http -// request associated with it. -func RequestFromContext(ctx context.Context) (*http.Request, error) { - if r, ok := ctx.Value("http.request").(*http.Request); r != nil && ok { - return r, nil - } - return nil, ErrNoRequestContext -} - // UserInfo carries information about // an autenticated/authorized client. type UserInfo struct { @@ -102,6 +85,30 @@ type AccessController interface { Authorized(ctx context.Context, access ...Access) (context.Context, error) } +// WithUser returns a context with the authorized user info. +func WithUser(ctx context.Context, user UserInfo) context.Context { + return userInfoContext{ + Context: ctx, + user: user, + } +} + +type userInfoContext struct { + context.Context + user UserInfo +} + +func (uic userInfoContext) Value(key interface{}) interface{} { + switch key { + case "auth.user": + return uic.user + case "auth.user.name": + return uic.user.Name + } + + return uic.Context.Value(key) +} + // InitFunc is the type of an AccessController factory function and is used // to register the contsructor for different AccesController backends. type InitFunc func(options map[string]interface{}) (AccessController, error) diff --git a/auth/silly/access.go b/auth/silly/access.go index 2f0831e7..c3adba80 100644 --- a/auth/silly/access.go +++ b/auth/silly/access.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/docker/distribution/auth" + ctxu "github.com/docker/distribution/context" "golang.org/x/net/context" ) @@ -43,7 +44,7 @@ func newAccessController(options map[string]interface{}) (auth.AccessController, // Authorized simply checks for the existence of the authorization header, // responding with a bearer challenge if it doesn't exist. func (ac *accessController) Authorized(ctx context.Context, accessRecords ...auth.Access) (context.Context, error) { - req, err := auth.RequestFromContext(ctx) + req, err := ctxu.GetRequest(ctx) if err != nil { return nil, err } diff --git a/auth/token/accesscontroller.go b/auth/token/accesscontroller.go index 77232109..2f1e3d6d 100644 --- a/auth/token/accesscontroller.go +++ b/auth/token/accesscontroller.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/docker/distribution/auth" + ctxu "github.com/docker/distribution/context" "github.com/docker/libtrust" "golang.org/x/net/context" ) @@ -224,7 +225,7 @@ func (ac *accessController) Authorized(ctx context.Context, accessItems ...auth. accessSet: newAccessSet(accessItems...), } - req, err := auth.RequestFromContext(ctx) + req, err := ctxu.GetRequest(ctx) if err != nil { return nil, err } @@ -264,7 +265,7 @@ func (ac *accessController) Authorized(ctx context.Context, accessItems ...auth. } } - return context.WithValue(ctx, "auth.user", auth.UserInfo{Name: token.Claims.Subject}), nil + return auth.WithUser(ctx, auth.UserInfo{Name: token.Claims.Subject}), nil } // init handles registering the token auth backend.