GraphQL/ Rails 422 Unprocessable Entity - сохранение токена в сессию

В настоящее время я работаю над изменением рельсового бэкенда проекта с REST на graphql, и я сталкиваюсь с ошибкой аутентификации после их учебника - https://www.howtographql.com/graphql-ruby/4-authentication/

Я использую движок GraphiQL для проверки всех своих запросов и получения ошибки status 422 unprocessable Entity, User Must Exist

Это имеет смысл, потому что мутация, которую я выполняю, заключается в создании нового цвета, который имеет belongs_to отношение к пользователю.

Примерно на полпути по ссылке выше ^^^ написано так:

С маркером, что signinUser обеспечивает мутацию, приложения могут аутентифицировать последующие запросы. Есть несколько способов сделать это. В этом уроке мы просто собираемся использовать встроенный сеанс, поскольку он не добавляет никаких требований к клиентскому приложению. Сервер GraphQL должен иметь возможность получать токен из заголовка сеанса при каждом запросе, определять, к какому пользователю он относится, и передавать эту информацию обработчикам.

Я могу успешно вернуть токен авторизации через signinUser метод, подобный документам, показанным ранее на той же странице - метод, который он публикует, также сохраняет токен в этом предполагаемом сеансе в этом методе здесь (также по той же ссылке, опубликованной выше ^^^):

def call(_obj, args, ctx)
    input = args[:email]

    return unless input

    user = User.find_by email: input[:email]

    return unless user
    return unless user.authenticate(input[:password_digest])

    crypt = ActiveSupport::MessageEncryptor.new(ENV["SECRET_BASE_KEY"])

    token = crypt.encrypt_and_sign("user-id:#{ user.id }")

    puts "please **********************************"
    p ctx[:session]


    ctx[:session][:token] = token

    puts "please **********************************"
    p ctx[:session]

    OpenStruct.new({
      user: user,
      token: token
      })
  end

В моей отчаянной борьбе вы сможете увидеть, что я остановил сеанс непосредственно перед возвратом метода, и неудивительно, что он содержит маркер для входа тех пользователей.

Однако, когда я приступил к выполнению мутации для создания цвета, я ожидал, что сессия все еще будет содержать этот токен, и я смогу успешно зафиксировать этот цвет. Это был не тот случай, и когда я выводил сеанс для этого запроса, он возвращал пустой хеш.

Я не могу найти какую-либо информацию о том, как работает встроенный сеанс graphql - и я новичок в graphql в целом.


Моими основными вопросами было бы - должен ли сеанс graphql кэшировать информацию о токене? Почему информация не переносится на следующие запросы? signinUser? Должен ли я даже пытаться использовать аутентификацию в этом учебном пособии, поскольку документы утверждают, что этот метод аутентификации не является долгосрочным решением?


Я знаю, что это много, но был бы очень признателен за это.

Заранее спасибо!

PS. Я понимаю, что в руководстве используются ссылки, и я использую здесь цвета - это сделано намеренно, и я приложил все усилия, чтобы убедиться, что семантические различия не вызывают никаких ошибок.

  • Версия Rails - 5.2.2 (только с использованием API)

  • graphql - 1.7.4

  • Graphiql рельсы - 1.4.4

2 ответа

Решение

Мой коллега отметил, что "сессия" является частью рельсов и должна создать cookie, который будет доступен из следующего запроса.

Я упомянул, что я использую версию Rails - 5.2.2 (используя только API) - хорошо, когда вы используете -api флаг при инициализации нового проекта Rails, он добавляет эти строки в application.rb

# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.

# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
# Skip views, helpers and assets when generating a new resource.
config.api_only = true

Обратите внимание на эту строку, в частности - Middleware like session, flash, cookies can be added back manually.


Я закомментировал config.api_only = true и это добавило куки обратно в приложение / позволило мне сделать следующий запрос с существующим пользователем.

Вы также можете добавить эти строки, которые я нашел в "Lysender" в его посте - Rails 5 - Только API - Включить Cookies и Сессии, если вы не хотите удалять функцию только для API.

config.api_only = true
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore, key: '_coookie_name', expire_after: 30.days

Аналогично API REST GraphQL не хранит никакой информации между двумя последующими запросами. Вы должны передавать токен аутентификации, возвращенный при входе в мутацию, во все последующие запросы, где требуется текущая информация о пользователе.

Вы должны сделать что-то вроде ниже в graphql_controller.rb

class GraphqlController < ApplicationController
  def execute
    variables = ensure_hash(params[:variables])
    query = params[:query]
    operation_name = params[:operationName]
    context = {
      current_user: current_user
    }
    result = GraphqlTutorialSchema.execute(query, variables: variables, context: context, operation_name: operation_name)

    render json: result
  end

  private

  # set current user here
  def current_user
    # you can token here
    token = request.headers['Authorization']
    return nil unless token
    # find current user from this token
  end

  # Handle form data, JSON body, or a blank value
  def ensure_hash(ambiguous_param)
    # ...code
  end
end
Другие вопросы по тегам