Каналы Феникс

Реализация сокетов в варианте с Феникс 1.4 и Гардиан 1.0

defmodule ImconWeb.UserSocket do
  use Phoenix.Socket

  alias ImconWeb.{BranchChannel, TreeChannel, UserChannel, MessageChannel, EventChannel}
  
  # Channels
  channel "tree:*", TreeChannel
  channel "user:*", UserChannel
  channel "channel:*", MessageChannel
  channel "event:*", EventChannel

  def connect(%{"token" => token}, socket) do
    case Guardian.Phoenix.Socket.authenticate(socket, ImconWeb.Guardian, token) do
      {:ok, user} ->
        {:ok, assign(socket, :current_user, user)}

      {:error, _reason} ->
        :error
    end
  end

  def connect(_params, _socket), do: :error

  def id(socket), do: "user_socket:#{socket.assigns.current_user.id}"
end

Канал пользователя

defmodule ImconWeb.UserChannel do
  use ImconWeb, :channel

  def join("user:" <> user_id, _params, socket) do
  
    current_user = socket.assigns.current_user
IO.inspect(current_user)
    if String.to_integer(user_id) == current_user.id do
      {:ok, socket}
    else
      {:error, %{reason: "Invalid user"}}
    end
  end
end

Реализация сокетов в варианте с Феникс 1.3 и Гардиан 0.13

defmodule ImconWeb.UserSocket do
  use Phoenix.Socket

  alias ImconWeb.{GuardianSerializer, BoardChannel, UserChannel}

  # Channels
  channel "board:*", BoardChannel
  channel "user:*", UserChannel

  # Transports
  transport :websocket, Phoenix.Transports.WebSocket
  transport :longpoll, Phoenix.Transports.LongPoll

  def connect(%{"token" => token}, socket) do
    case Guardian.decode_and_verify(token) do
      {:ok, claims} ->
        case GuardianSerializer.from_token(claims["sub"]) do
          {:ok, user} ->
            {:ok, assign(socket, :current_user, user)}
          {:error, _reason} ->
            :error
        end
      {:error, _reason} ->
        :error
    end
  end

  def connect(_params, _socket), do: :error

  def id(socket), do: "user_socket:#{socket.assigns.current_user.id}"
end

Ошибка при входе на сайт, в ней видно, что отдаёт функция Guardian.Phoenix.Socket.authenticate , судя по примеру взятому с другими версиями библиотек, нам нужно получить [«sub»], то есть элемент массива по данному ключу. Что нужно добавить, чтоб функция {:ok, assign(socket, :current_user, auth)} получила данное значение?

[info] JOIN "user:1" to ImconWeb.UserChannel
  Transport:  :websocket
  Serializer: Phoenix.Socket.V2.JSONSerializer
  Parameters: %{}
%Phoenix.Socket{
  assigns: %{
    guardian_default_claims: %{
      "aud" => "imcon",
      "exp" => 1552558062,
      "iat" => 1550138862,
      "iss" => "imcon",
      "jti" => "8ffa3416-8502-430d-be22-62b882575a31",
      "nbf" => 1550138861,
      "sub" => "1",
      "typ" => "access"
    },
    guardian_default_resource: %{id: "1"},
    guardian_default_token: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpbWNvbiIsImV4cCI6MTU1MjU1ODA2MiwiaWF0IjoxNTUwMTM4ODYyLCJpc3MiOiJpbWNvbiIsImp0aSI6IjhmZmEzNDE2LTg1MDItNDMwZC1iZTIyLTYyYjg4MjU3NWEzMSIsIm5iZiI6MTU1MDEzODg2MSwic3ViIjoiMSIsInR5cCI6ImFjY2VzcyJ9.If_Y0yEe443yVqoOKPsY9a7Dwde3WEr2xnVVWsxeOl823f-AlKnFIL-n18VMrwQqlviiDDSNCrCz4owrMWW1rA"
  },
  channel: nil,
  channel_pid: nil,
  endpoint: ImconWeb.Endpoint,
  handler: ImconWeb.UserSocket,
  id: nil,
  join_ref: nil,
  joined: false,
  private: %{},
  pubsub_server: ImconWeb.PubSub,
  ref: nil,
  serializer: Phoenix.Socket.V2.JSONSerializer,
  topic: nil,
  transport: :websocket,
  transport_pid: nil
}
[info] Replied user:1 :error

Сделал такой вариант, как рекомендуется в мануале:

  def connect(%{"token" => token}, socket) do
    case Guardian.Phoenix.Socket.authenticate(socket, ImconWeb.Guardian, token) do
      {:ok, authed_socket} ->
        {:ok, authed_socket}

      {:error, _reason} ->
        :error
    end
  end

  def connect(_params, _socket), do: :error

  def id(socket), do: "user_socket:#{Guardian.Phoenix.Socket.current_resource(socket)}"
end
  def join("user:" <> user_id, _params, socket) do
  
    current_user = Guardian.Phoenix.Socket.current_resource(socket)

    if String.to_integer(user_id) == current_user.id do
      {:ok, socket}
    else
      {:error, 
%{reason: "Invalid user"}}
    end
  end
[error] #PID<0.651.0> running ImconWeb.Endpoint (connection #PID<0.650.0>, stream id 1) terminated
Server: caix.ru:4001 (http)
Request: GET /socket/websocket?token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJpbWNvbiIsImV4cCI6MTU1MjU3MzQ4OCwiaWF0IjoxNTUwMTU0Mjg4LCJpc3MiOiJpbWNvbiIsImp0aSI6IjQwOWE0MjhkLWU4NGEtNDJkNS05MmFjLTEzNTQ4MDEyYmYxYSIsIm5iZiI6MTU1MDE1NDI4Nywic3ViIjoiMSIsInR5cCI6ImFjY2VzcyJ9.1fAUEvMRRdmAcxSPQ8t1UK5tsHIczGhjwImvtBkCSBBzipPv_QceqfDQ7fwGKY1DpBm9uVd3x2lHsl1uFn1AXg&amp;vsn=2.0.0
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol String.Chars not implemented for %{id: "1"}. This protocol is implemented for: Atom, BitString, Date, DateTime, Decimal, Float, Hound.Element, Integer, List, NaiveDateTime, Postgrex.Copy, Postgrex.Query, Time, URI, Version, Version.Requirement
        (elixir) /home/build/elixir/lib/elixir/lib/string/chars.ex:3: String.Chars.impl_for!/1
        (elixir) /home/build/elixir/lib/elixir/lib/string/chars.ex:22: String.Chars.to_string/1
        (imcon) lib/imcon_web/channels/user_socket.ex:25: ImconWeb.UserSocket.id/1
        (phoenix) lib/phoenix/socket.ex:595: Phoenix.Socket.user_connect/6
        (phoenix) lib/phoenix/socket.ex:474: anonymous fn/8 in Phoenix.Socket.__connect__/3
        (imcon) lib/imcon_web/endpoint.ex:1: ImconWeb.Endpoint.instrument/4
        (phoenix) lib/phoenix/transports/websocket.ex:30: Phoenix.Transports.WebSocket.connect/4
        (phoenix) lib/phoenix/endpoint/cowboy2_handler.ex:20: Phoenix.Endpoint.Cowboy2Handler.init/2
        (cowboy) /opt/imcon_x/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
        (cowboy) /opt/imcon_x/deps/cowboy/src/cowboy_stream_h.erl:296: :cowboy_stream_h.execute/3
        (cowboy) /opt/imcon_x/deps/cowboy/src/cowboy_stream_h.erl:274: :cowboy_stream_h.request_process/3
        (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

Ошибка такая вот.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.