diff --git a/pkg/auth/context.go b/pkg/auth/context.go new file mode 100644 index 0000000..f6f9c94 --- /dev/null +++ b/pkg/auth/context.go @@ -0,0 +1,30 @@ +// Package auth — context keys and helpers for authentication state. +// +// This file owns the symbols that other packages use to read/write the +// authenticated user from a request context. Previously these symbols +// lived in pkg/greet/ which was the wrong home (auth concern in greet +// package) ; moved here as part of the middleware design cleanup. +package auth + +import ( + "context" + + "dance-lessons-coach/pkg/user" +) + +// contextKey is unexported to prevent collisions with other packages +// using string keys (Go convention). +type contextKey string + +// UserContextKey is the key under which the authenticated user is +// stored in the request context by AuthMiddleware. +const UserContextKey contextKey = "authenticatedUser" + +// GetAuthenticatedUserFromContext extracts the authenticated user from +// the request context. Returns (nil, false) if no user is present +// (which is the case for unauthenticated requests AND for requests +// that failed silent fail-through ; cf. AuthMiddleware semantics). +func GetAuthenticatedUserFromContext(ctx context.Context) (*user.User, bool) { + u, ok := ctx.Value(UserContextKey).(*user.User) + return u, ok +} diff --git a/pkg/greet/greet.go b/pkg/greet/greet.go index 54e6d0b..340bbfe 100644 --- a/pkg/greet/greet.go +++ b/pkg/greet/greet.go @@ -3,31 +3,17 @@ package greet import ( "context" - "dance-lessons-coach/pkg/user" + "dance-lessons-coach/pkg/auth" "github.com/rs/zerolog/log" ) -// Context key for storing authenticated user -type contextKey string - -const ( - // UserContextKey is the context key for storing authenticated user - UserContextKey contextKey = "authenticatedUser" -) - type Service struct{} func NewService() *Service { return &Service{} } -// GetAuthenticatedUserFromContext extracts the authenticated user from context -func GetAuthenticatedUserFromContext(ctx context.Context) (*user.User, bool) { - user, ok := ctx.Value(UserContextKey).(*user.User) - return user, ok -} - // Greet returns a greeting message for the given name. // If name is empty, it checks for authenticated user and uses their username. // If no authenticated user and no name, it defaults to "world". @@ -37,7 +23,7 @@ func (s *Service) Greet(ctx context.Context, name string) string { // If no name provided, check for authenticated user if name == "" { - if authenticatedUser, ok := GetAuthenticatedUserFromContext(ctx); ok { + if authenticatedUser, ok := auth.GetAuthenticatedUserFromContext(ctx); ok { name = authenticatedUser.Username log.Trace().Ctx(ctx).Str("authenticated_user", name).Msg("Using authenticated username for greeting") } diff --git a/pkg/server/middleware.go b/pkg/server/middleware.go index f9918c7..3c2c732 100644 --- a/pkg/server/middleware.go +++ b/pkg/server/middleware.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "dance-lessons-coach/pkg/greet" + "dance-lessons-coach/pkg/auth" "dance-lessons-coach/pkg/user" "github.com/rs/zerolog/log" @@ -54,7 +54,7 @@ func (m *AuthMiddleware) Middleware(next http.Handler) http.Handler { } // Add user to context - ctxWithUser := context.WithValue(ctx, greet.UserContextKey, validatedUser) + ctxWithUser := context.WithValue(ctx, auth.UserContextKey, validatedUser) r = r.WithContext(ctxWithUser) // Continue to next handler