Передача информации из распознавателя в промежуточное ПО после разрешения - PullRequest
0 голосов
/ 20 июня 2019

Я пытаюсь передать информацию из функции распознавателя на промежуточное программное обеспечение, чтобы в ответе я мог установить cookie.

Сценарий использования: я хочу создать ссылку авторизации Oauth2, которая позволяет клиенту начать поток Oauth2 с третьей стороной. Я хочу создать объект "состояния", который я могу указать в ответе как файл cookie.

Я пытался позвонить

   %{resolution | context: state}

внутри распознавателя, но, к сожалению, это, похоже, не передает это состояние.

Вот упрощенный пример моей функции распознавателя

def get_oauth_link(_parent, _args, resolution) do
    state = random_string(10)

    part_one = "https://github.com/login/oauth/authorize"
    part_two = "?client_id=XXX"
    part_three = "&redirect_uri=http://localhost:3000/login/callback"
    part_four = "&state=" <> state
    part_five = "&scope=user:email"

    url = part_one <> part_two <> part_three <> part_four <> part_five

    # try to add the state to the resolution to 
    %{resolution | context: state}

    {:ok, url}
  end

А потом в моей схеме

    @desc "Get oauth link"
    field :oauthlink non_null(:string) do
      resolve(&Resolvers.OauthResolver.get_oauth_link/3)

      # middleware after resolution to set a cookie with the provided state
      middleware fn resolution, _ ->
        # Here i want to extract the state generated in
        # the resolver and add to the context 
        IO.inspect(resolution, label: "Inside resolution")
      end
    end

Я ожидаю, что смогу установить cookie в методе "absinthe_before_send", как описано здесь: https://hexdocs.pm/absinthe_plug/Absinthe.Plug.html#module-before-send

Каков наилучший способ сделать это? Приведенный выше подход кажется мне интуитивно понятным, но состояние не доступно в промежуточном программном обеспечении после разрешения.

Ответы [ 2 ]

2 голосов
/ 20 июня 2019

Нельзя изменить разрешение в функции распознавателя.

Однако вы можете изменить разрешение в промежуточном программном обеспечении. Для этого и есть промежуточное ПО. Разрешение промежуточного программного обеспечения после распознавателя будет иметь поле value, которое содержит результат функции распознавателя (без атома :ok или :error).

Что вы можете сделать, так это вернуть state и url из функции распознавателя, затем в промежуточном программном обеспечении для разрешения постов извлекать состояние из поля разрешения value и сбросить разрешение value в URL. Как это:

   def get_oauth_link(_parent, _args, resolution) do
    state = random_string(10)

    part_one = "https://github.com/login/oauth/authorize"
    part_two = "?client_id=XXX"
    part_three = "&redirect_uri=http://localhost:3000/login/callback"
    part_four = "&state=" <> state
    part_five = "&scope=user:email"

    url = part_one <> part_two <> part_three <> part_four <> part_five

    {:ok, %{url: url, state: state}} # return state and url
  end


   field :oauthlink, non_null(:string) do
      resolve(&Resolvers.OauthResolver.get_oauth_link/3)
      middleware fn %{value: %{state: state, url: url}=resolution, _ ->        
        resolution
        |> Map.put(:context, state) # set context using state
        |> Map.put(:value, url) # reset value to url
      end
   end
1 голос
/ 20 июня 2019

Я не думаю, что вы можете изменить разрешение, как вы делаете.

Если честно, я не могу понять, почему вы не можете использовать только промежуточное программное обеспечение для настройки или нет.Почему вы не можете сгенерировать только это на промежуточном программном обеспечении?

Однако я вижу способ сделать это.

@desc "Return api version"
field :version, :version_payload do
  resolve(fn _, _ -> {:ok, %{version: OnCallAPI.version(), other: "Marcos"}} end)

  middleware fn resolution, _ ->
    # Here i want to extract the state generated in
    # the resolver and add to the context
    IO.inspect(resolution, label: "Inside resolution")
  end
end

Если вы проверите консоль, вы увидите other на values.Как это:

...
private: %{},
root_value: %{},
schema: OnCallAPIWeb.Schema,
source: %{},
state: :resolved,
value: %{other: "Marcos", version: "0.30.0-rc"}
...