From 78bd2a9b84cfa5505bf56ecbff44a31af5826832 Mon Sep 17 00:00:00 2001 From: Conrad Hoffmann Date: Wed, 16 Mar 2022 14:33:47 +0100 Subject: [PATCH] Keep context keys private Instead, offer type safe accessors, as documented here: https://pkg.go.dev/context#Context --- auth/imap.go | 3 +-- auth/interface.go | 16 ++++++++++++---- storage/filesystem.go | 10 +++++----- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/auth/imap.go b/auth/imap.go index 8db8c3f..0b8c4d3 100644 --- a/auth/imap.go +++ b/auth/imap.go @@ -1,7 +1,6 @@ package auth import ( - "context" "log" "net/http" @@ -59,7 +58,7 @@ func (prov *IMAPProvider) doAuth(next http.Handler, AuthMethod: "imap", UserName: user, } - ctx := context.WithValue(r.Context(), AuthCtxKey, &authCtx) + ctx := NewContext(r.Context(), &authCtx) r = r.WithContext(ctx) next.ServeHTTP(w, r) } diff --git a/auth/interface.go b/auth/interface.go index e2d1931..99ad722 100644 --- a/auth/interface.go +++ b/auth/interface.go @@ -1,14 +1,13 @@ package auth import ( + "context" "net/http" ) -var AuthCtxKey = &contextKey{"auth"} +type contextKey string -type contextKey struct { - name string -} +var authCtxKey contextKey = "auth" type AuthContext struct { AuthMethod string @@ -16,6 +15,15 @@ type AuthContext struct { // TODO more? } +func NewContext(ctx context.Context, a *AuthContext) context.Context { + return context.WithValue(ctx, authCtxKey, a) +} + +func FromContext(ctx context.Context) (*AuthContext, bool) { + a, ok := ctx.Value(authCtxKey).(*AuthContext) + return a, ok +} + // Abstracts the authentication backend for the server. type AuthProvider interface { // Returns HTTP middleware for performing authentication. diff --git a/storage/filesystem.go b/storage/filesystem.go index e37a210..52a4974 100644 --- a/storage/filesystem.go +++ b/storage/filesystem.go @@ -37,14 +37,14 @@ func NewFilesystem(path string) (carddav.Backend, error) { } func (b *filesystemBackend) pathForContext(ctx context.Context) (string, error) { - raw := ctx.Value(auth.AuthCtxKey) - if raw == nil { - return "", fmt.Errorf("unauthenticated requests are not supported") - } - authCtx, ok := raw.(*auth.AuthContext) + authCtx, ok := auth.FromContext(ctx) if !ok { panic("Invalid data in auth context!") } + if authCtx == nil { + return "", fmt.Errorf("unauthenticated requests are not supported") + } + userDir := base64.RawStdEncoding.EncodeToString([]byte(authCtx.UserName)) path := filepath.Join(b.path, userDir)