Keep context keys private

Instead, offer type safe accessors, as documented here:

https://pkg.go.dev/context#Context
This commit is contained in:
Conrad Hoffmann 2022-03-16 14:33:47 +01:00
parent 07c19a6f6c
commit 78bd2a9b84
3 changed files with 18 additions and 11 deletions

View File

@ -1,7 +1,6 @@
package auth package auth
import ( import (
"context"
"log" "log"
"net/http" "net/http"
@ -59,7 +58,7 @@ func (prov *IMAPProvider) doAuth(next http.Handler,
AuthMethod: "imap", AuthMethod: "imap",
UserName: user, UserName: user,
} }
ctx := context.WithValue(r.Context(), AuthCtxKey, &authCtx) ctx := NewContext(r.Context(), &authCtx)
r = r.WithContext(ctx) r = r.WithContext(ctx)
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
} }

View File

@ -1,14 +1,13 @@
package auth package auth
import ( import (
"context"
"net/http" "net/http"
) )
var AuthCtxKey = &contextKey{"auth"} type contextKey string
type contextKey struct { var authCtxKey contextKey = "auth"
name string
}
type AuthContext struct { type AuthContext struct {
AuthMethod string AuthMethod string
@ -16,6 +15,15 @@ type AuthContext struct {
// TODO more? // 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. // Abstracts the authentication backend for the server.
type AuthProvider interface { type AuthProvider interface {
// Returns HTTP middleware for performing authentication. // Returns HTTP middleware for performing authentication.

View File

@ -37,14 +37,14 @@ func NewFilesystem(path string) (carddav.Backend, error) {
} }
func (b *filesystemBackend) pathForContext(ctx context.Context) (string, error) { func (b *filesystemBackend) pathForContext(ctx context.Context) (string, error) {
raw := ctx.Value(auth.AuthCtxKey) authCtx, ok := auth.FromContext(ctx)
if raw == nil {
return "", fmt.Errorf("unauthenticated requests are not supported")
}
authCtx, ok := raw.(*auth.AuthContext)
if !ok { if !ok {
panic("Invalid data in auth context!") panic("Invalid data in auth context!")
} }
if authCtx == nil {
return "", fmt.Errorf("unauthenticated requests are not supported")
}
userDir := base64.RawStdEncoding.EncodeToString([]byte(authCtx.UserName)) userDir := base64.RawStdEncoding.EncodeToString([]byte(authCtx.UserName))
path := filepath.Join(b.path, userDir) path := filepath.Join(b.path, userDir)