Merge branch 'fix-tests' into 'develop'
authorlain <lain@soykaf.club>
Mon, 15 Nov 2021 14:31:27 +0000 (14:31 +0000)
committerlain <lain@soykaf.club>
Mon, 15 Nov 2021 14:31:27 +0000 (14:31 +0000)
Test fixes

See merge request pleroma/pleroma!3532

25 files changed:
.gitlab-ci.yml
CHANGELOG.md
config/config.exs
config/description.exs
docs/configuration/cheatsheet.md
docs/development/API/admin_api.md
lib/pleroma/activity.ex
lib/pleroma/instances/instance.ex
lib/pleroma/notification.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/activity_pub_controller.ex
lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
lib/pleroma/web/admin_api/controllers/instance_controller.ex [new file with mode: 0644]
lib/pleroma/web/feed/user_controller.ex
lib/pleroma/web/router.ex
lib/pleroma/workers/background_worker.ex
mix.exs
mix.lock
test/pleroma/instances/instance_test.exs
test/pleroma/web/activity_pub/activity_pub_test.exs
test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs
test/pleroma/web/admin_api/controllers/instance_controller_test.exs [new file with mode: 0644]
test/pleroma/web/feed/user_controller_test.exs
test/pleroma/web/mastodon_api/controllers/notification_controller_test.exs
test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs

index 9041443c5b6b46ae0140a2df19aaa9dc8ec8afce..c3192fbf239d30a9c89f7755f05fe0d08c6408dc 100644 (file)
@@ -298,7 +298,7 @@ arm:
   only: *release-only
   tags:
     - arm32-specified
-  image: arm32v7/elixir:1.10.3
+  image: arm32v7/elixir:1.10.4
   cache: *release-cache
   variables: *release-variables
   before_script: *before-release
@@ -322,7 +322,7 @@ arm64:
   only: *release-only
   tags:
     - arm
-  image: arm64v8/elixir:1.10.3
+  image: arm64v8/elixir:1.10.4
   cache: *release-cache
   variables: *release-variables
   before_script: *before-release
index 6a1ae9cb6d68244b75c2c5b4e81ffc25ad40563d..decf9ef471a74d66b96b7576f73856204deab9cc 100644 (file)
@@ -59,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - MRF (`FollowBotPolicy`): New MRF Policy which makes a designated local Bot account attempt to follow all users in public Notes received by your instance. Users who require approving follower requests or have #nobot in their profile are excluded.
 - Return OAuth token `id` (primary key) in POST `/oauth/token`.
 - AdminAPI: return `created_at` date with users.
+- AdminAPI: add DELETE `/api/v1/pleroma/admin/instances/:instance` to delete all content from a remote instance.
 - `AnalyzeMetadata` upload filter for extracting image/video attachment dimensions and generating blurhashes for images. Blurhashes for videos are not generated at this time.
 - Attachment dimensions and blurhashes are federated when available.
 - Mastodon API: support `poll` notification.
@@ -69,6 +70,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Checking activated Upload Filters for required commands.
 - Remote users can no longer reappear after being deleted.
 - Deactivated users may now be deleted.
+- Deleting an activity with a lot of likes/boosts no longer causes a database timeout.
 - Mix task `pleroma.database prune_objects`
 - Fixed rendering of JSON errors on ActivityPub endpoints.
 - Linkify: Parsing crash with URLs ending in unbalanced closed paren, no path separator, and no query parameters
@@ -133,6 +135,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Support pagination of blocks and mutes.
 - Account backup.
 - Configuration: Add `:instance, autofollowing_nicknames` setting to provide a way to make accounts automatically follow new users that register on the local Pleroma instance.
+- `[:activitypub, :blockers_visible]` config to control visibility of blockers.
 - Ability to view remote timelines, with ex. `/api/v1/timelines/public?instance=lain.com` and streams `public:remote` and `public:remote:media`.
 - The site title is now injected as a `title` tag like preloads or metadata.
 - Password reset tokens now are not accepted after a certain age.
index 66d394655657869f8f8346fdb4a070eb506e5d6a..681b498275d90bdc80ebb5bd28b6100075136a54 100644 (file)
@@ -349,6 +349,7 @@ config :pleroma, :manifest,
 config :pleroma, :activitypub,
   unfollow_blocked: true,
   outgoing_blocks: true,
+  blockers_visible: true,
   follow_handshake_timeout: 500,
   note_replies_output_limit: 5,
   sign_object_fetches: true,
index 7d1b29b230e1c4b52c6ea5bd1ded3966136dca1f..1c8c3b4a0e8af2e61d5705ac6e02214cfbb288c2 100644 (file)
@@ -1670,6 +1670,11 @@ config :pleroma, :config_description, [
         type: :boolean,
         description: "Whether to federate blocks to other instances"
       },
+      %{
+        key: :blockers_visible,
+        type: :boolean,
+        description: "Whether a user can see someone who has blocked them"
+      },
       %{
         key: :sign_object_fetches,
         type: :boolean,
index 251dc24e856312ae8ad2894262dcd0d30943ba79..40e81cffbe1f15e4a0d4c8e3c53451011e4f1fa7 100644 (file)
@@ -230,6 +230,7 @@ Notes:
 ### :activitypub
 * `unfollow_blocked`: Whether blocks result in people getting unfollowed
 * `outgoing_blocks`: Whether to federate blocks to other instances
+* `blockers_visible`: Whether a user can see the posts of users who blocked them
 * `deny_follow_blocked`: Whether to disallow following an account that has blocked the user in question
 * `sign_object_fetches`: Sign object fetches with HTTP signatures
 * `authorized_fetch_mode`: Require HTTP signatures for AP fetches
index 8f855d251a5ac2b9c2cb945c0534b8699d3f4605..82483fae71deaf9f82c8ff6afb3ef2f913183083 100644 (file)
@@ -319,6 +319,22 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
 }
 ```
 
+## `DELETE /api/v1/pleroma/admin/instances/:instance`
+
+### Delete all users and activities from a remote instance
+
+Note: this will trigger a job to remove instance content in the background.
+It may take some time.
+
+- Params:
+  - `instance`: remote instance host
+- Response:
+  - The `instance` name as a string
+
+```json
+"lain.com"
+```
+
 ## `GET /api/v1/pleroma/admin/statuses`
 
 ### Retrives all latest statuses
index 6a991c48e9300ee03e50c33097911f44c7e235ca..b88f74f4717ff27f24b12da153f6f65def14ed23 100644 (file)
@@ -302,7 +302,7 @@ defmodule Pleroma.Activity do
     |> Queries.by_object_id()
     |> Queries.exclude_type("Delete")
     |> select([u], u)
-    |> Repo.delete_all()
+    |> Repo.delete_all(timeout: :infinity)
     |> elem(1)
     |> Enum.find(fn
       %{data: %{"type" => "Create", "object" => ap_id}} when is_binary(ap_id) -> ap_id == id
index 4d0e8034d61400f623169a0d47c3bc21f236e1a6..2f338b3e2bae30518508b31f49f022dcccb0d436 100644 (file)
@@ -8,6 +8,8 @@ defmodule Pleroma.Instances.Instance do
   alias Pleroma.Instances
   alias Pleroma.Instances.Instance
   alias Pleroma.Repo
+  alias Pleroma.User
+  alias Pleroma.Workers.BackgroundWorker
 
   use Ecto.Schema
 
@@ -195,4 +197,24 @@ defmodule Pleroma.Instances.Instance do
         nil
     end
   end
+
+  @doc """
+  Deletes all users from an instance in a background task, thus also deleting
+  all of those users' activities and notifications.
+  """
+  def delete_users_and_activities(host) when is_binary(host) do
+    BackgroundWorker.enqueue("delete_instance", %{"host" => host})
+  end
+
+  def perform(:delete_instance, host) when is_binary(host) do
+    User.Query.build(%{nickname: "@#{host}"})
+    |> Repo.chunk_stream(100, :batches)
+    |> Stream.each(fn users ->
+      users
+      |> Enum.each(fn user ->
+        User.perform(:delete, user)
+      end)
+    end)
+    |> Stream.run()
+  end
 end
index 32f13df69c31a6400d77156b6fdfcaba36e0289d..9e0ce0329e2638652eded2a150d4fc1087c9d013 100644 (file)
@@ -128,6 +128,7 @@ defmodule Pleroma.Notification do
     |> where([user_actor: user_actor], user_actor.is_active)
     |> exclude_notification_muted(user, exclude_notification_muted_opts)
     |> exclude_blocked(user, exclude_blocked_opts)
+    |> exclude_blockers(user)
     |> exclude_filtered(user)
     |> exclude_visibility(opts)
   end
@@ -141,6 +142,17 @@ defmodule Pleroma.Notification do
     |> FollowingRelationship.keep_following_or_not_domain_blocked(user)
   end
 
+  defp exclude_blockers(query, user) do
+    if Pleroma.Config.get([:activitypub, :blockers_visible]) == true do
+      query
+    else
+      blocker_ap_ids = User.incoming_relationships_ungrouped_ap_ids(user, [:block])
+
+      query
+      |> where([n, a], a.actor not in ^blocker_ap_ids)
+    end
+  end
+
   defp exclude_notification_muted(query, _, %{@include_muted_option => true}) do
     query
   end
index dbaf06e7a34c3f843a8fa9fa3d86ad4fb35c49ba..8324ca22c80bcedace3bd1a2d1f8985d941c0945 100644 (file)
@@ -441,6 +441,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     |> maybe_preload_bookmarks(opts)
     |> maybe_set_thread_muted_field(opts)
     |> restrict_blocked(opts)
+    |> restrict_blockers_visibility(opts)
     |> restrict_recipients(recipients, opts[:user])
     |> restrict_filtered(opts)
     |> where(
@@ -1028,7 +1029,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
     from(
       [activity, object: o] in query,
+      # You don't block the author
       where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids),
+
+      # You don't block any recipients, and didn't author the post
       where:
         fragment(
           "((not (? && ?)) or ? = ?)",
@@ -1037,12 +1041,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
           activity.actor,
           ^user.ap_id
         ),
+
+      # You don't block the domain of any recipients, and didn't author the post
       where:
         fragment(
-          "recipients_contain_blocked_domains(?, ?) = false",
+          "(recipients_contain_blocked_domains(?, ?) = false) or ? = ?",
           activity.recipients,
-          ^domain_blocks
+          ^domain_blocks,
+          activity.actor,
+          ^user.ap_id
         ),
+
+      # It's not a boost of a user you block
       where:
         fragment(
           "not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",
@@ -1050,6 +1060,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
           activity.data,
           ^blocked_ap_ids
         ),
+
+      # You don't block the author's domain, and also don't follow the author
       where:
         fragment(
           "(not (split_part(?, '/', 3) = ANY(?))) or ? = ANY(?)",
@@ -1058,6 +1070,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
           activity.actor,
           ^following_ap_ids
         ),
+
+      # Same as above, but checks the Object
       where:
         fragment(
           "(not (split_part(?->>'actor', '/', 3) = ANY(?))) or (?->>'actor') = ANY(?)",
@@ -1071,6 +1085,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
 
   defp restrict_blocked(query, _), do: query
 
+  defp restrict_blockers_visibility(query, %{blocking_user: %User{} = user}) do
+    if Config.get([:activitypub, :blockers_visible]) == true do
+      query
+    else
+      blocker_ap_ids = User.incoming_relationships_ungrouped_ap_ids(user, [:block])
+
+      from(
+        activity in query,
+        # The author doesn't block you
+        where: fragment("not (? = ANY(?))", activity.actor, ^blocker_ap_ids),
+
+        # It's not a boost of a user that blocks you
+        where:
+          fragment(
+            "not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",
+            activity.data,
+            activity.data,
+            ^blocker_ap_ids
+          )
+      )
+    end
+  end
+
+  defp restrict_blockers_visibility(query, _), do: query
+
   defp restrict_unlisted(query, %{restrict_unlisted: true}) do
     from(
       activity in query,
@@ -1297,6 +1336,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
       |> restrict_state(opts)
       |> restrict_favorited_by(opts)
       |> restrict_blocked(restrict_blocked_opts)
+      |> restrict_blockers_visibility(opts)
       |> restrict_muted(restrict_muted_opts)
       |> restrict_filtered(opts)
       |> restrict_media(opts)
index 57ac40b42816273ff92616207ee5937fb16a70b1..4a19938f643d9f4e64e2e604ffd5833001861838 100644 (file)
@@ -283,15 +283,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
     json(conn, "ok")
   end
 
+  def inbox(%{assigns: %{valid_signature: false}} = conn, _params) do
+    conn
+    |> put_status(:bad_request)
+    |> json("Invalid HTTP Signature")
+  end
+
   # POST /relay/inbox -or- POST /internal/fetch/inbox
-  def inbox(conn, params) do
-    if params["type"] == "Create" && FederatingPlug.federating?() do
+  def inbox(conn, %{"type" => "Create"} = params) do
+    if FederatingPlug.federating?() do
       post_inbox_relayed_create(conn, params)
     else
-      post_inbox_fallback(conn, params)
+      conn
+      |> put_status(:bad_request)
+      |> json("Not federating")
     end
   end
 
+  def inbox(conn, _params) do
+    conn
+    |> put_status(:bad_request)
+    |> json("error, missing HTTP Signature")
+  end
+
   defp post_inbox_relayed_create(conn, params) do
     Logger.debug(
       "Signature missing or not from author, relayed Create message, fetching object from source"
@@ -302,23 +316,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
     json(conn, "ok")
   end
 
-  defp post_inbox_fallback(conn, params) do
-    headers = Enum.into(conn.req_headers, %{})
-
-    if headers["signature"] && params["actor"] &&
-         String.contains?(headers["signature"], params["actor"]) do
-      Logger.debug(
-        "Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
-      )
-
-      Logger.debug(inspect(conn.req_headers))
-    end
-
-    conn
-    |> put_status(:bad_request)
-    |> json(dgettext("errors", "error"))
-  end
-
   defp represent_service_actor(%User{} = user, conn) do
     with {:ok, user} <- User.ensure_keys_present(user) do
       conn
index 839ac1a8d9185381f56cc84ff14122da63cfb899..50aa294f0ff0aed48ac6089323a47a4a6e2353b7 100644 (file)
@@ -49,7 +49,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
   plug(
     OAuthScopesPlug,
     %{scopes: ["admin:read:statuses"]}
-    when action in [:list_user_statuses, :list_instance_statuses]
+    when action in [:list_user_statuses]
   )
 
   plug(
@@ -81,24 +81,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
 
   action_fallback(AdminAPI.FallbackController)
 
-  def list_instance_statuses(conn, %{"instance" => instance} = params) do
-    with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
-    {page, page_size} = page_params(params)
-
-    result =
-      ActivityPub.fetch_statuses(nil, %{
-        instance: instance,
-        limit: page_size,
-        offset: (page - 1) * page_size,
-        exclude_reblogs: not with_reblogs,
-        total: true
-      })
-
-    conn
-    |> put_view(AdminAPI.StatusView)
-    |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity})
-  end
-
   def list_user_statuses(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname} = params) do
     with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
     godmode = params["godmode"] == "true" || params["godmode"] == true
diff --git a/lib/pleroma/web/admin_api/controllers/instance_controller.ex b/lib/pleroma/web/admin_api/controllers/instance_controller.ex
new file mode 100644 (file)
index 0000000..0085798
--- /dev/null
@@ -0,0 +1,63 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.InstanceController do
+  use Pleroma.Web, :controller
+
+  import Pleroma.Web.ControllerHelper, only: [fetch_integer_param: 3]
+
+  alias Pleroma.Instances.Instance
+  alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.AdminAPI
+  alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+  require Logger
+
+  @default_page_size 50
+
+  plug(
+    OAuthScopesPlug,
+    %{scopes: ["admin:read:statuses"]}
+    when action in [:list_statuses]
+  )
+
+  plug(
+    OAuthScopesPlug,
+    %{scopes: ["admin:write:accounts", "admin:write:statuses"]}
+    when action in [:delete]
+  )
+
+  action_fallback(AdminAPI.FallbackController)
+
+  def list_statuses(conn, %{"instance" => instance} = params) do
+    with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
+    {page, page_size} = page_params(params)
+
+    result =
+      ActivityPub.fetch_statuses(nil, %{
+        instance: instance,
+        limit: page_size,
+        offset: (page - 1) * page_size,
+        exclude_reblogs: not with_reblogs,
+        total: true
+      })
+
+    conn
+    |> put_view(AdminAPI.StatusView)
+    |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity})
+  end
+
+  def delete(conn, %{"instance" => instance}) do
+    with {:ok, _job} <- Instance.delete_users_and_activities(instance) do
+      json(conn, instance)
+    end
+  end
+
+  defp page_params(params) do
+    {
+      fetch_integer_param(params, "page", 1),
+      fetch_integer_param(params, "page_size", @default_page_size)
+    }
+  end
+end
index fa7879cafdb38f94507a9aa09e8191a4c04aa3ed..739b1f0260e1d3257c74addc1898986e02821284 100644 (file)
@@ -18,6 +18,8 @@ defmodule Pleroma.Web.Feed.UserController do
   def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do
     with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
       Pleroma.Web.Fallback.RedirectController.redirector_with_meta(conn, %{user: user})
+    else
+      _ -> Pleroma.Web.Fallback.RedirectController.redirector(conn, nil)
     end
   end
 
index 1f84750b9df84c9ab0872ce9f9216222da230043..abb332ec2f1f9eed9b232f83fa34f50b0fa7b654 100644 (file)
@@ -211,7 +211,8 @@ defmodule Pleroma.Web.Router do
     get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
     get("/users/:nickname/chats", AdminAPIController, :list_user_chats)
 
-    get("/instances/:instance/statuses", AdminAPIController, :list_instance_statuses)
+    get("/instances/:instance/statuses", InstanceController, :list_statuses)
+    delete("/instances/:instance", InstanceController, :delete)
 
     get("/instance_document/:name", InstanceDocumentController, :show)
     patch("/instance_document/:name", InstanceDocumentController, :update)
index 1e28384cb188d7fe626e1cf9d9b7dc7cab7601c2..4db077232a850eac077dd98793496f217e2c8f36 100644 (file)
@@ -3,6 +3,7 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Workers.BackgroundWorker do
+  alias Pleroma.Instances.Instance
   alias Pleroma.User
 
   use Pleroma.Workers.WorkerHelper, queue: "background"
@@ -38,4 +39,8 @@ defmodule Pleroma.Workers.BackgroundWorker do
 
     Pleroma.FollowingRelationship.move_following(origin, target)
   end
+
+  def perform(%Job{args: %{"op" => "delete_instance", "host" => host}}) do
+    Instance.perform(:delete_instance, host)
+  end
 end
diff --git a/mix.exs b/mix.exs
index 91e70f238e9844386d5e9aa76ed120bd7313da12..ef5575f28266fb9b0b20434ad60f590abacb4b1b 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -146,7 +146,7 @@ defmodule Pleroma.Mixfile do
       {:bbcode_pleroma, "~> 0.2.0"},
       {:crypt,
        git: "https://github.com/msantos/crypt.git",
-       ref: "031d812ea45593de598bdbc3d28bf45a6e976de3"},
+       ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"},
       {:cors_plug, "~> 2.0"},
       {:web_push_encryption,
        git: "https://github.com/lanodan/elixir-web-push-encryption.git", branch: "bugfix/otp-24"},
@@ -158,7 +158,7 @@ defmodule Pleroma.Mixfile do
       {:timex, "~> 3.6"},
       {:ueberauth, "~> 0.4"},
       {:linkify, "~> 0.5.1"},
-      {:http_signatures, "~> 0.1.0"},
+      {:http_signatures, "~> 0.1.1"},
       {:telemetry, "~> 0.3"},
       {:poolboy, "~> 1.5"},
       {:prometheus, "~> 4.6"},
index 42aeda31f479ab0915b25b666e9ec53d76c18d67..bb7c5f184a16ad5acc0ef6df04276fb32a4a33a7 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -22,7 +22,7 @@
   "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
   "credo": {:hex, :credo, "1.5.5", "e8f422026f553bc3bebb81c8e8bf1932f498ca03339856c7fec63d3faac8424b", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dd8623ab7091956a855dc9f3062486add9c52d310dfd62748779c4315d8247de"},
   "crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
-  "crypt": {:git, "https://github.com/msantos/crypt.git", "031d812ea45593de598bdbc3d28bf45a6e976de3", [ref: "031d812ea45593de598bdbc3d28bf45a6e976de3"]},
+  "crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]},
   "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"},
   "db_connection": {:hex, :db_connection, "2.4.0", "d04b1b73795dae60cead94189f1b8a51cc9e1f911c234cc23074017c43c031e5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad416c21ad9f61b3103d254a71b63696ecadb6a917b36f563921e0de00d7d7c8"},
   "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
@@ -58,7 +58,7 @@
   "hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"},
   "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
   "html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
-  "http_signatures": {:hex, :http_signatures, "0.1.0", "4e4b501a936dbf4cb5222597038a89ea10781776770d2e185849fa829686b34c", [:mix], [], "hexpm", "f8a7b3731e3fd17d38fa6e343fcad7b03d6874a3b0a108c8568a71ed9c2cf824"},
+  "http_signatures": {:hex, :http_signatures, "0.1.1", "ca7ebc1b61542b163644c8c3b1f0e0f41037d35f2395940d3c6c7deceab41fd8", [:mix], [], "hexpm", "cc3b8a007322cc7b624c0c15eec49ee58ac977254ff529a3c482f681465942a3"},
   "httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
   "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
   "inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"},
index bacc0b19be1517756ee84f0acda65628a128756d..e49922724e12fc9890c2221e9dfc2f7f7ac043d2 100644 (file)
@@ -6,6 +6,8 @@ defmodule Pleroma.Instances.InstanceTest do
   alias Pleroma.Instances
   alias Pleroma.Instances.Instance
   alias Pleroma.Repo
+  alias Pleroma.Tests.ObanHelpers
+  alias Pleroma.Web.CommonAPI
 
   use Pleroma.DataCase
 
@@ -158,4 +160,33 @@ defmodule Pleroma.Instances.InstanceTest do
                "Instance.scrape_favicon(\"#{url}\") ignored unreachable host"
     end
   end
+
+  test "delete_users_and_activities/1 deletes remote instance users and activities" do
+    [mario, luigi, _peach, wario] =
+      users = [
+        insert(:user, nickname: "mario@mushroom.kingdom", name: "Mario"),
+        insert(:user, nickname: "luigi@mushroom.kingdom", name: "Luigi"),
+        insert(:user, nickname: "peach@mushroom.kingdom", name: "Peach"),
+        insert(:user, nickname: "wario@greedville.biz", name: "Wario")
+      ]
+
+    {:ok, post1} = CommonAPI.post(mario, %{status: "letsa go!"})
+    {:ok, post2} = CommonAPI.post(luigi, %{status: "itsa me... luigi"})
+    {:ok, post3} = CommonAPI.post(wario, %{status: "WHA-HA-HA!"})
+
+    {:ok, job} = Instance.delete_users_and_activities("mushroom.kingdom")
+    :ok = ObanHelpers.perform(job)
+
+    [mario, luigi, peach, wario] = Repo.reload(users)
+
+    refute mario.is_active
+    refute luigi.is_active
+    refute peach.is_active
+    refute peach.name == "Peach"
+
+    assert wario.is_active
+    assert wario.name == "Wario"
+
+    assert [nil, nil, %{}] = Repo.reload([post1, post2, post3])
+  end
 end
index 64e12066e58620ced13a96d2376e9b6fc5ef25a5..a61244c7676657e3be92e4bd0bd91871240afb9a 100644 (file)
@@ -776,6 +776,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     assert Enum.member?(activities, activity_one)
   end
 
+  test "always see your own posts even when they address people you block" do
+    user = insert(:user)
+    blockee = insert(:user)
+
+    {:ok, _} = User.block(user, blockee)
+    {:ok, activity} = CommonAPI.post(user, %{status: "hey! @#{blockee.nickname}"})
+
+    activities = ActivityPub.fetch_activities([], %{blocking_user: user})
+
+    assert Enum.member?(activities, activity)
+  end
+
   test "doesn't return transitive interactions concerning blocked users" do
     blocker = insert(:user)
     blockee = insert(:user)
@@ -875,6 +887,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     refute repeat_activity in activities
   end
 
+  test "see your own posts even when they adress actors from blocked domains" do
+    user = insert(:user)
+
+    domain = "dogwhistle.zone"
+    domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
+
+    {:ok, user} = User.block_domain(user, domain)
+
+    {:ok, activity} = CommonAPI.post(user, %{status: "hey! @#{domain_user.nickname}"})
+
+    activities = ActivityPub.fetch_activities([], %{blocking_user: user})
+
+    assert Enum.member?(activities, activity)
+  end
+
   test "does return activities from followed users on blocked domains" do
     domain = "meanies.social"
     domain_user = insert(:user, %{ap_id: "https://#{domain}/@pundit"})
index 262f93ec45a01f4b4dffc516306b2506a74eb39e..f8cd103c6a4bde72f162d1d1bdd305a291ba6208 100644 (file)
@@ -798,40 +798,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
     end
   end
 
-  describe "instances" do
-    test "GET /instances/:instance/statuses", %{conn: conn} do
-      user = insert(:user, local: false, ap_id: "https://archae.me/users/archaeme")
-      user2 = insert(:user, local: false, ap_id: "https://test.com/users/test")
-      insert_pair(:note_activity, user: user)
-      activity = insert(:note_activity, user: user2)
-
-      %{"total" => 2, "activities" => activities} =
-        conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
-
-      assert length(activities) == 2
-
-      %{"total" => 1, "activities" => [_]} =
-        conn |> get("/api/pleroma/admin/instances/test.com/statuses") |> json_response(200)
-
-      %{"total" => 0, "activities" => []} =
-        conn |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") |> json_response(200)
-
-      CommonAPI.repeat(activity.id, user)
-
-      %{"total" => 2, "activities" => activities} =
-        conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
-
-      assert length(activities) == 2
-
-      %{"total" => 3, "activities" => activities} =
-        conn
-        |> get("/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
-        |> json_response(200)
-
-      assert length(activities) == 3
-    end
-  end
-
   describe "PATCH /confirm_email" do
     test "it confirms emails of two users", %{conn: conn, admin: admin} do
       [first_user, second_user] = insert_pair(:user, is_confirmed: false)
diff --git a/test/pleroma/web/admin_api/controllers/instance_controller_test.exs b/test/pleroma/web/admin_api/controllers/instance_controller_test.exs
new file mode 100644 (file)
index 0000000..c78307f
--- /dev/null
@@ -0,0 +1,80 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.InstanceControllerTest do
+  use Pleroma.Web.ConnCase
+  use Oban.Testing, repo: Pleroma.Repo
+
+  import Pleroma.Factory
+
+  alias Pleroma.Repo
+  alias Pleroma.Tests.ObanHelpers
+  alias Pleroma.Web.CommonAPI
+
+  setup_all do
+    Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
+
+    :ok
+  end
+
+  setup do
+    admin = insert(:user, is_admin: true)
+    token = insert(:oauth_admin_token, user: admin)
+
+    conn =
+      build_conn()
+      |> assign(:user, admin)
+      |> assign(:token, token)
+
+    {:ok, %{admin: admin, token: token, conn: conn}}
+  end
+
+  test "GET /instances/:instance/statuses", %{conn: conn} do
+    user = insert(:user, local: false, ap_id: "https://archae.me/users/archaeme")
+    user2 = insert(:user, local: false, ap_id: "https://test.com/users/test")
+    insert_pair(:note_activity, user: user)
+    activity = insert(:note_activity, user: user2)
+
+    %{"total" => 2, "activities" => activities} =
+      conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
+
+    assert length(activities) == 2
+
+    %{"total" => 1, "activities" => [_]} =
+      conn |> get("/api/pleroma/admin/instances/test.com/statuses") |> json_response(200)
+
+    %{"total" => 0, "activities" => []} =
+      conn |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") |> json_response(200)
+
+    CommonAPI.repeat(activity.id, user)
+
+    %{"total" => 2, "activities" => activities} =
+      conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
+
+    assert length(activities) == 2
+
+    %{"total" => 3, "activities" => activities} =
+      conn
+      |> get("/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
+      |> json_response(200)
+
+    assert length(activities) == 3
+  end
+
+  test "DELETE /instances/:instance", %{conn: conn} do
+    user = insert(:user, nickname: "lain@lain.com")
+    post = insert(:note_activity, user: user)
+
+    response =
+      conn
+      |> delete("/api/pleroma/admin/instances/lain.com")
+      |> json_response(200)
+
+    [:ok] = ObanHelpers.perform_all()
+
+    assert response == "lain.com"
+    refute Repo.reload(user).is_active
+    refute Repo.reload(post)
+  end
+end
index 6f6ff433f193332cd4c177c6f7f2fb9b41dce06a..6e3f790b2f0ed1890266b78081bd97ddbfa39857 100644 (file)
@@ -196,13 +196,26 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
                ).resp_body
     end
 
-    test "with html format, it returns error when user is not found", %{conn: conn} do
+    test "with html format, it falls back to frontend when user is remote", %{conn: conn} do
+      user = insert(:user, local: false)
+
+      {:ok, _} = CommonAPI.post(user, %{status: "test"})
+
+      response =
+        conn
+        |> get("/users/#{user.nickname}")
+        |> response(200)
+
+      assert response =~ "</html>"
+    end
+
+    test "with html format, it falls back to frontend when user is not found", %{conn: conn} do
       response =
         conn
         |> get("/users/jimm")
-        |> json_response(404)
+        |> response(200)
 
-      assert response == %{"error" => "Not found"}
+      assert response =~ "</html>"
     end
 
     test "with non-html / non-json format, it redirects to user feed in atom format", %{
index 14bb7dae55f898c0b51c90b8f69e33b25a1dd608..d991f284f2fffe2b1f8a2cb6b3fe5542a5824368 100644 (file)
@@ -101,6 +101,25 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
     assert [_] = result
   end
 
+  test "excludes mentions from blockers when blockers_visible is false" do
+    clear_config([:activitypub, :blockers_visible], false)
+
+    %{user: user, conn: conn} = oauth_access(["read:notifications"])
+    blocker = insert(:user)
+
+    {:ok, _} = CommonAPI.block(blocker, user)
+    {:ok, activity} = CommonAPI.post(blocker, %{status: "hi @#{user.nickname}"})
+
+    {:ok, [_notification]} = Notification.create_notifications(activity)
+
+    conn =
+      conn
+      |> assign(:user, user)
+      |> get("/api/v1/notifications")
+
+    assert [] == json_response_and_validate_schema(conn, 200)
+  end
+
   test "getting a single notification" do
     %{user: user, conn: conn} = oauth_access(["read:notifications"])
     other_user = insert(:user)
index ed1286675cdb0419719998048e5bfc07bf74f86a..187982d92572b42b0cb21552bbc353de94aa6132 100644 (file)
@@ -273,6 +273,24 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
       [%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response
     end
 
+    test "doesn't return posts from users who blocked you when :blockers_visible is disabled" do
+      clear_config([:activitypub, :blockers_visible], false)
+
+      %{conn: conn, user: blockee} = oauth_access(["read:statuses"])
+      blocker = insert(:user)
+      {:ok, _} = User.block(blocker, blockee)
+
+      conn = assign(conn, :user, blockee)
+
+      {:ok, _} = CommonAPI.post(blocker, %{status: "hey!"})
+
+      response =
+        get(conn, "/api/v1/timelines/public")
+        |> json_response_and_validate_schema(200)
+
+      assert length(response) == 0
+    end
+
     test "doesn't return replies if follow is posting with users from blocked domain" do
       %{conn: conn, user: blocker} = oauth_access(["read:statuses"])
       friend = insert(:user)