diff --git a/CHANGELOG.md b/CHANGELOG.md
index bcbe3ba56..3adc79929 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Removed
+## 2.4.5 - 2022-08-27
+
+## Fixed
+- Image `class` attributes not being scrubbed, allowing to exploit frontend special classes [!3792](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3792)
+- Delete report notifs when demoting from superuser [!3642](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3642)
+- Validate `mediaType` only by it's format rather than using a list [!3597](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3597)
+- Pagination: Make mutes and blocks lists behave the same as other lists [!3693](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3693)
+- Compatibility with Elixir 1.14 [!3740](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3740)
+- Frontend installer: FediFE build URL [!3736](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3736)
+- Streaming: Don't stream ChatMessage into the home timeline [!3738](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3738)
+- Streaming: Stream local-only posts in the local timeline [!3738](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3738)
+- Signatures: Fix `keyId` lookup for GoToSocial [!3725](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3725)
+- Validator: Fix `replies` handling for GoToSocial [!3725](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3725)
+
## 2.4.4 - 2022-08-19
### Security
diff --git a/config/config.exs b/config/config.exs
index b50c910b1..2aab2f3d3 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -734,7 +734,7 @@ config :pleroma, :frontends,
"name" => "fedi-fe",
"git" => "https://git.pleroma.social/pleroma/fedi-fe",
"build_url" =>
- "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build_release",
"ref" => "master",
"custom-http-headers" => [
{"service-worker-allowed", "/"}
diff --git a/lib/pleroma/activity/ir/topics.ex b/lib/pleroma/activity/ir/topics.ex
index 7a603a615..3cc488fa6 100644
--- a/lib/pleroma/activity/ir/topics.ex
+++ b/lib/pleroma/activity/ir/topics.ex
@@ -13,6 +13,14 @@ defmodule Pleroma.Activity.Ir.Topics do
|> List.flatten()
end
+ defp generate_topics(%{data: %{"type" => "ChatMessage"}}, %{data: %{"type" => "Delete"}}) do
+ ["user", "user:pleroma_chat"]
+ end
+
+ defp generate_topics(%{data: %{"type" => "ChatMessage"}}, %{data: %{"type" => "Create"}}) do
+ []
+ end
+
defp generate_topics(%{data: %{"type" => "Answer"}}, _) do
[]
end
@@ -31,6 +39,10 @@ defmodule Pleroma.Activity.Ir.Topics do
end
|> item_creation_tags(object, activity)
+ "local" ->
+ ["public:local"]
+ |> item_creation_tags(object, activity)
+
"direct" ->
["direct"]
@@ -63,7 +75,18 @@ defmodule Pleroma.Activity.Ir.Topics do
defp attachment_topics(%{data: %{"attachment" => []}}, _act), do: []
- defp attachment_topics(_object, %{local: true}), do: ["public:media", "public:local:media"]
+ defp attachment_topics(_object, %{local: true} = activity) do
+ case Visibility.get_visibility(activity) do
+ "public" ->
+ ["public:media", "public:local:media"]
+
+ "local" ->
+ ["public:local:media"]
+
+ _ ->
+ []
+ end
+ end
defp attachment_topics(_object, %{actor: actor}) when is_binary(actor),
do: ["public:media", "public:remote:media:" <> URI.parse(actor).host]
diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex
index bf92f65cb..343ea1acb 100644
--- a/lib/pleroma/constants.ex
+++ b/lib/pleroma/constants.ex
@@ -27,4 +27,10 @@ defmodule Pleroma.Constants do
do:
~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc embed.js embed.css)
)
+
+ # basic regex, just there to weed out potential mistakes
+ # https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
+ const(mime_regex,
+ do: ~r/^[^[:cntrl:] ()<>@,;:\\"\/\[\]?=]+\/[^[:cntrl:] ()<>@,;:\\"\/\[\]?=]+(; .*)?$/
+ )
end
diff --git a/lib/pleroma/ecto_type/activity_pub/object_validators/mime.ex b/lib/pleroma/ecto_type/activity_pub/object_validators/mime.ex
new file mode 100644
index 000000000..31d51577d
--- /dev/null
+++ b/lib/pleroma/ecto_type/activity_pub/object_validators/mime.ex
@@ -0,0 +1,25 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.MIME do
+ use Ecto.Type
+
+ require Pleroma.Constants
+
+ def type, do: :string
+
+ def cast(mime) when is_binary(mime) do
+ if mime =~ Pleroma.Constants.mime_regex() do
+ {:ok, mime}
+ else
+ {:ok, "application/octet-stream"}
+ end
+ end
+
+ def cast(_), do: :error
+
+ def dump(data), do: {:ok, data}
+
+ def load(data), do: {:ok, data}
+end
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 7efbdc49a..71f57e6b2 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -328,6 +328,14 @@ defmodule Pleroma.Notification do
|> Repo.delete_all()
end
+ def destroy_multiple_from_types(%{id: user_id}, types) do
+ from(n in Notification,
+ where: n.user_id == ^user_id,
+ where: n.type in ^types
+ )
+ |> Repo.delete_all()
+ end
+
def dismiss(%Pleroma.Activity{} = activity) do
Notification
|> where([n], n.activity_id == ^activity.id)
diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex
index 43ab569a4..a71a504b3 100644
--- a/lib/pleroma/signature.ex
+++ b/lib/pleroma/signature.ex
@@ -10,17 +10,14 @@ defmodule Pleroma.Signature do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
+ @known_suffixes ["/publickey", "/main-key"]
+
def key_id_to_actor_id(key_id) do
uri =
- URI.parse(key_id)
+ key_id
+ |> URI.parse()
|> Map.put(:fragment, nil)
-
- uri =
- if not is_nil(uri.path) and String.ends_with?(uri.path, "/publickey") do
- Map.put(uri, :path, String.replace(uri.path, "/publickey", ""))
- else
- uri
- end
+ |> remove_suffix(@known_suffixes)
maybe_ap_id = URI.to_string(uri)
@@ -36,6 +33,16 @@ defmodule Pleroma.Signature do
end
end
+ defp remove_suffix(uri, [test | rest]) do
+ if not is_nil(uri.path) and String.ends_with?(uri.path, test) do
+ Map.put(uri, :path, String.replace(uri.path, test, ""))
+ else
+ remove_suffix(uri, rest)
+ end
+ end
+
+ defp remove_suffix(uri, []), do: uri
+
def fetch_public_key(conn) do
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
{:ok, actor_id} <- key_id_to_actor_id(kid),
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 62506f37a..03c5f91cc 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1087,10 +1087,24 @@ defmodule Pleroma.User do
|> update_and_set_cache()
end
- def update_and_set_cache(changeset) do
+ def update_and_set_cache(%{data: %Pleroma.User{} = user} = changeset) do
+ was_superuser_before_update = User.superuser?(user)
+
with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
set_cache(user)
end
+ |> maybe_remove_report_notifications(was_superuser_before_update)
+ end
+
+ defp maybe_remove_report_notifications({:ok, %Pleroma.User{} = user} = result, true) do
+ if not User.superuser?(user),
+ do: user |> Notification.destroy_multiple_from_types(["pleroma:report"])
+
+ result
+ end
+
+ defp maybe_remove_report_notifications(result, _) do
+ result
end
def get_user_friends_ap_ids(user) do
diff --git a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
index 0d987116c..825f2082f 100644
--- a/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/article_note_page_validator.ex
@@ -86,7 +86,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
defp fix_replies(%{"replies" => %{"items" => replies}} = data) when is_list(replies),
do: Map.put(data, "replies", replies)
- defp fix_replies(%{"replies" => replies} = data) when is_bitstring(replies),
+ # TODO: Pleroma does not have any support for Collections at the moment.
+ # If the `replies` field is not something the ObjectID validator can handle,
+ # the activity/object would be rejected, which is bad behavior.
+ defp fix_replies(%{"replies" => replies} = data) when not is_list(replies),
do: Map.drop(data, ["replies"])
defp fix_replies(data), do: data
diff --git a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
index 837787b9f..b86ce35fd 100644
--- a/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validators/attachment_validator.ex
@@ -12,14 +12,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
@primary_key false
embedded_schema do
field(:type, :string)
- field(:mediaType, :string, default: "application/octet-stream")
+ field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:name, :string)
field(:blurhash, :string)
embeds_many :url, UrlObjectValidator, primary_key: false do
field(:type, :string)
field(:href, ObjectValidators.Uri)
- field(:mediaType, :string, default: "application/octet-stream")
+ field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:width, :integer)
field(:height, :integer)
end
@@ -59,13 +59,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
end
def fix_media_type(data) do
- data = Map.put_new(data, "mediaType", data["mimeType"])
-
- if is_bitstring(data["mediaType"]) && MIME.extensions(data["mediaType"]) != [] do
- data
- else
- Map.put(data, "mediaType", "application/octet-stream")
- end
+ Map.put_new(data, "mediaType", data["mimeType"])
end
defp handle_href(href, mediaType) do
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 142af1a13..5766489be 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -203,13 +203,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
media_type =
cond do
- is_map(url) && MIME.extensions(url["mediaType"]) != [] ->
+ is_map(url) && url =~ Pleroma.Constants.mime_regex() ->
url["mediaType"]
- is_bitstring(data["mediaType"]) && MIME.extensions(data["mediaType"]) != [] ->
+ is_bitstring(data["mediaType"]) && data["mediaType"] =~ Pleroma.Constants.mime_regex() ->
data["mediaType"]
- is_bitstring(data["mimeType"]) && MIME.extensions(data["mimeType"]) != [] ->
+ is_bitstring(data["mimeType"]) && data["mimeType"] =~ Pleroma.Constants.mime_regex() ->
data["mimeType"]
true ->
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index 5fcbffc34..0a4a72bb4 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -453,7 +453,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
users =
user
|> User.muted_users_relation(_restrict_deactivated = true)
- |> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
+ |> Pleroma.Pagination.fetch_paginated(params)
conn
|> add_link_headers(users)
@@ -470,7 +470,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
users =
user
|> User.blocked_users_relation(_restrict_deactivated = true)
- |> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
+ |> Pleroma.Pagination.fetch_paginated(params)
conn
|> add_link_headers(users)
diff --git a/mix.exs b/mix.exs
index 0e2834fc6..ec63745ca 100644
--- a/mix.exs
+++ b/mix.exs
@@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
def project do
[
app: :pleroma,
- version: version("2.4.4"),
+ version: version("2.4.5"),
elixir: "~> 1.9",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
@@ -163,8 +163,8 @@ defmodule Pleroma.Mixfile do
{:poolboy, "~> 1.5"},
{:prometheus, "~> 4.6"},
{:prometheus_ex,
- git: "https://git.pleroma.social/pleroma/elixir-libraries/prometheus.ex.git",
- ref: "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5",
+ git: "https://github.com/lanodan/prometheus.ex.git",
+ branch: "fix/elixir-1.14",
override: true},
{:prometheus_plugs, "~> 1.1"},
{:prometheus_phoenix, "~> 1.3"},
diff --git a/mix.lock b/mix.lock
index 1fe713e8e..3ab8d6e96 100644
--- a/mix.lock
+++ b/mix.lock
@@ -104,7 +104,7 @@
"pot": {:hex, :pot, "1.0.1", "81b511b1fa7c3123171c265cb7065a1528cebd7277b0cbc94257c50a8b2e4c17", [:rebar3], [], "hexpm", "ed87f5976531d91528452faa1138a5328db7f9f20d8feaae15f5051f79bcfb6d"},
"prometheus": {:hex, :prometheus, "4.8.0", "1ce1e1002b173c336d61f186b56263346536e76814edd9a142e12aeb2d6c1ad2", [:mix, :rebar3], [], "hexpm", "0fc2e17103073edb3758a46a5d44b006191bf25b73cbaa2b779109de396afcb5"},
"prometheus_ecto": {:hex, :prometheus_ecto, "1.4.3", "3dd4da1812b8e0dbee81ea58bb3b62ed7588f2eae0c9e97e434c46807ff82311", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "8d66289f77f913b37eda81fd287340c17e61a447549deb28efc254532b2bed82"},
- "prometheus_ex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/prometheus.ex.git", "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5", [ref: "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5"]},
+ "prometheus_ex": {:git, "https://github.com/lanodan/prometheus.ex.git", "31f7fbe4b71b79ba27efc2a5085746c4011ceb8f", [branch: "fix/elixir-1.14"]},
"prometheus_phoenix": {:hex, :prometheus_phoenix, "1.3.0", "c4b527e0b3a9ef1af26bdcfbfad3998f37795b9185d475ca610fe4388fdd3bb5", [:mix], [{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm", "c4d1404ac4e9d3d963da601db2a7d8ea31194f0017057fabf0cfb9bf5a6c8c75"},
"prometheus_phx": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/prometheus-phx.git", "9cd8f248c9381ffedc799905050abce194a97514", [branch: "no-logging"]},
"prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm", "0273a6483ccb936d79ca19b0ab629aef0dba958697c94782bb728b920dfc6a79"},
diff --git a/priv/scrubbers/default.ex b/priv/scrubbers/default.ex
index 4694a92a5..d3561f169 100644
--- a/priv/scrubbers/default.ex
+++ b/priv/scrubbers/default.ex
@@ -64,13 +64,14 @@ defmodule Pleroma.HTML.Scrubber.Default do
@allow_inline_images Pleroma.Config.get([:markup, :allow_inline_images])
if @allow_inline_images do
+ Meta.allow_tag_with_this_attribute_values(:img, "class", ["emoji"])
+
# restrict img tags to http/https only, because of MediaProxy.
Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"])
Meta.allow_tag_with_these_attributes(:img, [
"width",
"height",
- "class",
"title",
"alt"
])
diff --git a/priv/scrubbers/twitter_text.ex b/priv/scrubbers/twitter_text.ex
index c4e796cad..bb8f3bc50 100644
--- a/priv/scrubbers/twitter_text.ex
+++ b/priv/scrubbers/twitter_text.ex
@@ -41,13 +41,14 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
# allow inline images for custom emoji
if Pleroma.Config.get([:markup, :allow_inline_images]) do
+ Meta.allow_tag_with_this_attribute_values(:img, "class", ["emoji"])
+
# restrict img tags to http/https only, because of MediaProxy.
Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"])
Meta.allow_tag_with_these_attributes(:img, [
"width",
"height",
- "class",
"title",
"alt"
])
diff --git a/test/pleroma/activity/ir/topics_test.exs b/test/pleroma/activity/ir/topics_test.exs
index 9c8e5d932..299fcae9d 100644
--- a/test/pleroma/activity/ir/topics_test.exs
+++ b/test/pleroma/activity/ir/topics_test.exs
@@ -13,6 +13,29 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
import Mock
+ describe "chat message" do
+ test "Create produces no topics" do
+ activity = %Activity{
+ object: %Object{data: %{"type" => "ChatMessage"}},
+ data: %{"type" => "Create"}
+ }
+
+ assert [] == Topics.get_activity_topics(activity)
+ end
+
+ test "Delete produces user and user:pleroma_chat" do
+ activity = %Activity{
+ object: %Object{data: %{"type" => "ChatMessage"}},
+ data: %{"type" => "Delete"}
+ }
+
+ topics = Topics.get_activity_topics(activity)
+ assert [_, _] = topics
+ assert "user" in topics
+ assert "user:pleroma_chat" in topics
+ end
+ end
+
describe "poll answer" do
test "produce no topics" do
activity = %Activity{object: %Object{data: %{"type" => "Answer"}}}
@@ -114,6 +137,36 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
end
end
+ describe "local-public visibility create events" do
+ setup do
+ activity = %Activity{
+ object: %Object{data: %{"attachment" => []}},
+ data: %{"type" => "Create", "to" => [Pleroma.Web.ActivityPub.Utils.as_local_public()]}
+ }
+
+ {:ok, activity: activity}
+ end
+
+ test "doesn't produce public topics", %{activity: activity} do
+ topics = Topics.get_activity_topics(activity)
+
+ refute Enum.member?(topics, "public")
+ end
+
+ test "produces public:local topics", %{activity: activity} do
+ topics = Topics.get_activity_topics(activity)
+
+ assert Enum.member?(topics, "public:local")
+ end
+
+ test "with no attachments doesn't produce public:media topics", %{activity: activity} do
+ topics = Topics.get_activity_topics(activity)
+
+ refute Enum.member?(topics, "public:media")
+ refute Enum.member?(topics, "public:local:media")
+ end
+ end
+
describe "public visibility create events with attachments" do
setup do
activity = %Activity{
@@ -152,6 +205,29 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
end
end
+ describe "local-public visibility create events with attachments" do
+ setup do
+ activity = %Activity{
+ object: %Object{data: %{"attachment" => ["foo"]}},
+ data: %{"type" => "Create", "to" => [Pleroma.Web.ActivityPub.Utils.as_local_public()]}
+ }
+
+ {:ok, activity: activity}
+ end
+
+ test "do not produce public:media topics", %{activity: activity} do
+ topics = Topics.get_activity_topics(activity)
+
+ refute Enum.member?(topics, "public:media")
+ end
+
+ test "produces public:local:media topics", %{activity: activity} do
+ topics = Topics.get_activity_topics(activity)
+
+ assert Enum.member?(topics, "public:local:media")
+ end
+ end
+
describe "non-public visibility" do
test "produces direct topic" do
activity = %Activity{object: %Object{data: %{"type" => "Note"}}, data: %{"to" => []}}
diff --git a/test/pleroma/html_test.exs b/test/pleroma/html_test.exs
index fe1a1ed57..a1e4bf457 100644
--- a/test/pleroma/html_test.exs
+++ b/test/pleroma/html_test.exs
@@ -17,6 +17,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed "rel" attribute: example.com
this is a link with not allowed "rel" attribute: example.com
this is an image:
+ this is an inline emoji:
"""
@@ -24,6 +25,10 @@ defmodule Pleroma.HTMLTest do
"""
+ @html_stillimage_sample """
+
+ """
+
@html_span_class_sample """
hi
"""
@@ -45,6 +50,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed "rel" attribute: example.com
this is a link with not allowed "rel" attribute: example.com
this is an image:
+ this is an inline emoji:
alert('hacked')
"""
@@ -67,6 +73,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed "rel" attribute: example.com
this is a link with not allowed "rel" attribute: example.com
this is an image:
+ this is an inline emoji:
alert('hacked')
"""
@@ -90,6 +97,15 @@ defmodule Pleroma.HTMLTest do
HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.TwitterText)
end
+ test "does not allow images with invalid classes" do
+ expected = """
+
+ """
+
+ assert expected ==
+ HTML.filter_tags(@html_stillimage_sample, Pleroma.HTML.Scrubber.TwitterText)
+ end
+
test "does allow microformats" do
expected = """
@foo
@@ -121,6 +137,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed "rel" attribute: example.com
this is a link with not allowed "rel" attribute: example.com
this is an image:
+ this is an inline emoji:
alert('hacked')
"""
@@ -143,6 +160,15 @@ defmodule Pleroma.HTMLTest do
assert expected == HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.Default)
end
+ test "does not allow images with invalid classes" do
+ expected = """
+
+ """
+
+ assert expected ==
+ HTML.filter_tags(@html_stillimage_sample, Pleroma.HTML.Scrubber.TwitterText)
+ end
+
test "does allow microformats" do
expected = """
@foo
diff --git a/test/pleroma/notification_test.exs b/test/pleroma/notification_test.exs
index 85f895f0f..5c2be9b5c 100644
--- a/test/pleroma/notification_test.exs
+++ b/test/pleroma/notification_test.exs
@@ -507,6 +507,25 @@ defmodule Pleroma.NotificationTest do
end
end
+ describe "destroy_multiple_from_types/2" do
+ test "clears all notifications of a certain type for a given user" do
+ report_activity = insert(:report_activity)
+ user1 = insert(:user, is_moderator: true, is_admin: true)
+ user2 = insert(:user, is_moderator: true, is_admin: true)
+ {:ok, _} = Notification.create_notifications(report_activity)
+
+ {:ok, _} =
+ CommonAPI.post(user2, %{
+ status: "hey @#{user1.nickname} !"
+ })
+
+ Notification.destroy_multiple_from_types(user1, ["pleroma:report"])
+
+ assert [%Pleroma.Notification{type: "mention"}] = Notification.for_user(user1)
+ assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user2)
+ end
+ end
+
describe "set_read_up_to()" do
test "it sets all notifications as read up to a specified notification ID" do
user = insert(:user)
diff --git a/test/pleroma/signature_test.exs b/test/pleroma/signature_test.exs
index 047c537e0..e3ae36b46 100644
--- a/test/pleroma/signature_test.exs
+++ b/test/pleroma/signature_test.exs
@@ -109,6 +109,11 @@ defmodule Pleroma.SignatureTest do
{:ok, "https://example.com/users/1234"}
end
+ test "it deduces the actor id for gotoSocial" do
+ assert Signature.key_id_to_actor_id("https://example.com/users/1234/main-key") ==
+ {:ok, "https://example.com/users/1234"}
+ end
+
test "it calls webfinger for 'acct:' accounts" do
with_mock(Pleroma.Web.WebFinger,
finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end
diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs
index 4021a565d..a6421890b 100644
--- a/test/pleroma/user_test.exs
+++ b/test/pleroma/user_test.exs
@@ -5,6 +5,7 @@
defmodule Pleroma.UserTest do
alias Pleroma.Activity
alias Pleroma.Builders.UserBuilder
+ alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.Tests.ObanHelpers
@@ -2123,6 +2124,26 @@ defmodule Pleroma.UserTest do
assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
end
+
+ test "removes report notifs when user isn't superuser any more" do
+ report_activity = insert(:report_activity)
+ user = insert(:user, is_moderator: true, is_admin: true)
+ {:ok, _} = Notification.create_notifications(report_activity)
+
+ assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
+
+ {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
+ # is still superuser because still admin
+ assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
+
+ {:ok, user} = user |> User.admin_api_update(%{is_moderator: true, is_admin: false})
+ # is still superuser because still moderator
+ assert [%Pleroma.Notification{type: "pleroma:report"}] = Notification.for_user(user)
+
+ {:ok, user} = user |> User.admin_api_update(%{is_moderator: false})
+ # is not a superuser any more
+ assert [] = Notification.for_user(user)
+ end
end
describe "following/followers synchronization" do
diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
index 720c17d8d..917009912 100644
--- a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
+++ b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs
@@ -32,4 +32,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
end
end
+
+ test "a Note without replies/first/items validates" do
+ insert(:user, ap_id: "https://mastodon.social/users/emelie")
+
+ note =
+ "test/fixtures/tesla_mock/status.emelie.json"
+ |> File.read!()
+ |> Jason.decode!()
+ |> pop_in(["replies", "first", "items"])
+ |> elem(1)
+
+ %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
+ end
end
diff --git a/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs
index 0e49fda99..a72460296 100644
--- a/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs
+++ b/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs
@@ -27,6 +27,46 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
assert attachment.mediaType == "application/octet-stream"
end
+ test "works with an unknown but valid mime type" do
+ attachment = %{
+ "mediaType" => "x-custom/x-type",
+ "type" => "Document",
+ "url" => "https://example.org"
+ }
+
+ assert {:ok, attachment} =
+ AttachmentValidator.cast_and_validate(attachment)
+ |> Ecto.Changeset.apply_action(:insert)
+
+ assert attachment.mediaType == "x-custom/x-type"
+ end
+
+ test "works with invalid mime types" do
+ attachment = %{
+ "mediaType" => "x-customx-type",
+ "type" => "Document",
+ "url" => "https://example.org"
+ }
+
+ assert {:ok, attachment} =
+ AttachmentValidator.cast_and_validate(attachment)
+ |> Ecto.Changeset.apply_action(:insert)
+
+ assert attachment.mediaType == "application/octet-stream"
+
+ attachment = %{
+ "mediaType" => "https://example.org",
+ "type" => "Document",
+ "url" => "https://example.org"
+ }
+
+ assert {:ok, attachment} =
+ AttachmentValidator.cast_and_validate(attachment)
+ |> Ecto.Changeset.apply_action(:insert)
+
+ assert attachment.mediaType == "application/octet-stream"
+ end
+
test "it turns mastodon attachments into our attachments" do
attachment = %{
"url" =>
diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs
index 3036e25b3..9ffdda5b3 100644
--- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs
@@ -1664,21 +1664,21 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/mutes")
|> json_response_and_validate_schema(200)
- assert [id1, id2, id3] == Enum.map(result, & &1["id"])
+ assert [id3, id2, id1] == Enum.map(result, & &1["id"])
result =
conn
|> get("/api/v1/mutes?limit=1")
|> json_response_and_validate_schema(200)
- assert [%{"id" => ^id1}] = result
+ assert [%{"id" => ^id3}] = result
result =
conn
|> get("/api/v1/mutes?since_id=#{id1}")
|> json_response_and_validate_schema(200)
- assert [%{"id" => ^id2}, %{"id" => ^id3}] = result
+ assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
result =
conn
@@ -1692,7 +1692,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/mutes?since_id=#{id1}&limit=1")
|> json_response_and_validate_schema(200)
- assert [%{"id" => ^id2}] = result
+ assert [%{"id" => ^id3}] = result
end
test "list of mutes with with_relationships parameter" do
@@ -1711,7 +1711,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert [
%{
- "id" => ^id1,
+ "id" => ^id3,
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
},
%{
@@ -1719,7 +1719,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
},
%{
- "id" => ^id3,
+ "id" => ^id1,
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
}
] =
@@ -1744,7 +1744,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks")
|> json_response_and_validate_schema(200)
- assert [id1, id2, id3] == Enum.map(result, & &1["id"])
+ assert [id3, id2, id1] == Enum.map(result, & &1["id"])
result =
conn
@@ -1752,7 +1752,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks?limit=1")
|> json_response_and_validate_schema(200)
- assert [%{"id" => ^id1}] = result
+ assert [%{"id" => ^id3}] = result
result =
conn
@@ -1760,7 +1760,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks?since_id=#{id1}")
|> json_response_and_validate_schema(200)
- assert [%{"id" => ^id2}, %{"id" => ^id3}] = result
+ assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
result =
conn
@@ -1776,6 +1776,30 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks?since_id=#{id1}&limit=1")
|> json_response_and_validate_schema(200)
- assert [%{"id" => ^id2}] = result
+ assert [%{"id" => ^id3}] = result
+
+ conn_res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/blocks?limit=2")
+
+ next_url =
+ ~r{<.+?(?/api[^>]+)>; rel=\"next\"}
+ |> Regex.named_captures(get_resp_header(conn_res, "link") |> Enum.at(0))
+ |> Map.get("link")
+
+ result =
+ conn_res
+ |> json_response_and_validate_schema(200)
+
+ assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
+
+ result =
+ conn
+ |> assign(:user, user)
+ |> get(next_url)
+ |> json_response_and_validate_schema(200)
+
+ assert [%{"id" => ^id1}] = result
end
end
diff --git a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs
index ed1286675..6abc55ea6 100644
--- a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs
@@ -885,7 +885,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
end
end
- describe "hashtag timeline handling of :restrict_unauthenticated setting" do
+ describe "hashtag timeline handling of restrict_unauthenticated setting" do
setup do
user = insert(:user)
{:ok, activity1} = CommonAPI.post(user, %{status: "test #tag1"})
diff --git a/test/pleroma/web/media_proxy/invalidation/script_test.exs b/test/pleroma/web/media_proxy/invalidation/script_test.exs
index e9629b72b..a6f88114f 100644
--- a/test/pleroma/web/media_proxy/invalidation/script_test.exs
+++ b/test/pleroma/web/media_proxy/invalidation/script_test.exs
@@ -10,11 +10,14 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.ScriptTest do
test "it logs error when script is not found" do
assert capture_log(fn ->
- assert Invalidation.Script.purge(
- ["http://example.com/media/example.jpg"],
- script_path: "./example"
- ) == {:error, "%ErlangError{original: :enoent}"}
- end) =~ "Error while cache purge: %ErlangError{original: :enoent}"
+ assert {:error, msg} =
+ Invalidation.Script.purge(
+ ["http://example.com/media/example.jpg"],
+ script_path: "./example"
+ )
+
+ assert msg =~ ~r/%ErlangError{original: :enoent(, reason: nil)?}/
+ end) =~ ~r/Error while cache purge: %ErlangError{original: :enoent(, reason: nil)?}/
capture_log(fn ->
assert Invalidation.Script.purge(