diff --git a/CHANGELOG.md b/CHANGELOG.md
index f01dc3bd2..947394ad1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.0.5] - 2020-05-13
+
+### Security
+- Fix possible private status leaks in Mastodon Streaming API
+
+### Fixed
+- Crashes when trying to block a user if block federation is disabled
+- Not being able to start the instance without `erlang-eldap` installed
+- Users with bios over the limit getting rejected
+- Follower counters not being updated on incoming follow accepts
+
+### Upgrade notes
+
+1. Restart Pleroma
+
## [2.0.4] - 2020-05-10
### Security
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 2f0333da0..3e8f19e30 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -501,7 +501,15 @@ def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do
params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now())
- params = if remote?, do: truncate_fields_param(params), else: params
+ params =
+ if remote? do
+ params
+ |> truncate_fields_param()
+ |> truncate_if_exists(:name, name_limit)
+ |> truncate_if_exists(:bio, bio_limit)
+ else
+ params
+ end
struct
|> cast(
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 5f895406d..c4f83f9e1 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -604,7 +604,6 @@ def block(blocker, blocked, activity_id \\ nil, local \\ true) do
end
defp do_block(blocker, blocked, activity_id, local) do
- outgoing_blocks = Config.get([:activitypub, :outgoing_blocks])
unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
if unfollow_blocked do
@@ -612,8 +611,7 @@ defp do_block(blocker, blocked, activity_id, local) do
if follow_activity, do: unfollow(blocker, blocked, nil, local)
end
- with true <- outgoing_blocks,
- block_data <- make_block_data(blocker, blocked, activity_id),
+ with block_data <- make_block_data(blocker, blocked, activity_id),
{:ok, activity} <- insert(block_data, local),
:ok <- maybe_federate(activity) do
{:ok, activity}
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 831739c5f..3fc4762d6 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -544,6 +544,9 @@ def handle_incoming(
{:ok, follow_activity} <- Utils.update_follow_state_for_all(follow_activity, "accept"),
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
{:ok, _relationship} <- FollowingRelationship.update(follower, followed, :follow_accept) do
+ User.update_follower_count(followed)
+ User.update_following_count(follower)
+
ActivityPub.accept(%{
to: follow_activity.data["to"],
type: "Accept",
@@ -553,7 +556,8 @@ def handle_incoming(
activity_id: id
})
else
- _e -> :error
+ _e ->
+ :error
end
end
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 15dd2ed45..a49cfa35e 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Ecto.Changeset
alias Ecto.UUID
alias Pleroma.Activity
+ alias Pleroma.Config
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
@@ -169,8 +170,11 @@ def create_context(context) do
Enqueues an activity for federation if it's local
"""
@spec maybe_federate(any()) :: :ok
- def maybe_federate(%Activity{local: true} = activity) do
- if Pleroma.Config.get!([:instance, :federating]) do
+ def maybe_federate(%Activity{local: true, data: %{"type" => type}} = activity) do
+ outgoing_blocks = Config.get([:activitypub, :outgoing_blocks])
+
+ with true <- Config.get!([:instance, :federating]),
+ true <- type != "Block" || outgoing_blocks do
Pleroma.Web.Federator.publish(activity)
end
diff --git a/lib/pleroma/web/mastodon_api/websocket_handler.ex b/lib/pleroma/web/mastodon_api/websocket_handler.ex
index 5652a37c1..b1aebe014 100644
--- a/lib/pleroma/web/mastodon_api/websocket_handler.ex
+++ b/lib/pleroma/web/mastodon_api/websocket_handler.ex
@@ -12,29 +12,15 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
@behaviour :cowboy_websocket
- @streams [
- "public",
- "public:local",
- "public:media",
- "public:local:media",
- "user",
- "user:notification",
- "direct",
- "list",
- "hashtag"
- ]
- @anonymous_streams ["public", "public:local", "hashtag"]
-
# Handled by periodic keepalive in Pleroma.Web.Streamer.Ping.
@timeout :infinity
def init(%{qs: qs} = req, state) do
- with params <- :cow_qs.parse_qs(qs),
+ with params <- Enum.into(: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, sec_websocket]),
- topic when is_binary(topic) <- expand_topic(stream, params) do
+ access_token <- Map.get(params, "access_token"),
+ {:ok, user} <- authenticate_request(access_token, sec_websocket),
+ {:ok, topic} <- Streamer.get_topic(Map.get(params, "stream"), user, params) do
req =
if sec_websocket do
:cowboy_req.set_resp_header("sec-websocket-protocol", sec_websocket, req)
@@ -44,14 +30,14 @@ def init(%{qs: qs} = req, state) do
{: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)
+ {:error, :bad_topic} ->
+ Logger.debug("#{__MODULE__} bad topic #{inspect(req)}")
+ {:ok, req} = :cowboy_req.reply(404, req)
{:ok, req, state}
- error ->
- Logger.debug("#{__MODULE__} denied connection: #{inspect(error)} - #{inspect(req)}")
- {:ok, req} = :cowboy_req.reply(400, req)
+ {:error, :unauthorized} ->
+ Logger.debug("#{__MODULE__} authentication error: #{inspect(req)}")
+ {:ok, req} = :cowboy_req.reply(401, req)
{:ok, req, state}
end
end
@@ -93,50 +79,23 @@ def terminate(reason, _req, state) do
end
# Public streams without authentication.
- defp allow_request(stream, [nil, nil]) when stream in @anonymous_streams do
+ defp authenticate_request(nil, nil) do
{:ok, nil}
end
# Authenticated streams.
- 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
+ defp authenticate_request(access_token, sec_websocket) do
+ token = access_token || sec_websocket
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}
+ _ -> {:error, :unauthorized}
end
end
- # Not authenticated.
- defp allow_request(stream, _) when stream in @streams, do: {:error, 403}
-
- # No matching stream.
- defp allow_request(_, _), do: {:error, 404}
-
- defp expand_topic("hashtag", params) do
- case List.keyfind(params, "tag", 0) do
- {_, tag} -> "hashtag:#{tag}"
- _ -> nil
- end
- end
-
- defp expand_topic("list", params) do
- case List.keyfind(params, "list", 0) do
- {_, list} -> "list:#{list}"
- _ -> nil
- end
- end
-
- defp expand_topic(topic, _), do: topic
-
defp streamer_socket(state) do
%{transport_pid: self(), assigns: state}
end
diff --git a/lib/pleroma/web/streamer/state.ex b/lib/pleroma/web/streamer/state.ex
index 999550b88..4eb462a1a 100644
--- a/lib/pleroma/web/streamer/state.ex
+++ b/lib/pleroma/web/streamer/state.ex
@@ -36,30 +36,28 @@ def handle_call(:get_state, _from, state) do
end
def handle_call({:add, topic, socket}, _from, %{sockets: sockets} = state) do
- internal_topic = internal_topic(topic, socket)
stream_socket = StreamerSocket.from_socket(socket)
sockets_for_topic =
sockets
- |> Map.get(internal_topic, [])
+ |> Map.get(topic, [])
|> List.insert_at(0, stream_socket)
|> Enum.uniq()
- state = put_in(state, [:sockets, internal_topic], sockets_for_topic)
+ state = put_in(state, [:sockets, topic], sockets_for_topic)
Logger.debug("Got new conn for #{topic}")
{:reply, state, state}
end
def handle_call({:remove, topic, socket}, _from, %{sockets: sockets} = state) do
- internal_topic = internal_topic(topic, socket)
stream_socket = StreamerSocket.from_socket(socket)
sockets_for_topic =
sockets
- |> Map.get(internal_topic, [])
+ |> Map.get(topic, [])
|> List.delete(stream_socket)
- state = Kernel.put_in(state, [:sockets, internal_topic], sockets_for_topic)
+ state = Kernel.put_in(state, [:sockets, topic], sockets_for_topic)
{:reply, state, state}
end
@@ -70,13 +68,4 @@ defp do_remove_socket(:test, _, _) do
defp do_remove_socket(_env, topic, socket) do
GenServer.call(__MODULE__, {:remove, topic, socket})
end
-
- defp internal_topic(topic, socket)
- when topic in ~w[user user:notification direct] do
- "#{topic}:#{socket.assigns[:user].id}"
- end
-
- defp internal_topic(topic, _) do
- topic
- end
end
diff --git a/lib/pleroma/web/streamer/streamer.ex b/lib/pleroma/web/streamer/streamer.ex
index 814d5a729..b7294d084 100644
--- a/lib/pleroma/web/streamer/streamer.ex
+++ b/lib/pleroma/web/streamer/streamer.ex
@@ -3,12 +3,77 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Streamer do
+ alias Pleroma.User
alias Pleroma.Web.Streamer.State
alias Pleroma.Web.Streamer.Worker
@timeout 60_000
@mix_env Mix.env()
+ @public_streams ["public", "public:local", "public:media", "public:local:media"]
+ @user_streams ["user", "user:notification", "direct"]
+
+ @doc "Expands and authorizes a stream, and registers the process for streaming."
+ @spec get_topic_and_add_socket(stream :: String.t(), State.t(), Map.t() | nil) ::
+ {:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized}
+ def get_topic_and_add_socket(stream, socket, params \\ %{}) do
+ user =
+ case socket do
+ %{assigns: %{user: user}} -> user
+ _ -> nil
+ end
+
+ case get_topic(stream, user, params) do
+ {:ok, topic} ->
+ add_socket(topic, socket)
+ {:ok, topic}
+
+ error ->
+ error
+ end
+ end
+
+ @doc "Expand and authorizes a stream"
+ @spec get_topic(stream :: String.t(), User.t() | nil, Map.t()) ::
+ {:ok, topic :: String.t()} | {:error, :bad_topic}
+ def get_topic(stream, user, params \\ %{})
+
+ # Allow all public steams.
+ def get_topic(stream, _, _) when stream in @public_streams do
+ {:ok, stream}
+ end
+
+ # Allow all hashtags streams.
+ def get_topic("hashtag", _, %{"tag" => tag}) do
+ {:ok, "hashtag:" <> tag}
+ end
+
+ # Expand user streams.
+ def get_topic(stream, %User{} = user, _) when stream in @user_streams do
+ {:ok, stream <> ":" <> to_string(user.id)}
+ end
+
+ def get_topic(stream, _, _) when stream in @user_streams do
+ {:error, :unauthorized}
+ end
+
+ # List streams.
+ def get_topic("list", %User{} = user, %{"list" => id}) do
+ if Pleroma.List.get(id, user) do
+ {:ok, "list:" <> to_string(id)}
+ else
+ {:error, :bad_topic}
+ end
+ end
+
+ def get_topic("list", _, _) do
+ {:error, :unauthorized}
+ end
+
+ def get_topic(_, _, _) do
+ {:error, :bad_topic}
+ end
+
def add_socket(topic, socket) do
State.add_socket(topic, socket)
end
diff --git a/mix.exs b/mix.exs
index 9f9679f62..cc7a415ca 100644
--- a/mix.exs
+++ b/mix.exs
@@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
def project do
[
app: :pleroma,
- version: version("2.0.4"),
+ version: version("2.0.5"),
elixir: "~> 1.8",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
@@ -36,7 +36,7 @@ def project do
releases: [
pleroma: [
include_executables_for: [:unix],
- applications: [ex_syslogger: :load, syslog: :load],
+ applications: [ex_syslogger: :load, syslog: :load, eldap: :transient],
steps: [:assemble, ©_files/1, ©_nginx_config/1]
]
]
@@ -69,8 +69,7 @@ def application do
:comeonin,
:quack,
:fast_sanitize,
- :ssl,
- :eldap
+ :ssl
],
included_applications: [:ex_syslogger]
]
diff --git a/priv/static/index.html b/priv/static/index.html
index 2958cda1b..e6ba16633 100644
--- a/priv/static/index.html
+++ b/priv/static/index.html
@@ -1 +1 @@
-
Pleroma
\ No newline at end of file
+Pleroma
\ No newline at end of file
diff --git a/priv/static/static/font/fontello.1588431888583.woff b/priv/static/static/font/fontello.1588431888583.woff
deleted file mode 100644
index a50623bbb..000000000
Binary files a/priv/static/static/font/fontello.1588431888583.woff and /dev/null differ
diff --git a/priv/static/static/font/fontello.1588431888583.woff2 b/priv/static/static/font/fontello.1588431888583.woff2
deleted file mode 100644
index 150c93c1a..000000000
Binary files a/priv/static/static/font/fontello.1588431888583.woff2 and /dev/null differ
diff --git a/priv/static/static/font/fontello.1588431888583.eot b/priv/static/static/font/fontello.1589314090288.eot
similarity index 91%
rename from priv/static/static/font/fontello.1588431888583.eot
rename to priv/static/static/font/fontello.1589314090288.eot
index 1f2934b93..538cb5c0a 100644
Binary files a/priv/static/static/font/fontello.1588431888583.eot and b/priv/static/static/font/fontello.1589314090288.eot differ
diff --git a/priv/static/static/font/fontello.1588431888583.svg b/priv/static/static/font/fontello.1589314090288.svg
similarity index 98%
rename from priv/static/static/font/fontello.1588431888583.svg
rename to priv/static/static/font/fontello.1589314090288.svg
index 71f81f435..e63fb7529 100644
--- a/priv/static/static/font/fontello.1588431888583.svg
+++ b/priv/static/static/font/fontello.1589314090288.svg
@@ -114,6 +114,8 @@
+
+
diff --git a/priv/static/static/font/fontello.1588431888583.ttf b/priv/static/static/font/fontello.1589314090288.ttf
similarity index 91%
rename from priv/static/static/font/fontello.1588431888583.ttf
rename to priv/static/static/font/fontello.1589314090288.ttf
index b4fb51df0..8ea898a13 100644
Binary files a/priv/static/static/font/fontello.1588431888583.ttf and b/priv/static/static/font/fontello.1589314090288.ttf differ
diff --git a/priv/static/static/font/fontello.1589314090288.woff b/priv/static/static/font/fontello.1589314090288.woff
new file mode 100644
index 000000000..b4572ee03
Binary files /dev/null and b/priv/static/static/font/fontello.1589314090288.woff differ
diff --git a/priv/static/static/font/fontello.1589314090288.woff2 b/priv/static/static/font/fontello.1589314090288.woff2
new file mode 100644
index 000000000..38cb1616a
Binary files /dev/null and b/priv/static/static/font/fontello.1589314090288.woff2 differ
diff --git a/priv/static/static/fontello.1588431888583.css b/priv/static/static/fontello.1589314090288.css
similarity index 88%
rename from priv/static/static/fontello.1588431888583.css
rename to priv/static/static/fontello.1589314090288.css
index cb9ad1025..528b8cf1c 100644
Binary files a/priv/static/static/fontello.1588431888583.css and b/priv/static/static/fontello.1589314090288.css differ
diff --git a/priv/static/static/fontello.json b/priv/static/static/fontello.json
index 5963b68b4..7f0e7cdd5 100755
--- a/priv/static/static/fontello.json
+++ b/priv/static/static/fontello.json
@@ -346,6 +346,12 @@
"code": 59427,
"src": "fontawesome"
},
+ {
+ "uid": "4aad6bb50b02c18508aae9cbe14e784e",
+ "css": "share",
+ "code": 61920,
+ "src": "fontawesome"
+ },
{
"uid": "8b80d36d4ef43889db10bc1f0dc9a862",
"css": "user",
diff --git a/priv/static/static/js/2.93c984e8c993f92c77a1.js b/priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js
similarity index 79%
rename from priv/static/static/js/2.93c984e8c993f92c77a1.js
rename to priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js
index 4faa3d66f..f366644a2 100644
Binary files a/priv/static/static/js/2.93c984e8c993f92c77a1.js and b/priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js differ
diff --git a/priv/static/static/js/2.93c984e8c993f92c77a1.js.map b/priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js.map
similarity index 98%
rename from priv/static/static/js/2.93c984e8c993f92c77a1.js.map
rename to priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js.map
index 12e4d0c12..76a131851 100644
Binary files a/priv/static/static/js/2.93c984e8c993f92c77a1.js.map and b/priv/static/static/js/2.f9a5c4aba770b3f9f9e0.js.map differ
diff --git a/priv/static/static/js/app.57951e6e5e198d1a1266.js b/priv/static/static/js/app.57951e6e5e198d1a1266.js
deleted file mode 100644
index f68e594d9..000000000
Binary files a/priv/static/static/js/app.57951e6e5e198d1a1266.js and /dev/null differ
diff --git a/priv/static/static/js/app.57951e6e5e198d1a1266.js.map b/priv/static/static/js/app.57951e6e5e198d1a1266.js.map
deleted file mode 100644
index cb97ac977..000000000
Binary files a/priv/static/static/js/app.57951e6e5e198d1a1266.js.map and /dev/null differ
diff --git a/priv/static/static/js/app.82334f8362acc4bbcb6f.js b/priv/static/static/js/app.82334f8362acc4bbcb6f.js
new file mode 100644
index 000000000..82b6bf598
Binary files /dev/null and b/priv/static/static/js/app.82334f8362acc4bbcb6f.js differ
diff --git a/priv/static/static/js/app.82334f8362acc4bbcb6f.js.map b/priv/static/static/js/app.82334f8362acc4bbcb6f.js.map
new file mode 100644
index 000000000..2d3aaba6a
Binary files /dev/null and b/priv/static/static/js/app.82334f8362acc4bbcb6f.js.map differ
diff --git a/priv/static/static/js/vendors~app.c67e1a363ece7f1f7152.js b/priv/static/static/js/vendors~app.a516afd698489b59a809.js
similarity index 95%
rename from priv/static/static/js/vendors~app.c67e1a363ece7f1f7152.js
rename to priv/static/static/js/vendors~app.a516afd698489b59a809.js
index 2a98ce02b..434f6c8af 100644
Binary files a/priv/static/static/js/vendors~app.c67e1a363ece7f1f7152.js and b/priv/static/static/js/vendors~app.a516afd698489b59a809.js differ
diff --git a/priv/static/static/js/vendors~app.a516afd698489b59a809.js.map b/priv/static/static/js/vendors~app.a516afd698489b59a809.js.map
new file mode 100644
index 000000000..63b5974a7
Binary files /dev/null and b/priv/static/static/js/vendors~app.a516afd698489b59a809.js.map differ
diff --git a/priv/static/static/js/vendors~app.c67e1a363ece7f1f7152.js.map b/priv/static/static/js/vendors~app.c67e1a363ece7f1f7152.js.map
deleted file mode 100644
index c32cda3bd..000000000
Binary files a/priv/static/static/js/vendors~app.c67e1a363ece7f1f7152.js.map and /dev/null differ
diff --git a/priv/static/static/static-fe.css b/priv/static/static/static-fe.css
deleted file mode 100644
index 19c56387b..000000000
Binary files a/priv/static/static/static-fe.css and /dev/null differ
diff --git a/priv/static/sw-pleroma.js b/priv/static/sw-pleroma.js
index 362b6dba5..65983b9f7 100644
Binary files a/priv/static/sw-pleroma.js and b/priv/static/sw-pleroma.js differ
diff --git a/test/integration/mastodon_websocket_test.exs b/test/integration/mastodon_websocket_test.exs
index bd229c55f..39be5ad08 100644
--- a/test/integration/mastodon_websocket_test.exs
+++ b/test/integration/mastodon_websocket_test.exs
@@ -35,7 +35,7 @@ def start_socket(qs \\ nil, headers \\ []) do
test "refuses invalid requests" do
capture_log(fn ->
- assert {:error, {400, _}} = start_socket()
+ assert {:error, {404, _}} = start_socket()
assert {:error, {404, _}} = start_socket("?stream=ncjdk")
Process.sleep(30)
end)
@@ -43,8 +43,8 @@ test "refuses invalid requests" do
test "requires authentication and a valid token for protected streams" do
capture_log(fn ->
- assert {:error, {403, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
- assert {:error, {403, _}} = start_socket("?stream=user")
+ assert {:error, {401, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
+ assert {:error, {401, _}} = start_socket("?stream=user")
Process.sleep(30)
end)
end
@@ -103,7 +103,7 @@ test "accepts the 'user' stream", %{token: token} = _state do
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
assert capture_log(fn ->
- assert {:error, {403, "Forbidden"}} = start_socket("?stream=user")
+ assert {:error, {401, _}} = start_socket("?stream=user")
Process.sleep(30)
end) =~ ":badarg"
end
@@ -112,7 +112,7 @@ test "accepts the 'user:notification' stream", %{token: token} = _state do
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
assert capture_log(fn ->
- assert {:error, {403, "Forbidden"}} = start_socket("?stream=user:notification")
+ assert {:error, {401, _}} = start_socket("?stream=user:notification")
Process.sleep(30)
end) =~ ":badarg"
end
@@ -121,7 +121,7 @@ test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
assert capture_log(fn ->
- assert {:error, {403, "Forbidden"}} =
+ assert {:error, {401, _}} =
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
Process.sleep(30)
diff --git a/test/notification_test.exs b/test/notification_test.exs
index e12418db3..d04754a9d 100644
--- a/test/notification_test.exs
+++ b/test/notification_test.exs
@@ -164,12 +164,13 @@ test "it creates a notification for user and send to the 'user' and the 'user:no
user = insert(:user)
task = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
task_user_notification = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
- Streamer.add_socket("user", %{transport_pid: task.pid, assigns: %{user: user}})
- Streamer.add_socket(
- "user:notification",
- %{transport_pid: task_user_notification.pid, assigns: %{user: user}}
- )
+ Streamer.get_topic_and_add_socket("user", %{transport_pid: task.pid, assigns: %{user: user}})
+
+ Streamer.get_topic_and_add_socket("user:notification", %{
+ transport_pid: task_user_notification.pid,
+ assigns: %{user: user}
+ })
activity = insert(:note_activity)
diff --git a/test/user_test.exs b/test/user_test.exs
index e63c44360..368bdae12 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -570,7 +570,10 @@ test "returns nil for nonexistant local user" do
assert fetched_user == "not found nonexistant"
end
+ clear_config([:instance, :user_bio_length])
+
test "updates an existing user, if stale" do
+ Pleroma.Config.put([:instance, :user_bio_length], 1)
a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
orig_user =
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index c418232da..153adc703 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -310,7 +310,11 @@ test "cached purged after activity deletion", %{conn: conn} do
end
describe "/inbox" do
+ clear_config([:instance, :user_bio_length])
+
test "it inserts an incoming activity into the database", %{conn: conn} do
+ Pleroma.Config.put([:instance, :user_bio_length], 1)
+
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
conn =
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index 433859dab..e6c4299ba 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -1351,15 +1351,44 @@ test "reverts block activity on error" do
assert Repo.aggregate(Object, :count, :id) == 0
end
+ clear_config([:instance, :federating])
+
test "creates a block activity" do
+ Config.put([:instance, :federating], true)
blocker = insert(:user)
blocked = insert(:user)
- {:ok, activity} = ActivityPub.block(blocker, blocked)
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ {:ok, activity} = ActivityPub.block(blocker, blocked)
- assert activity.data["type"] == "Block"
- assert activity.data["actor"] == blocker.ap_id
- assert activity.data["object"] == blocked.ap_id
+ assert activity.data["type"] == "Block"
+ assert activity.data["actor"] == blocker.ap_id
+ assert activity.data["object"] == blocked.ap_id
+
+ assert called(Pleroma.Web.Federator.publish(activity))
+ end
+ end
+
+ clear_config([:instance, :federating])
+ clear_config([:activitypub, :outgoing_blocks])
+
+ test "works with outgoing blocks disabled, but doesn't federate" do
+ Config.put([:instance, :federating], true)
+ Config.put([:activitypub, :outgoing_blocks], false)
+ blocker = insert(:user)
+ blocked = insert(:user)
+
+ with_mock Pleroma.Web.Federator,
+ publish: fn _ -> nil end do
+ {:ok, activity} = ActivityPub.block(blocker, blocked)
+
+ assert activity.data["type"] == "Block"
+ assert activity.data["actor"] == blocker.ap_id
+ assert activity.data["object"] == blocked.ap_id
+
+ refute called(Pleroma.Web.Federator.publish(:_))
+ end
end
test "reverts unblock activity on error" do
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 2a3fd92b4..601e5f966 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -1120,6 +1120,12 @@ test "it works for incoming accepts which are referenced by IRI only" do
follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == true
+
+ follower = User.get_by_id(follower.id)
+ assert follower.following_count == 1
+
+ followed = User.get_by_id(followed.id)
+ assert followed.follower_count == 1
end
test "it fails for incoming accepts which cannot be correlated" do
diff --git a/test/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
index 8d0e70db8..f120bd0cd 100644
--- a/test/web/mastodon_api/controllers/suggestion_controller_test.exs
+++ b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
@@ -5,8 +5,6 @@
defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
use Pleroma.Web.ConnCase
- alias Pleroma.Config
-
setup do: oauth_access(["read"])
test "returns empty result", %{conn: conn} do
diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs
index 720f8fa44..cbd5ec462 100644
--- a/test/web/streamer/streamer_test.exs
+++ b/test/web/streamer/streamer_test.exs
@@ -17,11 +17,81 @@ defmodule Pleroma.Web.StreamerTest do
@moduletag needs_streamer: true, capture_log: true
- @streamer_timeout 150
+ @streamer_timeout 300
@streamer_start_wait 10
clear_config([:instance, :skip_thread_containment])
+ describe "get_topic without an user" do
+ test "allows public" do
+ assert {:ok, "public"} = Streamer.get_topic("public", nil)
+ assert {:ok, "public:local"} = Streamer.get_topic("public:local", nil)
+ assert {:ok, "public:media"} = Streamer.get_topic("public:media", nil)
+ assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", nil)
+ end
+
+ test "allows hashtag streams" do
+ assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", nil, %{"tag" => "cofe"})
+ end
+
+ test "disallows user streams" do
+ assert {:error, _} = Streamer.get_topic("user", nil)
+ assert {:error, _} = Streamer.get_topic("user:notification", nil)
+ assert {:error, _} = Streamer.get_topic("direct", nil)
+ end
+
+ test "disallows list streams" do
+ assert {:error, _} = Streamer.get_topic("list", nil, %{"list" => 42})
+ end
+ end
+
+ describe "get_topic with an user" do
+ setup do
+ user = insert(:user)
+ {:ok, %{user: user}}
+ end
+
+ test "allows public streams", %{user: user} do
+ assert {:ok, "public"} = Streamer.get_topic("public", user)
+ assert {:ok, "public:local"} = Streamer.get_topic("public:local", user)
+ assert {:ok, "public:media"} = Streamer.get_topic("public:media", user)
+ assert {:ok, "public:local:media"} = Streamer.get_topic("public:local:media", user)
+ end
+
+ test "allows user streams", %{user: user} do
+ expected_user_topic = "user:#{user.id}"
+ expected_notif_topic = "user:notification:#{user.id}"
+ expected_direct_topic = "direct:#{user.id}"
+ assert {:ok, ^expected_user_topic} = Streamer.get_topic("user", user)
+ assert {:ok, ^expected_notif_topic} = Streamer.get_topic("user:notification", user)
+ assert {:ok, ^expected_direct_topic} = Streamer.get_topic("direct", user)
+ end
+
+ test "allows hashtag streams", %{user: user} do
+ assert {:ok, "hashtag:cofe"} = Streamer.get_topic("hashtag", user, %{"tag" => "cofe"})
+ end
+
+ test "disallows registering to an user stream", %{user: user} do
+ another_user = insert(:user)
+ assert {:error, _} = Streamer.get_topic("user:#{another_user.id}", user)
+ assert {:error, _} = Streamer.get_topic("user:notification:#{another_user.id}", user)
+ assert {:error, _} = Streamer.get_topic("direct:#{another_user.id}", user)
+ end
+
+ test "allows list stream that are owned by the user", %{user: user} do
+ {:ok, list} = List.create("Test", user)
+ assert {:error, _} = Streamer.get_topic("list:#{list.id}", user)
+ assert {:ok, _} = Streamer.get_topic("list", user, %{"list" => list.id})
+ end
+
+ test "disallows list stream that are not owned by the user", %{user: user} do
+ another_user = insert(:user)
+ {:ok, list} = List.create("Test", another_user)
+ assert {:error, _} = Streamer.get_topic("list:#{list.id}", user)
+ assert {:error, _} = Streamer.get_topic("list", user, %{"list" => list.id})
+ end
+ end
+
describe "user streams" do
setup do
user = insert(:user)
@@ -35,7 +105,7 @@ test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do
assert_receive {:text, _}, @streamer_timeout
end)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"user",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -50,7 +120,7 @@ test "it sends notify to in the 'user:notification' stream", %{user: user, notif
assert_receive {:text, _}, @streamer_timeout
end)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"user:notification",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -70,7 +140,7 @@ test "it doesn't send notify to the 'user:notification' stream when a user is bl
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"user:notification",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -90,7 +160,7 @@ test "it doesn't send notify to the 'user:notification' stream when a thread is
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"user:notification",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -110,7 +180,7 @@ test "it doesn't send notify to the 'user:notification' stream' when a domain is
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"user:notification",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -127,7 +197,7 @@ test "it sends follow activities to the 'user:notification' stream", %{
Process.sleep(@streamer_start_wait)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"user:notification",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -415,14 +485,10 @@ test "it sends wanted private posts to list" do
assert_receive {:text, _}, 1_000
end)
- fake_socket = %StreamerSocket{
- transport_pid: task.pid,
- user: user_a
- }
-
- Streamer.add_socket(
- "list:#{list.id}",
- fake_socket
+ Streamer.get_topic_and_add_socket(
+ "list",
+ %{transport_pid: task.pid, assigns: %{user: user_a}},
+ %{"list" => list.id}
)
Worker.handle_call({:stream, "list", activity}, self(), %{})
@@ -497,7 +563,7 @@ test "it doesn't send posts from muted threads" do
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"user",
%{transport_pid: task.pid, assigns: %{user: user2}}
)
@@ -527,7 +593,7 @@ test "it sends conversation update to the 'direct' stream", %{} do
assert last_status["pleroma"]["direct_conversation_id"] == participation.id
end)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"direct",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -561,7 +627,7 @@ test "it doesn't send conversation update to the 'direct' stream when the last m
Process.sleep(@streamer_start_wait)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"direct",
%{transport_pid: task.pid, assigns: %{user: user}}
)
@@ -604,7 +670,7 @@ test "it sends conversation update to the 'direct' stream when a message is dele
Process.sleep(@streamer_start_wait)
- Streamer.add_socket(
+ Streamer.get_topic_and_add_socket(
"direct",
%{transport_pid: task.pid, assigns: %{user: user}}
)