Merge branch 'test-docker-images' into 'develop'
authorrinpatch <rin@patch.cx>
Wed, 17 Feb 2021 17:09:24 +0000 (17:09 +0000)
committerrinpatch <rin@patch.cx>
Wed, 17 Feb 2021 17:09:24 +0000 (17:09 +0000)
Generate custom docker images for testing

See merge request pleroma/pleroma!3326

20 files changed:
CHANGELOG.md
COPYING
lib/pleroma/conversation.ex
lib/pleroma/conversation/participation.ex
lib/pleroma/notification.ex
lib/pleroma/web/api_spec/operations/chat_operation.ex
lib/pleroma/web/api_spec/operations/conversation_operation.ex
lib/pleroma/web/mastodon_api/controllers/app_controller.ex
lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex
lib/pleroma/web/mastodon_api/views/app_view.ex
lib/pleroma/web/pleroma_api/controllers/chat_controller.ex
lib/pleroma/web/plugs/ensure_authenticated_plug.ex
lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex
lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex
lib/pleroma/web/router.ex
priv/static/images/avi.png
test/pleroma/conversation/participation_test.exs
test/pleroma/web/mastodon_api/controllers/app_controller_test.exs
test/pleroma/web/mastodon_api/controllers/conversation_controller_test.exs
test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs

index bbd898bdfc978fdfdfbbb25b3876ba63de47204c..e26c8d26158ad9fe93729d5aeedcc671965593aa 100644 (file)
@@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Provide redirect of external posts from `/notice/:id` to their original URL
 - Admins no longer receive notifications for reports if they are the actor making the report.
 - Improved Mailer configuration setting descriptions for AdminFE.
+- Updated default avatar to look nicer.
 
 <details>
   <summary>API Changes</summary>
@@ -31,6 +32,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - **Breaking:** AdminAPI `GET /api/pleroma/admin/users/:nickname_or_id/statuses` changed response format and added the number of total users posts.
 - **Breaking:** AdminAPI `GET /api/pleroma/admin/instances/:instance/statuses` changed response format and added the number of total users posts.
 - Admin API: Reports now ordered by newest
+- Pleroma API: `GET /api/v1/pleroma/chats` is deprecated in favor of `GET /api/v2/pleroma/chats`.
 
 </details>
 
@@ -57,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 <details>
   <summary>API Changes</summary>
 - Admin API: (`GET /api/pleroma/admin/users`) filter users by `unconfirmed` status and `actor_type`.
+- Pleroma API: `GET /api/v2/pleroma/chats` added. It is exactly like `GET /api/v1/pleroma/chats` except supports pagination.
 - Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.
 - Pleroma API: (`GET /api/v1/pleroma/federation_status`) Add a way to get a list of unreachable instances.
 - Mastodon API: User and conversation mutes can now auto-expire if `expires_in` parameter was given while adding the mute.
@@ -66,6 +69,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Mastodon API: Add monthly active users to `/api/v1/instance` (`pleroma.stats.mau`).
 - Mastodon API: Home, public, hashtag & list timelines accept `only_media`, `remote` & `local` parameters for filtration.
 - Mastodon API: `/api/v1/accounts/:id` & `/api/v1/mutes` endpoints accept `with_relationships` parameter and return filled `pleroma.relationship` field.
+- Mastodon API: Endpoint to remove a conversation (`DELETE /api/v1/conversations/:id`).
 </details>
 
 ### Fixed
diff --git a/COPYING b/COPYING
index eb60dbd5668338ffe1cd69c884b06c8a14af63dd..dd25f1d81ddc95abf1453abe421ba5fe1a9b341a 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -5,6 +5,13 @@ copy of the license file as AGPL-3.
 
 ---
 
+Files inside docs directory are copyright © 2021 Pleroma Authors
+<https://pleroma.social/>, and are distributed under the Creative Commons
+Attribution 4.0 International license, you should have received
+a copy of the license file as CC-BY-4.0.
+
+---
+
 The following files are copyright © 2019 shitposter.club, and are distributed
 under the Creative Commons Attribution-ShareAlike 4.0 International license,
 you should have received a copy of the license file as CC-BY-SA-4.0.
index 8812b456ddd54a2eb7f7b899bf122f91fb0cfc2e..828e274504a2d6b394a520ece4bff61e6cc06b9b 100644 (file)
@@ -61,9 +61,8 @@ defmodule Pleroma.Conversation do
          "Create" <- activity.data["type"],
          %Object{} = object <- Object.normalize(activity, fetch: false),
          true <- object.data["type"] in ["Note", "Question"],
