defmodule BirdyChatWeb.ServerChannel do use BirdyChatWeb, :channel @impl true def join("server:" <> server_id, payload, socket) do if authorised?(payload, server_id) do {:ok, socket} else {:error, %{reason: "unauthorised"}} end end @impl true def handle_in("new_message", {:binary, message}, socket) do result = :erlang.binary_to_term(message, [:safe]) # TODO: Add validation that this is the right server. case BirdyChat.Message.validate(result) do {:ok, changeset} -> case BirdyChat.MessageWriter.write(changeset.changes) do :ok -> {:reply, {:ok, {:binary, message}}, socket} end end end # Simple token-based authentication. Servers should use the same Phoenix secret key so they will # have the basis for generating tokens. defp authorised?(%{"token" => token}, server_id) do case Phoenix.Token.verify(BirdyChatWeb.Endpoint, "serverAuth", token, max_age: 86400) do {:ok, id} -> id == server_id {:error, :invalid} -> false end end end