package grpcserver import ( "context" "database/sql" "git.wntrmute.dev/kyle/eng-pad-server/internal/auth" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) type contextKey string const userIDKey contextKey = "user_id" // UserIDFromContext extracts the authenticated user ID from the context. func UserIDFromContext(ctx context.Context) (int64, bool) { id, ok := ctx.Value(userIDKey).(int64) return id, ok } // AuthInterceptor verifies username/password from gRPC metadata. func AuthInterceptor(database *sql.DB) grpc.UnaryServerInterceptor { return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, status.Error(codes.Unauthenticated, "missing metadata") } usernames := md.Get("x-engpad-username") passwords := md.Get("x-engpad-password") if len(usernames) == 0 || len(passwords) == 0 { return nil, status.Error(codes.Unauthenticated, "missing credentials") } userID, err := auth.AuthenticateUser(database, usernames[0], passwords[0]) if err != nil { return nil, status.Error(codes.Unauthenticated, "invalid credentials") } ctx = context.WithValue(ctx, userIDKey, userID) return handler(ctx, req) } }