package auth import ( "context" "errors" "tercul/internal/domain" "tercul/internal/platform/auth" "tercul/internal/platform/log" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" ) var ( ErrUserNotFound = errors.New("user not found") ErrContextRequired = errors.New("context is required") ) // AuthQueries contains the query handlers for authentication. type AuthQueries struct { userRepo domain.UserRepository jwtManager auth.JWTManagement tracer trace.Tracer } // NewAuthQueries creates a new AuthQueries handler. func NewAuthQueries(userRepo domain.UserRepository, jwtManager auth.JWTManagement) *AuthQueries { return &AuthQueries{ userRepo: userRepo, jwtManager: jwtManager, tracer: otel.Tracer("auth.queries"), } } // GetUserFromContext extracts user from context func (q *AuthQueries) GetUserFromContext(ctx context.Context) (*domain.User, error) { if ctx == nil { return nil, ErrContextRequired } ctx, span := q.tracer.Start(ctx, "GetUserFromContext") defer span.End() logger := log.FromContext(ctx) logger.Debug("Attempting to get user from context") claims, err := auth.RequireAuth(ctx) if err != nil { logger.Warn("Failed to get user from context - authentication required") return nil, err } logger = logger.With("user_id", claims.UserID) logger.Debug("Claims found in context") user, err := q.userRepo.GetByID(ctx, claims.UserID) if err != nil { logger.Warn("Failed to get user from context - user not found") return nil, ErrUserNotFound } if !user.Active { logger.Warn("Failed to get user from context - user inactive") return nil, ErrInvalidCredentials } logger.Debug("User retrieved from context successfully") return user, nil } // ValidateToken validates a JWT token and returns the user func (q *AuthQueries) ValidateToken(ctx context.Context, tokenString string) (*domain.User, error) { if ctx == nil { return nil, ErrContextRequired } ctx, span := q.tracer.Start(ctx, "ValidateToken") defer span.End() logger := log.FromContext(ctx) if tokenString == "" { logger.Warn("Token validation failed - empty token") return nil, auth.ErrMissingToken } logger.Debug("Attempting to validate token") claims, err := q.jwtManager.ValidateToken(tokenString) if err != nil { logger.Error(err, "Token validation failed - invalid token") return nil, err } logger = logger.With("user_id", claims.UserID) logger.Debug("Token claims validated") user, err := q.userRepo.GetByID(ctx, claims.UserID) if err != nil { logger.Error(err, "Token validation failed - user not found") return nil, ErrUserNotFound } if !user.Active { logger.Warn("Token validation failed - user inactive") return nil, ErrInvalidCredentials } logger.Info("Token validated successfully") return user, nil }