Merge branch 'preload-fixups-2' into preloadfixups
authorlain <lain@soykaf.club>
Tue, 30 Jun 2020 09:40:34 +0000 (11:40 +0200)
committerlain <lain@soykaf.club>
Tue, 30 Jun 2020 09:40:34 +0000 (11:40 +0200)
40 files changed:
.gitlab/issue_templates/Bug.md
CHANGELOG.md
config/config.exs
docs/API/differences_in_mastoapi_responses.md
lib/pleroma/html.ex
lib/pleroma/notification.ex
lib/pleroma/object/fetcher.ex
lib/pleroma/user.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/builder.ex
lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
lib/pleroma/web/activity_pub/object_validator.ex
lib/pleroma/web/activity_pub/object_validators/block_validator.ex [new file with mode: 0644]
lib/pleroma/web/activity_pub/side_effects.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/activity_pub/visibility.ex
lib/pleroma/web/api_spec/cast_and_validate.ex
lib/pleroma/web/api_spec/schemas/account.ex
lib/pleroma/web/api_spec/schemas/status.ex
lib/pleroma/web/common_api/common_api.ex
lib/pleroma/web/mastodon_api/controllers/account_controller.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/preload/instance.ex
mix.exs
mix.lock
test/fixtures/preload_static/instance/panel.html [new file with mode: 0644]
test/html_test.exs
test/notification_test.exs
test/web/activity_pub/activity_pub_test.exs
test/web/activity_pub/mrf/anti_link_spam_policy_test.exs
test/web/activity_pub/object_validator_test.exs
test/web/activity_pub/side_effects_test.exs
test/web/activity_pub/transmogrifier/block_handling_test.exs [new file with mode: 0644]
test/web/activity_pub/transmogrifier_test.exs
test/web/activity_pub/utils_test.exs
test/web/common_api/common_api_test.exs
test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
test/web/mastodon_api/controllers/account_controller_test.exs
test/web/mastodon_api/views/status_view_test.exs
test/web/preload/instance_test.exs

index 66fbc510edeb020a29533548ef1e0bb681752bae..9ce9b69182441ad145ebcf5dacfa0994954072bb 100644 (file)
@@ -14,7 +14,7 @@
 * Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE): 
 * Elixir version (`elixir -v` for from source installations, N/A for OTP):
 * Operating system:
-* PostgreSQL version (`postgres -V`):
+* PostgreSQL version (`psql -V`):
 
 
 ### Bug description
index 71963d206e7a3bac5ef1e0cbd03c0fd487932383..5b6928dcd7d14766ae05e48b7276711151fada9d 100644 (file)
@@ -51,6 +51,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 
 <details>
   <summary>API Changes</summary>
+- Mastodon API: Add pleroma.parents_visible field to statuses.
 - Mastodon API: Extended `/api/v1/instance`.
 - Mastodon API: Support for `include_types` in `/api/v1/notifications`.
 - Mastodon API: Added `/api/v1/notifications/:id/dismiss` endpoint.
index 5b1c576e7a5edcf7aba348817ee7f6d38502beb4..9b550920cb144e469eda74394f67079e133cce37 100644 (file)
@@ -437,8 +437,6 @@ config :pleroma, Pleroma.Web.Metadata,
 config :pleroma, Pleroma.Web.Preload,
   providers: [
     Pleroma.Web.Preload.Providers.Instance,
-    Pleroma.Web.Preload.Providers.User,
-    Pleroma.Web.Preload.Providers.Timelines,
     Pleroma.Web.Preload.Providers.StatusNet
   ]
 
index 7c3546f4ff9c4709379cf81d3ca760f9dc566587..13920e5f9818bbcd7f2e9b5fea71fc03d5712874 100644 (file)
@@ -27,6 +27,7 @@ Has these additional fields under the `pleroma` object:
 - `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
 - `thread_muted`: true if the thread the post belongs to is muted
 - `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
+- `parent_visible`: If the parent of this post is visible to the user or not.
 
 ## Media Attachments
 
@@ -51,11 +52,14 @@ The `id` parameter can also be the `nickname` of the user. This only works in th
 
 Has these additional fields under the `pleroma` object:
 
+- `ap_id`: nullable URL string, ActivityPub id of the user
+- `background_image`: nullable URL string, background image of the user
 - `tags`: Lists an array of tags for the user
-- `relationship{}`: Includes fields as documented for Mastodon API https://docs.joinmastodon.org/entities/relationship/
+- `relationship` (object): Includes fields as documented for Mastodon API https://docs.joinmastodon.org/entities/relationship/
 - `is_moderator`: boolean, nullable,  true if user is a moderator
 - `is_admin`: boolean, nullable, true if user is an admin
 - `confirmation_pending`: boolean, true if a new user account is waiting on email confirmation to be activated
+- `hide_favorites`: boolean, true when the user has hiding favorites enabled
 - `hide_followers`: boolean, true when the user has follower hiding enabled
 - `hide_follows`: boolean, true when the user has follow hiding enabled
 - `hide_followers_count`: boolean, true when the user has follower stat hiding enabled
@@ -66,6 +70,7 @@ Has these additional fields under the `pleroma` object:
 - `allow_following_move`: boolean, true when the user allows automatically follow moved following accounts
 - `unread_conversation_count`: The count of unread conversations. Only returned to the account owner.
 - `unread_notifications_count`: The count of unread notifications. Only returned to the account owner.
+- `notification_settings`: object, can be absent. See `/api/pleroma/notification_settings` for the parameters/keys returned.
 
 ### Source
 
index d78c5f2025ced17c45649393954cc164841dd8d2..dc1b9b840c006694b365cfea71eb288461fc5cac 100644 (file)
@@ -109,7 +109,7 @@ defmodule Pleroma.HTML do
       result =
         content
         |> Floki.parse_fragment!()
-        |> Floki.filter_out("a.mention,a.hashtag,a[rel~=\"tag\"]")
+        |> Floki.filter_out("a.mention,a.hashtag,a.attachment,a[rel~=\"tag\"]")
         |> Floki.attribute("a", "href")
         |> Enum.at(0)
 
index 9ee9606becb9fd9bf779d81b6b72a01c5b4595ac..2ef1a80c5746a27013282f63cc91f39eb3724c2b 100644 (file)
@@ -367,6 +367,7 @@ defmodule Pleroma.Notification do
         do_send = do_send && user in enabled_receivers
         create_notification(activity, user, do_send)
       end)
+      |> Enum.reject(&is_nil/1)
 
     {:ok, notifications}
   end
index 263ded5dd50f54fa36c2e5b64576144c1b38f731..3e2949ee2354f3009ae68142a1a01a5a10b86c6b 100644 (file)
@@ -83,8 +83,8 @@ defmodule Pleroma.Object.Fetcher do
       {:transmogrifier, {:error, {:reject, nil}}} ->
         {:reject, nil}
 
-      {:transmogrifier, _} ->
-        {:error, "Transmogrifier failure."}
+      {:transmogrifier, _} = e ->
+        {:error, e}
 
       {:object, data, nil} ->
         reinject_object(%Object{}, data)
index 1d70a37efa6277f9abddc832a84e918e2a25ff97..9d5c61e7981debc500f376941a47c4d8a26c9257 100644 (file)
@@ -1309,7 +1309,8 @@ defmodule Pleroma.User do
 
     unsubscribe(blocked, blocker)
 
-    if following?(blocked, blocker), do: unfollow(blocked, blocker)
+    unfollowing_blocked = Config.get([:activitypub, :unfollow_blocked], true)
+    if unfollowing_blocked && following?(blocked, blocker), do: unfollow(blocked, blocker)
 
     {:ok, blocker} = update_follower_count(blocker)
     {:ok, blocker, _} = Participation.mark_all_as_read(blocker, blocked)
@@ -1527,8 +1528,7 @@ defmodule Pleroma.User do
       blocked_identifiers,
       fn blocked_identifier ->
         with {:ok, %User{} = blocked} <- get_or_fetch(blocked_identifier),
-             {:ok, _user_block} <- block(blocker, blocked),
-             {:ok, _} <- ActivityPub.block(blocker, blocked) do
+             {:ok, _block} <- CommonAPI.block(blocker, blocked) do
           blocked
         else
           err ->
index 7cd3eab3906c76579c69fe73ca34d0f0e2f03a1c..05bd824f58d2edef836f1fdc18a7f6361b386b2f 100644 (file)
@@ -366,33 +366,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     end
   end
 
-  @spec block(User.t(), User.t(), String.t() | nil, boolean()) ::
-          {:ok, Activity.t()} | {:error, any()}
-  def block(blocker, blocked, activity_id \\ nil, local \\ true) do
-    with {:ok, result} <-
-           Repo.transaction(fn -> do_block(blocker, blocked, activity_id, local) end) do
-      result
-    end
-  end
-
-  defp do_block(blocker, blocked, activity_id, local) do
-    unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
-
-    if unfollow_blocked and fetch_latest_follow(blocker, blocked) do
-      unfollow(blocker, blocked, nil, local)
-    end
-
-    block_data = make_block_data(blocker, blocked, activity_id)
-
-    with {:ok, activity} <- insert(block_data, local),
-         _ <- notify_and_stream(activity),
-         :ok <- maybe_federate(activity) do
-      {:ok, activity}
-    else
-      {:error, error} -> Repo.rollback(error)
-    end
-  end
-
   @spec flag(map()) :: {:ok, Activity.t()} | {:error, any()}
   def flag(
         %{
index 135a5c431eca0c271cda0e2479170419a8583271..cabc28de94cf4302fdea4a7b50a18f3e1c15dfe3 100644 (file)
@@ -138,6 +138,18 @@ defmodule Pleroma.Web.ActivityPub.Builder do
      }, []}
   end
 
+  @spec block(User.t(), User.t()) :: {:ok, map(), keyword()}
+  def block(blocker, blocked) do
+    {:ok,
+     %{
+       "id" => Utils.generate_activity_id(),
+       "type" => "Block",
+       "actor" => blocker.ap_id,
+       "object" => blocked.ap_id,
+       "to" => [blocked.ap_id]
+     }, []}
+  end
+
   @spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()}
   def announce(actor, object, options \\ []) do
     public? = Keyword.get(options, :public, false)
index 9e78009975e8cda92ee599ac83b81e542c436632..a7e187b5e4df03ab5c474df31194712b38362a8f 100644 (file)
@@ -27,11 +27,14 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
 
   @impl true
   def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
-    with {:ok, %User{} = u} <- User.get_or_fetch_by_ap_id(actor),
+    with {:ok, %User{local: false} = u} <- User.get_or_fetch_by_ap_id(actor),
          {:contains_links, true} <- {:contains_links, contains_links?(object)},
          {:old_user, true} <- {:old_user, old_user?(u)} do
       {:ok, message}
     else
+      {:ok, %User{local: true}} ->
+        {:ok, message}
+
       {:contains_links, false} ->
         {:ok, message}
 
index 2c657b46788b79f2b45ed0033d2b0767945fe9ae..bb6324460dcf08078d701942fdc1b7cbdff0355b 100644 (file)
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
   alias Pleroma.Object
   alias Pleroma.User
   alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
+  alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator
   alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
@@ -24,6 +25,25 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
   @spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
   def validate(object, meta)
 
+  def validate(%{"type" => "Block"} = block_activity, meta) do
+    with {:ok, block_activity} <-
+           block_activity
+           |> BlockValidator.cast_and_validate()
+           |> Ecto.Changeset.apply_action(:insert) do
+      block_activity = stringify_keys(block_activity)
+      outgoing_blocks = Pleroma.Config.get([:activitypub, :outgoing_blocks])
+
+      meta =
+        if !outgoing_blocks do
+          Keyword.put(meta, :do_not_federate, true)
+        else
+          meta
+        end
+
+      {:ok, block_activity, meta}
+    end
+  end
+
   def validate(%{"type" => "Update"} = update_activity, meta) do
     with {:ok, update_activity} <-
            update_activity
diff --git a/lib/pleroma/web/activity_pub/object_validators/block_validator.ex b/lib/pleroma/web/activity_pub/object_validators/block_validator.ex
new file mode 100644 (file)
index 0000000..1dde771
--- /dev/null
@@ -0,0 +1,42 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator do
+  use Ecto.Schema
+
+  alias Pleroma.EctoType.ActivityPub.ObjectValidators
+
+  import Ecto.Changeset
+  import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
+
+  @primary_key false
+
+  embedded_schema do
+    field(:id, ObjectValidators.ObjectID, primary_key: true)
+    field(:type, :string)
+    field(:actor, ObjectValidators.ObjectID)
+    field(:to, ObjectValidators.Recipients, default: [])
+    field(:cc, ObjectValidators.Recipients, default: [])
+    field(:object, ObjectValidators.ObjectID)
+  end
+
+  def cast_data(data) do
+    %__MODULE__{}
+    |> cast(data, __schema__(:fields))
+  end
+
+  def validate_data(cng) do
+    cng
+    |> validate_required([:id, :type, :actor, :to, :cc, :object])
+    |> validate_inclusion(:type, ["Block"])
+    |> validate_actor_presence()
+    |> validate_actor_presence(field_name: :object)
+  end
+
+  def cast_and_validate(data) do
+    data
+    |> cast_data
+    |> validate_data
+  end
+end
index de143b8f0a6a90b53cb44d815b4989da9ad79834..5cc2eb378d76a62a9a429ebe9d285f34dc318a62 100644 (file)
@@ -20,6 +20,21 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
 
   def handle(object, meta \\ [])
 
+  # Tasks this handles:
+  # - Unfollow and block
+  def handle(
+        %{data: %{"type" => "Block", "object" => blocked_user, "actor" => blocking_user}} =
+          object,
+        meta
+      ) do
+    with %User{} = blocker <- User.get_cached_by_ap_id(blocking_user),
+         %User{} = blocked <- User.get_cached_by_ap_id(blocked_user) do
+      User.block(blocker, blocked)
+    end
+
+    {:ok, object, meta}
+  end
+
   # Tasks this handles:
   # - Update the user
   #
index 4e318e89cf2d9d4cd7f08b08051b62ba1d74d5a9..278fbbeab14ddab7b8e65b0cf4957373e2147d8e 100644 (file)
@@ -673,7 +673,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   end
 
   def handle_incoming(%{"type" => type} = data, _options)
-      when type in ["Like", "EmojiReact", "Announce"] do
+      when type in ~w{Like EmojiReact Announce} do
     with :ok <- ObjectValidator.fetch_actor_and_object(data),
          {:ok, activity, _meta} <-
            Pipeline.common_pipeline(data, local: false) do
@@ -684,9 +684,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
   end
 
   def handle_incoming(
-        %{"type" => "Update"} = data,
+        %{"type" => type} = data,
         _options
-      ) do
+      )
+      when type in ~w{Update Block} do
     with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
          {:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
       {:ok, activity}
@@ -765,21 +766,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     end
   end
 
-  def handle_incoming(
-        %{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = _data,
-        _options
-      ) do
-    with %User{local: true} = blocked = User.get_cached_by_ap_id(blocked),
-         {:ok, %User{} = blocker} = User.get_or_fetch_by_ap_id(blocker),
-         {:ok, activity} <- ActivityPub.block(blocker, blocked, id, false) do
-      User.unfollow(blocker, blocked)
-      User.block(blocker, blocked)
-      {:ok, activity}
-    else
-      _e -> :error
-    end
-  end
-
   def handle_incoming(
         %{
           "type" => "Move",
index 453a6842edbc88d83f9bc740ddd1875c2b0aa590..343f41caa6a6399bd05b4b6261542fac1843595b 100644 (file)
@@ -47,6 +47,10 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
   @spec visible_for_user?(Activity.t(), User.t() | nil) :: boolean()
   def visible_for_user?(%{actor: ap_id}, %User{ap_id: ap_id}), do: true
 
+  def visible_for_user?(nil, _), do: false
+
+  def visible_for_user?(%{data: %{"listMessage" => _}}, nil), do: false
+
   def visible_for_user?(%{data: %{"listMessage" => list_ap_id}} = activity, %User{} = user) do
     user.ap_id in activity.data["to"] ||
       list_ap_id
@@ -54,8 +58,6 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
       |> Pleroma.List.member?(user)
   end
 
-  def visible_for_user?(%{data: %{"listMessage" => _}}, nil), do: false
-
   def visible_for_user?(%{local: local} = activity, nil) do
     cfg_key =
       if local,
index bd9026237044c7ba9f576c8718d69dadc101e9b7..fbfc27d6f7655cd3efe38556c9e3c706421a6081 100644 (file)
@@ -40,7 +40,7 @@ defmodule Pleroma.Web.ApiSpec.CastAndValidate do
           |> List.first()
 
         _ ->
-          nil
+          "application/json"
       end
 
     private_data = Map.put(private_data, :operation_id, operation_id)
index d54e2158d7ac2618ede9c0905feadc91d76d9a20..84f18f1b683e7189a2dc099d7706f26da7317ddf 100644 (file)
@@ -40,20 +40,53 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
       pleroma: %Schema{
         type: :object,
         properties: %{
-          allow_following_move: %Schema{type: :boolean},
-          background_image: %Schema{type: :string, nullable: true},
+          allow_following_move: %Schema{
+            type: :boolean,
+            description: "whether the user allows automatically follow moved following accounts"
+          },
+          background_image: %Schema{type: :string, nullable: true, format: :uri},
           chat_token: %Schema{type: :string},
-          confirmation_pending: %Schema{type: :boolean},
+          confirmation_pending: %Schema{
+            type: :boolean,
+            description:
+              "whether the user account is waiting on email confirmation to be activated"
+          },
           hide_favorites: %Schema{type: :boolean},
-          hide_followers_count: %Schema{type: :boolean},
-          hide_followers: %Schema{type: :boolean},
-          hide_follows_count: %Schema{type: :boolean},
-          hide_follows: %Schema{type: :boolean},
-          is_admin: %Schema{type: :boolean},
-          is_moderator: %Schema{type: :boolean},
+          hide_followers_count: %Schema{
+            type: :boolean,
+            description: "whether the user has follower stat hiding enabled"
+          },
+          hide_followers: %Schema{
+            type: :boolean,
+            description: "whether the user has follower hiding enabled"
+          },
+          hide_follows_count: %Schema{
+            type: :boolean,
+            description: "whether the user has follow stat hiding enabled"
+          },
+          hide_follows: %Schema{
+            type: :boolean,
+            description: "whether the user has follow hiding enabled"
+          },
+          is_admin: %Schema{
+            type: :boolean,
+            description: "whether the user is an admin of the local instance"
+          },
+          is_moderator: %Schema{
+            type: :boolean,
+            description: "whether the user is a moderator of the local instance"
+          },
           skip_thread_containment: %Schema{type: :boolean},
-          tags: %Schema{type: :array, items: %Schema{type: :string}},
-          unread_conversation_count: %Schema{type: :integer},
+          tags: %Schema{
+            type: :array,
+            items: %Schema{type: :string},
+            description:
+              "List of tags being used for things like extra roles or moderation(ie. marking all media as nsfw all)."
+          },
+          unread_conversation_count: %Schema{
+            type: :integer,
+            description: "The count of unread conversations. Only returned to the account owner."
+          },
           notification_settings: %Schema{
             type: :object,
             properties: %{
@@ -66,7 +99,9 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
           },
           relationship: AccountRelationship,
           settings_store: %Schema{
-            type: :object
+            type: :object,
+            description:
+              "A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`"
           }
         }
       },
@@ -74,16 +109,32 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
         type: :object,
         properties: %{
           fields: %Schema{type: :array, items: AccountField},
-          note: %Schema{type: :string},
+          note: %Schema{
+            type: :string,
+            description:
+              "Plaintext version of the bio without formatting applied by the backend, used for editing the bio."
+          },
           privacy: VisibilityScope,
           sensitive: %Schema{type: :boolean},
           pleroma: %Schema{
             type: :object,
             properties: %{
               actor_type: ActorType,
-              discoverable: %Schema{type: :boolean},
-              no_rich_text: %Schema{type: :boolean},
-              show_role: %Schema{type: :boolean}
+              discoverable: %Schema{
+                type: :boolean,
+                description:
+                  "whether the user allows discovery of the account in search results and other services."
+              },
+              no_rich_text: %Schema{
+                type: :boolean,
+                description:
+                  "whether the HTML tags for rich-text formatting are stripped from all statuses requested from the API."
+              },
+              show_role: %Schema{
+                type: :boolean,
+                description:
+                  "whether the user wants their role (e.g admin, moderator) to be shown"
+              }
             }
           }
         }
index 8b87cb25b24d22291cf4e17bc6fce36243b6feb1..28cde963e61ca9d51a9fadc007b50b4434c69303 100644 (file)
@@ -184,6 +184,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
           thread_muted: %Schema{
             type: :boolean,
             description: "`true` if the thread the post belongs to is muted"
+          },
+          parent_visible: %Schema{
+            type: :boolean,
+            description: "`true` if the parent post is visible to the user"
           }
         }
       },
index 04e081a8e88def3de6bf6139ff3a08854d612699..fd714907953901aaf3f2dd814e0347909c9d4f76 100644 (file)
@@ -25,6 +25,13 @@ defmodule Pleroma.Web.CommonAPI do
   require Pleroma.Constants
   require Logger
 
+  def block(blocker, blocked) do
+    with {:ok, block_data, _} <- Builder.block(blocker, blocked),
+         {:ok, block, _} <- Pipeline.common_pipeline(block_data, local: true) do
+      {:ok, block}
+    end
+  end
+
   def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ []) do
     with maybe_attachment <- opts[:media_id] && Object.get_by_id(opts[:media_id]),
          :ok <- validate_chat_content_length(content, !!maybe_attachment),
index 7a88a847c412f2818eddb863f54df41ac95980b1..b5008d69b261daca246932809629bf0fe5bf821c 100644 (file)
@@ -385,8 +385,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
 
   @doc "POST /api/v1/accounts/:id/block"
   def block(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do
-    with {:ok, _user_block} <- User.block(blocker, blocked),
-         {:ok, _activity} <- ActivityPub.block(blocker, blocked) do
+    with {:ok, _activity} <- CommonAPI.block(blocker, blocked) do
       render(conn, "relationship.json", user: blocker, target: blocked)
     else
       {:error, message} -> json_response(conn, :forbidden, %{error: message})
index 2c49bedb36760f23698836d988eb952845b9c982..6ee17f4dd05e3ad484db6c018500d2a96dc836d8 100644 (file)
@@ -21,7 +21,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
   alias Pleroma.Web.MastodonAPI.StatusView
   alias Pleroma.Web.MediaProxy
 
-  import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1]
+  import Pleroma.Web.ActivityPub.Visibility, only: [get_visibility: 1, visible_for_user?: 2]
 
   # TODO: Add cached version.
   defp get_replied_to_activities([]), do: %{}
@@ -364,7 +364,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
         expires_at: expires_at,
         direct_conversation_id: direct_conversation_id,
         thread_muted: thread_muted?,
-        emoji_reactions: emoji_reactions
+        emoji_reactions: emoji_reactions,
+        parent_visible: visible_for_user?(reply_to, opts[:for])
       }
     }
   end
index b34d7cf37218ab328bd9a70afc5d89a96c55e3dd..3d16f290bcbd02a90cd19f8406b75607ab8363b7 100644 (file)
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.Preload.Providers.Instance do
   alias Pleroma.Web.MastodonAPI.InstanceView
   alias Pleroma.Web.Nodeinfo.Nodeinfo
   alias Pleroma.Web.Preload.Providers.Provider
+  alias Pleroma.Plugs.InstanceStatic
 
   @behaviour Provider
   @instance_url "/api/v1/instance"
@@ -27,7 +28,7 @@ defmodule Pleroma.Web.Preload.Providers.Instance do
   end
 
   defp build_panel_tag(acc) do
-    instance_path = Path.join(:code.priv_dir(:pleroma), "static/instance/panel.html")
+    instance_path = InstanceStatic.file_path(@panel_url |> to_string())
 
     if File.exists?(instance_path) do
       panel_data = File.read!(instance_path)
diff --git a/mix.exs b/mix.exs
index b638be541870d1ca44a6a822179b7c2556b9f03b..e2ab53bdeee0f73d91f7676b8b085038714d6337 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -159,7 +159,10 @@ defmodule Pleroma.Mixfile do
       {:cors_plug, "~> 1.5"},
       {:ex_doc, "~> 0.21", only: :dev, runtime: false},
       {:web_push_encryption, "~> 0.2.1"},
-      {:swoosh, "~> 0.23.2"},
+      {:swoosh,
+       git: "https://github.com/swoosh/swoosh",
+       ref: "c96e0ca8a00d8f211ec1f042a4626b09f249caa5",
+       override: true},
       {:phoenix_swoosh, "~> 0.2"},
       {:gen_smtp, "~> 0.13"},
       {:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test},
index 5ad49391dbab3a0ab009aad04fe9f8482b27a97c..4f2777fa721b0a9b98217d95a46533d3e40720cb 100644 (file)
--- a/mix.lock
+++ b/mix.lock
   "sleeplocks": {:hex, :sleeplocks, "1.1.1", "3d462a0639a6ef36cc75d6038b7393ae537ab394641beb59830a1b8271faeed3", [:rebar3], [], "hexpm", "84ee37aeff4d0d92b290fff986d6a95ac5eedf9b383fadfd1d88e9b84a1c02e1"},
   "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
   "sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"},
-  "swoosh": {:hex, :swoosh, "0.23.5", "bfd9404bbf5069b1be2ffd317923ce57e58b332e25dbca2a35dedd7820dfee5a", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "e3928e1d2889a308aaf3e42755809ac21cffd77cb58eef01cbfdab4ce2fd1e21"},
+  "swoosh": {:git, "https://github.com/swoosh/swoosh", "c96e0ca8a00d8f211ec1f042a4626b09f249caa5", [ref: "c96e0ca8a00d8f211ec1f042a4626b09f249caa5"]},
   "syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},
-  "telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"},
+  "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
   "tesla": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/tesla.git", "61b7503cef33f00834f78ddfafe0d5d9dec2270b", [ref: "61b7503cef33f00834f78ddfafe0d5d9dec2270b"]},
   "timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "f354efb2400dd7a80fd9eb6c8419068c4f632da4ac47f3d8822d6e33f08bc852"},
   "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},
diff --git a/test/fixtures/preload_static/instance/panel.html b/test/fixtures/preload_static/instance/panel.html
new file mode 100644 (file)
index 0000000..fc58e4e
--- /dev/null
@@ -0,0 +1 @@
+HEY!
index 0a4b4ebbcbf23e2d87fb15e633f03df406327a58..f8907c8b4b425d44834caaff55b4936fa70d9fd3 100644 (file)
@@ -237,5 +237,19 @@ defmodule Pleroma.HTMLTest do
 
       assert {:ok, nil} = HTML.extract_first_external_url(object, object.data["content"])
     end
+
+    test "skips attachment links" do
+      user = insert(:user)
+
+      {:ok, activity} =
+        CommonAPI.post(user, %{
+          status:
+            "<a href=\"https://pleroma.gov/media/d24caa3a498e21e0298377a9ca0149a4f4f8b767178aacf837542282e2d94fb1.png?name=image.png\" class=\"attachment\">image.png</a>"
+        })
+
+      object = Object.normalize(activity)
+
+      assert {:ok, nil} = HTML.extract_first_external_url(object, object.data["content"])
+    end
   end
 end
index 526f43fab7a53f1313bd602e2f0f392a6c70820c..6add3f7eba39c9cc4287fcc2c62a6717e13981d6 100644 (file)
@@ -22,6 +22,16 @@ defmodule Pleroma.NotificationTest do
   alias Pleroma.Web.Streamer
 
   describe "create_notifications" do
+    test "never returns nil" do
+      user = insert(:user)
+      other_user = insert(:user, %{invisible: true})
+
+      {:ok, activity} = CommonAPI.post(user, %{status: "yeah"})
+      {:ok, activity} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
+
+      refute {:ok, [nil]} == Notification.create_notifications(activity)
+    end
+
     test "creates a notification for an emoji reaction" do
       user = insert(:user)
       other_user = insert(:user)
index be7ab2ae4691a8bd8b747fec83e8b47e4ccb455d..575e0c5db0b6b19b3acebc3d85500b6b365c00b5 100644 (file)
@@ -992,54 +992,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
     end
   end
 
-  describe "blocking" do
-    test "reverts block activity on error" do
-      [blocker, blocked] = insert_list(2, :user)
-
-      with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
-        assert {:error, :reverted} = ActivityPub.block(blocker, blocked)
-      end
-
-      assert Repo.aggregate(Activity, :count, :id) == 0
-      assert Repo.aggregate(Object, :count, :id) == 0
-    end
-
-    test "creates a block activity" do
-      clear_config([:instance, :federating], true)
-      blocker = insert(:user)
-      blocked = insert(:user)
-
-      with_mock Pleroma.Web.Federator,
-        publish: fn _ -> nil end do
-        {:ok, activity} = ActivityPub.block(blocker, blocked)
-
-        assert activity.data["type"] == "Block"
-        assert activity.data["actor"] == blocker.ap_id
-        assert activity.data["object"] == blocked.ap_id
-
-        assert called(Pleroma.Web.Federator.publish(activity))
-      end
-    end
-
-    test "works with outgoing blocks disabled, but doesn't federate" do
-      clear_config([:instance, :federating], true)
-      clear_config([:activitypub, :outgoing_blocks], false)
-      blocker = insert(:user)
-      blocked = insert(:user)
-
-      with_mock Pleroma.Web.Federator,
-        publish: fn _ -> nil end do
-        {:ok, activity} = ActivityPub.block(blocker, blocked)
-
-        assert activity.data["type"] == "Block"
-        assert activity.data["actor"] == blocker.ap_id
-        assert activity.data["object"] == blocked.ap_id
-
-        refute called(Pleroma.Web.Federator.publish(:_))
-      end
-    end
-  end
-
   describe "timeline post-processing" do
     test "it filters broken threads" do
       user1 = insert(:user)
index 1a13699bef1bffd63dde77ae4ea85972b5b09e3a..6867c98534885e2e72281f33b4927a2eb65bf6d9 100644 (file)
@@ -33,7 +33,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
 
   describe "with new user" do
     test "it allows posts without links" do
-      user = insert(:user)
+      user = insert(:user, local: false)
 
       assert user.note_count == 0
 
@@ -45,7 +45,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
     end
 
     test "it disallows posts with links" do
-      user = insert(:user)
+      user = insert(:user, local: false)
 
       assert user.note_count == 0
 
@@ -55,6 +55,18 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do
 
       {:reject, _} = AntiLinkSpamPolicy.filter(message)
     end
+
+    test "it allows posts with links for local users" do
+      user = insert(:user)
+
+      assert user.note_count == 0
+
+      message =
+        @linkful_message
+        |> Map.put("actor", user.ap_id)
+
+      {:ok, _message} = AntiLinkSpamPolicy.filter(message)
+    end
   end
 
   describe "with old user" do
index 770a8dcf8e34a4a0e2116b47ec91bd4b92e46927..f38bf7e0803ee1ad0eefc98431886f3cf37280a7 100644 (file)
@@ -654,4 +654,31 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidatorTest do
       assert {:error, _cng} = ObjectValidator.validate(update, [])
     end
   end
+
+  describe "blocks" do
+    setup do
+      user = insert(:user, local: false)
+      blocked = insert(:user)
+
+      {:ok, valid_block, []} = Builder.block(user, blocked)
+
+      %{user: user, valid_block: valid_block}
+    end
+
+    test "validates a basic object", %{
+      valid_block: valid_block
+    } do
+      assert {:ok, _block, []} = ObjectValidator.validate(valid_block, [])
+    end
+
+    test "returns an error if we don't know the blocked user", %{
+      valid_block: valid_block
+    } do
+      block =
+        valid_block
+        |> Map.put("object", "https://gensokyo.2hu/users/raymoo")
+
+      assert {:error, _cng} = ObjectValidator.validate(block, [])
+    end
+  end
 end
index 12c9ef1da6e2dd3efc893b81d922145eb18c68f5..af27c34b48edd84df389ccabcbb34929221b0d9d 100644 (file)
@@ -64,6 +64,47 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
     end
   end
 
+  describe "blocking users" do
+    setup do
+      user = insert(:user)
+      blocked = insert(:user)
+      User.follow(blocked, user)
+      User.follow(user, blocked)
+
+      {:ok, block_data, []} = Builder.block(user, blocked)
+      {:ok, block, _meta} = ActivityPub.persist(block_data, local: true)
+
+      %{user: user, blocked: blocked, block: block}
+    end
+
+    test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do
+      assert User.following?(user, blocked)
+      assert User.following?(blocked, user)
+
+      {:ok, _, _} = SideEffects.handle(block)
+
+      refute User.following?(user, blocked)
+      refute User.following?(blocked, user)
+      assert User.blocks?(user, blocked)
+    end
+
+    test "it blocks but does not unfollow if the relevant setting is set", %{
+      user: user,
+      blocked: blocked,
+      block: block
+    } do
+      clear_config([:activitypub, :unfollow_blocked], false)
+      assert User.following?(user, blocked)
+      assert User.following?(blocked, user)
+
+      {:ok, _, _} = SideEffects.handle(block)
+
+      refute User.following?(user, blocked)
+      assert User.following?(blocked, user)
+      assert User.blocks?(user, blocked)
+    end
+  end
+
   describe "update users" do
     setup do
       user = insert(:user)
@@ -242,8 +283,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
       {:ok, like} = CommonAPI.favorite(user, post.id)
       {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
       {:ok, announce} = CommonAPI.repeat(post.id, user)
-      {:ok, block} = ActivityPub.block(user, poster)
-      User.block(user, poster)
+      {:ok, block} = CommonAPI.block(user, poster)
 
       {:ok, undo_data, _meta} = Builder.undo(user, like)
       {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
diff --git a/test/web/activity_pub/transmogrifier/block_handling_test.exs b/test/web/activity_pub/transmogrifier/block_handling_test.exs
new file mode 100644 (file)
index 0000000..71f1a0e
--- /dev/null
@@ -0,0 +1,63 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.Transmogrifier.BlockHandlingTest do
+  use Pleroma.DataCase
+
+  alias Pleroma.Activity
+  alias Pleroma.User
+  alias Pleroma.Web.ActivityPub.Transmogrifier
+
+  import Pleroma.Factory
+
+  test "it works for incoming blocks" do
+    user = insert(:user)
+
+    data =
+      File.read!("test/fixtures/mastodon-block-activity.json")
+      |> Poison.decode!()
+      |> Map.put("object", user.ap_id)
+
+    blocker = insert(:user, ap_id: data["actor"])
+
+    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+    assert data["type"] == "Block"
+    assert data["object"] == user.ap_id
+    assert data["actor"] == "http://mastodon.example.org/users/admin"
+
+    assert User.blocks?(blocker, user)
+  end
+
+  test "incoming blocks successfully tear down any follow relationship" do
+    blocker = insert(:user)
+    blocked = insert(:user)
+
+    data =
+      File.read!("test/fixtures/mastodon-block-activity.json")
+      |> Poison.decode!()
+      |> Map.put("object", blocked.ap_id)
+      |> Map.put("actor", blocker.ap_id)
+
+    {:ok, blocker} = User.follow(blocker, blocked)
+    {:ok, blocked} = User.follow(blocked, blocker)
+
+    assert User.following?(blocker, blocked)
+    assert User.following?(blocked, blocker)
+
+    {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+    assert data["type"] == "Block"
+    assert data["object"] == blocked.ap_id
+    assert data["actor"] == blocker.ap_id
+
+    blocker = User.get_cached_by_ap_id(data["actor"])
+    blocked = User.get_cached_by_ap_id(data["object"])
+
+    assert User.blocks?(blocker, blocked)
+
+    refute User.following?(blocker, blocked)
+    refute User.following?(blocked, blocker)
+  end
+end
index 100821056203140c700efd960336b8a9337824e9..6a53fd3f09050262f9af1f67b83a516680faa1ab 100644 (file)
@@ -445,56 +445,6 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
       assert [^pending_follower] = User.get_follow_requests(user)
     end
 
-    test "it works for incoming blocks" do
-      user = insert(:user)
-
-      data =
-        File.read!("test/fixtures/mastodon-block-activity.json")
-        |> Poison.decode!()
-        |> Map.put("object", user.ap_id)
-
-      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
-      assert data["type"] == "Block"
-      assert data["object"] == user.ap_id
-      assert data["actor"] == "http://mastodon.example.org/users/admin"
-
-      blocker = User.get_cached_by_ap_id(data["actor"])
-
-      assert User.blocks?(blocker, user)
-    end
-
-    test "incoming blocks successfully tear down any follow relationship" do
-      blocker = insert(:user)
-      blocked = insert(:user)
-
-      data =
-        File.read!("test/fixtures/mastodon-block-activity.json")
-        |> Poison.decode!()
-        |> Map.put("object", blocked.ap_id)
-        |> Map.put("actor", blocker.ap_id)
-
-      {:ok, blocker} = User.follow(blocker, blocked)
-      {:ok, blocked} = User.follow(blocked, blocker)
-
-      assert User.following?(blocker, blocked)
-      assert User.following?(blocked, blocker)
-
-      {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
-      assert data["type"] == "Block"
-      assert data["object"] == blocked.ap_id
-      assert data["actor"] == blocker.ap_id
-
-      blocker = User.get_cached_by_ap_id(data["actor"])
-      blocked = User.get_cached_by_ap_id(data["object"])
-
-      assert User.blocks?(blocker, blocked)
-
-      refute User.following?(blocker, blocked)
-      refute User.following?(blocked, blocker)
-    end
-
     test "it works for incoming accepts which were pre-accepted" do
       follower = insert(:user)
       followed = insert(:user)
index 15f03f193b29a0df8c704a4561233361235b26bb..2f9ecb5a3220873fa0c8a4c9cdf43c4822cd195a 100644 (file)
@@ -27,16 +27,6 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
     end
   end
 
-  describe "fetch the latest Block" do
-    test "fetches the latest Block activity" do
-      blocker = insert(:user)
-      blocked = insert(:user)
-      {:ok, activity} = ActivityPub.block(blocker, blocked)
-
-      assert activity == Utils.fetch_latest_block(blocker, blocked)
-    end
-  end
-
   describe "determine_explicit_mentions()" do
     test "works with an object that has mentions" do
       object = %{
@@ -344,9 +334,9 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
       user1 = insert(:user)
       user2 = insert(:user)
 
-      assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
-      assert {:ok, %Activity{} = _} = ActivityPub.block(user1, user2)
-      assert {:ok, %Activity{} = activity} = ActivityPub.block(user1, user2)
+      assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
+      assert {:ok, %Activity{} = _} = CommonAPI.block(user1, user2)
+      assert {:ok, %Activity{} = activity} = CommonAPI.block(user1, user2)
 
       assert Utils.fetch_latest_block(user1, user2) == activity
     end
index 6bd26050ef003b04cf763f1f6e599de6b900942e..fc3bb845d8755bbdc9bbdd7a1154442aa0a6aa17 100644 (file)
@@ -25,6 +25,52 @@ defmodule Pleroma.Web.CommonAPITest do
   setup do: clear_config([:instance, :limit])
   setup do: clear_config([:instance, :max_pinned_statuses])
 
+  describe "blocking" do
+    setup do
+      blocker = insert(:user)
+      blocked = insert(:user)
+      User.follow(blocker, blocked)
+      User.follow(blocked, blocker)
+      %{blocker: blocker, blocked: blocked}
+    end
+
+    test "it blocks and federates", %{blocker: blocker, blocked: blocked} do
+      clear_config([:instance, :federating], true)
+
+      with_mock Pleroma.Web.Federator,
+        publish: fn _ -> nil end do
+        assert {:ok, block} = CommonAPI.block(blocker, blocked)
+
+        assert block.local
+        assert User.blocks?(blocker, blocked)
+        refute User.following?(blocker, blocked)
+        refute User.following?(blocked, blocker)
+
+        assert called(Pleroma.Web.Federator.publish(block))
+      end
+    end
+
+    test "it blocks and does not federate if outgoing blocks are disabled", %{
+      blocker: blocker,
+      blocked: blocked
+    } do
+      clear_config([:instance, :federating], true)
+      clear_config([:activitypub, :outgoing_blocks], false)
+
+      with_mock Pleroma.Web.Federator,
+        publish: fn _ -> nil end do
+        assert {:ok, block} = CommonAPI.block(blocker, blocked)
+
+        assert block.local
+        assert User.blocks?(blocker, blocked)
+        refute User.following?(blocker, blocked)
+        refute User.following?(blocked, blocker)
+
+        refute called(Pleroma.Web.Federator.publish(block))
+      end
+    end
+  end
+
   describe "posting chat messages" do
     setup do: clear_config([:instance, :chat_limit])
 
index f67d294ba2239ed81441044f9449e02335e6f3ef..31f0edf970162551594adfcb80c1eda39090d159 100644 (file)
@@ -216,10 +216,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
         filename: "an_image.jpg"
       }
 
-      conn = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
+      res =
+        conn
+        |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
 
-      assert user_response = json_response_and_validate_schema(conn, 200)
+      assert user_response = json_response_and_validate_schema(res, 200)
       assert user_response["avatar"] != User.avatar_url(user)
+
+      # Also removes it
+      res =
+        conn
+        |> patch("/api/v1/accounts/update_credentials", %{"avatar" => nil})
+
+      assert user_response = json_response_and_validate_schema(res, 200)
+      assert user_response["avatar"] == User.avatar_url(user)
     end
 
     test "updates the user's banner", %{user: user, conn: conn} do
@@ -229,10 +239,21 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
         filename: "an_image.jpg"
       }
 
-      conn = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
+      res =
+        conn
+        |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
 
-      assert user_response = json_response_and_validate_schema(conn, 200)
+      assert user_response = json_response_and_validate_schema(res, 200)
       assert user_response["header"] != User.banner_url(user)
+
+      # Also removes it
+
+      res =
+        conn
+        |> patch("/api/v1/accounts/update_credentials", %{"header" => nil})
+
+      assert user_response = json_response_and_validate_schema(res, 200)
+      assert user_response["header"] == User.banner_url(user)
     end
 
     test "updates the user's background", %{conn: conn} do
@@ -242,13 +263,25 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
         filename: "an_image.jpg"
       }
 
-      conn =
-        patch(conn, "/api/v1/accounts/update_credentials", %{
+      res =
+        conn
+        |> patch("/api/v1/accounts/update_credentials", %{
           "pleroma_background_image" => new_header
         })
 
-      assert user_response = json_response_and_validate_schema(conn, 200)
+      assert user_response = json_response_and_validate_schema(res, 200)
       assert user_response["pleroma"]["background_image"]
+
+      # Also removes it
+
+      res =
+        conn
+        |> patch("/api/v1/accounts/update_credentials", %{
+          "pleroma_background_image" => nil
+        })
+
+      assert user_response = json_response_and_validate_schema(res, 200)
+      refute user_response["pleroma"]["background_image"]
     end
 
     test "requires 'write:accounts' permission" do
index ebfcedd0196dcb7feb139fa8d4e8e712576c8fb5..260ad2306bb4ba2a3ff46ff577ea902cb2c87b3a 100644 (file)
@@ -780,7 +780,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
 
       assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
                conn
-               |> put_req_header("content-type", "application/json")
                |> post("/api/v1/accounts/#{other_user.id}/mute")
                |> json_response_and_validate_schema(200)
 
index 5cbadf0fcc6703e856916df95c1d074328dd45eb..f90a0c2731df46826ac4373653314966e706575a 100644 (file)
@@ -226,7 +226,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
         expires_at: nil,
         direct_conversation_id: nil,
         thread_muted: false,
-        emoji_reactions: []
+        emoji_reactions: [],
+        parent_visible: false
       }
     }
 
@@ -620,4 +621,20 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     assert status.visibility == "list"
   end
+
+  test "has a field for parent visibility" do
+    user = insert(:user)
+    poster = insert(:user)
+
+    {:ok, invisible} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
+
+    {:ok, visible} =
+      CommonAPI.post(poster, %{status: "hey", visibility: "private", in_reply_to_id: invisible.id})
+
+    status = StatusView.render("show.json", activity: visible, for: user)
+    refute status.pleroma.parent_visible
+
+    status = StatusView.render("show.json", activity: visible, for: poster)
+    assert status.pleroma.parent_visible
+  end
 end
index 5bb6c598117052307677186401e0da252a0c8d25..a46f2831248626a0340dfbe0865e3f7168701d6a 100644 (file)
@@ -25,6 +25,17 @@ defmodule Pleroma.Web.Preload.Providers.InstanceTest do
            )
   end
 
+  test "it works with overrides" do
+    clear_config([:instance, :static_dir], "test/fixtures/preload_static")
+
+    %{"/instance/panel.html" => panel} = Instance.generate_terms(nil)
+
+    assert String.contains?(
+             panel,
+             "HEY!"
+           )
+  end
+
   test "it renders the node_info", %{"/nodeinfo/2.0.json" => nodeinfo} do
     %{
       metadata: metadata,