Compare commits

...

18 Commits

Author SHA1 Message Date
Haelwenn
d8e326467c Merge branch 'fix/2.4.5-release-date' into 'stable'
Fix changelog date

See merge request pleroma/pleroma!3796
2022-11-28 04:35:51 +00:00
Sean King
75c9f7770f
Fix changelog date 2022-11-27 20:17:48 -07:00
Haelwenn
76bdb01c18 Merge branch 'release/2.4.5' into 'stable'
Release 2.4.5

See merge request pleroma/pleroma!3793
2022-11-27 21:24:19 +00:00
Haelwenn (lanodan) Monnier
2614f431b9 Release 2.4.5 2022-11-27 13:17:21 +01:00
Hélène
542bb17258 ArticleNotePageValidator: fix replies fixing
Some software, like GoToSocial, expose replies as ActivityPub
Collections, but do not expose any item array directly in the object,
causing validation to fail via the ObjectID validator. Now, Pleroma will
drop that field in this situation too.
2022-11-27 04:54:19 +01:00
FloatingGhost
747311f623 fix resolution of GTS user keys 2022-11-27 04:54:18 +01:00
Tusooa Zhu
11d5ad24c5 Make local-only posts stream in local timeline 2022-11-27 04:39:32 +01:00
Tusooa Zhu
e46c3a0595 Do not stream out Create of ChatMessage 2022-11-27 04:39:32 +01:00
Sean King
9b68778887 Fix fedi-fe build URL 2022-11-27 04:34:33 +01:00
Haelwenn (lanodan) Monnier
f2221d539c script_test: Fix %ErlangError for Elixir 1.14 2022-11-27 04:25:48 +01:00
Haelwenn (lanodan) Monnier
915c7319c6 mix: Switch prometheus_ex to fix/elixir-1.14 branch 2022-11-27 04:25:48 +01:00
Haelwenn (lanodan) Monnier
f12ddcd697 timeline_controller_test: Fix test name for elixir 1.14 2022-11-27 04:25:48 +01:00
Tusooa Zhu
09ab51eebb Make mutes and blocks behave the same as other lists 2022-11-27 04:21:58 +01:00
Haelwenn (lanodan) Monnier
7ec3469bea Transmogrifier: Use validating regex for "mediaType" 2022-11-27 04:21:31 +01:00
Haelwenn (lanodan) Monnier
8640d217b1 AttachmentValidator: Use custom ecto type and regex for "mediaType" 2022-11-27 04:21:31 +01:00
Haelwenn (lanodan) Monnier
da71092003 EctoType: Add MIME validator 2022-11-27 04:21:31 +01:00
Ilja
4504c81080 Delete report notifs when demoting from superuser
When someone isn't a superuser any more, they shouldn't see the reporsts any more either.
Here we delete the report notifications from a user when that user gets updated from being a superuser to a non-superuser.
2022-11-27 04:20:11 +01:00
Haelwenn (lanodan) Monnier
508b438b53 scrubbers: Scrub img class attribute
Closes: https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3790
2022-11-27 04:04:17 +01:00
26 changed files with 371 additions and 48 deletions

View File

@ -14,6 +14,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Removed ### Removed
## 2.4.5 - 2022-11-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 ## 2.4.4 - 2022-08-19
### Security ### Security

View File

@ -734,7 +734,7 @@ config :pleroma, :frontends,
"name" => "fedi-fe", "name" => "fedi-fe",
"git" => "https://git.pleroma.social/pleroma/fedi-fe", "git" => "https://git.pleroma.social/pleroma/fedi-fe",
"build_url" => "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", "ref" => "master",
"custom-http-headers" => [ "custom-http-headers" => [
{"service-worker-allowed", "/"} {"service-worker-allowed", "/"}

View File

@ -13,6 +13,14 @@ defmodule Pleroma.Activity.Ir.Topics do
|> List.flatten() |> List.flatten()
end 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 defp generate_topics(%{data: %{"type" => "Answer"}}, _) do
[] []
end end
@ -31,6 +39,10 @@ defmodule Pleroma.Activity.Ir.Topics do
end end
|> item_creation_tags(object, activity) |> item_creation_tags(object, activity)
"local" ->
["public:local"]
|> item_creation_tags(object, activity)
"direct" -> "direct" ->
["direct"] ["direct"]
@ -63,7 +75,18 @@ defmodule Pleroma.Activity.Ir.Topics do
defp attachment_topics(%{data: %{"attachment" => []}}, _act), 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), defp attachment_topics(_object, %{actor: actor}) when is_binary(actor),
do: ["public:media", "public:remote:media:" <> URI.parse(actor).host] do: ["public:media", "public:remote:media:" <> URI.parse(actor).host]

View File

@ -27,4 +27,10 @@ defmodule Pleroma.Constants do
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) ~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 end