-         ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"] do
-      {:ok, conversation} = create_for_ap_id(ap_id)
-
+         ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"],
+         {:ok, conversation} <- create_for_ap_id(ap_id) do
       users = User.get_users_from_set(activity.recipients, local_only: false)
 
       participations =
index da5e57714d60e6758d515326fa15f32c2537a73e..e0a3af28b9b62fdeaa2b0a31bf2ac663578b3eb0 100644 (file)
@@ -220,4 +220,8 @@ defmodule Pleroma.Conversation.Participation do
       select: %{count: count(p.id)}
     )
   end
+
+  def delete(%__MODULE__{} = participation) do
+    Repo.delete(participation)
+  end
 end
index 1970fbf65d1611ac907fdeaa78aa6f660404e5d2..7efbdc49afe1811a145a78cc548ad0dd54935849 100644 (file)
@@ -112,13 +112,6 @@ defmodule Pleroma.Notification do
 
     Notification
     |> where(user_id: ^user.id)
-    |> where(
-      [n, a],
-      fragment(
-        "? not in (SELECT ap_id FROM users WHERE is_active = 'false')",
-        a.actor
-      )
-    )
     |> join(:inner, [n], activity in assoc(n, :activity))
     |> join(:left, [n, a], object in Object,
       on:
@@ -129,7 +122,9 @@ defmodule Pleroma.Notification do
           a.data
         )
     )
+    |> join(:inner, [_n, a], u in User, on: u.ap_id == a.actor, as: :user_actor)
     |> preload([n, a, o], activity: {a, object: o})
+    |> where([user_actor: user_actor], user_actor.is_active)
     |> exclude_notification_muted(user, exclude_notification_muted_opts)
     |> exclude_blocked(user, exclude_blocked_opts)
     |> exclude_filtered(user)
@@ -156,9 +151,10 @@ defmodule Pleroma.Notification do
     query
     |> where([n, a], a.actor not in ^notification_muted_ap_ids)
     |> join(:left, [n, a], tm in ThreadMute,
-      on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
+      on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data),
+      as: :thread_mute
     )
-    |> where([n, a, o, tm], is_nil(tm.user_id))
+    |> where([thread_mute: thread_mute], is_nil(thread_mute.user_id))
   end
 
   defp exclude_filtered(query, user) do
index b4970017256ea9e5211655a6b5c75add5c77a216..23cb66392b0cb32fc9981a1641ac78c7ea2fdd20 100644 (file)
@@ -131,8 +131,30 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
   def index_operation do
     %Operation{
       tags: ["Chats"],
-      summary: "Retrieve list of chats",
+      summary: "Retrieve list of chats (unpaginated)",
+      deprecated: true,
+      description:
+        "Deprecated due to no support for pagination. Using [/api/v2/pleroma/chats](#operation/ChatController.index2) instead is recommended.",
       operationId: "ChatController.index",
+      parameters: [
+        Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
+      ],
+      responses: %{
+        200 => Operation.response("The chats of the user", "application/json", chats_response())
+      },
+      security: [
+        %{
+          "oAuth" => ["read:chats"]
+        }
+      ]
+    }
+  end
+
+  def index2_operation do
+    %Operation{
+      tags: ["Chats"],
+      summary: "Retrieve list of chats",
+      operationId: "ChatController.index2",
       parameters: [
         Operation.parameter(:with_muted, :query, BooleanLike, "Include chats from muted users")
         | pagination_params()
index 367f4125a4a3f72c3f76becdcc726bbe72d6f352..17ed1af5e5ca861329e74d1624b4297a9b3e519a 100644 (file)
@@ -46,16 +46,31 @@ defmodule Pleroma.Web.ApiSpec.ConversationOperation do
       tags: ["Conversations"],
       summary: "Mark conversation as read",
       operationId: "ConversationController.mark_as_read",
-      parameters: [
-        Operation.parameter(:id, :path, :string, "Conversation ID",
-          example: "123",
-          required: true
-        )
-      ],
+      parameters: [id_param()],
       security: [%{"oAuth" => ["write:conversations"]}],
       responses: %{
         200 => Operation.response("Conversation", "application/json", Conversation)
       }
     }
   end
+
+  def delete_operation do
+    %Operation{
+      tags: ["Conversations"],
+      summary: "Remove conversation",
+      operationId: "ConversationController.delete",
+      parameters: [id_param()],
+      security: [%{"oAuth" => ["write:conversations"]}],
+      responses: %{
+        200 => empty_object_response()
+      }
+    }
+  end
+
+  def id_param do
+    Operation.parameter(:id, :path, :string, "Conversation ID",
+      example: "123",
+      required: true
+    )
+  end
 end
index a7e4d93f5a3127e974278fafda64172e49e23387..dd3b39c7789db7bc8fb3be29f046568edb4ad7a9 100644 (file)
@@ -3,6 +3,11 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.MastodonAPI.AppController do
+  @moduledoc """
+  Controller for supporting app-related actions.
+  If authentication is an option, app tokens (user-unbound) must be supported.
+  """
+
   use Pleroma.Web, :controller
 
   alias Pleroma.Repo
@@ -17,11 +22,9 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
   plug(
     :skip_plug,
     [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug]
-    when action == :create
+    when action in [:create, :verify_credentials]
   )
 
-  plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :verify_credentials)
-
   plug(Pleroma.Web.ApiSpec.CastAndValidate)
 
   @local_mastodon_name "Mastodon-Local"
