Disconnect streaming sessions when token is revoked
This commit is contained in:
parent
b22843a982
commit
c62a4f1c17
4 changed files with 81 additions and 6 deletions
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
req
|
req
|
||||||
end
|
end
|
||||||
|
|
||||||
{:cowboy_websocket, req, %{user: user, topic: topic, count: 0, timer: nil},
|
{:cowboy_websocket, req, %{user: user, topic: topic, oauth_token: oauth_token, count: 0, timer: nil},
|
||||||
%{idle_timeout: @timeout}}
|
%{idle_timeout: @timeout}}
|
||||||
else
|
else
|
||||||
{:error, :bad_topic} ->
|
{:error, :bad_topic} ->
|
||||||
|
@ -54,7 +54,7 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
}, topic #{state.topic}"
|
}, topic #{state.topic}"
|
||||||
)
|
)
|
||||||
|
|
||||||
Streamer.add_socket(state.topic, state.user)
|
Streamer.add_socket(state.topic, state.oauth_token)
|
||||||
{:ok, %{state | timer: timer()}}
|
{:ok, %{state | timer: timer()}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -100,6 +100,10 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
{:reply, :ping, %{state | timer: nil, count: 0}, :hibernate}
|
{:reply, :ping, %{state | timer: nil, count: 0}, :hibernate}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def websocket_info(:close, state) do
|
||||||
|
{:stop, state}
|
||||||
|
end
|
||||||
|
|
||||||
# State can be `[]` only in case we terminate before switching to websocket,
|
# State can be `[]` only in case we terminate before switching to websocket,
|
||||||
# we already log errors for these cases in `init/1`, so just do nothing here
|
# we already log errors for these cases in `init/1`, so just do nothing here
|
||||||
def terminate(_reason, _req, []), do: :ok
|
def terminate(_reason, _req, []), do: :ok
|
||||||
|
|
|
@ -22,5 +22,6 @@ defmodule Pleroma.Web.OAuth.Token.Strategy.Revoke do
|
||||||
@spec revoke(Token.t()) :: {:ok, Token.t()} | {:error, Ecto.Changeset.t()}
|
@spec revoke(Token.t()) :: {:ok, Token.t()} | {:error, Ecto.Changeset.t()}
|
||||||
def revoke(%Token{} = token) do
|
def revoke(%Token{} = token) do
|
||||||
Repo.delete(token)
|
Repo.delete(token)
|
||||||
|
Pleroma.Web.Streamer.close_streams_by_oauth_token(token)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,7 +37,7 @@ defmodule Pleroma.Web.Streamer do
|
||||||
{:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized}
|
{:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized}
|
||||||
def get_topic_and_add_socket(stream, user, oauth_token, params \\ %{}) do
|
def get_topic_and_add_socket(stream, user, oauth_token, params \\ %{}) do
|
||||||
with {:ok, topic} <- get_topic(stream, user, oauth_token, params) do
|
with {:ok, topic} <- get_topic(stream, user, oauth_token, params) do
|
||||||
add_socket(topic, user)
|
add_socket(topic, oauth_token)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -120,10 +120,10 @@ defmodule Pleroma.Web.Streamer do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "Registers the process for streaming. Use `get_topic/3` to get the full authorized topic."
|
@doc "Registers the process for streaming. Use `get_topic/3` to get the full authorized topic."
|
||||||
def add_socket(topic, user) do
|
def add_socket(topic, oauth_token) do
|
||||||
if should_env_send?() do
|
if should_env_send?() do
|
||||||
auth? = if user, do: true
|
oauth_token_id = if oauth_token, do: oauth_token.id, else: false
|
||||||
Registry.register(@registry, topic, auth?)
|
Registry.register(@registry, topic, oauth_token_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
{:ok, topic}
|
{:ok, topic}
|
||||||
|
@ -320,6 +320,22 @@ defmodule Pleroma.Web.Streamer do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def close_streams_by_oauth_token(oauth_token) do
|
||||||
|
if should_env_send?() do
|
||||||
|
Registry.select(
|
||||||
|
@registry,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
{:"$1", :"$2", :"$3"},
|
||||||
|
[{:==, :"$3", oauth_token.id}],
|
||||||
|
[:"$2"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|> Enum.each(fn pid -> send(pid, :close) end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# In test environement, only return true if the registry is started.
|
# In test environement, only return true if the registry is started.
|
||||||
# In benchmark environment, returns false.
|
# In benchmark environment, returns false.
|
||||||
# In any other environment, always returns true.
|
# In any other environment, always returns true.
|
||||||
|
|
|
@ -813,4 +813,58 @@ defmodule Pleroma.Web.StreamerTest do
|
||||||
assert last_status["id"] == to_string(create_activity.id)
|
assert last_status["id"] == to_string(create_activity.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "stop streaming if token got revoked" do
|
||||||
|
test "do not revoke other tokens" do
|
||||||
|
%{user: user, token: token} = oauth_access(["read"])
|
||||||
|
%{token: token2} = oauth_access(["read"], user: user)
|
||||||
|
%{user: user2, token: user2_token} = oauth_access(["read"])
|
||||||
|
|
||||||
|
post_user = insert(:user)
|
||||||
|
CommonAPI.follow(user, post_user)
|
||||||
|
CommonAPI.follow(user2, post_user)
|
||||||
|
|
||||||
|
Streamer.get_topic_and_add_socket("user", user, token)
|
||||||
|
Streamer.get_topic_and_add_socket("user", user, token2)
|
||||||
|
Streamer.get_topic_and_add_socket("user", user2, user2_token)
|
||||||
|
|
||||||
|
{:ok, _} =
|
||||||
|
CommonAPI.post(post_user, %{
|
||||||
|
status: "hi"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert_receive {:render_with_user, _, "update.json", _}
|
||||||
|
assert_receive {:render_with_user, _, "update.json", _}
|
||||||
|
assert_receive {:render_with_user, _, "update.json", _}
|
||||||
|
|
||||||
|
Pleroma.Web.OAuth.Token.Strategy.Revoke.revoke(token)
|
||||||
|
|
||||||
|
assert_receive :close
|
||||||
|
refute_receive :close
|
||||||
|
end
|
||||||
|
|
||||||
|
test "revoke all streams for this token" do
|
||||||
|
%{user: user, token: token} = oauth_access(["read"])
|
||||||
|
|
||||||
|
post_user = insert(:user)
|
||||||
|
CommonAPI.follow(user, post_user)
|
||||||
|
|
||||||
|
Streamer.get_topic_and_add_socket("user", user, token)
|
||||||
|
Streamer.get_topic_and_add_socket("user", user, token)
|
||||||
|
|
||||||
|
{:ok, _} =
|
||||||
|
CommonAPI.post(post_user, %{
|
||||||
|
status: "hi"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert_receive {:render_with_user, _, "update.json", _}
|
||||||
|
assert_receive {:render_with_user, _, "update.json", _}
|
||||||
|
|
||||||
|
Pleroma.Web.OAuth.Token.Strategy.Revoke.revoke(token)
|
||||||
|
|
||||||
|
assert_receive :close
|
||||||
|
assert_receive :close
|
||||||
|
refute_receive :close
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue