Merge remote-tracking branch 'remotes/origin/develop' into feature/object-hashtags-rework
This commit is contained in:
commit
4134abef63
205 changed files with 682 additions and 443 deletions
|
|
@ -24,6 +24,8 @@ defmodule Pleroma.Activity do
|
|||
|
||||
@primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
schema "activities" do
|
||||
field(:data, :map)
|
||||
field(:local, :boolean, default: true)
|
||||
|
|
@ -298,7 +300,7 @@ defmodule Pleroma.Activity do
|
|||
|
||||
defp purge_web_resp_cache(%Activity{} = activity) do
|
||||
%{path: path} = URI.parse(activity.data["id"])
|
||||
Cachex.del(:web_resp_cache, path)
|
||||
@cachex.del(:web_resp_cache, path)
|
||||
activity
|
||||
end
|
||||
|
||||
|
|
|
|||
19
lib/pleroma/caching.ex
Normal file
19
lib/pleroma/caching.ex
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Caching do
|
||||
@callback get!(Cachex.cache(), any()) :: any()
|
||||
@callback get(Cachex.cache(), any()) :: {atom(), any()}
|
||||
@callback put(Cachex.cache(), any(), any(), Keyword.t()) :: {Cachex.status(), boolean()}
|
||||
@callback put(Cachex.cache(), any(), any()) :: {Cachex.status(), boolean()}
|
||||
@callback fetch!(Cachex.cache(), any(), function() | nil) :: any()
|
||||
# @callback del(Cachex.cache(), any(), Keyword.t()) :: {Cachex.status(), boolean()}
|
||||
@callback del(Cachex.cache(), any()) :: {Cachex.status(), boolean()}
|
||||
@callback stream!(Cachex.cache(), any()) :: Enumerable.t()
|
||||
@callback expire_at(Cachex.cache(), binary(), number()) :: {Cachex.status(), boolean()}
|
||||
@callback exists?(Cachex.cache(), any()) :: {Cachex.status(), boolean()}
|
||||
@callback execute!(Cachex.cache(), function()) :: any()
|
||||
@callback get_and_update(Cachex.cache(), any(), function()) ::
|
||||
{:commit | :ignore, any()}
|
||||
end
|
||||
|
|
@ -7,6 +7,8 @@ defmodule Pleroma.Captcha do
|
|||
alias Plug.Crypto.KeyGenerator
|
||||
alias Plug.Crypto.MessageEncryptor
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
@doc """
|
||||
Ask the configured captcha service for a new captcha
|
||||
"""
|
||||
|
|
@ -86,7 +88,7 @@ defmodule Pleroma.Captcha do
|
|||
end
|
||||
|
||||
defp validate_usage(token) do
|
||||
if is_nil(Cachex.get!(:used_captcha_cache, token)) do
|
||||
if is_nil(@cachex.get!(:used_captcha_cache, token)) do
|
||||
:ok
|
||||
else
|
||||
{:error, :already_used}
|
||||
|
|
@ -95,7 +97,7 @@ defmodule Pleroma.Captcha do
|
|||
|
||||
defp mark_captcha_as_used(token) do
|
||||
ttl = seconds_valid() |> :timer.seconds()
|
||||
Cachex.put(:used_captcha_cache, token, true, ttl: ttl)
|
||||
@cachex.put(:used_captcha_cache, token, true, ttl: ttl)
|
||||
end
|
||||
|
||||
defp method, do: Pleroma.Config.get!([__MODULE__, :method])
|
||||
|
|
|
|||
|
|
@ -3,14 +3,18 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Config do
|
||||
@behaviour Pleroma.Config.Getting
|
||||
defmodule Error do
|
||||
defexception [:message]
|
||||
end
|
||||
|
||||
@impl true
|
||||
def get(key), do: get(key, nil)
|
||||
|
||||
@impl true
|
||||
def get([key], default), do: get(key, default)
|
||||
|
||||
@impl true
|
||||
def get([_ | _] = path, default) do
|
||||
case fetch(path) do
|
||||
{:ok, value} -> value
|
||||
|
|
@ -18,6 +22,7 @@ defmodule Pleroma.Config do
|
|||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def get(key, default) do
|
||||
Application.get_env(:pleroma, key, default)
|
||||
end
|
||||
|
|
|
|||
8
lib/pleroma/config/getting.ex
Normal file
8
lib/pleroma/config/getting.ex
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Config.Getting do
|
||||
@callback get(any()) :: any()
|
||||
@callback get(any(), any()) :: any()
|
||||
end
|
||||
|
|
@ -20,6 +20,8 @@ defmodule Pleroma.Emoji.Pack do
|
|||
name: String.t()
|
||||
}
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
alias Pleroma.Emoji
|
||||
alias Pleroma.Emoji.Pack
|
||||
alias Pleroma.Utils
|
||||
|
|
@ -415,7 +417,7 @@ defmodule Pleroma.Emoji.Pack do
|
|||
ttl_per_file = Pleroma.Config.get!([:emoji, :shared_pack_cache_seconds_per_file])
|
||||
overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files))
|
||||
|
||||
Cachex.put!(
|
||||
@cachex.put(
|
||||
:emoji_packs_cache,
|
||||
pack.name,
|
||||
# if pack.json MD5 changes, the cache is not valid anymore
|
||||
|
|
@ -618,7 +620,7 @@ defmodule Pleroma.Emoji.Pack do
|
|||
defp fetch_archive(pack) do
|
||||
hash = :crypto.hash(:md5, File.read!(pack.pack_file))
|
||||
|
||||
case Cachex.get!(:emoji_packs_cache, pack.name) do
|
||||
case @cachex.get!(:emoji_packs_cache, pack.name) do
|
||||
%{hash: ^hash, pack_data: archive} -> archive
|
||||
_ -> create_archive_and_cache(pack, hash)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ defmodule Pleroma.HTML do
|
|||
# Scrubbers are compiled on boot so they can be configured in OTP releases
|
||||
# @on_load :compile_scrubbers
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
def compile_scrubbers do
|
||||
dir = Path.join(:code.priv_dir(:pleroma), "scrubbers")
|
||||
|
||||
|
|
@ -56,7 +58,7 @@ defmodule Pleroma.HTML do
|
|||
) do
|
||||
key = "#{key}#{generate_scrubber_signature(scrubbers)}|#{activity.id}"
|
||||
|
||||
Cachex.fetch!(:scrubber_cache, key, fn _key ->
|
||||
@cachex.fetch!(:scrubber_cache, key, fn _key ->
|
||||
object = Pleroma.Object.normalize(activity)
|
||||
ensure_scrubbed_html(content, scrubbers, object.data["fake"] || false, callback)
|
||||
end)
|
||||
|
|
@ -105,7 +107,7 @@ defmodule Pleroma.HTML do
|
|||
unless object.data["fake"] do
|
||||
key = "URL|#{object.id}"
|
||||
|
||||
Cachex.fetch!(:scrubber_cache, key, fn _key ->
|
||||
@cachex.fetch!(:scrubber_cache, key, fn _key ->
|
||||
{:commit, {:ok, extract_first_external_url(content)}}
|
||||
end)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ defmodule Pleroma.Object do
|
|||
|
||||
@derive {Jason.Encoder, only: [:data]}
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
schema "objects" do
|
||||
field(:data, :map)
|
||||
|
||||
|
|
@ -189,9 +191,9 @@ defmodule Pleroma.Object do
|
|||
def get_cached_by_ap_id(ap_id) do
|
||||
key = "object:#{ap_id}"
|
||||
|
||||
with {:ok, nil} <- Cachex.get(:object_cache, key),
|
||||
with {:ok, nil} <- @cachex.get(:object_cache, key),
|
||||
object when not is_nil(object) <- get_by_ap_id(ap_id),
|
||||
{:ok, true} <- Cachex.put(:object_cache, key, object) do
|
||||
{:ok, true} <- @cachex.put(:object_cache, key, object) do
|
||||
object
|
||||
else
|
||||
{:ok, object} -> object
|
||||
|
|
@ -249,13 +251,13 @@ defmodule Pleroma.Object do
|
|||
end
|
||||
|
||||
def invalid_object_cache(%Object{data: %{"id" => id}}) do
|
||||
with {:ok, true} <- Cachex.del(:object_cache, "object:#{id}") do
|
||||
Cachex.del(:web_resp_cache, URI.parse(id).path)
|
||||
with {:ok, true} <- @cachex.del(:object_cache, "object:#{id}") do
|
||||
@cachex.del(:web_resp_cache, URI.parse(id).path)
|
||||
end
|
||||
end
|
||||
|
||||
def set_cache(%Object{data: %{"id" => ap_id}} = object) do
|
||||
Cachex.put(:object_cache, "object:#{ap_id}", object)
|
||||
@cachex.put(:object_cache, "object:#{ap_id}", object)
|
||||
{:ok, object}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ defmodule Pleroma.ReverseProxy do
|
|||
@failed_request_ttl :timer.seconds(60)
|
||||
@methods ~w(GET HEAD)
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
def max_read_duration_default, do: @max_read_duration
|
||||
def default_cache_control_header, do: @default_cache_control_header
|
||||
|
||||
|
|
@ -107,7 +109,7 @@ defmodule Pleroma.ReverseProxy do
|
|||
opts
|
||||
end
|
||||
|
||||
with {:ok, nil} <- Cachex.get(:failed_proxy_url_cache, url),
|
||||
with {:ok, nil} <- @cachex.get(:failed_proxy_url_cache, url),
|
||||
{:ok, code, headers, client} <- request(method, url, req_headers, client_opts),
|
||||
:ok <-
|
||||
header_length_constraint(
|
||||
|
|
@ -427,6 +429,6 @@ defmodule Pleroma.ReverseProxy do
|
|||
nil
|
||||
end
|
||||
|
||||
Cachex.put(:failed_proxy_url_cache, url, true, ttl: ttl)
|
||||
@cachex.put(:failed_proxy_url_cache, url, true, ttl: ttl)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ defmodule Pleroma.User do
|
|||
]
|
||||
]
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
schema "users" do
|
||||
field(:bio, :string, default: "")
|
||||
field(:raw_bio, :string)
|
||||
|
|
@ -246,13 +248,13 @@ defmodule Pleroma.User do
|
|||
end
|
||||
|
||||
def cached_blocked_users_ap_ids(user) do
|
||||
Cachex.fetch!(:user_cache, "blocked_users_ap_ids:#{user.ap_id}", fn _ ->
|
||||
@cachex.fetch!(:user_cache, "blocked_users_ap_ids:#{user.ap_id}", fn _ ->
|
||||
blocked_users_ap_ids(user)
|
||||
end)
|
||||
end
|
||||
|
||||
def cached_muted_users_ap_ids(user) do
|
||||
Cachex.fetch!(:user_cache, "muted_users_ap_ids:#{user.ap_id}", fn _ ->
|
||||
@cachex.fetch!(:user_cache, "muted_users_ap_ids:#{user.ap_id}", fn _ ->
|
||||
muted_users_ap_ids(user)
|
||||
end)
|
||||
end
|
||||
|
|
@ -1048,9 +1050,9 @@ defmodule Pleroma.User do
|
|||
def set_cache({:error, err}), do: {:error, err}
|
||||
|
||||
def set_cache(%User{} = user) do
|
||||
Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
|
||||
Cachex.put(:user_cache, "nickname:#{user.nickname}", user)
|
||||
Cachex.put(:user_cache, "friends_ap_ids:#{user.nickname}", get_user_friends_ap_ids(user))
|
||||
@cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
|
||||
@cachex.put(:user_cache, "nickname:#{user.nickname}", user)
|
||||
@cachex.put(:user_cache, "friends_ap_ids:#{user.nickname}", get_user_friends_ap_ids(user))
|
||||
{:ok, user}
|
||||
end
|
||||
|
||||
|
|
@ -1073,26 +1075,26 @@ defmodule Pleroma.User do
|
|||
|
||||
@spec get_cached_user_friends_ap_ids(User.t()) :: [String.t()]
|
||||
def get_cached_user_friends_ap_ids(user) do
|
||||
Cachex.fetch!(:user_cache, "friends_ap_ids:#{user.ap_id}", fn _ ->
|
||||
@cachex.fetch!(:user_cache, "friends_ap_ids:#{user.ap_id}", fn _ ->
|
||||
get_user_friends_ap_ids(user)
|
||||
end)
|
||||
end
|
||||
|
||||
def invalidate_cache(user) do
|
||||
Cachex.del(:user_cache, "ap_id:#{user.ap_id}")
|
||||
Cachex.del(:user_cache, "nickname:#{user.nickname}")
|
||||
Cachex.del(:user_cache, "friends_ap_ids:#{user.ap_id}")
|
||||
Cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||
Cachex.del(:user_cache, "muted_users_ap_ids:#{user.ap_id}")
|
||||
@cachex.del(:user_cache, "ap_id:#{user.ap_id}")
|
||||
@cachex.del(:user_cache, "nickname:#{user.nickname}")
|
||||
@cachex.del(:user_cache, "friends_ap_ids:#{user.ap_id}")
|
||||
@cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||
@cachex.del(:user_cache, "muted_users_ap_ids:#{user.ap_id}")
|
||||
end
|
||||
|
||||
@spec get_cached_by_ap_id(String.t()) :: User.t() | nil
|
||||
def get_cached_by_ap_id(ap_id) do
|
||||
key = "ap_id:#{ap_id}"
|
||||
|
||||
with {:ok, nil} <- Cachex.get(:user_cache, key),
|
||||
with {:ok, nil} <- @cachex.get(:user_cache, key),
|
||||
user when not is_nil(user) <- get_by_ap_id(ap_id),
|
||||
{:ok, true} <- Cachex.put(:user_cache, key, user) do
|
||||
{:ok, true} <- @cachex.put(:user_cache, key, user) do
|
||||
user
|
||||
else
|
||||
{:ok, user} -> user
|
||||
|
|
@ -1104,11 +1106,11 @@ defmodule Pleroma.User do
|
|||
key = "id:#{id}"
|
||||
|
||||
ap_id =
|
||||
Cachex.fetch!(:user_cache, key, fn _ ->
|
||||
@cachex.fetch!(:user_cache, key, fn _ ->
|
||||
user = get_by_id(id)
|
||||
|
||||
if user do
|
||||
Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
|
||||
@cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
|
||||
{:commit, user.ap_id}
|
||||
else
|
||||
{:ignore, ""}
|
||||
|
|
@ -1121,7 +1123,7 @@ defmodule Pleroma.User do
|
|||
def get_cached_by_nickname(nickname) do
|
||||
key = "nickname:#{nickname}"
|
||||
|
||||
Cachex.fetch!(:user_cache, key, fn ->
|
||||
@cachex.fetch!(:user_cache, key, fn _ ->
|
||||
case get_or_fetch_by_nickname(nickname) do
|
||||
{:ok, user} -> {:commit, user}
|
||||
{:error, _error} -> {:ignore, nil}
|
||||
|
|
@ -1390,7 +1392,7 @@ defmodule Pleroma.User do
|
|||
)
|
||||
end
|
||||
|
||||
Cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
|
||||
@cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
|
||||
|
||||
{:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
|
||||
end
|
||||
|
|
@ -1400,7 +1402,7 @@ defmodule Pleroma.User do
|
|||
with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee),
|
||||
{:ok, user_notification_mute} <-
|
||||
UserRelationship.delete_notification_mute(muter, mutee) do
|
||||
Cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
|
||||
@cachex.del(:user_cache, "muted_users_ap_ids:#{muter.ap_id}")
|
||||
{:ok, [user_mute, user_notification_mute]}
|
||||
end
|
||||
end
|
||||
|
|
@ -2408,7 +2410,7 @@ defmodule Pleroma.User do
|
|||
{:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()}
|
||||
defp add_to_block(%User{} = user, %User{} = blocked) do
|
||||
with {:ok, relationship} <- UserRelationship.create_block(user, blocked) do
|
||||
Cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||
@cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||
{:ok, relationship}
|
||||
end
|
||||
end
|
||||
|
|
@ -2417,7 +2419,7 @@ defmodule Pleroma.User do
|
|||
{:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()}
|
||||
defp remove_from_block(%User{} = user, %User{} = blocked) do
|
||||
with {:ok, relationship} <- UserRelationship.delete_block(user, blocked) do
|
||||
Cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||
@cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}")
|
||||
{:ok, relationship}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
require Logger
|
||||
require Pleroma.Constants
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.ActivityPub.Persisting
|
||||
|
||||
defp get_recipients(%{"type" => "Create"} = data) do
|
||||
to = Map.get(data, "to", [])
|
||||
cc = Map.get(data, "cc", [])
|
||||
|
|
@ -85,13 +87,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
defp increase_replies_count_if_reply(_create_data), do: :noop
|
||||
|
||||
@object_types ~w[ChatMessage Question Answer Audio Video Event Article]
|
||||
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
|
||||
@impl true
|
||||
def persist(%{"type" => type} = object, meta) when type in @object_types do
|
||||
with {:ok, object} <- Object.create(object) do
|
||||
{:ok, object, meta}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def persist(object, meta) do
|
||||
with local <- Keyword.fetch!(meta, :local),
|
||||
{recipients, _, _} <- get_recipients(object),
|
||||
|
|
|
|||
7
lib/pleroma/web/activity_pub/activity_pub/persisting.ex
Normal file
7
lib/pleroma/web/activity_pub/activity_pub/persisting.ex
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# 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.ActivityPub.Persisting do
|
||||
@callback persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
|
||||
end
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
defmodule Pleroma.Web.ActivityPub.MRF do
|
||||
require Logger
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.MRF.PipelineFiltering
|
||||
|
||||
@mrf_config_descriptions [
|
||||
%{
|
||||
group: :pleroma,
|
||||
|
|
@ -70,6 +72,7 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
|
||||
def filter(%{} = object), do: get_policies() |> filter(object)
|
||||
|
||||
@impl true
|
||||
def pipeline_filter(%{} = message, meta) do
|
||||
object = meta[:object_data]
|
||||
ap_id = message["object"]
|
||||
|
|
|
|||
7
lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex
Normal file
7
lib/pleroma/web/activity_pub/mrf/pipeline_filtering.ex
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# 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.MRF.PipelineFiltering do
|
||||
@callback pipeline_filter(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
||||
end
|
||||
|
|
@ -9,6 +9,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
|||
the system.
|
||||
"""
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.ObjectValidator.Validating
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
||||
alias Pleroma.Object
|
||||
|
|
@ -32,7 +34,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
|||
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
|
||||
alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator
|
||||
|
||||
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
||||
@impl true
|
||||
def validate(object, meta)
|
||||
|
||||
def validate(%{"type" => type} = object, meta)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
# 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.ObjectValidator.Validating do
|
||||
@callback validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
||||
end
|
||||
|
|
@ -14,12 +14,19 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
|
|||
alias Pleroma.Web.ActivityPub.Visibility
|
||||
alias Pleroma.Web.Federator
|
||||
|
||||
@side_effects Config.get([:pipeline, :side_effects], SideEffects)
|
||||
@federator Config.get([:pipeline, :federator], Federator)
|
||||
@object_validator Config.get([:pipeline, :object_validator], ObjectValidator)
|
||||
@mrf Config.get([:pipeline, :mrf], MRF)
|
||||
@activity_pub Config.get([:pipeline, :activity_pub], ActivityPub)
|
||||
@config Config.get([:pipeline, :config], Config)
|
||||
|
||||
@spec common_pipeline(map(), keyword()) ::
|
||||
{:ok, Activity.t() | Object.t(), keyword()} | {:error, any()}
|
||||
def common_pipeline(object, meta) do
|
||||
case Repo.transaction(fn -> do_common_pipeline(object, meta) end) do
|
||||
{:ok, {:ok, activity, meta}} ->
|
||||
SideEffects.handle_after_transaction(meta)
|
||||
@side_effects.handle_after_transaction(meta)
|
||||
{:ok, activity, meta}
|
||||
|
||||
{:ok, value} ->
|
||||
|
|
@ -35,13 +42,13 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
|
|||
|
||||
def do_common_pipeline(object, meta) do
|
||||
with {_, {:ok, validated_object, meta}} <-
|
||||
{:validate_object, ObjectValidator.validate(object, meta)},
|
||||
{:validate_object, @object_validator.validate(object, meta)},
|
||||
{_, {:ok, mrfd_object, meta}} <-
|
||||
{:mrf_object, MRF.pipeline_filter(validated_object, meta)},
|
||||
{:mrf_object, @mrf.pipeline_filter(validated_object, meta)},
|
||||
{_, {:ok, activity, meta}} <-
|
||||
{:persist_object, ActivityPub.persist(mrfd_object, meta)},
|
||||
{:persist_object, @activity_pub.persist(mrfd_object, meta)},
|
||||
{_, {:ok, activity, meta}} <-
|
||||
{:execute_side_effects, SideEffects.handle(activity, meta)},
|
||||
{:execute_side_effects, @side_effects.handle(activity, meta)},
|
||||
{_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do
|
||||
{:ok, activity, meta}
|
||||
else
|
||||
|
|
@ -54,7 +61,7 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
|
|||
|
||||
defp maybe_federate(%Activity{} = activity, meta) do
|
||||
with {:ok, local} <- Keyword.fetch(meta, :local) do
|
||||
do_not_federate = meta[:do_not_federate] || !Config.get([:instance, :federating])
|
||||
do_not_federate = meta[:do_not_federate] || !@config.get([:instance, :federating])
|
||||
|
||||
if !do_not_federate and local and not Visibility.is_local_public?(activity) do
|
||||
activity =
|
||||
|
|
@ -64,7 +71,7 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
|
|||
activity
|
||||
end
|
||||
|
||||
Federator.publish(activity)
|
||||
@federator.publish(activity)
|
||||
{:ok, :federated}
|
||||
else
|
||||
{:ok, :not_federated}
|
||||
|
|
|
|||
|
|
@ -27,11 +27,17 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
|
||||
require Logger
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
@behaviour Pleroma.Web.ActivityPub.SideEffects.Handling
|
||||
|
||||
@impl true
|
||||
def handle(object, meta \\ [])
|
||||
|
||||
# Task this handles
|
||||
# - Follows
|
||||
# - Sends a notification
|
||||
@impl true
|
||||
def handle(
|
||||
%{
|
||||
data: %{
|
||||
|
|
@ -59,6 +65,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
# - Rejects all existing follow activities for this person
|
||||
# - Updates the follow state
|
||||
# - Dismisses notification
|
||||
@impl true
|
||||
def handle(
|
||||
%{
|
||||
data: %{
|
||||
|
|
@ -85,6 +92,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
# - Follows if possible
|
||||
# - Sends a notification
|
||||
# - Generates accept or reject if appropriate
|
||||
@impl true
|
||||
def handle(
|
||||
%{
|
||||
data: %{
|
||||
|
|
@ -126,6 +134,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
|
||||
# Tasks this handles:
|
||||
# - Unfollow and block
|
||||
@impl true
|
||||
def handle(
|
||||
%{data: %{"type" => "Block", "object" => blocked_user, "actor" => blocking_user}} =
|
||||
object,
|
||||
|
|
@ -144,6 +153,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
#
|
||||
# For a local user, we also get a changeset with the full information, so we
|
||||
# can update non-federating, non-activitypub settings as well.
|
||||
@impl true
|
||||
def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do
|
||||
if changeset = Keyword.get(meta, :user_update_changeset) do
|
||||
changeset
|
||||
|
|
@ -162,6 +172,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
# Tasks this handles:
|
||||
# - Add like to object
|
||||
# - Set up notification
|
||||
@impl true
|
||||
def handle(%{data: %{"type" => "Like"}} = object, meta) do
|
||||
liked_object = Object.get_by_ap_id(object.data["object"])
|
||||
Utils.add_like_to_object(object, liked_object)
|
||||
|
|
@ -179,6 +190,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
# - Increase replies count
|
||||
# - Set up ActivityExpiration
|
||||
# - Set up notifications
|
||||
@impl true
|
||||
def handle(%{data: %{"type" => "Create"}} = activity, meta) do
|
||||
with {:ok, object, meta} <- handle_object_creation(meta[:object_data], meta),
|
||||
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
|
||||
|
|
@ -207,6 +219,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
# - Add announce to object
|
||||
# - Set up notification
|
||||
# - Stream out the announce
|
||||
@impl true
|
||||
def handle(%{data: %{"type" => "Announce"}} = object, meta) do
|
||||
announced_object = Object.get_by_ap_id(object.data["object"])
|
||||
user = User.get_cached_by_ap_id(object.data["actor"])
|
||||
|
|
@ -224,6 +237,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
{:ok, object, meta}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, meta) do
|
||||
with undone_object <- Activity.get_by_ap_id(undone_object),
|
||||
:ok <- handle_undoing(undone_object) do
|
||||
|
|
@ -234,6 +248,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
# Tasks this handles:
|
||||
# - Add reaction to object
|
||||
# - Set up notification
|
||||
@impl true
|
||||
def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do
|
||||
reacted_object = Object.get_by_ap_id(object.data["object"])
|
||||
Utils.add_emoji_reaction_to_object(object, reacted_object)
|
||||
|
|
@ -250,6 +265,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
# - Reduce the user note count
|
||||
# - Reduce the reply count
|
||||
# - Stream out the activity
|
||||
@impl true
|
||||
def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
|
||||
deleted_object =
|
||||
Object.normalize(deleted_object, false) ||
|
||||
|
|
@ -295,6 +311,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
end
|
||||
|
||||
# Nothing to do
|
||||
@impl true
|
||||
def handle(object, meta) do
|
||||
{:ok, object, meta}
|
||||
end
|
||||
|
|
@ -312,7 +329,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
{:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
|
||||
{:ok, cm_ref} = MessageReference.create(chat, object, user.ap_id != actor.ap_id)
|
||||
|
||||
Cachex.put(
|
||||
@cachex.put(
|
||||
:chat_message_id_idempotency_key_cache,
|
||||
cm_ref.id,
|
||||
meta[:idempotency_key]
|
||||
|
|
@ -439,6 +456,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
|
|||
|> Keyword.put(:notifications, notifications ++ existing)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_after_transaction(meta) do
|
||||
meta
|
||||
|> send_notifications()
|
||||
|
|
|
|||
8
lib/pleroma/web/activity_pub/side_effects/handling.ex
Normal file
8
lib/pleroma/web/activity_pub/side_effects/handling.ex
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# 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.SideEffects.Handling do
|
||||
@callback handle(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
|
||||
@callback handle_after_transaction(map()) :: map()
|
||||
end
|
||||
|
|
@ -9,6 +9,8 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
|
|||
alias Pleroma.Web.MediaProxy
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
|
||||
plug(
|
||||
|
|
@ -38,7 +40,7 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
|
|||
|
||||
defp fetch_entries(params) do
|
||||
MediaProxy.cache_table()
|
||||
|> Cachex.stream!(Cachex.Query.create(true, :key))
|
||||
|> @cachex.stream!(Cachex.Query.create(true, :key))
|
||||
|> filter_entries(params[:query])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ defmodule Pleroma.Web.Federator do
|
|||
|
||||
require Logger
|
||||
|
||||
@behaviour Pleroma.Web.Federator.Publishing
|
||||
|
||||
@doc """
|
||||
Returns `true` if the distance to target object does not exceed max configured value.
|
||||
Serves to prevent fetching of very long threads, especially useful on smaller instances.
|
||||
|
|
@ -39,10 +41,12 @@ defmodule Pleroma.Web.Federator do
|
|||
ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params})
|
||||
end
|
||||
|
||||
@impl true
|
||||
def publish(%{id: "pleroma:fakeid"} = activity) do
|
||||
perform(:publish, activity)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def publish(activity) do
|
||||
PublisherWorker.enqueue("publish", %{"activity_id" => activity.id})
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
Postgrex.Types.define(
|
||||
Pleroma.PostgresTypes,
|
||||
[] ++ Ecto.Adapters.Postgres.extensions(),
|
||||
json: Jason
|
||||
)
|
||||
defmodule Pleroma.Web.Federator.Publishing do
|
||||
@callback publish(map()) :: any()
|
||||
end
|
||||
|
|
@ -26,6 +26,8 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
|
|||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PollOperation
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
@doc "GET /api/v1/polls/:id"
|
||||
def show(%{assigns: %{user: user}} = conn, %{id: id}) do
|
||||
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
|
||||
|
|
@ -55,7 +57,7 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
|
|||
defp get_cached_vote_or_vote(user, object, choices) do
|
||||
idempotency_key = "polls:#{user.id}:#{object.data["id"]}"
|
||||
|
||||
Cachex.fetch!(:idempotency_cache, idempotency_key, fn ->
|
||||
@cachex.fetch!(:idempotency_cache, idempotency_key, fn _ ->
|
||||
case CommonAPI.vote(user, object, choices) do
|
||||
{:error, _message} = res -> {:ignore, res}
|
||||
res -> {:commit, res}
|
||||
|
|
|
|||
|
|
@ -12,29 +12,31 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
@base64_opts [padding: false]
|
||||
@cache_table :banned_urls_cache
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
def cache_table, do: @cache_table
|
||||
|
||||
@spec in_banned_urls(String.t()) :: boolean()
|
||||
def in_banned_urls(url), do: elem(Cachex.exists?(@cache_table, url(url)), 1)
|
||||
def in_banned_urls(url), do: elem(@cachex.exists?(@cache_table, url(url)), 1)
|
||||
|
||||
def remove_from_banned_urls(urls) when is_list(urls) do
|
||||
Cachex.execute!(@cache_table, fn cache ->
|
||||
Enum.each(Invalidation.prepare_urls(urls), &Cachex.del(cache, &1))
|
||||
@cachex.execute!(@cache_table, fn cache ->
|
||||
Enum.each(Invalidation.prepare_urls(urls), &@cachex.del(cache, &1))
|
||||
end)
|
||||
end
|
||||
|
||||
def remove_from_banned_urls(url) when is_binary(url) do
|
||||
Cachex.del(@cache_table, url(url))
|
||||
@cachex.del(@cache_table, url(url))
|
||||
end
|
||||
|
||||
def put_in_banned_urls(urls) when is_list(urls) do
|
||||
Cachex.execute!(@cache_table, fn cache ->
|
||||
Enum.each(Invalidation.prepare_urls(urls), &Cachex.put(cache, &1, true))
|
||||
@cachex.execute!(@cache_table, fn cache ->
|
||||
Enum.each(Invalidation.prepare_urls(urls), &@cachex.put(cache, &1, true))
|
||||
end)
|
||||
end
|
||||
|
||||
def put_in_banned_urls(url) when is_binary(url) do
|
||||
Cachex.put(@cache_table, url(url), true)
|
||||
@cachex.put(@cache_table, url(url), true)
|
||||
end
|
||||
|
||||
def url(url) when is_nil(url) or url == "", do: nil
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
|
|||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
def render(
|
||||
"show.json",
|
||||
%{
|
||||
|
|
@ -51,7 +53,7 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
|
|||
end
|
||||
|
||||
defp put_idempotency_key(data) do
|
||||
with {:ok, idempotency_key} <- Cachex.get(:chat_message_id_idempotency_key_cache, data.id) do
|
||||
with {:ok, idempotency_key} <- @cachex.get(:chat_message_id_idempotency_key_cache, data.id) do
|
||||
data
|
||||
|> Maps.put_if_present(:idempotency_key, idempotency_key)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ defmodule Pleroma.Web.Plugs.Cache do
|
|||
|
||||
@defaults %{ttl: nil, query_params: true}
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
@impl true
|
||||
def init([]), do: @defaults
|
||||
|
||||
|
|
@ -53,7 +55,7 @@ defmodule Pleroma.Web.Plugs.Cache do
|
|||
def call(%{method: "GET"} = conn, opts) do
|
||||
key = cache_key(conn, opts)
|
||||
|
||||
case Cachex.get(:web_resp_cache, key) do
|
||||
case @cachex.get(:web_resp_cache, key) do
|
||||
{:ok, nil} ->
|
||||
cache_resp(conn, opts)
|
||||
|
||||
|
|
@ -97,11 +99,11 @@ defmodule Pleroma.Web.Plugs.Cache do
|
|||
|
||||
conn =
|
||||
unless opts[:tracking_fun] do
|
||||
Cachex.put(:web_resp_cache, key, {content_type, body}, ttl: ttl)
|
||||
@cachex.put(:web_resp_cache, key, {content_type, body}, ttl: ttl)
|
||||
conn
|
||||
else
|
||||
tracking_fun_data = Map.get(conn.assigns, :tracking_fun_data, nil)
|
||||
Cachex.put(:web_resp_cache, key, {content_type, body, tracking_fun_data}, ttl: ttl)
|
||||
@cachex.put(:web_resp_cache, key, {content_type, body, tracking_fun_data}, ttl: ttl)
|
||||
|
||||
opts.tracking_fun.(conn, tracking_fun_data)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ defmodule Pleroma.Web.Plugs.IdempotencyPlug do
|
|||
|
||||
@behaviour Plug
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
@impl true
|
||||
def init(opts), do: opts
|
||||
|
||||
|
|
@ -25,7 +27,7 @@ defmodule Pleroma.Web.Plugs.IdempotencyPlug do
|
|||
def call(conn, _), do: conn
|
||||
|
||||
def process_request(conn, key) do
|
||||
case Cachex.get(:idempotency_cache, key) do
|
||||
case @cachex.get(:idempotency_cache, key) do
|
||||
{:ok, nil} ->
|
||||
cache_resposnse(conn, key)
|
||||
|
||||
|
|
@ -43,7 +45,7 @@ defmodule Pleroma.Web.Plugs.IdempotencyPlug do
|
|||
content_type = get_content_type(conn)
|
||||
|
||||
record = {request_id, content_type, conn.status, conn.resp_body}
|
||||
{:ok, _} = Cachex.put(:idempotency_cache, key, record)
|
||||
{:ok, _} = @cachex.put(:idempotency_cache, key, record)
|
||||
|
||||
conn
|
||||
|> put_resp_header("idempotency-key", key)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ defmodule Pleroma.Web.Plugs.RateLimiter do
|
|||
|
||||
require Logger
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
@doc false
|
||||
def init(plug_opts) do
|
||||
plug_opts
|
||||
|
|
@ -124,7 +126,7 @@ defmodule Pleroma.Web.Plugs.RateLimiter do
|
|||
key_name = make_key_name(action_settings)
|
||||
limit = get_limits(action_settings)
|
||||
|
||||
case Cachex.get(bucket_name, key_name) do
|
||||
case @cachex.get(bucket_name, key_name) do
|
||||
{:error, :no_cache} ->
|
||||
@inspect_bucket_not_found
|
||||
|
||||
|
|
@ -157,7 +159,7 @@ defmodule Pleroma.Web.Plugs.RateLimiter do
|
|||
key_name = make_key_name(action_settings)
|
||||
limit = get_limits(action_settings)
|
||||
|
||||
case Cachex.get_and_update(bucket_name, key_name, &increment_value(&1, limit)) do
|
||||
case @cachex.get_and_update(bucket_name, key_name, &increment_value(&1, limit)) do
|
||||
{:commit, value} ->
|
||||
{:ok, value}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ defmodule Pleroma.Web.RelMe do
|
|||
if Pleroma.Config.get(:env) == :test do
|
||||
def parse(url) when is_binary(url), do: parse_url(url)
|
||||
else
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
def parse(url) when is_binary(url) do
|
||||
Cachex.fetch!(:rel_me_cache, url, fn _ ->
|
||||
@cachex.fetch!(:rel_me_cache, url, fn _ ->
|
||||
{:commit, parse_url(url)}
|
||||
end)
|
||||
rescue
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
defmodule Pleroma.Web.RichMedia.Parser do
|
||||
require Logger
|
||||
|
||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||
|
||||
defp parsers do
|
||||
Pleroma.Config.get([:rich_media, :parsers])
|
||||
end
|
||||
|
|
@ -24,7 +26,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
|
|||
end
|
||||
|
||||
defp get_cached_or_parse(url) do
|
||||
case Cachex.fetch(:rich_media_cache, url, fn ->
|
||||
case @cachex.fetch(:rich_media_cache, url, fn ->
|
||||
case parse_url(url) do
|
||||
{:ok, _} = res ->
|
||||
{:commit, res}
|
||||
|
|
@ -64,7 +66,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
|
|||
|
||||
defp set_error_ttl(url, _reason) do
|
||||
ttl = Pleroma.Config.get([:rich_media, :failure_backoff], 60_000)
|
||||
Cachex.expire(:rich_media_cache, url, ttl)
|
||||
@cachex.expire(:rich_media_cache, url, ttl)
|
||||
:ok
|
||||
end
|
||||
|
||||
|
|
@ -106,7 +108,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
|
|||
{:ok, ttl} when is_number(ttl) ->
|
||||
ttl = ttl * 1000
|
||||
|
||||
case Cachex.expire_at(:rich_media_cache, url, ttl) do
|
||||
case @cachex.expire_at(:rich_media_cache, url, ttl) do
|
||||
{:ok, true} -> {:ok, ttl}
|
||||
{:ok, false} -> {:error, :no_key}
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue