Merge branch 'feature/split-hide-network-v2' into 'develop'
authorkaniini <nenolod@gmail.com>
Tue, 5 Feb 2019 18:56:59 +0000 (18:56 +0000)
committerkaniini <nenolod@gmail.com>
Tue, 5 Feb 2019 18:56:59 +0000 (18:56 +0000)
Split hide_network into hide_followers & hide_followings (fixed)

See merge request pleroma/pleroma!765

13 files changed:
.gitignore
config/config.exs
docs/config.md
lib/mix/tasks/pleroma/user.ex
lib/pleroma/config/deprecation_warnings.ex
lib/pleroma/html.ex
lib/pleroma/mime.ex
lib/pleroma/upload.ex
lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
lib/pleroma/web/activity_pub/mrf/tag_policy.ex [new file with mode: 0644]
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
test/web/twitter_api/util_controller_test.exs

index 72fe2ce430dab93a386bd72e391b3ea79375caf3..04c61ede784db368780dcaced5f043ad7d1b0cc4 100644 (file)
@@ -25,6 +25,7 @@ erl_crash.dump
 # secrets files as long as you replace their contents by environment
 # variables.
 /config/*.secret.exs
+/config/generated_config.exs
 
 # Database setup file, some may forget to delete it
 /config/setup_db.psql
index d0d53a64a2fa25127c8d9f1a226ee727b87db190..8b42a53513626b0ee58d9c31e9375d29cafc728d 100644 (file)
@@ -227,7 +227,9 @@ config :pleroma, :mrf_rejectnonpublic,
   allow_followersonly: false,
   allow_direct: false
 
-config :pleroma, :mrf_hellthread, threshold: 10
+config :pleroma, :mrf_hellthread,
+  delist_threshold: 5,
+  reject_threshold: 10
 
 config :pleroma, :mrf_simple,
   media_removal: [],
index c14746d932fb9c573560363d2c73ecd5769e7766..e042d216fdeb502097ddca98f078930236f81fd8 100644 (file)
@@ -17,7 +17,7 @@ Note: `strip_exif` has been replaced by `Pleroma.Upload.Filter.Mogrify`.
 
 ## Pleroma.Upload.Filter.Mogrify
 
-* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", {"impode", "1"}]`.
+* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"impode", "1"}]`.
 
 ## Pleroma.Upload.Filter.Dedupe
 
@@ -148,7 +148,8 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i
 * `allow_direct`: whether to allow direct messages
 
 ## :mrf_hellthread
-* `threshold`: Number of mentioned users after which the message gets discarded as spam
+* `delist_threshold`: Number of mentioned users after which the message gets delisted (the message can still be seen, but it will not show up in public timelines and mentioned users won't get notifications about it). Set to 0 to disable.
+* `reject_threshold`: Number of mentioned users after which the messaged gets rejected. Set to 0 to disable.
 
 ## :media_proxy
 * `enabled`: Enables proxying of remote media to the instance’s proxy
index c311d48e0d258e1b50954a48d281b9d67586c697..ffc45fd037d2fe0f1336962385255449d4a5d49a 100644 (file)
@@ -52,6 +52,14 @@ defmodule Mix.Tasks.Pleroma.User do
   - `--locked`/`--no-locked` - whether the user's account is locked
   - `--moderator`/`--no-moderator` - whether the user is a moderator
   - `--admin`/`--no-admin` - whether the user is an admin
+
+  ## Add tags to a user.
+
+      mix pleroma.user tag NICKNAME TAGS
+
+  ## Delete tags from a user.
+
+      mix pleroma.user untag NICKNAME TAGS
   """
   def run(["new", nickname, email | rest]) do
     {options, [], []} =
@@ -249,6 +257,32 @@ defmodule Mix.Tasks.Pleroma.User do
     end
   end
 
+  def run(["tag", nickname | tags]) do
+    Common.start_pleroma()
+
+    with %User{} = user <- User.get_by_nickname(nickname) do
+      user = user |> User.tag(tags)
+
+      Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}")
+    else
+      _ ->
+        Mix.shell().error("Could not change user tags for #{nickname}")
+    end
+  end
+
+  def run(["untag", nickname | tags]) do
+    Common.start_pleroma()
+
+    with %User{} = user <- User.get_by_nickname(nickname) do
+      user = user |> User.untag(tags)
+
+      Mix.shell().info("Tags of #{user.nickname}: #{inspect(tags)}")
+    else
+      _ ->
+        Mix.shell().error("Could not change user tags for #{nickname}")
+    end
+  end
+
   def run(["invite"]) do
     Common.start_pleroma()
 
index dc50682eed19cf09b6c5805929a3d119202ce55d..7451fd0a7675d8c63b1ab10e398b34462eb7721f 100644 (file)
@@ -14,7 +14,17 @@ defmodule Pleroma.Config.DeprecationWarnings do
     end
   end
 
+  def check_hellthread_threshold do
+    if Pleroma.Config.get([:mrf_hellthread, :threshold]) do
+      Logger.warn("""
+      !!!DEPRECATION WARNING!!!
+      You are using the old configuration mechanism for the hellthread filter. Please check config.md.
+      """)
+    end
+  end
+
   def warn do
     check_frontend_config_mechanism()
+    check_hellthread_threshold()
   end
 end
index bf5daa9482bdb1da279502b5a8c5b937f805d5fc..b4a4742ee30c39699e0ecaf079a8226415ead5f3 100644 (file)
@@ -59,6 +59,8 @@ defmodule Pleroma.HTML do
     end)
   end
 
+  def extract_first_external_url(_, nil), do: {:error, "No content"}
+
   def extract_first_external_url(object, content) do
     key = "URL|#{object.id}"
 
index 84fb536e0630644f94e492302ae34333eaec096e..36771533f01336c8331ebd7d989273437212228d 100644 (file)
@@ -102,10 +102,18 @@ defmodule Pleroma.MIME do
     "audio/ogg"
   end
 
-  defp check_mime_type(<<0x52, 0x49, 0x46, 0x46, _::binary>>) do
+  defp check_mime_type(<<"RIFF", _::binary-size(4), "WAVE", _::binary>>) do
     "audio/wav"
   end
 
+  defp check_mime_type(<<"RIFF", _::binary-size(4), "WEBP", _::binary>>) do
+    "image/webp"
+  end
+
+  defp check_mime_type(<<"RIFF", _::binary-size(4), "AVI.", _::binary>>) do
+    "video/avi"
+  end
+
   defp check_mime_type(_) do
     @default
   end
index 0a19e737bbd18d77377eb5857291c08bded1c65f..ce2a1b69633344607415767f4d58bb9ffdfda8af 100644 (file)
@@ -124,10 +124,10 @@ defmodule Pleroma.Upload do
 
           :pleroma, Pleroma.Upload, [filters: [Pleroma.Upload.Filter.Mogrify]]
 
-          :pleroma, Pleroma.Upload.Filter.Mogrify, args: "strip"
+          :pleroma, Pleroma.Upload.Filter.Mogrify, args: ["strip", "auto-orient"]
         """)
 
-        Pleroma.Config.put([Pleroma.Upload.Filter.Mogrify], args: "strip")
+        Pleroma.Config.put([Pleroma.Upload.Filter.Mogrify], args: ["strip", "auto-orient"])
         Map.put(opts, :filters, opts.filters ++ [Pleroma.Upload.Filter.Mogrify])
       else
         opts
index a3f516ae7fde83b0680c7ec6f9f98ad8c9a72a3c..4c6e612b28357025f8b436c6ea3065e1bdce6bf7 100644 (file)
@@ -3,20 +3,46 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
+  alias Pleroma.User
   @behaviour Pleroma.Web.ActivityPub.MRF
 
+  defp delist_message(message) do
+    follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
+
+    message
+    |> Map.put("to", [follower_collection])
+    |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"])
+  end
+
   @impl true
-  def filter(%{"type" => "Create"} = object) do
-    threshold = Pleroma.Config.get([:mrf_hellthread, :threshold])
-    recipients = (object["to"] || []) ++ (object["cc"] || [])
-
-    if length(recipients) > threshold do
-      {:reject, nil}
-    else
-      {:ok, object}
+  def filter(%{"type" => "Create"} = message) do
+    delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
+
+    reject_threshold =
+      Pleroma.Config.get(
+        [:mrf_hellthread, :reject_threshold],
+        Pleroma.Config.get([:mrf_hellthread, :threshold])
+      )
+
+    recipients = (message["to"] || []) ++ (message["cc"] || [])
+
+    cond do
+      length(recipients) > reject_threshold and reject_threshold > 0 ->
+        {:reject, nil}
+
+      length(recipients) > delist_threshold and delist_threshold > 0 ->
+        if Enum.member?(message["to"], "https://www.w3.org/ns/activitystreams#Public") or
+             Enum.member?(message["cc"], "https://www.w3.org/ns/activitystreams#Public") do
+          {:ok, delist_message(message)}
+        else
+          {:ok, message}
+        end
+
+      true ->
+        {:ok, message}
     end
   end
 
   @impl true
-  def filter(object), do: {:ok, object}
+  def filter(message), do: {:ok, message}
 end
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
new file mode 100644 (file)
index 0000000..b242e44
--- /dev/null
@@ -0,0 +1,139 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
+  alias Pleroma.User
+  @behaviour Pleroma.Web.ActivityPub.MRF
+
+  defp get_tags(%User{tags: tags}) when is_list(tags), do: tags
+  defp get_tags(_), do: []
+
+  defp process_tag(
+         "mrf_tag:media-force-nsfw",
+         %{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
+       )
+       when length(child_attachment) > 0 do
+    tags = (object["tag"] || []) ++ ["nsfw"]
+
+    object =
+      object
+      |> Map.put("tags", tags)
+      |> Map.put("sensitive", true)
+
+    message = Map.put(message, "object", object)
+
+    {:ok, message}
+  end
+
+  defp process_tag(
+         "mrf_tag:media-strip",
+         %{"type" => "Create", "object" => %{"attachment" => child_attachment} = object} = message
+       )
+       when length(child_attachment) > 0 do
+    object = Map.delete(object, "attachment")
+    message = Map.put(message, "object", object)
+
+    {:ok, message}
+  end
+
+  defp process_tag(
+         "mrf_tag:force-unlisted",
+         %{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
+       ) do
+    user = User.get_cached_by_ap_id(actor)
+
+    if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") do
+      to =
+        List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
+
+      cc =
+        List.delete(cc, user.follower_address) ++ ["https://www.w3.org/ns/activitystreams#Public"]
+
+      object =
+        message["object"]
+        |> Map.put("to", to)
+        |> Map.put("cc", cc)
+
+      message =
+        message
+        |> Map.put("to", to)
+        |> Map.put("cc", cc)
+        |> Map.put("object", object)
+
+      {:ok, message}
+    else
+      {:ok, message}
+    end
+  end
+
+  defp process_tag(
+         "mrf_tag:sandbox",
+         %{"type" => "Create", "to" => to, "cc" => cc, "actor" => actor} = message
+       ) do
+    user = User.get_cached_by_ap_id(actor)
+
+    if Enum.member?(to, "https://www.w3.org/ns/activitystreams#Public") or
+         Enum.member?(cc, "https://www.w3.org/ns/activitystreams#Public") do
+      to =
+        List.delete(to, "https://www.w3.org/ns/activitystreams#Public") ++ [user.follower_address]
+
+      cc = List.delete(cc, "https://www.w3.org/ns/activitystreams#Public")
+
+      object =
+        message["object"]
+        |> Map.put("to", to)
+        |> Map.put("cc", cc)
+
+      message =
+        message
+        |> Map.put("to", to)
+        |> Map.put("cc", cc)
+        |> Map.put("object", object)
+
+      {:ok, message}
+    else
+      {:ok, message}
+    end
+  end
+
+  defp process_tag(
+         "mrf_tag:disable-remote-subscription",
+         %{"type" => "Follow", "actor" => actor} = message
+       ) do
+    user = User.get_cached_by_ap_id(actor)
+
+    if user.local == true do
+      {:ok, message}
+    else
+      {:reject, nil}
+    end
+  end
+
+  defp process_tag("mrf_tag:disable-any-subscription", %{"type" => "Follow"}), do: {:reject, nil}
+
+  defp process_tag(_, message), do: {:ok, message}
+
+  def filter_message(actor, message) do
+    User.get_cached_by_ap_id(actor)
+    |> get_tags()
+    |> Enum.reduce({:ok, message}, fn
+      tag, {:ok, message} ->
+        process_tag(tag, message)
+
+      _, error ->
+        error
+    end)
+  end
+
+  @impl true
+  def filter(%{"object" => target_actor, "type" => "Follow"} = message),
+    do: filter_message(target_actor, message)
+
+  @impl true
+  def filter(%{"actor" => actor, "type" => "Create"} = message),
+    do: filter_message(actor, message)
+
+  @impl true
+  def filter(message), do: {:ok, message}
+end
index 43725c3db9f273cb37c28099b6c88eb5ed28a7af..7151efdeb79774b1356403b4f7e291601b77098a 100644 (file)
@@ -313,6 +313,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
     |> Map.put("tag", combined)
   end
 
+  def fix_tag(%{"tag" => %{} = tag} = object), do: Map.put(object, "tag", [tag])
+
   def fix_tag(object), do: object
 
   # content map usually only has one language so this will do for now.
index d5b7e68c78af54c45673e8fe2636ce0a476fe597..c0e289ef8013b7ed3a1e6a1b9a84e0ed2ff627cd 100644 (file)
@@ -182,8 +182,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
   end
 
   def render("card.json", %{rich_media: rich_media, page_url: page_url}) do
-    page_url = rich_media[:url] || page_url
-    page_url_data = URI.parse(page_url)
+    page_url_data =
+      if rich_media[:url] != nil do
+        URI.merge(URI.parse(page_url), URI.parse(rich_media[:url]))
+      else
+        page_url
+      end
+
+    page_url = page_url_data |> to_string
+
+    image_url =
+      if rich_media[:image] != nil do
+        URI.merge(page_url_data, URI.parse(rich_media[:image]))
+        |> to_string
+      else
+        nil
+      end
+
     site_name = rich_media[:site_name] || page_url_data.host
 
     %{
@@ -191,7 +206,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
       provider_name: site_name,
       provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
       url: page_url,
-      image: rich_media[:image] |> MediaProxy.url(),
+      image: image_url |> MediaProxy.url(),
       title: rich_media[:title],
       description: rich_media[:description],
       pleroma: %{
index dc9bad3693d8b027b02db2520b7dfc6e59dc55ee..8e152ecd4a3ca69e78816f2425b3cfa3f828e4f5 100644 (file)
@@ -36,6 +36,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
   describe "GET /api/statusnet/config.json" do
     test "it returns the managed config", %{conn: conn} do
       Pleroma.Config.put([:instance, :managed_config], false)
+      Pleroma.Config.put([:fe, :theme], "rei-ayanami-towel")
 
       response =
         conn