Merge remote-tracking branch 'origin/develop' into fork

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-05-16 22:45:37 +02:00
commit cc4fccdd80
20 changed files with 126 additions and 396 deletions

View file

@ -0,0 +1 @@
Add instance rules

View file

@ -0,0 +1 @@
Strip actor property from objects before federating

View file

@ -0,0 +1 @@
Web Push notifications are no longer generated for muted/blocked threads and users.

View file

@ -9,6 +9,7 @@ defmodule Pleroma.Constants do
const(object_internal_fields, const(object_internal_fields,
do: [ do: [
"actor",
"reactions", "reactions",
"reaction_count", "reaction_count",
"likes", "likes",
@ -20,6 +21,7 @@ defmodule Pleroma.Constants do
"deleted_activity_id", "deleted_activity_id",
"pleroma_internal", "pleroma_internal",
"generator", "generator",
"rules",
"assigned_account", "assigned_account",
"rules", "rules",
"content_type", "content_type",

View file

@ -368,20 +368,20 @@ def dismiss(%{id: user_id} = _user, id) do
end end
end end
@spec create_notifications(Activity.t(), keyword()) :: {:ok, [Notification.t()] | []} @spec create_notifications(Activity.t()) :: {:ok, [Notification.t()] | []}
def create_notifications(activity, options \\ []) def create_notifications(activity)
def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity, options) do def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity) do
object = Object.normalize(activity, fetch: false) object = Object.normalize(activity, fetch: false)
if object && object.data["type"] == "Answer" do if object && object.data["type"] == "Answer" do
{:ok, []} {:ok, []}
else else
do_create_notifications(activity, options) do_create_notifications(activity)
end end
end end
def create_notifications(%Activity{data: %{"type" => type}} = activity, options) def create_notifications(%Activity{data: %{"type" => type}} = activity)
when type in [ when type in [
"Follow", "Follow",
"Like", "Like",
@ -393,41 +393,29 @@ def create_notifications(%Activity{data: %{"type" => type}} = activity, options)
"Accept", "Accept",
"Join" "Join"
] do ] do
do_create_notifications(activity, options) do_create_notifications(activity)
end end
def create_notifications(_, _), do: {:ok, []} def create_notifications(_), do: {:ok, []}
defp do_create_notifications(%Activity{} = activity, options) do defp do_create_notifications(%Activity{} = activity) do
do_send = Keyword.get(options, :do_send, true) enabled_participants = get_notified_participants_from_activity(activity)
{enabled_participants, disabled_participants} = enabled_receivers = get_notified_from_activity(activity) -- enabled_participants
get_notified_participants_from_activity(activity)
potential_participants = enabled_participants ++ disabled_participants enabled_subscribers =
get_notified_subscribers_from_activity(activity) --
{enabled_receivers, disabled_receivers} = get_notified_from_activity(activity) (enabled_participants ++ enabled_receivers)
potential_receivers = (enabled_receivers ++ disabled_receivers) -- potential_participants
{enabled_subscribers, disabled_subscribers} = get_notified_subscribers_from_activity(activity)
potential_subscribers =
(enabled_subscribers ++ disabled_subscribers) --
(potential_participants ++ potential_receivers)
notifications = notifications =
(Enum.map(potential_receivers, fn user -> (Enum.map(enabled_receivers, fn user ->
do_send = do_send && user in enabled_receivers create_notification(activity, user)
create_notification(activity, user, do_send: do_send)
end) ++ end) ++
Enum.map(potential_subscribers, fn user -> Enum.map(enabled_subscribers, fn user ->
do_send = do_send && user in enabled_subscribers create_notification(activity, user, type: "status")
create_notification(activity, user, do_send: do_send, type: "status")
end) ++ end) ++
Enum.map(potential_participants, fn user -> Enum.map(enabled_participants, fn user ->
do_send = do_send && user in enabled_participants create_notification(activity, user, type: "pleroma:event_update")
create_notification(activity, user, do_send: do_send, type: "pleroma:event_update")
end)) end))
|> Enum.reject(&is_nil/1) |> Enum.reject(&is_nil/1)
@ -493,7 +481,6 @@ defp type_from_activity_object(%{data: %{"type" => "Create"}} = activity) do
# TODO move to sql, too. # TODO move to sql, too.
def create_notification(%Activity{} = activity, %User{} = user, opts \\ []) do def create_notification(%Activity{} = activity, %User{} = user, opts \\ []) do
do_send = Keyword.get(opts, :do_send, true)
type = Keyword.get(opts, :type, type_from_activity(activity)) type = Keyword.get(opts, :type, type_from_activity(activity))
unless skip?(activity, user, opts) do unless skip?(activity, user, opts) do
@ -508,11 +495,6 @@ def create_notification(%Activity{} = activity, %User{} = user, opts \\ []) do
|> Marker.multi_set_last_read_id(user, "notifications") |> Marker.multi_set_last_read_id(user, "notifications")
|> Repo.transaction() |> Repo.transaction()
if do_send do
Streamer.stream(["user", "user:notification"], notification)
Push.send(notification)
end
notification notification
end end
end end
@ -594,10 +576,7 @@ def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, lo
|> exclude_relationship_restricted_ap_ids(activity) |> exclude_relationship_restricted_ap_ids(activity)
|> exclude_thread_muter_ap_ids(activity) |> exclude_thread_muter_ap_ids(activity)
notification_enabled_users = Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
{notification_enabled_users, potential_receivers -- notification_enabled_users}
end end
def get_notified_from_activity(_, _local_only), do: {[], []} def get_notified_from_activity(_, _local_only), do: {[], []}
@ -615,10 +594,7 @@ def get_notified_subscribers_from_activity(
potential_receivers = potential_receivers =
User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only) User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only)
notification_enabled_users = Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
{notification_enabled_users, potential_receivers -- notification_enabled_users}
end end
def get_notified_subscribers_from_activity(_, _), do: {[], []} def get_notified_subscribers_from_activity(_, _), do: {[], []}
@ -636,10 +612,7 @@ def get_notified_participants_from_activity(
potential_receivers = potential_receivers =
User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only) User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only)
notification_enabled_users = Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
Enum.filter(potential_receivers, fn u -> u.ap_id in notification_enabled_ap_ids end)
{notification_enabled_users, potential_receivers -- notification_enabled_users}
end end
def get_notified_participants_from_activity(_, _), do: {[], []} def get_notified_participants_from_activity(_, _), do: {[], []}
@ -780,6 +753,7 @@ def skip?(activity, user, opts \\ [])
def skip?(%Activity{} = activity, %User{} = user, opts) do def skip?(%Activity{} = activity, %User{} = user, opts) do
[ [
:self, :self,
:internal,
:invisible, :invisible,
:block_from_strangers, :block_from_strangers,
:recently_followed, :recently_followed,
@ -799,6 +773,12 @@ def skip?(:self, %Activity{} = activity, %User{} = user, opts) do
end end
end end
def skip?(:internal, %Activity{} = activity, _user, _opts) do
actor = activity.data["actor"]
user = User.get_cached_by_ap_id(actor)
User.internal?(user)
end
def skip?(:invisible, %Activity{} = activity, _user, _opts) do def skip?(:invisible, %Activity{} = activity, _user, _opts) do
actor = activity.data["actor"] actor = activity.data["actor"]
user = User.get_cached_by_ap_id(actor) user = User.get_cached_by_ap_id(actor)
@ -885,4 +865,12 @@ def mark_context_as_read(%User{id: id}, context) do
) )
|> Repo.update_all(set: [seen: true]) |> Repo.update_all(set: [seen: true])
end end
@spec send(list(Notification.t())) :: :ok
def send(notifications) do
Enum.each(notifications, fn notification ->
Streamer.stream(["user", "user:notification"], notification)
Push.send(notification)
end)
end
end end

View file

@ -1515,6 +1515,7 @@ def fetch_activities_query(recipients, opts \\ %{}) do
|> restrict_announce_object_actor(opts) |> restrict_announce_object_actor(opts)
|> restrict_object(opts) |> restrict_object(opts)
|> restrict_filtered(opts) |> restrict_filtered(opts)
|> restrict_rule(opts)
|> restrict_quote_url(opts) |> restrict_quote_url(opts)
|> restrict_rule(opts) |> restrict_rule(opts)
|> maybe_restrict_deactivated_users(opts) |> maybe_restrict_deactivated_users(opts)

View file

@ -21,7 +21,6 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Pipeline alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Push
alias Pleroma.Web.Streamer alias Pleroma.Web.Streamer
alias Pleroma.Workers.EventReminderWorker alias Pleroma.Workers.EventReminderWorker
alias Pleroma.Workers.PollWorker alias Pleroma.Workers.PollWorker
@ -115,7 +114,7 @@ def handle(
nil nil
end end
{:ok, notifications} = Notification.create_notifications(object, do_send: false) {:ok, notifications} = Notification.create_notifications(object)
meta = meta =
meta meta
@ -174,7 +173,11 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do
liked_object = Object.get_by_ap_id(object.data["object"]) liked_object = Object.get_by_ap_id(object.data["object"])
Utils.add_like_to_object(object, liked_object) Utils.add_like_to_object(object, liked_object)
Notification.create_notifications(object) {:ok, notifications} = Notification.create_notifications(object)
meta =
meta
|> add_notifications(notifications)
{:ok, object, meta} {:ok, object, meta}
end end
@ -192,7 +195,7 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do
def handle(%{data: %{"type" => "Create"}} = activity, meta) do def handle(%{data: %{"type" => "Create"}} = activity, meta) do
with {:ok, object, meta} <- handle_object_creation(meta[:object_data], activity, meta), with {:ok, object, meta} <- handle_object_creation(meta[:object_data], activity, meta),
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
{:ok, notifications} = Notification.create_notifications(activity, do_send: false) {:ok, notifications} = Notification.create_notifications(activity)
{:ok, _user} = ActivityPub.increase_note_count_if_public(user, object) {:ok, _user} = ActivityPub.increase_note_count_if_public(user, object)
{:ok, _user} = ActivityPub.update_last_status_at_if_public(user, object) {:ok, _user} = ActivityPub.update_last_status_at_if_public(user, object)
@ -250,11 +253,13 @@ def handle(%{data: %{"type" => "Announce"}} = object, meta) do
Utils.add_announce_to_object(object, announced_object) Utils.add_announce_to_object(object, announced_object)
if !User.internal?(user) do {:ok, notifications} = Notification.create_notifications(object)
Notification.create_notifications(object)
ap_streamer().stream_out(object) if !User.internal?(user), do: ap_streamer().stream_out(object)
end
meta =
meta
|> add_notifications(notifications)
{:ok, object, meta} {:ok, object, meta}
end end
@ -275,7 +280,11 @@ def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do
reacted_object = Object.get_by_ap_id(object.data["object"]) reacted_object = Object.get_by_ap_id(object.data["object"])
Utils.add_emoji_reaction_to_object(object, reacted_object) Utils.add_emoji_reaction_to_object(object, reacted_object)
Notification.create_notifications(object) {:ok, notifications} = Notification.create_notifications(object)
meta =
meta
|> add_notifications(notifications)
{:ok, object, meta} {:ok, object, meta}
end end
@ -679,10 +688,7 @@ defp delete_object(object) do
defp send_notifications(meta) do defp send_notifications(meta) do
Keyword.get(meta, :notifications, []) Keyword.get(meta, :notifications, [])
|> Enum.each(fn notification -> |> Notification.send()
Streamer.stream(["user", "user:notification"], notification)
Push.send(notification)
end)
meta meta
end end

View file

@ -60,8 +60,8 @@ def render("show.json", %{
}), }),
state: report.data["state"], state: report.data["state"],
notes: render(__MODULE__, "index_notes.json", %{notes: report.report_notes}), notes: render(__MODULE__, "index_notes.json", %{notes: report.report_notes}),
assigned_account: assigned_account, rules: rules(Map.get(report.data, "rules", nil)),
rules: rules(Map.get(report.data, "rules", nil)) assigned_account: assigned_account
} }
end end

View file

@ -97,6 +97,7 @@ def spec(opts \\ []) do
"Frontend management", "Frontend management",
"Instance configuration", "Instance configuration",
"Instance documents", "Instance documents",
"Instance rule managment",
"Invites", "Invites",
"MediaProxy cache", "MediaProxy cache",
"OAuth application management", "OAuth application management",

View file

@ -198,9 +198,6 @@ defp report do
} }
} }
}, },
assigned_account:
account_admin()
|> Map.put(:nullable, true),
rules: %Schema{ rules: %Schema{
type: :array, type: :array,
items: %Schema{ items: %Schema{
@ -211,7 +208,10 @@ defp report do
hint: %Schema{type: :string, nullable: true} hint: %Schema{type: :string, nullable: true}
} }
} }
} },
assigned_account:
account_admin()
|> Map.put(:nullable, true)
} }
} }
end end

View file

@ -185,10 +185,10 @@ def features do
defp common_information(instance) do defp common_information(instance) do
%{ %{
title: Keyword.get(instance, :name),
version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.compat_version()})",
languages: Keyword.get(instance, :languages, ["en"]), languages: Keyword.get(instance, :languages, ["en"]),
rules: render(__MODULE__, "rules.json") rules: render(__MODULE__, "rules.json"),
title: Keyword.get(instance, :name),
version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.compat_version()})"
} }
end end

View file

@ -1,155 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RichMedia.Parser.Card do
alias Pleroma.Web.RichMedia.Parser.Card
alias Pleroma.Web.RichMedia.Parser.Embed
@types ["link", "photo", "video", "rich"]
# https://docs.joinmastodon.org/entities/card/
defstruct url: nil,
title: nil,
description: "",
type: "link",
author_name: "",
author_url: "",
provider_name: "",
provider_url: "",
html: "",
width: 0,
height: 0,
image: nil,
image_description: "",
embed_url: "",
blurhash: nil
def parse(%Embed{url: url, oembed: %{"type" => type, "title" => title} = oembed} = embed)
when type in @types and is_binary(url) do
uri = URI.parse(url)
%Card{
url: url,
title: title,
description: get_description(embed),
type: oembed["type"],
author_name: oembed["author_name"],
author_url: oembed["author_url"],
provider_name: oembed["provider_name"] || uri.host,
provider_url: oembed["provider_url"] || "#{uri.scheme}://#{uri.host}",
html: sanitize_html(oembed["html"]),
width: oembed["width"],
height: oembed["height"],
image: get_image(oembed) |> fix_uri(url) |> proxy(),
image_description: get_image_description(embed),
embed_url: oembed["url"] |> fix_uri(url) |> proxy()
}
|> IO.inspect
|> validate()
end
def parse(%Embed{url: url} = embed) when is_binary(url) do
uri = URI.parse(url)
%Card{
url: url,
title: get_title(embed),
description: get_description(embed),
type: "link",
provider_name: uri.host,
provider_url: "#{uri.scheme}://#{uri.host}",
image: get_image(embed) |> fix_uri(url) |> proxy(),
image_description: get_image_description(embed),
}
|> validate()
end
def parse(card), do: {:error, {:invalid_metadata, card}}
defp get_title(embed) do
case embed do
%{meta: %{"twitter:title" => title}} when is_binary(title) and title != "" -> title
%{meta: %{"og:title" => title}} when is_binary(title) and title != "" -> title
%{title: title} when is_binary(title) and title != "" -> title
_ -> nil
end
end
defp get_description(%{meta: meta}) do
case meta do
%{"twitter:description" => desc} when is_binary(desc) and desc != "" -> desc
%{"og:description" => desc} when is_binary(desc) and desc != "" -> desc
%{"description" => desc} when is_binary(desc) and desc != "" -> desc
_ -> ""
end
end
defp get_image(%{meta: meta}) do
case meta do
%{"twitter:image" => image} when is_binary(image) and image != "" -> image
%{"og:image" => image} when is_binary(image) and image != "" -> image
_ -> ""
end
end
defp get_image(%{"thumbnail_url" => image}) when is_binary(image) and image != "", do: image
defp get_image(%{"type" => "photo", "url" => image}), do: image
defp get_image(_), do: ""
defp get_image_description(%{meta: %{"og:image:alt" => image_description}}), do: image_description
defp get_image_description(_), do: ""
defp sanitize_html(html) do
with {:ok, html} <- FastSanitize.Sanitizer.scrub(html, Pleroma.HTML.Scrubber.OEmbed),
{:ok, [{"iframe", _, _}]} <- Floki.parse_fragment(html) do
html
else
_ -> ""
end
end
def to_map(%Card{} = card) do
card
|> Map.from_struct()
|> stringify_keys()
end
def to_map(%{} = card), do: stringify_keys(card)
defp stringify_keys(%{} = map), do: Map.new(map, fn {k, v} -> {Atom.to_string(k), v} end)
def fix_uri("http://" <> _ = uri, _base_uri), do: uri
def fix_uri("https://" <> _ = uri, _base_uri), do: uri
def fix_uri("/" <> _ = uri, base_uri), do: URI.merge(base_uri, uri) |> URI.to_string()
def fix_uri("", _base_uri), do: nil
def fix_uri(uri, base_uri) when is_binary(uri),
do: URI.merge(base_uri, "/#{uri}") |> URI.to_string()
def fix_uri(_uri, _base_uri), do: nil
defp proxy(url) when is_binary(url), do: Pleroma.Web.MediaProxy.url(url)
defp proxy(_), do: nil
def validate(%Card{type: type, html: html} = card)
when type in ["video", "rich"] and (is_binary(html) == false or html == "") do
card
|> Map.put(:type, "link")
|> validate()
end
def validate(%Card{type: type, title: title} = card)
when type in @types and is_binary(title) and title != "" do
{:ok, card}
end
def validate(%Embed{} = embed) do
case Card.parse(embed) do
{:ok, %Card{} = card} -> validate(card)
card -> {:error, {:invalid_metadata, card}}
end
end
def validate(card), do: {:error, {:invalid_metadata, card}}
end

View file

@ -14,8 +14,9 @@ defmodule Pleroma.Workers.NotificationWorker do
@impl Oban.Worker @impl Oban.Worker
@spec perform(Oban.Job.t()) :: {:error, :activity_not_found} | {:ok, [Pleroma.Notification.t()]} @spec perform(Oban.Job.t()) :: {:error, :activity_not_found} | {:ok, [Pleroma.Notification.t()]}
def perform(%Job{args: %{"op" => "create", "activity_id" => activity_id}}) do def perform(%Job{args: %{"op" => "create", "activity_id" => activity_id}}) do
with %Activity{} = activity <- find_activity(activity_id) do with %Activity{} = activity <- find_activity(activity_id),
Notification.create_notifications(activity) {:ok, notifications} <- Notification.create_notifications(activity) do
Notification.send(notifications)
end end
end end

View file

@ -1,10 +1,10 @@
{ {
"actor": "http://2hu.gensokyo/users/raymoo", "actor": "http://mastodon.example.org/users/admin",
"id": "http://2hu.gensokyo/objects/1", "id": "http://mastodon.example.org/objects/1",
"object": { "object": {
"attributedTo": "http://2hu.gensokyo/users/raymoo", "attributedTo": "http://mastodon.example.org/users/admin",
"content": "You expected a cute girl? Too bad. <script>alert('XSS')</script>", "content": "You expected a cute girl? Too bad. <script>alert('XSS')</script>",
"id": "http://2hu.gensokyo/objects/2", "id": "http://mastodon.example.org/objects/2",
"published": "2020-02-12T14:08:20Z", "published": "2020-02-12T14:08:20Z",
"to": [ "to": [
"http://2hu.gensokyo/users/marisa" "http://2hu.gensokyo/users/marisa"

View file

@ -6,7 +6,6 @@ defmodule Pleroma.NotificationTest do
use Pleroma.DataCase, async: false use Pleroma.DataCase, async: false
import Pleroma.Factory import Pleroma.Factory
import Mock
alias Pleroma.FollowingRelationship alias Pleroma.FollowingRelationship
alias Pleroma.Notification alias Pleroma.Notification
@ -18,8 +17,6 @@ defmodule Pleroma.NotificationTest do
alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI.NotificationView alias Pleroma.Web.MastodonAPI.NotificationView
alias Pleroma.Web.Push
alias Pleroma.Web.Streamer
setup do setup do
Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config) Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config)
@ -392,83 +389,6 @@ test "create_poll_notifications/1" do
end end
describe "create_notification" do describe "create_notification" do
@tag needs_streamer: true
test "it creates a notification for user and send to the 'user' and the 'user:notification' stream" do
%{user: user, token: oauth_token} = oauth_access(["read"])
task =
Task.async(fn ->
{:ok, _topic} = Streamer.get_topic_and_add_socket("user", user, oauth_token)
assert_receive {:render_with_user, _, _, _, _}, 4_000
end)
task_user_notification =
Task.async(fn ->
{:ok, _topic} =
Streamer.get_topic_and_add_socket("user:notification", user, oauth_token)
assert_receive {:render_with_user, _, _, _, _}, 4_000
end)
activity = insert(:note_activity)
notify = Notification.create_notification(activity, user)
assert notify.user_id == user.id
Task.await(task)
Task.await(task_user_notification)
end
test "it creates a notification for user if the user blocks the activity author" do
activity = insert(:note_activity)
author = User.get_cached_by_ap_id(activity.data["actor"])
user = insert(:user)
{:ok, _user_relationship} = User.block(user, author)
assert Notification.create_notification(activity, user)
end
test "it creates a notification for the user if the user mutes the activity author" do
muter = insert(:user)
muted = insert(:user)
{:ok, _} = User.mute(muter, muted)
muter = Repo.get(User, muter.id)
{:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
notification = Notification.create_notification(activity, muter)
assert notification.id
assert notification.seen
end
test "notification created if user is muted without notifications" do
muter = insert(:user)
muted = insert(:user)
{:ok, _user_relationships} = User.mute(muter, muted, %{notifications: false})
{:ok, activity} = CommonAPI.post(muted, %{status: "Hi @#{muter.nickname}"})
assert Notification.create_notification(activity, muter)
end
test "it creates a notification for an activity from a muted thread" do
muter = insert(:user)
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(muter, %{status: "hey"})
CommonAPI.add_mute(muter, activity)
{:ok, activity} =
CommonAPI.post(other_user, %{
status: "Hi @#{muter.nickname}",
in_reply_to_status_id: activity.id
})
notification = Notification.create_notification(activity, muter)
assert notification.id
assert notification.seen
end
test "it disables notifications from strangers" do test "it disables notifications from strangers" do
follower = insert(:user) follower = insert(:user)
@ -856,7 +776,7 @@ test "it sends notifications to addressed users in new messages" do
status: "hey @#{other_user.nickname}!" status: "hey @#{other_user.nickname}!"
}) })
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) enabled_receivers = Notification.get_notified_from_activity(activity)
assert other_user in enabled_receivers assert other_user in enabled_receivers
end end
@ -888,7 +808,7 @@ test "it sends notifications to mentioned users in new messages" do
{:ok, activity} = Transmogrifier.handle_incoming(create_activity) {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) enabled_receivers = Notification.get_notified_from_activity(activity)
assert other_user in enabled_receivers assert other_user in enabled_receivers
end end
@ -915,7 +835,7 @@ test "it does not send notifications to users who are only cc in new messages" d
{:ok, activity} = Transmogrifier.handle_incoming(create_activity) {:ok, activity} = Transmogrifier.handle_incoming(create_activity)
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(activity) enabled_receivers = Notification.get_notified_from_activity(activity)
assert other_user not in enabled_receivers assert other_user not in enabled_receivers
end end
@ -932,8 +852,7 @@ test "it does not send notification to mentioned users in likes" do
{:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id) {:ok, activity_two} = CommonAPI.favorite(third_user, activity_one.id)
{enabled_receivers, _disabled_receivers} = enabled_receivers = Notification.get_notified_from_activity(activity_two)
Notification.get_notified_from_activity(activity_two)
assert other_user not in enabled_receivers assert other_user not in enabled_receivers
end end
@ -955,7 +874,7 @@ test "it only notifies the post's author in likes" do
|> Map.put("to", [other_user.ap_id | like_data["to"]]) |> Map.put("to", [other_user.ap_id | like_data["to"]])
|> ActivityPub.persist(local: true) |> ActivityPub.persist(local: true)
{enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like) enabled_receivers = Notification.get_notified_from_activity(like)
assert other_user not in enabled_receivers assert other_user not in enabled_receivers
end end
@ -972,39 +891,36 @@ test "it does not send notification to mentioned users in announces" do
{:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user) {:ok, activity_two} = CommonAPI.repeat(activity_one.id, third_user)
{enabled_receivers, _disabled_receivers} = enabled_receivers = Notification.get_notified_from_activity(activity_two)
Notification.get_notified_from_activity(activity_two)
assert other_user not in enabled_receivers assert other_user not in enabled_receivers
end end
test "it returns blocking recipient in disabled recipients list" do test "it does not return blocking recipient in recipients list" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
{:ok, _user_relationship} = User.block(other_user, user) {:ok, _user_relationship} = User.block(other_user, user)
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"}) {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) enabled_receivers = Notification.get_notified_from_activity(activity)
assert [] == enabled_receivers assert [] == enabled_receivers
assert [other_user] == disabled_receivers
end end
test "it returns notification-muting recipient in disabled recipients list" do test "it does not return notification-muting recipient in recipients list" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
{:ok, _user_relationships} = User.mute(other_user, user) {:ok, _user_relationships} = User.mute(other_user, user)
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"}) {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) enabled_receivers = Notification.get_notified_from_activity(activity)
assert [] == enabled_receivers assert [] == enabled_receivers
assert [other_user] == disabled_receivers
end end
test "it returns thread-muting recipient in disabled recipients list" do test "it does not return thread-muting recipient in recipients list" do
user = insert(:user) user = insert(:user)
other_user = insert(:user) other_user = insert(:user)
@ -1018,14 +934,12 @@ test "it returns thread-muting recipient in disabled recipients list" do
in_reply_to_status_id: activity.id in_reply_to_status_id: activity.id
}) })
{enabled_receivers, disabled_receivers} = enabled_receivers = Notification.get_notified_from_activity(same_context_activity)
Notification.get_notified_from_activity(same_context_activity)
assert [other_user] == disabled_receivers
refute other_user in enabled_receivers refute other_user in enabled_receivers
end end
test "it returns non-following domain-blocking recipient in disabled recipients list" do test "it does not return non-following domain-blocking recipient in recipients list" do
blocked_domain = "blocked.domain" blocked_domain = "blocked.domain"
user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"}) user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
other_user = insert(:user) other_user = insert(:user)
@ -1034,10 +948,9 @@ test "it returns non-following domain-blocking recipient in disabled recipients
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"}) {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) enabled_receivers = Notification.get_notified_from_activity(activity)
assert [] == enabled_receivers assert [] == enabled_receivers
assert [other_user] == disabled_receivers
end end
test "it returns following domain-blocking recipient in enabled recipients list" do test "it returns following domain-blocking recipient in enabled recipients list" do
@ -1050,10 +963,9 @@ test "it returns following domain-blocking recipient in enabled recipients list"
{:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"}) {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{other_user.nickname}!"})
{enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity) enabled_receivers = Notification.get_notified_from_activity(activity)
assert [other_user] == enabled_receivers assert [other_user] == enabled_receivers
assert [] == disabled_receivers
end end
test "it sends edited notifications to those who repeated a status" do test "it sends edited notifications to those who repeated a status" do
@ -1073,11 +985,10 @@ test "it sends edited notifications to those who repeated a status" do
status: "hey @#{other_user.nickname}! mew mew" status: "hey @#{other_user.nickname}! mew mew"
}) })
{enabled_receivers, _disabled_receivers} = enabled_receivers = Notification.get_notified_from_activity(edit_activity)
Notification.get_notified_from_activity(edit_activity)
assert repeated_user in enabled_receivers assert repeated_user in enabled_receivers
assert other_user not in enabled_receivers refute other_user in enabled_receivers
end end
end end
@ -1354,7 +1265,7 @@ test "it doesn't return notifications for muted thread", %{user: user} do
assert Notification.for_user(user) == [] assert Notification.for_user(user) == []
end end
test "it returns notifications from a muted user when with_muted is set", %{user: user} do test "it doesn't return notifications from a muted user when with_muted is set", %{user: user} do
muted = insert(:user) muted = insert(:user)
{:ok, _user_relationships} = User.mute(user, muted) {:ok, _user_relationships} = User.mute(user, muted)
@ -1362,7 +1273,7 @@ test "it returns notifications from a muted user when with_muted is set", %{user
Pleroma.Tests.ObanHelpers.perform_all() Pleroma.Tests.ObanHelpers.perform_all()
assert length(Notification.for_user(user, %{with_muted: true})) == 1 assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
end end
test "it doesn't return notifications from a blocked user when with_muted is set", %{ test "it doesn't return notifications from a blocked user when with_muted is set", %{

View file

@ -230,7 +230,6 @@ test "it creates a zip archive with user data" do
"orderedItems" => [ "orderedItems" => [
%{ %{
"object" => %{ "object" => %{
"actor" => "http://cofe.io/users/cofe",
"content" => "status1", "content" => "status1",
"type" => "Note" "type" => "Note"
}, },
@ -238,7 +237,6 @@ test "it creates a zip archive with user data" do
}, },
%{ %{
"object" => %{ "object" => %{
"actor" => "http://cofe.io/users/cofe",
"content" => "status2" "content" => "status2"
} }
}, },

View file

@ -854,31 +854,6 @@ test "creates a notification", %{announce: announce, poster: poster} do
{:ok, announce, _} = SideEffects.handle(announce) {:ok, announce, _} = SideEffects.handle(announce)
assert Repo.get_by(Notification, user_id: poster.id, activity_id: announce.id) assert Repo.get_by(Notification, user_id: poster.id, activity_id: announce.id)
end end
test "it streams out the announce", %{announce: announce} do
with_mocks([
{
Pleroma.Web.Streamer,
[],
[
stream: fn _, _ -> nil end
]
},
{
Pleroma.Web.Push,
[],
[
send: fn _ -> nil end
]
}
]) do
{:ok, announce, _} = SideEffects.handle(announce)
assert called(Pleroma.Web.Streamer.stream(["user", "list"], announce))
assert called(Pleroma.Web.Push.send(:_))
end
end
end end
describe "removing a follower" do describe "removing a follower" do

View file

@ -116,8 +116,6 @@ test "it fetches the actor if they aren't in our system" do
data = data =
File.read!("test/fixtures/create-chat-message.json") File.read!("test/fixtures/create-chat-message.json")
|> Jason.decode!() |> Jason.decode!()
|> Map.put("actor", "http://mastodon.example.org/users/admin")
|> put_in(["object", "actor"], "http://mastodon.example.org/users/admin")
_recipient = insert(:user, ap_id: List.first(data["to"]), local: true) _recipient = insert(:user, ap_id: List.first(data["to"]), local: true)

View file

@ -169,7 +169,7 @@ test "it inlines private announced objects" do
{:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data) {:ok, modified} = Transmogrifier.prepare_outgoing(announce_activity.data)
assert modified["object"]["content"] == "hey" assert modified["object"]["content"] == "hey"
assert modified["object"]["actor"] == modified["object"]["attributedTo"] assert activity.actor == modified["object"]["attributedTo"]
end end
test "it turns mentions into tags" do test "it turns mentions into tags" do
@ -220,7 +220,7 @@ test "it sets the 'attributedTo' property to the actor of the object if it doesn
{:ok, activity} = CommonAPI.post(user, %{status: "hey"}) {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data) {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["object"]["actor"] == modified["object"]["attributedTo"] assert activity.actor == modified["object"]["attributedTo"]
end end
test "it strips internal hashtag data" do test "it strips internal hashtag data" do
@ -266,6 +266,7 @@ test "it strips internal fields" do
assert is_nil(modified["object"]["announcements"]) assert is_nil(modified["object"]["announcements"])
assert is_nil(modified["object"]["announcement_count"]) assert is_nil(modified["object"]["announcement_count"])
assert is_nil(modified["object"]["generator"]) assert is_nil(modified["object"]["generator"])
assert is_nil(modified["object"]["actor"])
end end
test "it strips internal fields of article" do test "it strips internal fields of article" do

View file

@ -103,31 +103,6 @@ test "get peers", %{conn: conn} do
assert ["peer1.com", "peer2.com"] == Enum.sort(result) assert ["peer1.com", "peer2.com"] == Enum.sort(result)
end end
test "get instance rules", %{conn: conn} do
Rule.create(%{text: "Example rule", hint: "Rule description", priority: 1})
Rule.create(%{text: "Third rule", priority: 2})
Rule.create(%{text: "Second rule", priority: 1})
conn = get(conn, "/api/v1/instance")
assert result = json_response_and_validate_schema(conn, 200)
assert [
%{
"text" => "Example rule",
"hint" => "Rule description"
},
%{
"text" => "Second rule",
"hint" => ""
},
%{
"text" => "Third rule",
"hint" => ""
}
] = result["rules"]
end
test "get instance configuration", %{conn: conn} do test "get instance configuration", %{conn: conn} do
clear_config([:instance, :limit], 476) clear_config([:instance, :limit], 476)
@ -275,4 +250,29 @@ test "instance domains", %{conn: conn} do
|> get("/api/v1/instance") |> get("/api/v1/instance")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
end end
test "get instance rules", %{conn: conn} do
Rule.create(%{text: "Example rule", hint: "Rule description", priority: 1})
Rule.create(%{text: "Third rule", priority: 2})
Rule.create(%{text: "Second rule", priority: 1})
conn = get(conn, "/api/v1/instance")
assert result = json_response_and_validate_schema(conn, 200)
assert [
%{
"text" => "Example rule",
"hint" => "Rule description"
},
%{
"text" => "Second rule",
"hint" => ""
},
%{
"text" => "Third rule",
"hint" => ""
}
] = result["rules"]
end
end end