View File

@ -0,0 +1,25 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# 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

View File

@ -328,6 +328,14 @@ defmodule Pleroma.Notification do
|> Repo.delete_all() |> Repo.delete_all()
end 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 def dismiss(%Pleroma.Activity{} = activity) do
Notification Notification
|> where([n], n.activity_id == ^activity.id) |> where([n], n.activity_id == ^activity.id)

View File

@ -10,17 +10,14 @@ defmodule Pleroma.Signature do
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@known_suffixes ["/publickey", "/main-key"]
def key_id_to_actor_id(key_id) do def key_id_to_actor_id(key_id) do
uri = uri =
URI.parse(key_id) key_id
|> URI.parse()
|> Map.put(:fragment, nil) |> Map.put(:fragment, nil)
|> remove_suffix(@known_suffixes)
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
maybe_ap_id = URI.to_string(uri) maybe_ap_id = URI.to_string(uri)
@ -36,6 +33,16 @@ defmodule Pleroma.Signature do
end end
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 def fetch_public_key(conn) do
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn), with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
{:ok, actor_id} <- key_id_to_actor_id(kid), {:ok, actor_id} <- key_id_to_actor_id(kid),

View File

@ -1087,10 +1087,24 @@ defmodule Pleroma.User do
|> update_and_set_cache() |> update_and_set_cache()
end 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 with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do
set_cache(user) set_cache(user)
end 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 end
def get_user_friends_ap_ids(user) do def get_user_friends_ap_ids(user) do

View File

@ -86,7 +86,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
defp fix_replies(%{"replies" => %{"items" => replies}} = data) when is_list(replies), defp fix_replies(%{"replies" => %{"items" => replies}} = data) when is_list(replies),
do: Map.put(data, "replies", 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"]) do: Map.drop(data, ["replies"])
defp fix_replies(data), do: data defp fix_replies(data), do: data

View File

@ -12,14 +12,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
@primary_key false @primary_key false
embedded_schema do embedded_schema do
field(:type, :string) field(:type, :string)
field(:mediaType, :string, default: "application/octet-stream") field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:name, :string) field(:name, :string)
field(:blurhash, :string) field(:blurhash, :string)
embeds_many :url, UrlObjectValidator, primary_key: false do embeds_many :url, UrlObjectValidator, primary_key: false do
field(:type, :string) field(:type, :string)
field(:href, ObjectValidators.Uri) field(:href, ObjectValidators.Uri)
field(:mediaType, :string, default: "application/octet-stream") field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
field(:width, :integer) field(:width, :integer)
field(:height, :integer) field(:height, :integer)
end end
@ -59,13 +59,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
end end
def fix_media_type(data) do def fix_media_type(data) do
data = Map.put_new(data, "mediaType", data["mimeType"]) 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
end end
defp handle_href(href, mediaType) do defp handle_href(href, mediaType) do

View File

@ -203,13 +203,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
media_type = media_type =
cond do cond do
is_map(url) && MIME.extensions(url["mediaType"]) != [] -> is_map(url) && url =~ Pleroma.Constants.mime_regex() ->
url["mediaType"] url["mediaType"]
is_bitstring(data["mediaType"]) && MIME.extensions(data["mediaType"]) != [] -> is_bitstring(data["mediaType"]) && data["mediaType"] =~ Pleroma.Constants.mime_regex() ->
data["mediaType"] data["mediaType"]
is_bitstring(data["mimeType"]) && MIME.extensions(data["mimeType"]) != [] -> is_bitstring(data["mimeType"]) && data["mimeType"] =~ Pleroma.Constants.mime_regex() ->
data["mimeType"] data["mimeType"]
true -> true ->

View File

@ -453,7 +453,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
users = users =
user user
|> User.muted_users_relation(_restrict_deactivated = true) |> User.muted_users_relation(_restrict_deactivated = true)
|> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true)) |> Pleroma.Pagination.fetch_paginated(params)
conn conn
|> add_link_headers(users) |> add_link_headers(users)
@ -470,7 +470,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
users = users =
user user
|> User.blocked_users_relation(_restrict_deactivated = true) |> User.blocked_users_relation(_restrict_deactivated = true)
|> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true)) |> Pleroma.Pagination.fetch_paginated(params)
conn conn
|> add_link_headers(users) |> add_link_headers(users)

View File

@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
def project do def project do
[ [
app: :pleroma, app: :pleroma,
version: version("2.4.4"), version: version("2.4.5"),
elixir: "~> 1.9", elixir: "~> 1.9",
elixirc_paths: elixirc_paths(Mix.env()), elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(), compilers: [:phoenix, :gettext] ++ Mix.compilers(),
@ -163,8 +163,8 @@ defmodule Pleroma.Mixfile do
{:poolboy, "~> 1.5"}, {:poolboy, "~> 1.5"},
{:prometheus, "~> 4.6"}, {:prometheus, "~> 4.6"},
{:prometheus_ex, {:prometheus_ex,
git: "https://git.pleroma.social/pleroma/elixir-libraries/prometheus.ex.git", git: "https://github.com/lanodan/prometheus.ex.git",
ref: "a4e9beb3c1c479d14b352fd9d6dd7b1f6d7deee5", branch: "fix/elixir-1.14",
override: true}, override: true},
{:prometheus_plugs, "~> 1.1"}, {:prometheus_plugs, "~> 1.1"},
{:prometheus_phoenix, "~> 1.3"}, {:prometheus_phoenix, "~> 1.3"},

View File

@ -104,7 +104,7 @@
"pot": {:hex, :pot, "1.0.1", "81b511b1fa7c3123171c265cb7065a1528cebd7277b0cbc94257c50a8b2e4c17", [:rebar3], [], "hexpm", "ed87f5976531d91528452faa1138a5328db7f9f20d8feaae15f5051f79bcfb6d"}, "pot": {:hex, :pot, "1.0.1", "81b511b1fa7c3123171c265cb7065a1528cebd7277b0cbc94257c50a8b2e4c17", [:rebar3], [], "hexpm", "ed87f5976531d91528452faa1138a5328db7f9f20d8feaae15f5051f79bcfb6d"},
"prometheus": {:hex, :prometheus, "4.8.0", "1ce1e1002b173c336d61f186b56263346536e76814edd9a142e12aeb2d6c1ad2", [:mix, :rebar3], [], "hexpm", "0fc2e17103073edb3758a46a5d44b006191bf25b73cbaa2b779109de396afcb5"}, "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_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_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_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"}, "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"},

View File

@ -64,13 +64,14 @@ defmodule Pleroma.HTML.Scrubber.Default do
@allow_inline_images Pleroma.Config.get([:markup, :allow_inline_images]) @allow_inline_images Pleroma.Config.get([:markup, :allow_inline_images])
if @allow_inline_images do 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. # restrict img tags to http/https only, because of MediaProxy.
Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"]) Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"])
Meta.allow_tag_with_these_attributes(:img, [ Meta.allow_tag_with_these_attributes(:img, [
"width", "width",
"height", "height",
"class",
"title", "title",
"alt" "alt"
]) ])

View File

@ -41,13 +41,14 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
# allow inline images for custom emoji # allow inline images for custom emoji
if Pleroma.Config.get([:markup, :allow_inline_images]) do 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. # restrict img tags to http/https only, because of MediaProxy.
Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"]) Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"])
Meta.allow_tag_with_these_attributes(:img, [ Meta.allow_tag_with_these_attributes(:img, [
"width", "width",
"height", "height",
"class",
"title", "title",
"alt" "alt"
]) ])

View File

@ -13,6 +13,29 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
import Mock 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 describe "poll answer" do
test "produce no topics" do test "produce no topics" do
activity = %Activity{object: %Object{data: %{"type" => "Answer"}}} activity = %Activity{object: %Object{data: %{"type" => "Answer"}}}
@ -114,6 +137,36 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
end end
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 describe "public visibility create events with attachments" do
setup do setup do
activity = %Activity{ activity = %Activity{
@ -152,6 +205,29 @@ defmodule Pleroma.Activity.Ir.TopicsTest do
end end
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 describe "non-public visibility" do
test "produces direct topic" do test "produces direct topic" do
activity = %Activity{object: %Object{data: %{"type" => "Note"}}, data: %{"to" => []}} activity = %Activity{object: %Object{data: %{"type" => "Note"}}, data: %{"to" => []}}

View File

@ -17,6 +17,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a> this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
this is a link with not allowed "rel" attribute: <a href="http://example.com/" rel="tag noallowed">example.com</a> this is a link with not allowed "rel" attribute: <a href="http://example.com/" rel="tag noallowed">example.com</a>
this is an image: <img src="http://example.com/image.jpg"><br /> this is an image: <img src="http://example.com/image.jpg"><br />
this is an inline emoji: <img class="emoji" src="http://example.com/image.jpg"><br />
<script>alert('hacked')</script> <script>alert('hacked')</script>
""" """
@ -24,6 +25,10 @@ defmodule Pleroma.HTMLTest do
<img src="http://example.com/image.jpg" onerror="alert('hacked')"> <img src="http://example.com/image.jpg" onerror="alert('hacked')">
""" """
@html_stillimage_sample """
<img class="still-image" src="http://example.com/image.jpg">
"""
@html_span_class_sample """ @html_span_class_sample """
<span class="animate-spin">hi</span> <span class="animate-spin">hi</span>
""" """
@ -45,6 +50,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed &quot;rel&quot; attribute: example.com this is a link with allowed &quot;rel&quot; attribute: example.com
this is a link with not allowed &quot;rel&quot; attribute: example.com this is a link with not allowed &quot;rel&quot; attribute: example.com
this is an image: this is an image:
this is an inline emoji:
alert(&#39;hacked&#39;) alert(&#39;hacked&#39;)
""" """
@ -67,6 +73,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a> this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a> this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
this is an image: <img src="http://example.com/image.jpg"/><br/> this is an image: <img src="http://example.com/image.jpg"/><br/>
this is an inline emoji: <img class="emoji" src="http://example.com/image.jpg"/><br/>
alert(&#39;hacked&#39;) alert(&#39;hacked&#39;)
""" """
@ -90,6 +97,15 @@ defmodule Pleroma.HTMLTest do
HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.TwitterText) HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.TwitterText)
end end
test "does not allow images with invalid classes" do
expected = """
<img src="http://example.com/image.jpg"/>
"""
assert expected ==
HTML.filter_tags(@html_stillimage_sample, Pleroma.HTML.Scrubber.TwitterText)
end
test "does allow microformats" do test "does allow microformats" do
expected = """ expected = """
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span> <span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
@ -121,6 +137,7 @@ defmodule Pleroma.HTMLTest do
this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a> this is a link with allowed &quot;rel&quot; attribute: <a href="http://example.com/" rel="tag">example.com</a>
this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a> this is a link with not allowed &quot;rel&quot; attribute: <a href="http://example.com/">example.com</a>
this is an image: <img src="http://example.com/image.jpg"/><br/> this is an image: <img src="http://example.com/image.jpg"/><br/>
this is an inline emoji: <img class="emoji" src="http://example.com/image.jpg"/><br/>
alert(&#39;hacked&#39;) alert(&#39;hacked&#39;)
""" """
@ -143,6 +160,15 @@ defmodule Pleroma.HTMLTest do
assert expected == HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.Default) assert expected == HTML.filter_tags(@html_span_class_sample, Pleroma.HTML.Scrubber.Default)
end end
test "does not allow images with invalid classes" do
expected = """
<img src="http://example.com/image.jpg"/>
"""
assert expected ==
HTML.filter_tags(@html_stillimage_sample, Pleroma.HTML.Scrubber.TwitterText)
end
test "does allow microformats" do test "does allow microformats" do
expected = """ expected = """
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span> <span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>

View File

@ -507,6 +507,25 @@ defmodule Pleroma.NotificationTest do
end end
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 describe "set_read_up_to()" do
test "it sets all notifications as read up to a specified notification ID" do test "it sets all notifications as read up to a specified notification ID" do
user = insert(:user) user = insert(:user)

View File

@ -109,6 +109,11 @@ defmodule Pleroma.SignatureTest do
{:ok, "https://example.com/users/1234"} {:ok, "https://example.com/users/1234"}
end 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 test "it calls webfinger for 'acct:' accounts" do
with_mock(Pleroma.Web.WebFinger, with_mock(Pleroma.Web.WebFinger,
finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end

View File

@ -5,6 +5,7 @@
defmodule Pleroma.UserTest do defmodule Pleroma.UserTest do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Builders.UserBuilder alias Pleroma.Builders.UserBuilder
alias Pleroma.Notification
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Tests.ObanHelpers 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 {: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) assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
end 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 end
describe "following/followers synchronization" do describe "following/followers synchronization" do

View File

@ -32,4 +32,17 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note) %{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
end end
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 end

View File

@ -27,6 +27,46 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
assert attachment.mediaType == "application/octet-stream" assert attachment.mediaType == "application/octet-stream"
end 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 test "it turns mastodon attachments into our attachments" do
attachment = %{ attachment = %{
"url" => "url" =>

View File

@ -1664,21 +1664,21 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/mutes") |> get("/api/v1/mutes")
|> json_response_and_validate_schema(200) |> 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 = result =
conn conn
|> get("/api/v1/mutes?limit=1") |> get("/api/v1/mutes?limit=1")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert [%{"id" => ^id1}] = result assert [%{"id" => ^id3}] = result
result = result =
conn conn
|> get("/api/v1/mutes?since_id=#{id1}") |> get("/api/v1/mutes?since_id=#{id1}")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert [%{"id" => ^id2}, %{"id" => ^id3}] = result assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
result = result =
conn conn
@ -1692,7 +1692,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/mutes?since_id=#{id1}&limit=1") |> get("/api/v1/mutes?since_id=#{id1}&limit=1")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert [%{"id" => ^id2}] = result assert [%{"id" => ^id3}] = result
end end
test "list of mutes with with_relationships parameter" do test "list of mutes with with_relationships parameter" do
@ -1711,7 +1711,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert [ assert [
%{ %{
"id" => ^id1, "id" => ^id3,
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}} "pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
}, },
%{ %{
@ -1719,7 +1719,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}} "pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
}, },
%{ %{
"id" => ^id3, "id" => ^id1,
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}} "pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
} }
] = ] =
@ -1744,7 +1744,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks") |> get("/api/v1/blocks")
|> json_response_and_validate_schema(200) |> 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 = result =
conn conn
@ -1752,7 +1752,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks?limit=1") |> get("/api/v1/blocks?limit=1")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert [%{"id" => ^id1}] = result assert [%{"id" => ^id3}] = result
result = result =
conn conn
@ -1760,7 +1760,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks?since_id=#{id1}") |> get("/api/v1/blocks?since_id=#{id1}")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
assert [%{"id" => ^id2}, %{"id" => ^id3}] = result assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
result = result =
conn conn
@ -1776,6 +1776,30 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/blocks?since_id=#{id1}&limit=1") |> get("/api/v1/blocks?since_id=#{id1}&limit=1")
|> json_response_and_validate_schema(200) |> 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{<.+?(?<link>/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
end end

View File

@ -885,7 +885,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
end end
end end
describe "hashtag timeline handling of :restrict_unauthenticated setting" do describe "hashtag timeline handling of restrict_unauthenticated setting" do
setup do setup do
user = insert(:user) user = insert(:user)
{:ok, activity1} = CommonAPI.post(user, %{status: "test #tag1"}) {:ok, activity1} = CommonAPI.post(user, %{status: "test #tag1"})

View File

@ -10,11 +10,14 @@ defmodule Pleroma.Web.MediaProxy.Invalidation.ScriptTest do
test "it logs error when script is not found" do test "it logs error when script is not found" do
assert capture_log(fn -> assert capture_log(fn ->
assert Invalidation.Script.purge( assert {:error, msg} =
Invalidation.Script.purge(
["http://example.com/media/example.jpg"], ["http://example.com/media/example.jpg"],
script_path: "./example" script_path: "./example"
) == {:error, "%ErlangError{original: :enoent}"} )
end) =~ "Error while cache purge: %ErlangError{original: :enoent}"
assert msg =~ ~r/%ErlangError{original: :enoent(, reason: nil)?}/
end) =~ ~r/Error while cache purge: %ErlangError{original: :enoent(, reason: nil)?}/
capture_log(fn -> capture_log(fn ->
assert Invalidation.Script.purge( assert Invalidation.Script.purge(