@@ -44,10 +47,13 @@ defmodule Pleroma.Web.MastodonAPI.AppController do
     end
   end
 
-  @doc "GET /api/v1/apps/verify_credentials"
-  def verify_credentials(%{assigns: %{user: _user, token: token}} = conn, _) do
-    with %Token{app: %App{} = app} <- Repo.preload(token, :app) do
-      render(conn, "short.json", app: app)
+  @doc """
+  GET /api/v1/apps/verify_credentials
+  Gets compact non-secret representation of the app. Supports app tokens and user tokens.
+  """
+  def verify_credentials(%{assigns: %{token: %Token{} = token}} = conn, _) do
+    with %{app: %App{} = app} <- Repo.preload(token, :app) do
+      render(conn, "compact_non_secret.json", app: app)
     end
   end
 end
index 4526d3c7acbaa10dd32e3927f372acbed3ef10aa..f2a0949e853c62475af264f8300a1702a2d5ab20 100644 (file)
@@ -36,4 +36,13 @@ defmodule Pleroma.Web.MastodonAPI.ConversationController do
       render(conn, "participation.json", participation: participation, for: user)
     end
   end
+
+  @doc "DELETE /api/v1/conversations/:id"
+  def delete(%{assigns: %{user: user}} = conn, %{id: participation_id}) do
+    with %Participation{} = participation <-
+           Repo.get_by(Participation, id: participation_id, user_id: user.id),
+         {:ok, _} <- Participation.delete(participation) do
+      json(conn, %{})
+    end
+  end
 end
index 3d7131e09ac3f055f38e4278d3de81824bba5f8b..c406b5a27f939a32d1a877182ed38f86a6d2d66e 100644 (file)
@@ -34,10 +34,10 @@ defmodule Pleroma.Web.MastodonAPI.AppView do
     |> with_vapid_key()
   end
 
-  def render("short.json", %{app: %App{website: webiste, client_name: name}}) do
+  def render("compact_non_secret.json", %{app: %App{website: website, client_name: name}}) do
     %{
       name: name,
-      website: webiste
+      website: website
     }
     |> with_vapid_key()
   end
index f3cd1fbf6f590792e0bb936028b9c9df0c9d65bb..4adc685fe9eb60591e6d6538848c9f867ca495df 100644 (file)
@@ -35,7 +35,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
 
   plug(
     OAuthScopesPlug,
-    %{scopes: ["read:chats"]} when action in [:messages, :index, :show]
+    %{scopes: ["read:chats"]} when action in [:messages, :index, :index2, :show]
   )
 
   plug(OpenApiSpex.Plug.CastAndValidate, render_error: Pleroma.Web.ApiSpec.RenderError)
@@ -138,20 +138,32 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
     end
   end
 
-  def index(%{assigns: %{user: %{id: user_id} = user}} = conn, params) do
-    exclude_users =
-      User.cached_blocked_users_ap_ids(user) ++
-        if params[:with_muted], do: [], else: User.cached_muted_users_ap_ids(user)
-
+  def index(%{assigns: %{user: user}} = conn, params) do
     chats =
-      user_id
-      |> Chat.for_user_query()
-      |> where([c], c.recipient not in ^exclude_users)
+      index_query(user, params)
       |> Repo.all()
 
     render(conn, "index.json", chats: chats)
   end
 
+  def index2(%{assigns: %{user: user}} = conn, params) do
+    chats =
+      index_query(user, params)
+      |> Pagination.fetch_paginated(params)
+
+    render(conn, "index.json", chats: chats)
+  end
+
+  defp index_query(%{id: user_id} = user, params) do
+    exclude_users =
+      User.cached_blocked_users_ap_ids(user) ++
+        if params[:with_muted], do: [], else: User.cached_muted_users_ap_ids(user)
+
+    user_id
+    |> Chat.for_user_query()
+    |> where([c], c.recipient not in ^exclude_users)
+  end
+
   def create(%{assigns: %{user: user}} = conn, %{id: id}) do
     with %User{ap_id: recipient} <- User.get_cached_by_id(id),
          {:ok, %Chat{} = chat} <- Chat.get_or_create(user.id, recipient) do
index a4b5dc257039193d9e9dfb4a42d9b9eccd896ea4..31e7410d627b9fe5b0b2231ab85be2ba81a881e6 100644 (file)
@@ -3,6 +3,10 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.Plugs.EnsureAuthenticatedPlug do
+  @moduledoc """
+  Ensures _user_ authentication (app-bound user-unbound tokens are not accepted).
+  """
+
   import Plug.Conn
   import Pleroma.Web.TranslationHelpers
 
index b6dfc4f3ca8cb7a0e1a597743aeb91f14f8a2ad2..8a8532f4156f31d33f8e72a282c7ea4bb8305315 100644 (file)
@@ -3,6 +3,11 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.Plugs.EnsurePublicOrAuthenticatedPlug do
+  @moduledoc """
+  Ensures instance publicity or _user_ authentication
+  (app-bound user-unbound tokens are accepted only if the instance is public).
+  """
+
   import Pleroma.Web.TranslationHelpers
   import Plug.Conn
 
index 3a2b5dda866708a39a179e9182e49e30cb0b5105..534b0cff188b4bd620bbbafdc57014db235f16ac 100644 (file)
@@ -28,6 +28,11 @@ defmodule Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug do
     end
   end
 
+  # App-bound token case (obtained with client_id and client_secret)
+  def call(%{assigns: %{token: %Token{user_id: nil}}} = conn, _) do
+    assign(conn, :user, nil)
+  end
+
   def call(conn, _) do
     conn
     |> assign(:user, nil)
index 2105d7e9ed2bbf842a97032d4a81e693c0ae2921..d71011033cbf8b6e0f6616fc12d4d2c571f1cc47 100644 (file)
@@ -37,11 +37,13 @@ defmodule Pleroma.Web.Router do
     plug(Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug)
   end
 
-  pipeline :expect_authentication do
+  # Note: expects _user_ authentication (user-unbound app-bound tokens don't qualify)
+  pipeline :expect_user_authentication do
     plug(Pleroma.Web.Plugs.ExpectAuthenticatedCheckPlug)
   end
 
-  pipeline :expect_public_instance_or_authentication do
+  # Note: expects public instance or _user_ authentication (user-unbound tokens don't qualify)
+  pipeline :expect_public_instance_or_user_authentication do
     plug(Pleroma.Web.Plugs.ExpectPublicOrAuthenticatedCheckPlug)
   end
 
@@ -66,23 +68,30 @@ defmodule Pleroma.Web.Router do
     plug(OpenApiSpex.Plug.PutApiSpec, module: Pleroma.Web.ApiSpec)
   end
 
-  pipeline :api do
-    plug(:expect_public_instance_or_authentication)
+  pipeline :no_auth_or_privacy_expectations_api do
     plug(:base_api)
     plug(:after_auth)
     plug(Pleroma.Web.Plugs.IdempotencyPlug)
   end
 
+  # Pipeline for app-related endpoints (no user auth checks — app-bound tokens must be supported)
+  pipeline :app_api do
+    plug(:no_auth_or_privacy_expectations_api)
+  end
+
+  pipeline :api do
+    plug(:expect_public_instance_or_user_authentication)
+    plug(:no_auth_or_privacy_expectations_api)
+  end
+
   pipeline :authenticated_api do
-    plug(:expect_authentication)
-    plug(:base_api)
-    plug(:after_auth)
+    plug(:expect_user_authentication)
+    plug(:no_auth_or_privacy_expectations_api)
     plug(Pleroma.Web.Plugs.EnsureAuthenticatedPlug)
-    plug(Pleroma.Web.Plugs.IdempotencyPlug)
   end
 
   pipeline :admin_api do
-    plug(:expect_authentication)
+    plug(:expect_user_authentication)
     plug(:base_api)
     plug(Pleroma.Web.Plugs.AdminSecretAuthenticationPlug)
     plug(:after_auth)
@@ -411,6 +420,13 @@ defmodule Pleroma.Web.Router do
     get("/federation_status", InstancesController, :show)
   end
 
+  scope "/api/v2/pleroma", Pleroma.Web.PleromaAPI do
+    scope [] do
+      pipe_through(:authenticated_api)
+      get("/chats", ChatController, :index2)
+    end
+  end
+
   scope "/api/v1", Pleroma.Web.MastodonAPI do
     pipe_through(:authenticated_api)
 
@@ -432,10 +448,9 @@ defmodule Pleroma.Web.Router do
     post("/accounts/:id/mute", AccountController, :mute)
     post("/accounts/:id/unmute", AccountController, :unmute)
 
-    get("/apps/verify_credentials", AppController, :verify_credentials)
-
     get("/conversations", ConversationController, :index)
     post("/conversations/:id/read", ConversationController, :mark_as_read)
+    delete("/conversations/:id", ConversationController, :delete)
 
     get("/domain_blocks", DomainBlockController, :index)
     post("/domain_blocks", DomainBlockController, :create)
@@ -524,6 +539,13 @@ defmodule Pleroma.Web.Router do
     put("/settings", MastoFEController, :put_settings)
   end
 
+  scope "/api/v1", Pleroma.Web.MastodonAPI do
+    pipe_through(:app_api)
+
+    post("/apps", AppController, :create)
+    get("/apps/verify_credentials", AppController, :verify_credentials)
+  end
+
   scope "/api/v1", Pleroma.Web.MastodonAPI do
     pipe_through(:api)
 
@@ -540,8 +562,6 @@ defmodule Pleroma.Web.Router do
     get("/instance", InstanceController, :show)
     get("/instance/peers", InstanceController, :peers)
 
-    post("/apps", AppController, :create)
-
     get("/statuses", StatusController, :index)
     get("/statuses/:id", StatusController, :show)
     get("/statuses/:id/context", StatusController, :context)
index c6595adadd982f9a2c003a085a5de794c1074dba..df4e2d23364c8923ffb5ac1f17d108cc36a54c45 100644 (file)
Binary files a/priv/static/images/avi.png and b/priv/static/images/avi.png differ
index 8b039cd78de8cb7d30376491e6711006c8bf93a7..a25e17c957f1206b8b510cc75e67184d0b14535d 100644 (file)
@@ -359,4 +359,16 @@ defmodule Pleroma.Conversation.ParticipationTest do
       assert Participation.unread_count(blocked) == 1
     end
   end
+
+  test "deletes a conversation" do
+    user = insert(:user)
+    other_user = insert(:user)
+
+    {:ok, _activity} =
+      CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
+
+    assert [participation] = Participation.for_user(other_user)
+    assert {:ok, _} = Participation.delete(participation)
+    assert [] == Participation.for_user(other_user)
+  end
 end
index 238fd265b974a777747e9662ad7271a695aa77ff..76d81b942333274ae69d3c279375fa82c52aff88 100644 (file)
@@ -12,22 +12,26 @@ defmodule Pleroma.Web.MastodonAPI.AppControllerTest do
   import Pleroma.Factory
 
   test "apps/verify_credentials", %{conn: conn} do
-    token = insert(:oauth_token)
+    user_bound_token = insert(:oauth_token)
+    app_bound_token = insert(:oauth_token, user: nil)
+    refute app_bound_token.user
 
-    conn =
-      conn
-      |> put_req_header("authorization", "Bearer #{token.token}")
-      |> get("/api/v1/apps/verify_credentials")
+    for token <- [app_bound_token, user_bound_token] do
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer #{token.token}")
+        |> get("/api/v1/apps/verify_credentials")
 
-    app = Repo.preload(token, :app).app
+      app = Repo.preload(token, :app).app
 
-    expected = %{
-      "name" => app.client_name,
-      "website" => app.website,
-      "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
-    }
+      expected = %{
+        "name" => app.client_name,
+        "website" => app.website,
+        "vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
+      }
 
-    assert expected == json_response_and_validate_schema(conn, 200)
+      assert expected == json_response_and_validate_schema(conn, 200)
+    end
   end
 
   test "creates an oauth app", %{conn: conn} do
index 29bc4fd1784c5979078153b72940e52426fecd38..3176f12968069aac77bbdb8d15e321589dbabc52 100644 (file)
@@ -217,6 +217,32 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do
     assert %{"ancestors" => [], "descendants" => []} == json_response(res_conn, 200)
   end
 
+  test "Removes a conversation", %{user: user_one, conn: conn} do
+    user_two = insert(:user)
+    token = insert(:oauth_token, user: user_one, scopes: ["read:statuses", "write:conversations"])
+
+    {:ok, _direct} = create_direct_message(user_one, [user_two])
+    {:ok, _direct} = create_direct_message(user_one, [user_two])
+
+    assert [%{"id" => conv1_id}, %{"id" => conv2_id}] =
+             conn
+             |> assign(:token, token)
+             |> get("/api/v1/conversations")
+             |> json_response_and_validate_schema(200)
+
+    assert %{} =
+             conn
+             |> assign(:token, token)
+             |> delete("/api/v1/conversations/#{conv1_id}")
+             |> json_response_and_validate_schema(200)
+
+    assert [%{"id" => ^conv2_id}] =
+             conn
+             |> assign(:token, token)
+             |> get("/api/v1/conversations")
+             |> json_response_and_validate_schema(200)
+  end
+
   defp create_direct_message(sender, recips) do
     hellos =
       recips
index 372613b8bdeb1e9b8d160f4aab37fcf012c9c96c..99b0d43a7e5d2f60b7dab3804653e9724389c334 100644 (file)
@@ -304,139 +304,165 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
     end
   end
 
-  describe "GET /api/v1/pleroma/chats" do
-    setup do: oauth_access(["read:chats"])
-
-    test "it does not return chats with deleted users", %{conn: conn, user: user} do
-      recipient = insert(:user)
-      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-
-      Pleroma.Repo.delete(recipient)
-      User.invalidate_cache(recipient)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 0
-    end
-
-    test "it does not return chats with users you blocked", %{conn: conn, user: user} do
-      recipient = insert(:user)
-
-      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 1
-
-      User.block(user, recipient)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 0
-    end
-
-    test "it does not return chats with users you muted", %{conn: conn, user: user} do
-      recipient = insert(:user)
-
-      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 1
+  for tested_endpoint <- ["/api/v1/pleroma/chats", "/api/v2/pleroma/chats"] do
+    describe "GET #{tested_endpoint}" do
+      setup do: oauth_access(["read:chats"])
 
