Merge branch 'develop' into 'fix/admin-api-user-deletion'
# Conflicts: # CHANGELOG.md
This commit is contained in:
commit
ec969eec51
93 changed files with 1283 additions and 432 deletions
|
|
@ -520,6 +520,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
from(activity in Activity)
|
||||
|> maybe_preload_objects(opts)
|
||||
|> maybe_preload_bookmarks(opts)
|
||||
|> maybe_set_thread_muted_field(opts)
|
||||
|> restrict_blocked(opts)
|
||||
|> restrict_recipients(recipients, opts["user"])
|
||||
|> where(
|
||||
|
|
@ -533,6 +535,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
)
|
||||
)
|
||||
|> exclude_poll_votes(opts)
|
||||
|> exclude_id(opts)
|
||||
|> order_by([activity], desc: activity.id)
|
||||
end
|
||||
|
||||
|
|
@ -625,6 +628,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
params =
|
||||
params
|
||||
|> Map.put("type", ["Create", "Announce"])
|
||||
|> Map.put("user", reading_user)
|
||||
|> Map.put("actor_id", user.ap_id)
|
||||
|> Map.put("whole_db", true)
|
||||
|> Map.put("pinned_activity_ids", user.info.pinned_activities)
|
||||
|
|
@ -872,6 +876,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
end
|
||||
end
|
||||
|
||||
defp exclude_id(query, %{"exclude_id" => id}) when is_binary(id) do
|
||||
from(activity in query, where: activity.id != ^id)
|
||||
end
|
||||
|
||||
defp exclude_id(query, _), do: query
|
||||
|
||||
defp maybe_preload_objects(query, %{"skip_preload" => true}), do: query
|
||||
|
||||
defp maybe_preload_objects(query, _) do
|
||||
|
|
|
|||
|
|
@ -28,11 +28,43 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
|
||||
@spec subdomains_regex([String.t()]) :: [Regex.t()]
|
||||
def subdomains_regex(domains) when is_list(domains) do
|
||||
for domain <- domains, do: ~r(^#{String.replace(domain, "*.", "(.*\\.)*")}$)
|
||||
for domain <- domains, do: ~r(^#{String.replace(domain, "*.", "(.*\\.)*")}$)i
|
||||
end
|
||||
|
||||
@spec subdomain_match?([Regex.t()], String.t()) :: boolean()
|
||||
def subdomain_match?(domains, host) do
|
||||
Enum.any?(domains, fn domain -> Regex.match?(domain, host) end)
|
||||
end
|
||||
|
||||
@callback describe() :: {:ok | :error, Map.t()}
|
||||
|
||||
def describe(policies) do
|
||||
{:ok, policy_configs} =
|
||||
policies
|
||||
|> Enum.reduce({:ok, %{}}, fn
|
||||
policy, {:ok, data} ->
|
||||
{:ok, policy_data} = policy.describe()
|
||||
{:ok, Map.merge(data, policy_data)}
|
||||
|
||||
_, error ->
|
||||
error
|
||||
end)
|
||||
|
||||
mrf_policies =
|
||||
get_policies()
|
||||
|> Enum.map(fn policy -> to_string(policy) |> String.split(".") |> List.last() end)
|
||||
|
||||
exclusions = Pleroma.Config.get([:instance, :mrf_transparency_exclusions])
|
||||
|
||||
base =
|
||||
%{
|
||||
mrf_policies: mrf_policies,
|
||||
exclusions: length(exclusions) > 0
|
||||
}
|
||||
|> Map.merge(policy_configs)
|
||||
|
||||
{:ok, base}
|
||||
end
|
||||
|
||||
def describe, do: get_policies() |> describe()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -62,4 +62,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
|
||||
alias Pleroma.User
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
require Logger
|
||||
|
||||
# has the user successfully posted before?
|
||||
|
|
@ -22,6 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
|
|||
|
||||
defp contains_links?(_), do: false
|
||||
|
||||
@impl true
|
||||
def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
|
||||
with {:ok, %User{} = u} <- User.get_or_fetch_by_ap_id(actor),
|
||||
{:contains_links, true} <- {:contains_links, contains_links?(object)},
|
||||
|
|
@ -45,4 +48,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
|
|||
|
||||
# in all other cases, pass through
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,4 +12,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
|
|||
Logger.info("REJECTING #{inspect(object)}")
|
||||
{:reject, object}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -39,4 +39,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
|
|||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -90,4 +90,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe,
|
||||
do: {:ok, %{mrf_hellthread: Pleroma.Config.get(:mrf_hellthread) |> Enum.into(%{})}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -96,4 +96,36 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
# This horror is needed to convert regex sigils to strings
|
||||
mrf_keyword =
|
||||
Pleroma.Config.get(:mrf_keyword, [])
|
||||
|> Enum.map(fn {key, value} ->
|
||||
{key,
|
||||
Enum.map(value, fn
|
||||
{pattern, replacement} ->
|
||||
%{
|
||||
"pattern" =>
|
||||
if not is_binary(pattern) do
|
||||
inspect(pattern)
|
||||
else
|
||||
pattern
|
||||
end,
|
||||
"replacement" => replacement
|
||||
}
|
||||
|
||||
pattern ->
|
||||
if not is_binary(pattern) do
|
||||
inspect(pattern)
|
||||
else
|
||||
pattern
|
||||
end
|
||||
end)}
|
||||
end)
|
||||
|> Enum.into(%{})
|
||||
|
||||
{:ok, %{mrf_keyword: mrf_keyword}}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,4 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,4 +21,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,4 +19,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,4 +10,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
|
|||
def filter(object) do
|
||||
{:ok, object}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,4 +21,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
|
|||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,4 +44,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
|
|||
|
||||
@impl true
|
||||
def filter(object), do: {:ok, object}
|
||||
|
||||
@impl true
|
||||
def describe,
|
||||
do: {:ok, %{mrf_rejectnonpublic: Pleroma.Config.get(:mrf_rejectnonpublic) |> Enum.into(%{})}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -177,4 +177,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
exclusions = Pleroma.Config.get([:instance, :mrf_transparency_exclusions])
|
||||
|
||||
mrf_simple =
|
||||
Pleroma.Config.get(:mrf_simple)
|
||||
|> Enum.map(fn {k, v} -> {k, Enum.reject(v, fn v -> v in exclusions end)} end)
|
||||
|> Enum.into(%{})
|
||||
|
||||
{:ok, %{mrf_simple: mrf_simple}}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,4 +37,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -165,4 +165,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
|
|||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
@impl true
|
||||
def describe, do: {:ok, %{}}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,4 +32,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
|
|||
end
|
||||
|
||||
def filter(object), do: {:ok, object}
|
||||
|
||||
@impl true
|
||||
def describe do
|
||||
mrf_user_allowlist =
|
||||
Config.get([:mrf_user_allowlist], [])
|
||||
|> Enum.into(%{}, fn {k, v} -> {k, length(v)} end)
|
||||
|
||||
{:ok, %{mrf_user_allowlist: mrf_user_allowlist}}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
37
lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
Normal file
37
lib/pleroma/web/activity_pub/mrf/vocabulary_policy.ex
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# 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.VocabularyPolicy do
|
||||
@moduledoc "Filter messages which belong to certain activity vocabularies"
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
def filter(%{"type" => "Undo", "object" => child_message} = message) do
|
||||
with {:ok, _} <- filter(child_message) do
|
||||
{:ok, message}
|
||||
else
|
||||
{:reject, nil} ->
|
||||
{:reject, nil}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(%{"type" => message_type} = message) do
|
||||
with accepted_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :accept]),
|
||||
rejected_vocabulary <- Pleroma.Config.get([:mrf_vocabulary, :reject]),
|
||||
true <-
|
||||
length(accepted_vocabulary) == 0 || Enum.member?(accepted_vocabulary, message_type),
|
||||
false <-
|
||||
length(rejected_vocabulary) > 0 && Enum.member?(rejected_vocabulary, message_type),
|
||||
{:ok, _} <- filter(message["object"]) do
|
||||
{:ok, message}
|
||||
else
|
||||
_ -> {:reject, nil}
|
||||
end
|
||||
end
|
||||
|
||||
def filter(message), do: {:ok, message}
|
||||
|
||||
def describe,
|
||||
do: {:ok, %{mrf_vocabulary: Pleroma.Config.get(:mrf_vocabulary) |> Enum.into(%{})}}
|
||||
end
|
||||
|
|
@ -46,7 +46,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
"""
|
||||
def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do
|
||||
Logger.info("Federating #{id} to #{inbox}")
|
||||
host = URI.parse(inbox).host
|
||||
%{host: host, path: path} = URI.parse(inbox)
|
||||
|
||||
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
|
||||
|
||||
|
|
@ -56,6 +56,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
|
||||
signature =
|
||||
Pleroma.Signature.sign(actor, %{
|
||||
"(request-target)": "post #{path}",
|
||||
host: host,
|
||||
"content-length": byte_size(json),
|
||||
digest: digest,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do
|
|||
|> User.get_or_create_service_actor_by_ap_id()
|
||||
end
|
||||
|
||||
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
def follow(target_instance) do
|
||||
with %User{} = local_user <- get_actor(),
|
||||
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance),
|
||||
|
|
@ -21,12 +22,17 @@ defmodule Pleroma.Web.ActivityPub.Relay do
|
|||
Logger.info("relay: followed instance: #{target_instance}; id=#{activity.data["id"]}")
|
||||
{:ok, activity}
|
||||
else
|
||||
{:error, _} = error ->
|
||||
Logger.error("error: #{inspect(error)}")
|
||||
error
|
||||
|
||||
e ->
|
||||
Logger.error("error: #{inspect(e)}")
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
@spec unfollow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
def unfollow(target_instance) do
|
||||
with %User{} = local_user <- get_actor(),
|
||||
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance),
|
||||
|
|
@ -34,20 +40,27 @@ defmodule Pleroma.Web.ActivityPub.Relay do
|
|||
Logger.info("relay: unfollowed instance: #{target_instance}: id=#{activity.data["id"]}")
|
||||
{:ok, activity}
|
||||
else
|
||||
{:error, _} = error ->
|
||||
Logger.error("error: #{inspect(error)}")
|
||||
error
|
||||
|
||||
e ->
|
||||
Logger.error("error: #{inspect(e)}")
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
@spec publish(any()) :: {:ok, Activity.t(), Object.t()} | {:error, any()}
|
||||
def publish(%Activity{data: %{"type" => "Create"}} = activity) do
|
||||
with %User{} = user <- get_actor(),
|
||||
%Object{} = object <- Object.normalize(activity) do
|
||||
ActivityPub.announce(user, object, nil, true, false)
|
||||
else
|
||||
e -> Logger.error("error: #{inspect(e)}")
|
||||
e ->
|
||||
Logger.error("error: #{inspect(e)}")
|
||||
{:error, inspect(e)}
|
||||
end
|
||||
end
|
||||
|
||||
def publish(_), do: nil
|
||||
def publish(_), do: {:error, "Not implemented"}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
"""
|
||||
def fix_object(object, options \\ []) do
|
||||
object
|
||||
|> strip_internal_fields
|
||||
|> fix_actor
|
||||
|> fix_url
|
||||
|> fix_attachments
|
||||
|
|
@ -34,7 +35,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> fix_emoji
|
||||
|> fix_tag
|
||||
|> fix_content_map
|
||||
|> fix_likes
|
||||
|> fix_addressing
|
||||
|> fix_summary
|
||||
|> fix_type(options)
|
||||
|
|
@ -151,20 +151,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> Map.put("actor", Containment.get_actor(%{"actor" => actor}))
|
||||
end
|
||||
|
||||
# Check for standardisation
|
||||
# This is what Peertube does
|
||||
# curl -H 'Accept: application/activity+json' $likes | jq .totalItems
|
||||
# Prismo returns only an integer (count) as "likes"
|
||||
def fix_likes(%{"likes" => likes} = object) when not is_map(likes) do
|
||||
object
|
||||
|> Map.put("likes", [])
|
||||
|> Map.put("like_count", 0)
|
||||
end
|
||||
|
||||
def fix_likes(object) do
|
||||
object
|
||||
end
|
||||
|
||||
def fix_in_reply_to(object, options \\ [])
|
||||
|
||||
def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options)
|
||||
|
|
@ -347,13 +333,15 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|
||||
def fix_type(object, options \\ [])
|
||||
|
||||
def fix_type(%{"inReplyTo" => reply_id} = object, options) when is_binary(reply_id) do
|
||||
def fix_type(%{"inReplyTo" => reply_id, "name" => _} = object, options)
|
||||
when is_binary(reply_id) do
|
||||
reply =
|
||||
if Federator.allowed_incoming_reply_depth?(options[:depth]) do
|
||||
Object.normalize(reply_id, true)
|
||||
with true <- Federator.allowed_incoming_reply_depth?(options[:depth]),
|
||||
{:ok, object} <- get_obj_helper(reply_id, options) do
|
||||
object
|
||||
end
|
||||
|
||||
if reply && (reply.data["type"] == "Question" and object["name"]) do
|
||||
if reply && reply.data["type"] == "Question" do
|
||||
Map.put(object, "type", "Answer")
|
||||
else
|
||||
object
|
||||
|
|
@ -713,8 +701,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
} = _data,
|
||||
_options
|
||||
) do
|
||||
with true <- Pleroma.Config.get([:activitypub, :accept_blocks]),
|
||||
%User{local: true} = blocked <- User.get_cached_by_ap_id(blocked),
|
||||
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.unblock(blocker, blocked, id, false) do
|
||||
User.unblock(blocker, blocked)
|
||||
|
|
@ -728,8 +715,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
%{"type" => "Block", "object" => blocked, "actor" => blocker, "id" => id} = _data,
|
||||
_options
|
||||
) do
|
||||
with true <- Pleroma.Config.get([:activitypub, :accept_blocks]),
|
||||
%User{local: true} = blocked = User.get_cached_by_ap_id(blocked),
|
||||
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)
|
||||
|
|
@ -784,7 +770,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> add_mention_tags
|
||||
|> add_emoji_tags
|
||||
|> add_attributed_to
|
||||
|> add_likes
|
||||
|> prepare_attachments
|
||||
|> set_conversation
|
||||
|> set_reply_to_uri
|
||||
|
|
@ -971,22 +956,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> Map.put("attributedTo", attributed_to)
|
||||
end
|
||||
|
||||
def add_likes(%{"id" => id, "like_count" => likes} = object) do
|
||||
likes = %{
|
||||
"id" => "#{id}/likes",
|
||||
"first" => "#{id}/likes?page=1",
|
||||
"type" => "OrderedCollection",
|
||||
"totalItems" => likes
|
||||
}
|
||||
|
||||
object
|
||||
|> Map.put("likes", likes)
|
||||
end
|
||||
|
||||
def add_likes(object) do
|
||||
object
|
||||
end
|
||||
|
||||
def prepare_attachments(object) do
|
||||
attachments =
|
||||
(object["attachment"] || [])
|
||||
|
|
@ -1002,6 +971,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
defp strip_internal_fields(object) do
|
||||
object
|
||||
|> Map.drop([
|
||||
"likes",
|
||||
"like_count",
|
||||
"announcements",
|
||||
"announcement_count",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue