logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma
commit: 90537f398160eddfb8033c1cdfe1acc21ee63c4a
parent: 6d74a7528c31e6215d808627f1c393ab53d99782
Author: rinpatch <rinpatch@sdf.org>
Date:   Sun, 29 Sep 2019 20:07:37 +0000

Merge branch 'revert/subscription-refactoring' into 'develop'

Revert subscription refactoring.

See merge request pleroma/pleroma!1741

Diffstat:

MCHANGELOG.md9++-------
Mlib/pleroma/notification.ex1+
Dlib/pleroma/subscription_notification.ex260-------------------------------------------------------------------------------
Mlib/pleroma/web/activity_pub/activity_pub.ex2--
Dlib/pleroma/web/pleroma_api/controllers/subscription_notification_controller.ex71-----------------------------------------------------------------------
Dlib/pleroma/web/pleroma_api/pleroma_api.ex40----------------------------------------
Dlib/pleroma/web/pleroma_api/views/subscription_notification_view.ex61-------------------------------------------------------------
Mlib/pleroma/web/push/impl.ex3+--
Mlib/pleroma/web/router.ex8--------
Dpriv/repo/migrations/20190824195028_create_subscription_notifications.exs15---------------
Mtest/notification_test.exs12+++++-------
Mtest/web/mastodon_api/mastodon_api_test.exs4++--
Dtest/web/pleroma_api/controllers/subscription_notification_controller_test.exs234-------------------------------------------------------------------------------
Rtest/web/pleroma_api/controllers/pleroma_api_controller_test.exs -> test/web/pleroma_api/pleroma_api_controller_test.exs0
14 files changed, 11 insertions(+), 709 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -7,12 +7,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Refreshing poll results for remote polls - Admin API: Add ability to require password reset -- Pleroma API: `GET /api/v1/pleroma/subscription_notifications/` to get list of subscription notifications -- Pleroma API: `GET /api/v1/pleroma/subscription_notifications/:id` to get a subscription notification -- Pleroma API: `POST /api/v1/pleroma/subscription_notifications/clear` to clear all subscription notifications -- Pleroma API: `POST /api/v1/pleroma/subscription_notifications/dismiss` to clear a subscription notification -- Pleroma API: `DELETE /api/v1/pleroma/subscription_notifications/destroy_multiple` to clear multiple subscription notifications -- Mastodon API: Account entities now include `follow_requests_count` (planned Mastodon 3.x addition) ### Changed - **Breaking:** Elixir >=1.8 is now required (was >= 1.7) @@ -21,7 +15,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Introduced [quantum](https://github.com/quantum-elixir/quantum-core) job scheduler - Admin API: Return `total` when querying for reports - Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`) -- Mastodon API: notifications no longer include subscription notifications - they are now served from new endpoints in Pleroma API +- Admin API: Return link alongside with token on password reset + ### Fixed - Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex @@ -230,6 +230,7 @@ defmodule Pleroma.Notification do [] |> Utils.maybe_notify_to_recipients(activity) |> Utils.maybe_notify_mentioned_recipients(activity) + |> Utils.maybe_notify_subscribers(activity) |> Enum.uniq() User.get_users_from_set(recipients, local_only) diff --git a/lib/pleroma/subscription_notification.ex b/lib/pleroma/subscription_notification.ex @@ -1,260 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.SubscriptionNotification do - use Ecto.Schema - - alias Pleroma.Activity - alias Pleroma.Object - alias Pleroma.Pagination - alias Pleroma.Repo - alias Pleroma.SubscriptionNotification - alias Pleroma.User - alias Pleroma.Web.CommonAPI.Utils - alias Pleroma.Web.Push - alias Pleroma.Web.Streamer - - import Ecto.Query - import Ecto.Changeset - - @type t :: %__MODULE__{} - - schema "subscription_notifications" do - belongs_to(:user, User, type: FlakeId.Ecto.CompatType) - belongs_to(:activity, Activity, type: FlakeId.Ecto.CompatType) - - timestamps() - end - - def changeset(%SubscriptionNotification{} = notification, attrs) do - cast(notification, attrs, []) - end - - def for_user_query(user, opts \\ []) do - query = - SubscriptionNotification - |> where(user_id: ^user.id) - |> where( - [n, a], - fragment( - "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')", - a.actor - ) - ) - |> join(:inner, [n], activity in assoc(n, :activity)) - |> join(:left, [n, a], object in Object, - on: - fragment( - "(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)", - object.data, - a.data - ) - ) - |> preload([n, a, o], activity: {a, object: o}) - - if opts[:with_muted] do - query - else - query - |> where([n, a], a.actor not in ^user.info.muted_notifications) - |> where([n, a], a.actor not in ^user.info.blocks) - |> where( - [n, a], - fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks - ) - |> join(:left, [n, a], tm in Pleroma.ThreadMute, - on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data) - ) - |> where([n, a, o, tm], is_nil(tm.user_id)) - end - end - - def for_user(user, opts \\ %{}) do - user - |> for_user_query(opts) - |> Pagination.fetch_paginated(opts) - end - - @doc """ - Returns notifications for user received since given date. - - ## Examples - - iex> Pleroma.SubscriptionNotification.for_user_since(%Pleroma.User{}, ~N[2019-04-13 11:22:33]) - [%Pleroma.SubscriptionNotification{}, %Pleroma.SubscriptionNotification{}] - - iex> Pleroma.SubscriptionNotification.for_user_since(%Pleroma.User{}, ~N[2019-04-15 11:22:33]) - [] - """ - @spec for_user_since(Pleroma.User.t(), NaiveDateTime.t()) :: [t()] - def for_user_since(user, date) do - user - |> for_user_query() - |> where([n], n.updated_at > ^date) - |> Repo.all() - end - - def clear_up_to(%{id: user_id} = _user, id) do - from( - n in SubscriptionNotification, - where: n.user_id == ^user_id, - where: n.id <= ^id - ) - |> Repo.delete_all([]) - end - - def get(%{id: user_id} = _user, id) do - query = - from( - n in SubscriptionNotification, - where: n.id == ^id, - join: activity in assoc(n, :activity), - preload: [activity: activity] - ) - - case Repo.one(query) do - %{user_id: ^user_id} = notification -> - {:ok, notification} - - _ -> - {:error, "Cannot get notification"} - end - end - - def clear(user) do - from(n in SubscriptionNotification, where: n.user_id == ^user.id) - |> Repo.delete_all() - end - - def destroy_multiple(%{id: user_id} = _user, ids) do - from(n in SubscriptionNotification, - where: n.id in ^ids, - where: n.user_id == ^user_id - ) - |> Repo.delete_all() - end - - def dismiss(%{id: user_id} = _user, id) do - case Repo.get(SubscriptionNotification, id) do - %{user_id: ^user_id} = notification -> - Repo.delete(notification) - - _ -> - {:error, "Cannot dismiss notification"} - end - end - - def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity) do - case Object.normalize(activity) do - %{data: %{"type" => "Answer"}} -> - {:ok, []} - - _ -> - users = get_notified_from_activity(activity) - notifications = Enum.map(users, fn user -> create_notification(activity, user) end) - {:ok, notifications} - end - end - - def create_notifications(%Activity{data: %{"to" => _, "type" => type}} = activity) - when type in ["Like", "Announce", "Follow"] do - notifications = - activity - |> get_notified_from_activity() - |> Enum.map(&create_notification(activity, &1)) - - {:ok, notifications} - end - - def create_notifications(_), do: {:ok, []} - - # TODO move to sql, too. - def create_notification(%Activity{} = activity, %User{} = user) do - unless skip?(activity, user) do - notification = %SubscriptionNotification{user_id: user.id, activity: activity} - {:ok, notification} = Repo.insert(notification) - Streamer.stream("user", notification) - Streamer.stream("user:subscription_notification", notification) - Push.send(notification) - notification - end - end - - def get_notified_from_activity(activity, local_only \\ true) - - def get_notified_from_activity( - %Activity{data: %{"to" => _, "type" => type} = _data} = activity, - local_only - ) - when type in ["Create", "Like", "Announce", "Follow"] do - [] - |> Utils.maybe_notify_subscribers(activity) - |> Enum.uniq() - |> User.get_users_from_set(local_only) - end - - def get_notified_from_activity(_, _local_only), do: [] - - @spec skip?(Activity.t(), User.t()) :: boolean() - def skip?(activity, user) do - [ - :self, - :followers, - :follows, - :non_followers, - :non_follows, - :recently_followed - ] - |> Enum.any?(&skip?(&1, activity, user)) - end - - @spec skip?(atom(), Activity.t(), User.t()) :: boolean() - def skip?(:self, activity, user) do - activity.data["actor"] == user.ap_id - end - - def skip?( - :followers, - %{data: %{"actor" => actor}}, - %{info: %{notification_settings: %{"followers" => false}}} = user - ) do - actor - |> User.get_cached_by_ap_id() - |> User.following?(user) - end - - def skip?( - :non_followers, - activity, - %{info: %{notification_settings: %{"non_followers" => false}}} = user - ) do - actor = activity.data["actor"] - follower = User.get_cached_by_ap_id(actor) - !User.following?(follower, user) - end - - def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => false}}} = user) do - actor = activity.data["actor"] - followed = User.get_cached_by_ap_id(actor) - User.following?(user, followed) - end - - def skip?( - :non_follows, - activity, - %{info: %{notification_settings: %{"non_follows" => false}}} = user - ) do - actor = activity.data["actor"] - followed = User.get_cached_by_ap_id(actor) - !User.following?(user, followed) - end - - def skip?(:recently_followed, %{data: %{"type" => "Follow", "actor" => actor}}, user) do - user - |> SubscriptionNotification.for_user() - |> Enum.any?(&match?(%{activity: %{data: %{"type" => "Follow", "actor" => ^actor}}}, &1)) - end - - def skip?(_, _, _), do: false -end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -13,7 +13,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do alias Pleroma.Object.Fetcher alias Pleroma.Pagination alias Pleroma.Repo - alias Pleroma.SubscriptionNotification alias Pleroma.Upload alias Pleroma.User alias Pleroma.Web.ActivityPub.MRF @@ -152,7 +151,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do BackgroundWorker.enqueue("fetch_data_for_activity", %{"activity_id" => activity.id}) Notification.create_notifications(activity) - SubscriptionNotification.create_notifications(activity) participations = activity diff --git a/lib/pleroma/web/pleroma_api/controllers/subscription_notification_controller.ex b/lib/pleroma/web/pleroma_api/controllers/subscription_notification_controller.ex @@ -1,71 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.PleromaAPI.SubscriptionNotificationController do - use Pleroma.Web, :controller - - import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2] - - alias Pleroma.Activity - alias Pleroma.SubscriptionNotification - alias Pleroma.User - alias Pleroma.Web.PleromaAPI.PleromaAPI - - def index(%{assigns: %{user: user}} = conn, params) do - notifications = - user - |> PleromaAPI.get_subscription_notifications(params) - |> Enum.map(&build_notification_data/1) - - conn - |> add_link_headers(notifications) - |> render("index.json", %{notifications: notifications, for: user}) - end - - def show(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do - with {:ok, notification} <- SubscriptionNotification.get(user, id) do - render(conn, "show.json", %{ - subscription_notification: build_notification_data(notification), - for: user - }) - else - {:error, reason} -> - conn - |> put_status(:forbidden) - |> json(%{"error" => reason}) - end - end - - def clear(%{assigns: %{user: user}} = conn, _params) do - SubscriptionNotification.clear(user) - json(conn, %{}) - end - - def dismiss(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do - with {:ok, _notif} <- SubscriptionNotification.dismiss(user, id) do - json(conn, %{}) - else - {:error, reason} -> - conn - |> put_status(:forbidden) - |> json(%{"error" => reason}) - end - end - - def destroy_multiple( - %{assigns: %{user: user}} = conn, - %{"ids" => ids} = _params - ) do - SubscriptionNotification.destroy_multiple(user, ids) - json(conn, %{}) - end - - defp build_notification_data(%{activity: %{data: data}} = notification) do - %{ - notification: notification, - actor: User.get_cached_by_ap_id(data["actor"]), - parent_activity: Activity.get_create_by_object_ap_id(data["object"]) - } - end -end diff --git a/lib/pleroma/web/pleroma_api/pleroma_api.ex b/lib/pleroma/web/pleroma_api/pleroma_api.ex @@ -1,40 +0,0 @@ -defmodule Pleroma.Web.PleromaAPI.PleromaAPI do - import Ecto.Query - import Ecto.Changeset - - alias Pleroma.Activity - alias Pleroma.Pagination - alias Pleroma.SubscriptionNotification - - def get_subscription_notifications(user, params \\ %{}) do - options = cast_params(params) - - user - |> SubscriptionNotification.for_user_query(options) - |> restrict(:exclude_types, options) - |> Pagination.fetch_paginated(params) - end - - defp cast_params(params) do - param_types = %{ - exclude_types: {:array, :string}, - reblogs: :boolean, - with_muted: :boolean - } - - changeset = cast({%{}, param_types}, params, Map.keys(param_types)) - changeset.changes - end - - defp restrict(query, :exclude_types, %{exclude_types: mastodon_types = [_ | _]}) do - ap_types = - mastodon_types - |> Enum.map(&Activity.from_mastodon_notification_type/1) - |> Enum.filter(& &1) - - query - |> where([q, a], not fragment("? @> ARRAY[?->>'type']::varchar[]", ^ap_types, a.data)) - end - - defp restrict(query, _, _), do: query -end diff --git a/lib/pleroma/web/pleroma_api/views/subscription_notification_view.ex b/lib/pleroma/web/pleroma_api/views/subscription_notification_view.ex @@ -1,61 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.PleromaAPI.SubscriptionNotificationView do - use Pleroma.Web, :view - - alias Pleroma.Activity - alias Pleroma.Web.CommonAPI - alias Pleroma.Web.MastodonAPI.AccountView - alias Pleroma.Web.MastodonAPI.StatusView - alias Pleroma.Web.PleromaAPI.SubscriptionNotificationView - - def render("index.json", %{notifications: notifications, for: user}) do - safe_render_many(notifications, SubscriptionNotificationView, "show.json", %{for: user}) - end - - def render("show.json", %{ - subscription_notification: %{ - notification: %{activity: activity} = notification, - actor: actor, - parent_activity: parent_activity - }, - for: user - }) do - mastodon_type = Activity.mastodon_notification_type(activity) - - response = %{ - id: to_string(notification.id), - type: mastodon_type, - created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at), - account: AccountView.render("account.json", %{user: actor, for: user}) - } - - case mastodon_type do - "mention" -> - response - |> Map.merge(%{ - status: StatusView.render("show.json", %{activity: activity, for: user}) - }) - - "favourite" -> - response - |> Map.merge(%{ - status: StatusView.render("show.json", %{activity: parent_activity, for: user}) - }) - - "reblog" -> - response - |> Map.merge(%{ - status: StatusView.render("show.json", %{activity: parent_activity, for: user}) - }) - - "follow" -> - response - - _ -> - nil - end - end -end diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex @@ -9,7 +9,6 @@ defmodule Pleroma.Web.Push.Impl do alias Pleroma.Notification alias Pleroma.Object alias Pleroma.Repo - alias Pleroma.SubscriptionNotification alias Pleroma.User alias Pleroma.Web.Metadata.Utils alias Pleroma.Web.Push.Subscription @@ -20,7 +19,7 @@ defmodule Pleroma.Web.Push.Impl do @types ["Create", "Follow", "Announce", "Like"] @doc "Performs sending notifications for user subscriptions" - @spec perform(Notification.t() | SubscriptionNotification.t()) :: list(any) | :error + @spec perform(Notification.t()) :: list(any) | :error def perform( %{ activity: %{data: %{"type" => activity_type}, id: activity_id} = activity, diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex @@ -293,14 +293,6 @@ defmodule Pleroma.Web.Router do pipe_through(:oauth_read) get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses) get("/conversations/:id", PleromaAPIController, :conversation) - - scope "/subscription_notifications" do - post("/clear", SubscriptionNotificationController, :clear) - post("/dismiss", SubscriptionNotificationController, :dismiss) - delete("/destroy_multiple", SubscriptionNotificationController, :destroy_multiple) - get("/", SubscriptionNotificationController, :index) - get("/:id", SubscriptionNotificationController, :show) - end end scope [] do diff --git a/priv/repo/migrations/20190824195028_create_subscription_notifications.exs b/priv/repo/migrations/20190824195028_create_subscription_notifications.exs @@ -1,15 +0,0 @@ -defmodule Pleroma.Repo.Migrations.CreateSubscriptionNotifications do - use Ecto.Migration - - def change do - create_if_not_exists table(:subscription_notifications) do - add(:user_id, references(:users, type: :uuid, on_delete: :delete_all)) - add(:activity_id, references(:activities, type: :uuid, on_delete: :delete_all)) - - timestamps() - end - - create_if_not_exists(index(:subscription_notifications, [:user_id])) - create_if_not_exists(index(:subscription_notifications, ["id desc nulls last"])) - end -end diff --git a/test/notification_test.exs b/test/notification_test.exs @@ -33,16 +33,16 @@ defmodule Pleroma.NotificationTest do assert other_notification.activity_id == activity.id end - test "it does not create a notification for subscribed users" do + test "it creates a notification for subscribed users" do user = insert(:user) subscriber = insert(:user) User.subscribe(subscriber, user) {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"}) - {:ok, notifications} = Notification.create_notifications(status) + {:ok, [notification]} = Notification.create_notifications(status) - assert notifications == [] + assert notification.user_id == subscriber.id end test "does not create a notification for subscribed users if status is a reply" do @@ -182,16 +182,14 @@ defmodule Pleroma.NotificationTest do refute Notification.create_notification(activity_dupe, followed_user) end - test "it doesn't create notifications for follow+subscribed users" do + test "it doesn't create duplicate notifications for follow+subscribed users" do user = insert(:user) subscriber = insert(:user) {:ok, _, _, _} = CommonAPI.follow(subscriber, user) User.subscribe(subscriber, user) {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"}) - {:ok, notifications} = Notification.create_notifications(status) - - assert notifications == [] + {:ok, [_notif]} = Notification.create_notifications(status) end test "it doesn't create subscription notifications if the recipient cannot see the status" do diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs @@ -75,9 +75,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do User.subscribe(subscriber, user) - {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin @#{subscriber.nickname}"}) + {:ok, status} = CommonAPI.post(user, %{"status" => "Akariiiin"}) - {:ok, status1} = CommonAPI.post(user, %{"status" => "Magi @#{subscriber.nickname}"}) + {:ok, status1} = CommonAPI.post(user, %{"status" => "Magi"}) {:ok, [notification]} = Notification.create_notifications(status) {:ok, [notification1]} = Notification.create_notifications(status1) res = MastodonAPI.get_notifications(subscriber) diff --git a/test/web/pleroma_api/controllers/subscription_notification_controller_test.exs b/test/web/pleroma_api/controllers/subscription_notification_controller_test.exs @@ -1,234 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.PleromaAPI.SubscriptionNotificationControllerTest do - use Pleroma.Web.ConnCase - - alias Pleroma.Repo - alias Pleroma.SubscriptionNotification - alias Pleroma.User - alias Pleroma.Web.CommonAPI - import Pleroma.Factory - import Tesla.Mock - - setup do - mock(fn env -> apply(HttpRequestMock, :request, [env]) end) - :ok - end - - clear_config([:instance, :public]) - clear_config([:rich_media, :enabled]) - - describe "subscription_notifications" do - setup do - user = insert(:user) - subscriber = insert(:user) - - User.subscribe(subscriber, user) - - {:ok, %{user: user, subscriber: subscriber}} - end - - test "list of notifications", %{conn: conn, user: user, subscriber: subscriber} do - status_text = "Hello" - {:ok, _activity} = CommonAPI.post(user, %{"status" => status_text}) - path = subscription_notification_path(conn, :index) - - conn = - conn - |> assign(:user, subscriber) - |> get(path) - - assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200) - assert response == status_text - end - - test "getting a single notification", %{conn: conn, user: user, subscriber: subscriber} do - status_text = "Hello" - - {:ok, _activity} = CommonAPI.post(user, %{"status" => status_text}) - [notification] = Repo.all(SubscriptionNotification) - - path = subscription_notification_path(conn, :show, notification) - - conn = - conn - |> assign(:user, subscriber) - |> get(path) - - assert %{"status" => %{"content" => response}} = json_response(conn, 200) - assert response == status_text - end - - test "dismissing a single notification also deletes it", %{ - conn: conn, - user: user, - subscriber: subscriber - } do - status_text = "Hello" - {:ok, _activity} = CommonAPI.post(user, %{"status" => status_text}) - - [notification] = Repo.all(SubscriptionNotification) - - conn = - conn - |> assign(:user, subscriber) - |> post(subscription_notification_path(conn, :dismiss), %{"id" => notification.id}) - - assert %{} = json_response(conn, 200) - - assert Repo.all(SubscriptionNotification) == [] - end - - test "clearing all notifications also deletes them", %{ - conn: conn, - user: user, - subscriber: subscriber - } do - status_text1 = "Hello" - status_text2 = "Hello again" - {:ok, _activity1} = CommonAPI.post(user, %{"status" => status_text1}) - {:ok, _activity2} = CommonAPI.post(user, %{"status" => status_text2}) - - conn = - conn - |> assign(:user, subscriber) - |> post(subscription_notification_path(conn, :clear)) - - assert %{} = json_response(conn, 200) - - conn = - build_conn() - |> assign(:user, subscriber) - |> get(subscription_notification_path(conn, :index)) - - assert json_response(conn, 200) == [] - - assert Repo.all(SubscriptionNotification) == [] - end - - test "paginates notifications using min_id, since_id, max_id, and limit", %{ - conn: conn, - user: user, - subscriber: subscriber - } do - {:ok, activity1} = CommonAPI.post(user, %{"status" => "Hello 1"}) - {:ok, activity2} = CommonAPI.post(user, %{"status" => "Hello 2"}) - {:ok, activity3} = CommonAPI.post(user, %{"status" => "Hello 3"}) - {:ok, activity4} = CommonAPI.post(user, %{"status" => "Hello 4"}) - - notification1_id = - Repo.get_by(SubscriptionNotification, activity_id: activity1.id).id |> to_string() - - notification2_id = - Repo.get_by(SubscriptionNotification, activity_id: activity2.id).id |> to_string() - - notification3_id = - Repo.get_by(SubscriptionNotification, activity_id: activity3.id).id |> to_string() - - notification4_id = - Repo.get_by(SubscriptionNotification, activity_id: activity4.id).id |> to_string() - - conn = assign(conn, :user, subscriber) - - # min_id - conn_res = - get( - conn, - subscription_notification_path(conn, :index, %{ - "limit" => 2, - "min_id" => notification1_id - }) - ) - - result = json_response(conn_res, 200) - assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result - - # since_id - conn_res = - get( - conn, - subscription_notification_path(conn, :index, %{ - "limit" => 2, - "since_id" => notification1_id - }) - ) - - result = json_response(conn_res, 200) - assert [%{"id" => ^notification4_id}, %{"id" => ^notification3_id}] = result - - # max_id - conn_res = - get( - conn, - subscription_notification_path(conn, :index, %{ - "limit" => 2, - "max_id" => notification4_id - }) - ) - - result = json_response(conn_res, 200) - assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result - end - - test "destroy multiple", %{conn: conn, user: user1, subscriber: user2} do - # mutual subscription - User.subscribe(user1, user2) - - {:ok, activity1} = CommonAPI.post(user1, %{"status" => "Hello 1"}) - {:ok, activity2} = CommonAPI.post(user1, %{"status" => "World 1"}) - {:ok, activity3} = CommonAPI.post(user2, %{"status" => "Hello 2"}) - {:ok, activity4} = CommonAPI.post(user2, %{"status" => "World 2"}) - - notification1_id = - Repo.get_by(SubscriptionNotification, activity_id: activity1.id).id |> to_string() - - notification2_id = - Repo.get_by(SubscriptionNotification, activity_id: activity2.id).id |> to_string() - - notification3_id = - Repo.get_by(SubscriptionNotification, activity_id: activity3.id).id |> to_string() - - notification4_id = - Repo.get_by(SubscriptionNotification, activity_id: activity4.id).id |> to_string() - - conn = assign(conn, :user, user1) - - conn_res = get(conn, subscription_notification_path(conn, :index)) - - result = json_response(conn_res, 200) - - Enum.each(result, fn %{"id" => id} -> - assert id in [notification3_id, notification4_id] - end) - - conn2 = assign(conn, :user, user2) - - conn_res = get(conn2, subscription_notification_path(conn, :index)) - - result = json_response(conn_res, 200) - - Enum.each(result, fn %{"id" => id} -> - assert id in [notification1_id, notification2_id] - end) - - conn_destroy = - delete(conn, subscription_notification_path(conn, :destroy_multiple), %{ - "ids" => [notification3_id, notification4_id] - }) - - assert json_response(conn_destroy, 200) == %{} - - conn_res = get(conn2, subscription_notification_path(conn, :index)) - - result = json_response(conn_res, 200) - - Enum.each(result, fn %{"id" => id} -> - assert id in [notification1_id, notification2_id] - end) - - assert length(Repo.all(SubscriptionNotification)) == 2 - end - end -end diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/pleroma_api_controller_test.exs