-      User.mute(user, recipient)
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 0
-
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats?with_muted=true")
-        |> json_response_and_validate_schema(200)
-
-      assert length(result) == 1
-    end
-
-    test "it returns all chats", %{conn: conn, user: user} do
-      Enum.each(1..30, fn _ ->
+      test "it does not return chats with deleted users", %{conn: conn, user: user} do
         recipient = insert(:user)
         {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
-      end)
 
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
+        Pleroma.Repo.delete(recipient)
+        User.invalidate_cache(recipient)
 
-      assert length(result) == 30
-    end
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
 
-    test "it return a list of chats the current user is participating in, in descending order of updates",
-         %{conn: conn, user: user} do
-      har = insert(:user)
-      jafnhar = insert(:user)
-      tridi = insert(:user)
+        assert length(result) == 0
+      end
 
-      {:ok, chat_1} = Chat.get_or_create(user.id, har.ap_id)
-      {:ok, chat_1} = time_travel(chat_1, -3)
-      {:ok, chat_2} = Chat.get_or_create(user.id, jafnhar.ap_id)
-      {:ok, _chat_2} = time_travel(chat_2, -2)
-      {:ok, chat_3} = Chat.get_or_create(user.id, tridi.ap_id)
-      {:ok, chat_3} = time_travel(chat_3, -1)
+      test "it does not return chats with users you blocked", %{conn: conn, user: user} do
+        recipient = insert(:user)
 
-      # bump the second one
-      {:ok, chat_2} = Chat.bump_or_create(user.id, jafnhar.ap_id)
+        {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
 
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
 
-      ids = Enum.map(result, & &1["id"])
+        assert length(result) == 1
 
-      assert ids == [
-               chat_2.id |> to_string(),
-               chat_3.id |> to_string(),
-               chat_1.id |> to_string()
-             ]
-    end
+        User.block(user, recipient)
 
-    test "it is not affected by :restrict_unauthenticated setting (issue #1973)", %{
-      conn: conn,
-      user: user
-    } do
-      clear_config([:restrict_unauthenticated, :profiles, :local], true)
-      clear_config([:restrict_unauthenticated, :profiles, :remote], true)
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
 
-      user2 = insert(:user)
-      user3 = insert(:user, local: false)
+        assert length(result) == 0
+      end
 
-      {:ok, _chat_12} = Chat.get_or_create(user.id, user2.ap_id)
-      {:ok, _chat_13} = Chat.get_or_create(user.id, user3.ap_id)
+      test "it does not return chats with users you muted", %{conn: conn, user: user} do
+        recipient = insert(:user)
 
-      result =
-        conn
-        |> get("/api/v1/pleroma/chats")
-        |> json_response_and_validate_schema(200)
+        {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
 
-      account_ids = Enum.map(result, &get_in(&1, ["account", "id"]))
-      assert Enum.sort(account_ids) == Enum.sort([user2.id, user3.id])
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        assert length(result) == 1
+
+        User.mute(user, recipient)
+
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        assert length(result) == 0
+
+        result =
+          conn
+          |> get("#{unquote(tested_endpoint)}?with_muted=true")
+          |> json_response_and_validate_schema(200)
+
+        assert length(result) == 1
+      end
+
+      if tested_endpoint == "/api/v1/pleroma/chats" do
+        test "it returns all chats", %{conn: conn, user: user} do
+          Enum.each(1..30, fn _ ->
+            recipient = insert(:user)
+            {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
+          end)
+
+          result =
+            conn
+            |> get(unquote(tested_endpoint))
+            |> json_response_and_validate_schema(200)
+
+          assert length(result) == 30
+        end
+      else
+        test "it paginates chats", %{conn: conn, user: user} do
+          Enum.each(1..30, fn _ ->
+            recipient = insert(:user)
+            {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
+          end)
+
+          result =
+            conn
+            |> get(unquote(tested_endpoint))
+            |> json_response_and_validate_schema(200)
+
+          assert length(result) == 20
+          last_id = List.last(result)["id"]
+
+          result =
+            conn
+            |> get(unquote(tested_endpoint) <> "?max_id=#{last_id}")
+            |> json_response_and_validate_schema(200)
+
+          assert length(result) == 10
+        end
+      end
+
+      test "it return a list of chats the current user is participating in, in descending order of updates",
+           %{conn: conn, user: user} do
+        har = insert(:user)
+        jafnhar = insert(:user)
+        tridi = insert(:user)
+
+        {:ok, chat_1} = Chat.get_or_create(user.id, har.ap_id)
+        {:ok, chat_1} = time_travel(chat_1, -3)
+        {:ok, chat_2} = Chat.get_or_create(user.id, jafnhar.ap_id)
+        {:ok, _chat_2} = time_travel(chat_2, -2)
+        {:ok, chat_3} = Chat.get_or_create(user.id, tridi.ap_id)
+        {:ok, chat_3} = time_travel(chat_3, -1)
+
+        # bump the second one
+        {:ok, chat_2} = Chat.bump_or_create(user.id, jafnhar.ap_id)
+
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        ids = Enum.map(result, & &1["id"])
+
+        assert ids == [
+                 chat_2.id |> to_string(),
+                 chat_3.id |> to_string(),
+                 chat_1.id |> to_string()
+               ]
+      end
+
+      test "it is not affected by :restrict_unauthenticated setting (issue #1973)", %{
+        conn: conn,
+        user: user
+      } do
+        clear_config([:restrict_unauthenticated, :profiles, :local], true)
+        clear_config([:restrict_unauthenticated, :profiles, :remote], true)
+
+        user2 = insert(:user)
+        user3 = insert(:user, local: false)
+
+        {:ok, _chat_12} = Chat.get_or_create(user.id, user2.ap_id)
+        {:ok, _chat_13} = Chat.get_or_create(user.id, user3.ap_id)
+
+        result =
+          conn
+          |> get(unquote(tested_endpoint))
+          |> json_response_and_validate_schema(200)
+
+        account_ids = Enum.map(result, &get_in(&1, ["account", "id"]))
+        assert Enum.sort(account_ids) == Enum.sort([user2.id, user3.id])
+      end
     end
   end
 end