X-Git-Url: https://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fmastodon_api%2Fwebsocket_handler.ex;h=dbd3542eadcc57929addcbbad7f682fa95d34d2d;hb=c623b4324deaf236334a0f77a81435b5bffadf3c;hp=c0254c8e6471aa239b641ec0cb0f3863cf291764;hpb=1b1e92866742e75de84201b079ffee48c769886e;p=akkoma diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex index c0254c8e6..dbd3542ea 100644 --- a/lib/pleroma/web/mastodon_api/websocket_handler.ex +++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex @@ -5,10 +5,11 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do require Logger + alias Pleroma.Repo + alias Pleroma.User alias Pleroma.Web.OAuth.Token - alias Pleroma.{User, Repo} - @behaviour :cowboy_websocket_handler + @behaviour :cowboy_websocket @streams [ "public", @@ -16,6 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do "public:media", "public:local:media", "user", + "user:notification", "direct", "list", "hashtag" @@ -25,37 +27,38 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do # Handled by periodic keepalive in Pleroma.Web.Streamer. @timeout :infinity - def init(_type, _req, _opts) do - {:upgrade, :protocol, :cowboy_websocket} - end - - def websocket_init(_type, req, _opts) do - with {qs, req} <- :cowboy_req.qs(req), - params <- :cow_qs.parse_qs(qs), + def init(%{qs: qs} = req, state) do + with params <- :cow_qs.parse_qs(qs), + sec_websocket <- :cowboy_req.header("sec-websocket-protocol", req, nil), access_token <- List.keyfind(params, "access_token", 0), {_, stream} <- List.keyfind(params, "stream", 0), - {:ok, user} <- allow_request(stream, access_token), + {:ok, user} <- allow_request(stream, [access_token, sec_websocket]), topic when is_binary(topic) <- expand_topic(stream, params) do - send(self(), :subscribe) - {:ok, req, %{user: user, topic: topic}, @timeout} + {:cowboy_websocket, req, %{user: user, topic: topic}, %{idle_timeout: @timeout}} else {:error, code} -> Logger.debug("#{__MODULE__} denied connection: #{inspect(code)} - #{inspect(req)}") {:ok, req} = :cowboy_req.reply(code, req) - {:shutdown, req} + {:ok, req, state} error -> Logger.debug("#{__MODULE__} denied connection: #{inspect(error)} - #{inspect(req)}") - {:shutdown, req} + {:ok, req} = :cowboy_req.reply(400, req) + {:ok, req, state} end end + def websocket_init(state) do + send(self(), :subscribe) + {:ok, state} + end + # We never receive messages. - def websocket_handle(_frame, req, state) do - {:ok, req, state} + def websocket_handle(_frame, state) do + {:ok, state} end - def websocket_info(:subscribe, req, state) do + def websocket_info(:subscribe, state) do Logger.debug( "#{__MODULE__} accepted websocket connection for user #{ (state.user || %{id: "anonymous"}).id @@ -63,14 +66,14 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do ) Pleroma.Web.Streamer.add_socket(state.topic, streamer_socket(state)) - {:ok, req, state} + {:ok, state} end - def websocket_info({:text, message}, req, state) do - {:reply, {:text, message}, req, state} + def websocket_info({:text, message}, state) do + {:reply, {:text, message}, state} end - def websocket_terminate(reason, _req, state) do + def terminate(reason, _req, state) do Logger.debug( "#{__MODULE__} terminating websocket connection for user #{ (state.user || %{id: "anonymous"}).id @@ -82,14 +85,22 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do end # Public streams without authentication. - defp allow_request(stream, nil) when stream in @anonymous_streams do + defp allow_request(stream, [nil, nil]) when stream in @anonymous_streams do {:ok, nil} end # Authenticated streams. - defp allow_request(stream, {"access_token", access_token}) when stream in @streams do - with %Token{user_id: user_id} <- Repo.get_by(Token, token: access_token), - user = %User{} <- Repo.get(User, user_id) do + defp allow_request(stream, [access_token, sec_websocket]) when stream in @streams do + token = + with {"access_token", token} <- access_token do + token + else + _ -> sec_websocket + end + + with true <- is_bitstring(token), + %Token{user_id: user_id} <- Repo.get_by(Token, token: token), + user = %User{} <- User.get_cached_by_id(user_id) do {:ok, user} else _ -> {:error, 403}