Merge branch 'cachex-test' into 'develop'

Test framework overhaul (speed, reliability)

See merge request pleroma/pleroma!3209
This commit is contained in:
lain 2020-12-26 10:26:35 +00:00
commit e4f1d8f48c
203 changed files with 659 additions and 430 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
/db /db
/deps /deps
/*.ez /*.ez
/test/instance
/test/uploads /test/uploads
/.elixir_ls /.elixir_ls
/test/fixtures/DSCN0010_tmp.jpg /test/fixtures/DSCN0010_tmp.jpg

View File

@ -47,7 +47,6 @@
config :pleroma, ecto_repos: [Pleroma.Repo] config :pleroma, ecto_repos: [Pleroma.Repo]
config :pleroma, Pleroma.Repo, config :pleroma, Pleroma.Repo,
types: Pleroma.PostgresTypes,
telemetry_event: [Pleroma.Repo.Instrumenter], telemetry_event: [Pleroma.Repo.Instrumenter],
migration_lock: nil migration_lock: nil

View File

@ -47,7 +47,10 @@
password: "postgres", password: "postgres",
database: "pleroma_test", database: "pleroma_test",
hostname: System.get_env("DB_HOST") || "localhost", hostname: System.get_env("DB_HOST") || "localhost",
pool: Ecto.Adapters.SQL.Sandbox pool: Ecto.Adapters.SQL.Sandbox,
pool_size: 50
config :pleroma, :dangerzone, override_repo_pool_size: true
# Reduce hash rounds for testing # Reduce hash rounds for testing
config :pbkdf2_elixir, rounds: 1 config :pbkdf2_elixir, rounds: 1
@ -121,6 +124,16 @@
config :pleroma, :mrf, policies: [] config :pleroma, :mrf, policies: []
config :pleroma, :pipeline,
object_validator: Pleroma.Web.ActivityPub.ObjectValidatorMock,
mrf: Pleroma.Web.ActivityPub.MRFMock,
activity_pub: Pleroma.Web.ActivityPub.ActivityPubMock,
side_effects: Pleroma.Web.ActivityPub.SideEffectsMock,
federator: Pleroma.Web.FederatorMock,
config: Pleroma.ConfigMock
config :pleroma, :cachex, provider: Pleroma.CachexMock
if File.exists?("./config/test.secret.exs") do if File.exists?("./config/test.secret.exs") do
import_config "test.secret.exs" import_config "test.secret.exs"
else else

View File

@ -24,6 +24,8 @@ defmodule Pleroma.Activity do
@primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true} @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
schema "activities" do schema "activities" do
field(:data, :map) field(:data, :map)
field(:local, :boolean, default: true) field(:local, :boolean, default: true)
@ -298,7 +300,7 @@ def delete_all_by_object_ap_id(_), do: nil
defp purge_web_resp_cache(%Activity{} = activity) do defp purge_web_resp_cache(%Activity{} = activity) do
%{path: path} = URI.parse(activity.data["id"]) %{path: path} = URI.parse(activity.data["id"])
Cachex.del(:web_resp_cache, path) @cachex.del(:web_resp_cache, path)
activity activity
end end

19
lib/pleroma/caching.ex Normal file
View 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

View File

@ -7,6 +7,8 @@ defmodule Pleroma.Captcha do
alias Plug.Crypto.KeyGenerator alias Plug.Crypto.KeyGenerator
alias Plug.Crypto.MessageEncryptor alias Plug.Crypto.MessageEncryptor
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@doc """ @doc """
Ask the configured captcha service for a new captcha Ask the configured captcha service for a new captcha
""" """
@ -86,7 +88,7 @@ defp validate_expiration(created_at) do
end end
defp validate_usage(token) do 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 :ok
else else
{:error, :already_used} {:error, :already_used}
@ -95,7 +97,7 @@ defp validate_usage(token) do
defp mark_captcha_as_used(token) do defp mark_captcha_as_used(token) do
ttl = seconds_valid() |> :timer.seconds() ttl = seconds_valid() |> :timer.seconds()
Cachex.put(:used_captcha_cache, token, true, ttl: ttl) @cachex.put(:used_captcha_cache, token, true, ttl: ttl)
end end
defp method, do: Pleroma.Config.get!([__MODULE__, :method]) defp method, do: Pleroma.Config.get!([__MODULE__, :method])

View File

@ -3,14 +3,18 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Config do defmodule Pleroma.Config do
@behaviour Pleroma.Config.Getting
defmodule Error do defmodule Error do
defexception [:message] defexception [:message]
end end
@impl true
def get(key), do: get(key, nil) def get(key), do: get(key, nil)
@impl true
def get([key], default), do: get(key, default) def get([key], default), do: get(key, default)
@impl true
def get([_ | _] = path, default) do def get([_ | _] = path, default) do
case fetch(path) do case fetch(path) do
{:ok, value} -> value {:ok, value} -> value
@ -18,6 +22,7 @@ def get([_ | _] = path, default) do
end end
end end
@impl true
def get(key, default) do def get(key, default) do
Application.get_env(:pleroma, key, default) Application.get_env(:pleroma, key, default)
end end

View 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

View File

@ -20,6 +20,8 @@ defmodule Pleroma.Emoji.Pack do
name: String.t() name: String.t()
} }
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
alias Pleroma.Emoji alias Pleroma.Emoji
alias Pleroma.Emoji.Pack alias Pleroma.Emoji.Pack
alias Pleroma.Utils alias Pleroma.Utils
@ -415,7 +417,7 @@ defp create_archive_and_cache(pack, hash) do
ttl_per_file = Pleroma.Config.get!([:emoji, :shared_pack_cache_seconds_per_file]) ttl_per_file = Pleroma.Config.get!([:emoji, :shared_pack_cache_seconds_per_file])
overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files)) overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files))
Cachex.put!( @cachex.put(
:emoji_packs_cache, :emoji_packs_cache,
pack.name, pack.name,
# if pack.json MD5 changes, the cache is not valid anymore # if pack.json MD5 changes, the cache is not valid anymore
@ -618,7 +620,7 @@ defp download_archive(url, sha) do
defp fetch_archive(pack) do defp fetch_archive(pack) do
hash = :crypto.hash(:md5, File.read!(pack.pack_file)) 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 %{hash: ^hash, pack_data: archive} -> archive
_ -> create_archive_and_cache(pack, hash) _ -> create_archive_and_cache(pack, hash)
end end

View File

@ -6,6 +6,8 @@ defmodule Pleroma.HTML do
# Scrubbers are compiled on boot so they can be configured in OTP releases # Scrubbers are compiled on boot so they can be configured in OTP releases
# @on_load :compile_scrubbers # @on_load :compile_scrubbers
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
def compile_scrubbers do def compile_scrubbers do
dir = Path.join(:code.priv_dir(:pleroma), "scrubbers") dir = Path.join(:code.priv_dir(:pleroma), "scrubbers")
@ -56,7 +58,7 @@ def get_cached_scrubbed_html_for_activity(
) do ) do
key = "#{key}#{generate_scrubber_signature(scrubbers)}|#{activity.id}" 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) object = Pleroma.Object.normalize(activity)
ensure_scrubbed_html(content, scrubbers, object.data["fake"] || false, callback) ensure_scrubbed_html(content, scrubbers, object.data["fake"] || false, callback)
end) end)
@ -105,7 +107,7 @@ def extract_first_external_url_from_object(%{data: %{"content" => content}} = ob
unless object.data["fake"] do unless object.data["fake"] do
key = "URL|#{object.id}" 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)}} {:commit, {:ok, extract_first_external_url(content)}}
end) end)
else else

View File

@ -23,6 +23,8 @@ defmodule Pleroma.Object do
@derive {Jason.Encoder, only: [:data]} @derive {Jason.Encoder, only: [:data]}
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
schema "objects" do schema "objects" do
field(:data, :map) field(:data, :map)
@ -156,9 +158,9 @@ def authorize_access(%Object{}, %User{}), do: :ok
def get_cached_by_ap_id(ap_id) do def get_cached_by_ap_id(ap_id) do
key = "object:#{ap_id}" 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), 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 object
else else
{:ok, object} -> object {:ok, object} -> object
@ -216,13 +218,13 @@ def prune(%Object{data: %{"id" => _id}} = object) do
end end
def invalid_object_cache(%Object{data: %{"id" => id}}) do def invalid_object_cache(%Object{data: %{"id" => id}}) do
with {:ok, true} <- Cachex.del(:object_cache, "object:#{id}") do with {:ok, true} <- @cachex.del(:object_cache, "object:#{id}") do
Cachex.del(:web_resp_cache, URI.parse(id).path) @cachex.del(:web_resp_cache, URI.parse(id).path)
end end
end end
def set_cache(%Object{data: %{"id" => ap_id}} = object) do 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} {:ok, object}
end end

View File

@ -17,6 +17,8 @@ defmodule Pleroma.ReverseProxy do
@failed_request_ttl :timer.seconds(60) @failed_request_ttl :timer.seconds(60)
@methods ~w(GET HEAD) @methods ~w(GET HEAD)
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
def max_read_duration_default, do: @max_read_duration def max_read_duration_default, do: @max_read_duration
def default_cache_control_header, do: @default_cache_control_header def default_cache_control_header, do: @default_cache_control_header
@ -107,7 +109,7 @@ def call(conn = %{method: method}, url, opts) when method in @methods do
opts opts
end 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, code, headers, client} <- request(method, url, req_headers, client_opts),
:ok <- :ok <-
header_length_constraint( header_length_constraint(
@ -427,6 +429,6 @@ defp track_failed_url(url, error, opts) do
nil nil
end end
Cachex.put(:failed_proxy_url_cache, url, true, ttl: ttl) @cachex.put(:failed_proxy_url_cache, url, true, ttl: ttl)
end end
end end

View File

@ -81,6 +81,8 @@ defmodule Pleroma.User do
] ]
] ]
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
schema "users" do schema "users" do
field(:bio, :string, default: "") field(:bio, :string, default: "")
field(:raw_bio, :string) field(:raw_bio, :string)
@ -246,13 +248,13 @@ def unquote(:"#{outgoing_relation_target}_ap_ids")(user, restrict_deactivated? \
end end
def cached_blocked_users_ap_ids(user) do 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) blocked_users_ap_ids(user)
end) end)
end end
def cached_muted_users_ap_ids(user) do 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) muted_users_ap_ids(user)
end) end)
end end
@ -1048,9 +1050,9 @@ def set_cache({:ok, user}), do: set_cache(user)
def set_cache({:error, err}), do: {:error, err} def set_cache({:error, err}), do: {:error, err}
def set_cache(%User{} = user) do def set_cache(%User{} = user) do
Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user) @cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
Cachex.put(:user_cache, "nickname:#{user.nickname}", 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, "friends_ap_ids:#{user.nickname}", get_user_friends_ap_ids(user))
{:ok, user} {:ok, user}
end end
@ -1073,26 +1075,26 @@ def get_user_friends_ap_ids(user) do
@spec get_cached_user_friends_ap_ids(User.t()) :: [String.t()] @spec get_cached_user_friends_ap_ids(User.t()) :: [String.t()]
def get_cached_user_friends_ap_ids(user) do 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) get_user_friends_ap_ids(user)
end) end)
end end
def invalidate_cache(user) do def invalidate_cache(user) do
Cachex.del(:user_cache, "ap_id:#{user.ap_id}") @cachex.del(:user_cache, "ap_id:#{user.ap_id}")
Cachex.del(:user_cache, "nickname:#{user.nickname}") @cachex.del(:user_cache, "nickname:#{user.nickname}")
Cachex.del(:user_cache, "friends_ap_ids:#{user.ap_id}") @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, "blocked_users_ap_ids:#{user.ap_id}")
Cachex.del(:user_cache, "muted_users_ap_ids:#{user.ap_id}") @cachex.del(:user_cache, "muted_users_ap_ids:#{user.ap_id}")
end end
@spec get_cached_by_ap_id(String.t()) :: User.t() | nil @spec get_cached_by_ap_id(String.t()) :: User.t() | nil
def get_cached_by_ap_id(ap_id) do def get_cached_by_ap_id(ap_id) do
key = "ap_id:#{ap_id}" 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), 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 user
else else
{:ok, user} -> user {:ok, user} -> user
@ -1104,11 +1106,11 @@ def get_cached_by_id(id) do
key = "id:#{id}" key = "id:#{id}"
ap_id = ap_id =
Cachex.fetch!(:user_cache, key, fn _ -> @cachex.fetch!(:user_cache, key, fn _ ->
user = get_by_id(id) user = get_by_id(id)
if user do 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} {:commit, user.ap_id}
else else
{:ignore, ""} {:ignore, ""}
@ -1121,7 +1123,7 @@ def get_cached_by_id(id) do
def get_cached_by_nickname(nickname) do def get_cached_by_nickname(nickname) do
key = "nickname:#{nickname}" key = "nickname:#{nickname}"
Cachex.fetch!(:user_cache, key, fn -> @cachex.fetch!(:user_cache, key, fn _ ->
case get_or_fetch_by_nickname(nickname) do case get_or_fetch_by_nickname(nickname) do
{:ok, user} -> {:commit, user} {:ok, user} -> {:commit, user}
{:error, _error} -> {:ignore, nil} {:error, _error} -> {:ignore, nil}
@ -1390,7 +1392,7 @@ def mute(%User{} = muter, %User{} = mutee, params \\ %{}) do
) )
end 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)} {:ok, Enum.filter([user_mute, user_notification_mute], & &1)}
end end
@ -1400,7 +1402,7 @@ def unmute(%User{} = muter, %User{} = mutee) do
with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee), with {:ok, user_mute} <- UserRelationship.delete_mute(muter, mutee),
{:ok, user_notification_mute} <- {:ok, user_notification_mute} <-
UserRelationship.delete_notification_mute(muter, mutee) do 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]} {:ok, [user_mute, user_notification_mute]}
end end
end end
@ -2408,7 +2410,7 @@ def unblock_domain(user, domain_blocked) do
{:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()} {:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()}
defp add_to_block(%User{} = user, %User{} = blocked) do defp add_to_block(%User{} = user, %User{} = blocked) do
with {:ok, relationship} <- UserRelationship.create_block(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} {:ok, relationship}
end end
end end
@ -2417,7 +2419,7 @@ defp add_to_block(%User{} = user, %User{} = blocked) do
{:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()} {:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()}
defp remove_from_block(%User{} = user, %User{} = blocked) do defp remove_from_block(%User{} = user, %User{} = blocked) do
with {:ok, relationship} <- UserRelationship.delete_block(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} {:ok, relationship}
end end
end end

View File

@ -32,6 +32,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
require Logger require Logger
require Pleroma.Constants require Pleroma.Constants
@behaviour Pleroma.Web.ActivityPub.ActivityPub.Persisting
defp get_recipients(%{"type" => "Create"} = data) do defp get_recipients(%{"type" => "Create"} = data) do
to = Map.get(data, "to", []) to = Map.get(data, "to", [])
cc = Map.get(data, "cc", []) cc = Map.get(data, "cc", [])
@ -85,13 +87,14 @@ defp increase_replies_count_if_reply(%{
defp increase_replies_count_if_reply(_create_data), do: :noop defp increase_replies_count_if_reply(_create_data), do: :noop
@object_types ~w[ChatMessage Question Answer Audio Video Event Article] @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 def persist(%{"type" => type} = object, meta) when type in @object_types do
with {:ok, object} <- Object.create(object) do with {:ok, object} <- Object.create(object) do
{:ok, object, meta} {:ok, object, meta}
end end
end end
@impl true
def persist(object, meta) do def persist(object, meta) do
with local <- Keyword.fetch!(meta, :local), with local <- Keyword.fetch!(meta, :local),
{recipients, _, _} <- get_recipients(object), {recipients, _, _} <- get_recipients(object),

View 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

View File

@ -5,6 +5,8 @@
defmodule Pleroma.Web.ActivityPub.MRF do defmodule Pleroma.Web.ActivityPub.MRF do
require Logger require Logger
@behaviour Pleroma.Web.ActivityPub.MRF.PipelineFiltering
@mrf_config_descriptions [ @mrf_config_descriptions [
%{ %{
group: :pleroma, group: :pleroma,
@ -70,6 +72,7 @@ def filter(policies, %{} = message) do
def filter(%{} = object), do: get_policies() |> filter(object) def filter(%{} = object), do: get_policies() |> filter(object)
@impl true
def pipeline_filter(%{} = message, meta) do def pipeline_filter(%{} = message, meta) do
object = meta[:object_data] object = meta[:object_data]
ap_id = message["object"] ap_id = message["object"]

View 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

View File

@ -9,6 +9,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
the system. the system.
""" """
@behaviour Pleroma.Web.ActivityPub.ObjectValidator.Validating
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.EctoType.ActivityPub.ObjectValidators alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Object alias Pleroma.Object
@ -32,7 +34,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()} @impl true
def validate(object, meta) def validate(object, meta)
def validate(%{"type" => type} = object, meta) def validate(%{"type" => type} = object, meta)

View 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.ObjectValidator.Validating do
@callback validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
end

View File

@ -14,12 +14,19 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
alias Pleroma.Web.ActivityPub.Visibility alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Federator 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()) :: @spec common_pipeline(map(), keyword()) ::
{:ok, Activity.t() | Object.t(), keyword()} | {:error, any()} {:ok, Activity.t() | Object.t(), keyword()} | {:error, any()}
def common_pipeline(object, meta) do def common_pipeline(object, meta) do
case Repo.transaction(fn -> do_common_pipeline(object, meta) end) do case Repo.transaction(fn -> do_common_pipeline(object, meta) end) do
{:ok, {:ok, activity, meta}} -> {:ok, {:ok, activity, meta}} ->
SideEffects.handle_after_transaction(meta) @side_effects.handle_after_transaction(meta)
{:ok, activity, meta} {:ok, activity, meta}
{:ok, value} -> {:ok, value} ->
@ -35,13 +42,13 @@ def common_pipeline(object, meta) do
def do_common_pipeline(object, meta) do def do_common_pipeline(object, meta) do
with {_, {:ok, validated_object, meta}} <- with {_, {:ok, validated_object, meta}} <-
{:validate_object, ObjectValidator.validate(object, meta)}, {:validate_object, @object_validator.validate(object, meta)},
{_, {:ok, mrfd_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}} <- {_, {:ok, activity, meta}} <-
{:persist_object, ActivityPub.persist(mrfd_object, meta)}, {:persist_object, @activity_pub.persist(mrfd_object, meta)},
{_, {:ok, activity, 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, _}} <- {:federation, maybe_federate(activity, meta)} do
{:ok, activity, meta} {:ok, activity, meta}
else else
@ -54,7 +61,7 @@ defp maybe_federate(%Object{}, _), do: {:ok, :not_federated}
defp maybe_federate(%Activity{} = activity, meta) do defp maybe_federate(%Activity{} = activity, meta) do
with {:ok, local} <- Keyword.fetch(meta, :local) 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 if !do_not_federate and local and not Visibility.is_local_public?(activity) do
activity = activity =
@ -64,7 +71,7 @@ defp maybe_federate(%Activity{} = activity, meta) do
activity activity
end end
Federator.publish(activity) @federator.publish(activity)
{:ok, :federated} {:ok, :federated}
else else
{:ok, :not_federated} {:ok, :not_federated}

View File

@ -27,11 +27,17 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
require Logger require Logger
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@behaviour Pleroma.Web.ActivityPub.SideEffects.Handling
@impl true
def handle(object, meta \\ []) def handle(object, meta \\ [])
# Task this handles # Task this handles
# - Follows # - Follows
# - Sends a notification # - Sends a notification
@impl true
def handle( def handle(
%{ %{
data: %{ data: %{
@ -59,6 +65,7 @@ def handle(
# - Rejects all existing follow activities for this person # - Rejects all existing follow activities for this person
# - Updates the follow state # - Updates the follow state
# - Dismisses notification # - Dismisses notification
@impl true
def handle( def handle(
%{ %{
data: %{ data: %{
@ -85,6 +92,7 @@ def handle(
# - Follows if possible # - Follows if possible
# - Sends a notification # - Sends a notification
# - Generates accept or reject if appropriate # - Generates accept or reject if appropriate
@impl true
def handle( def handle(
%{ %{
data: %{ data: %{
@ -126,6 +134,7 @@ def handle(
# Tasks this handles: # Tasks this handles:
# - Unfollow and block # - Unfollow and block
@impl true
def handle( def handle(
%{data: %{"type" => "Block", "object" => blocked_user, "actor" => blocking_user}} = %{data: %{"type" => "Block", "object" => blocked_user, "actor" => blocking_user}} =
object, object,
@ -144,6 +153,7 @@ def handle(
# #
# For a local user, we also get a changeset with the full information, so we # For a local user, we also get a changeset with the full information, so we
# can update non-federating, non-activitypub settings as well. # can update non-federating, non-activitypub settings as well.
@impl true
def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object, meta) do
if changeset = Keyword.get(meta, :user_update_changeset) do if changeset = Keyword.get(meta, :user_update_changeset) do
changeset changeset
@ -162,6 +172,7 @@ def handle(%{data: %{"type" => "Update", "object" => updated_object}} = object,
# Tasks this handles: # Tasks this handles:
# - Add like to object # - Add like to object
# - Set up notification # - Set up notification
@impl true
def handle(%{data: %{"type" => "Like"}} = object, meta) do def handle(%{data: %{"type" => "Like"}} = object, meta) do
liked_object = Object.get_by_ap_id(object.data["object"]) liked_object = Object.get_by_ap_id(object.data["object"])
Utils.add_like_to_object(object, liked_object) Utils.add_like_to_object(object, liked_object)
@ -179,6 +190,7 @@ def handle(%{data: %{"type" => "Like"}} = object, meta) do
# - Increase replies count # - Increase replies count
# - Set up ActivityExpiration # - Set up ActivityExpiration
# - Set up notifications # - Set up notifications
@impl true
def handle(%{data: %{"type" => "Create"}} = activity, meta) do def handle(%{data: %{"type" => "Create"}} = activity, meta) do
with {:ok, object, meta} <- handle_object_creation(meta[:object_data], meta), with {:ok, object, meta} <- handle_object_creation(meta[:object_data], meta),
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do %User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
@ -207,6 +219,7 @@ def handle(%{data: %{"type" => "Create"}} = activity, meta) do
# - Add announce to object # - Add announce to object
# - Set up notification # - Set up notification
# - Stream out the announce # - Stream out the announce
@impl true
def handle(%{data: %{"type" => "Announce"}} = object, meta) do def handle(%{data: %{"type" => "Announce"}} = object, meta) do
announced_object = Object.get_by_ap_id(object.data["object"]) announced_object = Object.get_by_ap_id(object.data["object"])
user = User.get_cached_by_ap_id(object.data["actor"]) user = User.get_cached_by_ap_id(object.data["actor"])
@ -224,6 +237,7 @@ def handle(%{data: %{"type" => "Announce"}} = object, meta) do
{:ok, object, meta} {:ok, object, meta}
end end
@impl true
def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, meta) do def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, meta) do
with undone_object <- Activity.get_by_ap_id(undone_object), with undone_object <- Activity.get_by_ap_id(undone_object),
:ok <- handle_undoing(undone_object) do :ok <- handle_undoing(undone_object) do
@ -234,6 +248,7 @@ def handle(%{data: %{"type" => "Undo", "object" => undone_object}} = object, met
# Tasks this handles: # Tasks this handles:
# - Add reaction to object # - Add reaction to object
# - Set up notification # - Set up notification
@impl true
def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do
reacted_object = Object.get_by_ap_id(object.data["object"]) reacted_object = Object.get_by_ap_id(object.data["object"])
Utils.add_emoji_reaction_to_object(object, reacted_object) Utils.add_emoji_reaction_to_object(object, reacted_object)
@ -250,6 +265,7 @@ def handle(%{data: %{"type" => "EmojiReact"}} = object, meta) do
# - Reduce the user note count # - Reduce the user note count
# - Reduce the reply count # - Reduce the reply count
# - Stream out the activity # - Stream out the activity
@impl true
def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object, meta) do
deleted_object = deleted_object =
Object.normalize(deleted_object, false) || Object.normalize(deleted_object, false) ||
@ -295,6 +311,7 @@ def handle(%{data: %{"type" => "Delete", "object" => deleted_object}} = object,
end end
# Nothing to do # Nothing to do
@impl true
def handle(object, meta) do def handle(object, meta) do
{:ok, object, meta} {:ok, object, meta}
end end
@ -312,7 +329,7 @@ def handle_object_creation(%{"type" => "ChatMessage"} = object, meta) do
{:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) {: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) {:ok, cm_ref} = MessageReference.create(chat, object, user.ap_id != actor.ap_id)
Cachex.put( @cachex.put(
:chat_message_id_idempotency_key_cache, :chat_message_id_idempotency_key_cache,
cm_ref.id, cm_ref.id,
meta[:idempotency_key] meta[:idempotency_key]
@ -439,6 +456,7 @@ defp add_notifications(meta, notifications) do
|> Keyword.put(:notifications, notifications ++ existing) |> Keyword.put(:notifications, notifications ++ existing)
end end
@impl true
def handle_after_transaction(meta) do def handle_after_transaction(meta) do
meta meta
|> send_notifications() |> send_notifications()

View 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

View File

@ -9,6 +9,8 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
alias Pleroma.Web.MediaProxy alias Pleroma.Web.MediaProxy
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug( plug(
@ -38,7 +40,7 @@ def index(%{assigns: %{user: _}} = conn, params) do
defp fetch_entries(params) do defp fetch_entries(params) do
MediaProxy.cache_table() MediaProxy.cache_table()
|> Cachex.stream!(Cachex.Query.create(true, :key)) |> @cachex.stream!(Cachex.Query.create(true, :key))
|> filter_entries(params[:query]) |> filter_entries(params[:query])
end end

View File

@ -15,6 +15,8 @@ defmodule Pleroma.Web.Federator do
require Logger require Logger
@behaviour Pleroma.Web.Federator.Publishing
@doc """ @doc """
Returns `true` if the distance to target object does not exceed max configured value. 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. Serves to prevent fetching of very long threads, especially useful on smaller instances.
@ -39,10 +41,12 @@ def incoming_ap_doc(params) do
ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params}) ReceiverWorker.enqueue("incoming_ap_doc", %{"params" => params})
end end
@impl true
def publish(%{id: "pleroma:fakeid"} = activity) do def publish(%{id: "pleroma:fakeid"} = activity) do
perform(:publish, activity) perform(:publish, activity)
end end
@impl true
def publish(activity) do def publish(activity) do
PublisherWorker.enqueue("publish", %{"activity_id" => activity.id}) PublisherWorker.enqueue("publish", %{"activity_id" => activity.id})
end end

View File

@ -2,8 +2,6 @@
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
Postgrex.Types.define( defmodule Pleroma.Web.Federator.Publishing do
Pleroma.PostgresTypes, @callback publish(map()) :: any()
[] ++ Ecto.Adapters.Postgres.extensions(), end
json: Jason
)

View File

@ -26,6 +26,8 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PollOperation defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PollOperation
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@doc "GET /api/v1/polls/:id" @doc "GET /api/v1/polls/:id"
def show(%{assigns: %{user: user}} = conn, %{id: id}) do def show(%{assigns: %{user: user}} = conn, %{id: id}) do
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60), with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
@ -55,7 +57,7 @@ def vote(%{assigns: %{user: user}, body_params: %{choices: choices}} = conn, %{i
defp get_cached_vote_or_vote(user, object, choices) do defp get_cached_vote_or_vote(user, object, choices) do
idempotency_key = "polls:#{user.id}:#{object.data["id"]}" 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 case CommonAPI.vote(user, object, choices) do
{:error, _message} = res -> {:ignore, res} {:error, _message} = res -> {:ignore, res}
res -> {:commit, res} res -> {:commit, res}

View File

@ -12,29 +12,31 @@ defmodule Pleroma.Web.MediaProxy do
@base64_opts [padding: false] @base64_opts [padding: false]
@cache_table :banned_urls_cache @cache_table :banned_urls_cache
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
def cache_table, do: @cache_table def cache_table, do: @cache_table
@spec in_banned_urls(String.t()) :: boolean() @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 def remove_from_banned_urls(urls) when is_list(urls) do
Cachex.execute!(@cache_table, fn cache -> @cachex.execute!(@cache_table, fn cache ->
Enum.each(Invalidation.prepare_urls(urls), &Cachex.del(cache, &1)) Enum.each(Invalidation.prepare_urls(urls), &@cachex.del(cache, &1))
end) end)
end end
def remove_from_banned_urls(url) when is_binary(url) do def remove_from_banned_urls(url) when is_binary(url) do
Cachex.del(@cache_table, url(url)) @cachex.del(@cache_table, url(url))
end end
def put_in_banned_urls(urls) when is_list(urls) do def put_in_banned_urls(urls) when is_list(urls) do
Cachex.execute!(@cache_table, fn cache -> @cachex.execute!(@cache_table, fn cache ->
Enum.each(Invalidation.prepare_urls(urls), &Cachex.put(cache, &1, true)) Enum.each(Invalidation.prepare_urls(urls), &@cachex.put(cache, &1, true))
end) end)
end end
def put_in_banned_urls(url) when is_binary(url) do 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 end
def url(url) when is_nil(url) or url == "", do: nil def url(url) when is_nil(url) or url == "", do: nil

View File

@ -10,6 +10,8 @@ defmodule Pleroma.Web.PleromaAPI.Chat.MessageReferenceView do
alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MastodonAPI.StatusView
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
def render( def render(
"show.json", "show.json",
%{ %{
@ -51,7 +53,7 @@ def render("index.json", opts) do
end end
defp put_idempotency_key(data) do 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 data
|> Maps.put_if_present(:idempotency_key, idempotency_key) |> Maps.put_if_present(:idempotency_key, idempotency_key)
else else

View File

@ -41,6 +41,8 @@ def index(conn, _params) do
@defaults %{ttl: nil, query_params: true} @defaults %{ttl: nil, query_params: true}
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@impl true @impl true
def init([]), do: @defaults def init([]), do: @defaults
@ -53,7 +55,7 @@ def init(opts) do
def call(%{method: "GET"} = conn, opts) do def call(%{method: "GET"} = conn, opts) do
key = cache_key(conn, opts) key = cache_key(conn, opts)
case Cachex.get(:web_resp_cache, key) do case @cachex.get(:web_resp_cache, key) do
{:ok, nil} -> {:ok, nil} ->
cache_resp(conn, opts) cache_resp(conn, opts)
@ -97,11 +99,11 @@ defp cache_resp(conn, opts) do
conn = conn =
unless opts[:tracking_fun] do 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 conn
else else
tracking_fun_data = Map.get(conn.assigns, :tracking_fun_data, nil) 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) opts.tracking_fun.(conn, tracking_fun_data)
end end

View File

@ -8,6 +8,8 @@ defmodule Pleroma.Web.Plugs.IdempotencyPlug do
@behaviour Plug @behaviour Plug
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@impl true @impl true
def init(opts), do: opts def init(opts), do: opts
@ -25,7 +27,7 @@ def call(%{method: method} = conn, _) when method in ["POST", "PUT", "PATCH"] do
def call(conn, _), do: conn def call(conn, _), do: conn
def process_request(conn, key) do def process_request(conn, key) do
case Cachex.get(:idempotency_cache, key) do case @cachex.get(:idempotency_cache, key) do
{:ok, nil} -> {:ok, nil} ->
cache_resposnse(conn, key) cache_resposnse(conn, key)
@ -43,7 +45,7 @@ defp cache_resposnse(conn, key) do
content_type = get_content_type(conn) content_type = get_content_type(conn)
record = {request_id, content_type, conn.status, conn.resp_body} 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 conn
|> put_resp_header("idempotency-key", key) |> put_resp_header("idempotency-key", key)

View File

@ -72,6 +72,8 @@ defmodule Pleroma.Web.Plugs.RateLimiter do
require Logger require Logger
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
@doc false @doc false
def init(plug_opts) do def init(plug_opts) do
plug_opts plug_opts
@ -124,7 +126,7 @@ def inspect_bucket(conn, bucket_name_root, plug_opts) do
key_name = make_key_name(action_settings) key_name = make_key_name(action_settings)
limit = get_limits(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} -> {:error, :no_cache} ->
@inspect_bucket_not_found @inspect_bucket_not_found
@ -157,7 +159,7 @@ defp check_rate(action_settings) do
key_name = make_key_name(action_settings) key_name = make_key_name(action_settings)
limit = get_limits(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} -> {:commit, value} ->
{:ok, value} {:ok, value}

View File

@ -12,8 +12,9 @@ defmodule Pleroma.Web.RelMe do
if Pleroma.Config.get(:env) == :test do if Pleroma.Config.get(:env) == :test do
def parse(url) when is_binary(url), do: parse_url(url) def parse(url) when is_binary(url), do: parse_url(url)
else else
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
def parse(url) when is_binary(url) do 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)} {:commit, parse_url(url)}
end) end)
rescue rescue

View File

@ -5,6 +5,8 @@
defmodule Pleroma.Web.RichMedia.Parser do defmodule Pleroma.Web.RichMedia.Parser do
require Logger require Logger
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
defp parsers do defp parsers do
Pleroma.Config.get([:rich_media, :parsers]) Pleroma.Config.get([:rich_media, :parsers])
end end
@ -24,7 +26,7 @@ def parse(url) do
end end
defp get_cached_or_parse(url) do 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 case parse_url(url) do
{:ok, _} = res -> {:ok, _} = res ->
{:commit, res} {:commit, res}
@ -64,7 +66,7 @@ defp set_error_ttl(_url, {:content_type, _}), do: :ok
defp set_error_ttl(url, _reason) do defp set_error_ttl(url, _reason) do
ttl = Pleroma.Config.get([:rich_media, :failure_backoff], 60_000) 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 :ok
end end
@ -106,7 +108,7 @@ def set_ttl_based_on_image(data, url) do
{:ok, ttl} when is_number(ttl) -> {:ok, ttl} when is_number(ttl) ->
ttl = ttl * 1000 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, true} -> {:ok, ttl}
{:ok, false} -> {:error, :no_key} {:ok, false} -> {:error, :no_key}
end end

View File

@ -211,7 +211,7 @@ defp deps do
git: "https://git.pleroma.social/pleroma/elixir-libraries/hackney.git", git: "https://git.pleroma.social/pleroma/elixir-libraries/hackney.git",
ref: "7d7119f0651515d6d7669c78393fd90950a3ec6e", ref: "7d7119f0651515d6d7669c78393fd90950a3ec6e",
override: true}, override: true},
{:mox, "~> 0.5", only: :test}, {:mox, "~> 1.0", only: :test},
{:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test} {:websocket_client, git: "https://github.com/jeremyong/websocket_client.git", only: :test}
] ++ oauth_deps() ] ++ oauth_deps()
end end

View File

@ -76,7 +76,7 @@
"mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"}, "mochiweb": {:hex, :mochiweb, "2.18.0", "eb55f1db3e6e960fac4e6db4e2db9ec3602cc9f30b86cd1481d56545c3145d2e", [:rebar3], [], "hexpm"},
"mock": {:hex, :mock, "0.3.5", "feb81f52b8dcf0a0d65001d2fec459f6b6a8c22562d94a965862f6cc066b5431", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "6fae404799408300f863550392635d8f7e3da6b71abdd5c393faf41b131c8728"}, "mock": {:hex, :mock, "0.3.5", "feb81f52b8dcf0a0d65001d2fec459f6b6a8c22562d94a965862f6cc066b5431", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "6fae404799408300f863550392635d8f7e3da6b71abdd5c393faf41b131c8728"},
"mogrify": {:hex, :mogrify, "0.7.4", "9b2496dde44b1ce12676f85d7dc531900939e6367bc537c7243a1b089435b32d", [:mix], [], "hexpm", "50d79e337fba6bc95bfbef918058c90f50b17eed9537771e61d4619488f099c3"}, "mogrify": {:hex, :mogrify, "0.7.4", "9b2496dde44b1ce12676f85d7dc531900939e6367bc537c7243a1b089435b32d", [:mix], [], "hexpm", "50d79e337fba6bc95bfbef918058c90f50b17eed9537771e61d4619488f099c3"},
"mox": {:hex, :mox, "0.5.2", "55a0a5ba9ccc671518d068c8dddd20eeb436909ea79d1799e2209df7eaa98b6c", [:mix], [], "hexpm", "df4310628cd628ee181df93f50ddfd07be3e5ecc30232d3b6aadf30bdfe6092b"}, "mox": {:hex, :mox, "1.0.0", "4b3c7005173f47ff30641ba044eb0fe67287743eec9bd9545e37f3002b0a9f8b", [:mix], [], "hexpm", "201b0a20b7abdaaab083e9cf97884950f8a30a1350a1da403b3145e213c6f4df"},
"myhtmlex": {:git, "https://git.pleroma.social/pleroma/myhtmlex.git", "ad0097e2f61d4953bfef20fb6abddf23b87111e6", [ref: "ad0097e2f61d4953bfef20fb6abddf23b87111e6", submodules: true]}, "myhtmlex": {:git, "https://git.pleroma.social/pleroma/myhtmlex.git", "ad0097e2f61d4953bfef20fb6abddf23b87111e6", [ref: "ad0097e2f61d4953bfef20fb6abddf23b87111e6", submodules: true]},
"nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"}, "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"},
"nimble_pool": {:hex, :nimble_pool, "0.1.0", "ffa9d5be27eee2b00b0c634eb649aa27f97b39186fec3c493716c2a33e784ec6", [:mix], [], "hexpm", "343a1eaa620ddcf3430a83f39f2af499fe2370390d4f785cd475b4df5acaf3f9"}, "nimble_pool": {:hex, :nimble_pool, "0.1.0", "ffa9d5be27eee2b00b0c634eb649aa27f97b39186fec3c493716c2a33e784ec6", [:mix], [], "hexpm", "343a1eaa620ddcf3430a83f39f2af499fe2370390d4f785cd475b4df5acaf3f9"},

View File

@ -3,6 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.CountStatusesTest do defmodule Mix.Tasks.Pleroma.CountStatusesTest do
# Uses log capture, has to stay synchronous
use Pleroma.DataCase use Pleroma.DataCase
alias Pleroma.User alias Pleroma.User

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.DatabaseTest do defmodule Mix.Tasks.Pleroma.DatabaseTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
use Oban.Testing, repo: Pleroma.Repo use Oban.Testing, repo: Pleroma.Repo
alias Pleroma.Activity alias Pleroma.Activity

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-onl # SPDX-License-Identifier: AGPL-3.0-onl
defmodule Mix.Tasks.Pleroma.Ecto.MigrateTest do defmodule Mix.Tasks.Pleroma.Ecto.MigrateTest do
use Pleroma.DataCase, async: true use Pleroma.DataCase
import ExUnit.CaptureLog import ExUnit.CaptureLog
require Logger require Logger

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Ecto.RollbackTest do defmodule Mix.Tasks.Pleroma.Ecto.RollbackTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import ExUnit.CaptureLog import ExUnit.CaptureLog
require Logger require Logger

View File

@ -3,7 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.InstanceTest do defmodule Mix.Tasks.Pleroma.InstanceTest do
use ExUnit.Case # Modifies the Application Environment, has to stay synchronous.
use Pleroma.DataCase
setup do setup do
File.mkdir_p!(tmp_path()) File.mkdir_p!(tmp_path())
@ -15,15 +16,17 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do
if File.exists?(static_dir) do if File.exists?(static_dir) do
File.rm_rf(Path.join(static_dir, "robots.txt")) File.rm_rf(Path.join(static_dir, "robots.txt"))
end end
Pleroma.Config.put([:instance, :static_dir], static_dir)
end) end)
# Is being modified by the mix task.
clear_config([:instance, :static_dir])
:ok :ok
end end
@uuid Ecto.UUID.generate()
defp tmp_path do defp tmp_path do
"/tmp/generated_files/" "/tmp/generated_files/#{@uuid}/"
end end
test "running gen" do test "running gen" do

View File

@ -3,6 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.RefreshCounterCacheTest do defmodule Mix.Tasks.Pleroma.RefreshCounterCacheTest do
# Uses log capture, has to stay synchronous
use Pleroma.DataCase use Pleroma.DataCase
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
import ExUnit.CaptureIO, only: [capture_io: 1] import ExUnit.CaptureIO, only: [capture_io: 1]

View File

@ -100,7 +100,7 @@ test "unfollow when relay is dead" do
end) end)
Pleroma.Repo.delete(user) Pleroma.Repo.delete(user)
Cachex.clear(:user_cache) User.invalidate_cache(user)
Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance]) Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance])
@ -137,7 +137,7 @@ test "force unfollow when relay is dead" do
end) end)
Pleroma.Repo.delete(user) Pleroma.Repo.delete(user)
Cachex.clear(:user_cache) User.invalidate_cache(user)
Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance, "--force"]) Mix.Tasks.Pleroma.Relay.run(["unfollow", target_instance, "--force"])

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Activity.Ir.TopicsTest do defmodule Pleroma.Activity.Ir.TopicsTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Activity.Ir.Topics alias Pleroma.Activity.Ir.Topics

View File

@ -7,7 +7,7 @@ defmodule Pleroma.Activity.SearchTest do
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
import Pleroma.Factory import Pleroma.Factory
use Pleroma.DataCase use Pleroma.DataCase, async: true
test "it finds something" do test "it finds something" do
user = insert(:user) user = insert(:user)

View File

@ -15,6 +15,7 @@ defmodule Pleroma.ApplicationRequirementsTest do
describe "check_repo_pool_size!/1" do describe "check_repo_pool_size!/1" do
test "raises if the pool size is unexpected" do test "raises if the pool size is unexpected" do
clear_config([Pleroma.Repo, :pool_size], 11) clear_config([Pleroma.Repo, :pool_size], 11)
clear_config([:dangerzone, :override_repo_pool_size], false)
assert_raise Pleroma.ApplicationRequirements.VerifyError, assert_raise Pleroma.ApplicationRequirements.VerifyError,
"Repo.pool_size different than recommended value.", "Repo.pool_size different than recommended value.",

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.BBS.HandlerTest do defmodule Pleroma.BBS.HandlerTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.BBS.Handler alias Pleroma.BBS.Handler
alias Pleroma.Object alias Pleroma.Object

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.BookmarkTest do defmodule Pleroma.BookmarkTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Bookmark alias Pleroma.Bookmark
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI

View File

@ -80,7 +80,6 @@ test "validate" do
assert is_binary(answer) assert is_binary(answer)
assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer) assert :ok = Captcha.validate(token, "63615261b77f5354fb8c4e4986477555", answer)
Cachex.del(:used_captcha_cache, token)
end end
test "doesn't validate invalid answer" do test "doesn't validate invalid answer" do

View File

@ -73,7 +73,8 @@ test "a returning chat will have an updated `update_at` field" do
other_user = insert(:user) other_user = insert(:user)
{:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id) {:ok, chat} = Chat.bump_or_create(user.id, other_user.ap_id)
:timer.sleep(1500) {:ok, chat} = time_travel(chat, -2)
{:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id) {:ok, chat_two} = Chat.bump_or_create(user.id, other_user.ap_id)
assert chat.id == chat_two.id assert chat.id == chat_two.id

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.ConfigTest do defmodule Pleroma.ConfigTest do
use ExUnit.Case use Pleroma.DataCase
test "get/1 with an atom" do test "get/1 with an atom" do
assert Pleroma.Config.get(:instance) == Application.get_env(:pleroma, :instance) assert Pleroma.Config.get(:instance) == Application.get_env(:pleroma, :instance)

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Conversation.ParticipationTest do defmodule Pleroma.Conversation.ParticipationTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Conversation alias Pleroma.Conversation
alias Pleroma.Conversation.Participation alias Pleroma.Conversation.Participation
@ -96,12 +96,11 @@ test "it creates a participation for a conversation and a user" do
{:ok, %Participation{} = participation} = {:ok, %Participation{} = participation} =
Participation.create_for_user_and_conversation(user, conversation) Participation.create_for_user_and_conversation(user, conversation)
{:ok, participation} = time_travel(participation, -2)
assert participation.user_id == user.id assert participation.user_id == user.id
assert participation.conversation_id == conversation.id assert participation.conversation_id == conversation.id
# Needed because updated_at is accurate down to a second
:timer.sleep(1000)
# Creating again returns the same participation # Creating again returns the same participation
{:ok, %Participation{} = participation_two} = {:ok, %Participation{} = participation_two} =
Participation.create_for_user_and_conversation(user, conversation) Participation.create_for_user_and_conversation(user, conversation)

View File

@ -2,7 +2,7 @@
# Copyright © 2020 Pleroma Authors <https://pleroma.social/> # Copyright © 2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.EarmarkRendererTest do defmodule Pleroma.EarmarkRendererTest do
use ExUnit.Case use Pleroma.DataCase, async: true
test "Paragraph" do test "Paragraph" do
code = ~s[Hello\n\nWorld!] code = ~s[Hello\n\nWorld!]

View File

@ -4,7 +4,7 @@
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.DateTimeTest do defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.DateTimeTest do
alias Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime alias Pleroma.EctoType.ActivityPub.ObjectValidators.DateTime
use Pleroma.DataCase use Pleroma.DataCase, async: true
test "it validates an xsd:Datetime" do test "it validates an xsd:Datetime" do
valid_strings = [ valid_strings = [

View File

@ -4,7 +4,7 @@
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectIDTest do defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectIDTest do
alias Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectID alias Pleroma.EctoType.ActivityPub.ObjectValidators.ObjectID
use Pleroma.DataCase use Pleroma.DataCase, async: true
@uris [ @uris [
"http://lain.com/users/lain", "http://lain.com/users/lain",

View File

@ -4,7 +4,7 @@
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.RecipientsTest do defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.RecipientsTest do
alias Pleroma.EctoType.ActivityPub.ObjectValidators.Recipients alias Pleroma.EctoType.ActivityPub.ObjectValidators.Recipients
use Pleroma.DataCase use Pleroma.DataCase, async: true
test "it asserts that all elements of the list are object ids" do test "it asserts that all elements of the list are object ids" do
list = ["https://lain.com/users/lain", "invalid"] list = ["https://lain.com/users/lain", "invalid"]

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.SafeTextTest do defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.SafeTextTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.EctoType.ActivityPub.ObjectValidators.SafeText alias Pleroma.EctoType.ActivityPub.ObjectValidators.SafeText

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Emails.AdminEmailTest do defmodule Pleroma.Emails.AdminEmailTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Emails.AdminEmail alias Pleroma.Emails.AdminEmail

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Emails.UserEmailTest do defmodule Pleroma.Emails.UserEmailTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Emails.UserEmail alias Pleroma.Emails.UserEmail
alias Pleroma.Web.Endpoint alias Pleroma.Web.Endpoint

View File

@ -4,7 +4,7 @@
defmodule Pleroma.Emoji.FormatterTest do defmodule Pleroma.Emoji.FormatterTest do
alias Pleroma.Emoji.Formatter alias Pleroma.Emoji.Formatter
use Pleroma.DataCase use Pleroma.DataCase, async: true
describe "emojify" do describe "emojify" do
test "it adds cool emoji" do test "it adds cool emoji" do

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Emoji.PackTest do defmodule Pleroma.Emoji.PackTest do
use ExUnit.Case, async: true use Pleroma.DataCase
alias Pleroma.Emoji.Pack alias Pleroma.Emoji.Pack
@emoji_path Path.join( @emoji_path Path.join(

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.EmojiTest do defmodule Pleroma.EmojiTest do
use ExUnit.Case use ExUnit.Case, async: true
alias Pleroma.Emoji alias Pleroma.Emoji
describe "is_unicode_emoji?/1" do describe "is_unicode_emoji?/1" do

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.FilterTest do defmodule Pleroma.FilterTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.FollowingRelationshipTest do defmodule Pleroma.FollowingRelationshipTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.FollowingRelationship alias Pleroma.FollowingRelationship
alias Pleroma.Web.ActivityPub.InternalFetchActor alias Pleroma.Web.ActivityPub.InternalFetchActor

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.HealthcheckTest do defmodule Pleroma.HealthcheckTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Healthcheck alias Pleroma.Healthcheck
test "system_info/0" do test "system_info/0" do

View File

@ -6,7 +6,7 @@ defmodule Pleroma.HTMLTest do
alias Pleroma.HTML alias Pleroma.HTML
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.HTTP.AdapterHelper.GunTest do defmodule Pleroma.HTTP.AdapterHelper.GunTest do
use ExUnit.Case, async: true use ExUnit.Case
use Pleroma.Tests.Helpers use Pleroma.Tests.Helpers
import Mox import Mox

View File

@ -3,6 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Integration.MastodonWebsocketTest do defmodule Pleroma.Integration.MastodonWebsocketTest do
# Needs a streamer, needs to stay synchronous
use Pleroma.DataCase use Pleroma.DataCase
import ExUnit.CaptureLog import ExUnit.CaptureLog

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.KeysTest do defmodule Pleroma.KeysTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Keys alias Pleroma.Keys

View File

@ -4,7 +4,7 @@
defmodule Pleroma.ListTest do defmodule Pleroma.ListTest do
alias Pleroma.Repo alias Pleroma.Repo
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MarkerTest do defmodule Pleroma.MarkerTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Marker alias Pleroma.Marker
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA.BackupCodesTest do defmodule Pleroma.MFA.BackupCodesTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.MFA.BackupCodes alias Pleroma.MFA.BackupCodes

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFA.TOTPTest do defmodule Pleroma.MFA.TOTPTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.MFA.TOTP alias Pleroma.MFA.TOTP

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MFATest do defmodule Pleroma.MFATest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.MFA alias Pleroma.MFA

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MigrationHelper.NotificationBackfillTest do defmodule Pleroma.MigrationHelper.NotificationBackfillTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.MigrationHelper.NotificationBackfill alias Pleroma.MigrationHelper.NotificationBackfill

View File

@ -6,7 +6,7 @@ defmodule Pleroma.ModerationLogTest do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.ModerationLog alias Pleroma.ModerationLog
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.PaginationTest do defmodule Pleroma.PaginationTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.RegistrationTest do defmodule Pleroma.RegistrationTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -4,7 +4,7 @@
defmodule Pleroma.Repo.Migrations.FixLegacyTagsTest do defmodule Pleroma.Repo.Migrations.FixLegacyTagsTest do
alias Pleroma.User alias Pleroma.User
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
import Pleroma.Tests.Helpers import Pleroma.Tests.Helpers

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Repo.Migrations.MoveWelcomeSettingsTest do defmodule Pleroma.Repo.Migrations.MoveWelcomeSettingsTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
import Pleroma.Tests.Helpers import Pleroma.Tests.Helpers
alias Pleroma.ConfigDB alias Pleroma.ConfigDB

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.RepoTest do defmodule Pleroma.RepoTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.User alias Pleroma.User

View File

@ -4,7 +4,7 @@
defmodule Pleroma.ReportNoteTest do defmodule Pleroma.ReportNoteTest do
alias Pleroma.ReportNote alias Pleroma.ReportNote
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
test "create/3" do test "create/3" do

View File

@ -3,8 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.ReverseProxyTest do defmodule Pleroma.ReverseProxyTest do
use Pleroma.Web.ConnCase, async: true use Pleroma.Web.ConnCase
import ExUnit.CaptureLog import ExUnit.CaptureLog
import Mox import Mox

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.SafeJsonbSetTest do defmodule Pleroma.SafeJsonbSetTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
test "it doesn't wipe the object when asked to set the value to NULL" do test "it doesn't wipe the object when asked to set the value to NULL" do
assert %{rows: [[%{"key" => "value", "test" => nil}]]} = assert %{rows: [[%{"key" => "value", "test" => nil}]]} =

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.StatsTest do defmodule Pleroma.StatsTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.DedupeTest do defmodule Pleroma.Upload.Filter.DedupeTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Upload alias Pleroma.Upload
alias Pleroma.Upload.Filter.Dedupe alias Pleroma.Upload.Filter.Dedupe

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.ExiftoolTest do defmodule Pleroma.Upload.Filter.ExiftoolTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Upload.Filter alias Pleroma.Upload.Filter
test "apply exiftool filter" do test "apply exiftool filter" do

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Uploaders.LocalTest do defmodule Pleroma.Uploaders.LocalTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Uploaders.Local alias Pleroma.Uploaders.Local
describe "get_file/1" do describe "get_file/1" do

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.User.NotificationSettingTest do defmodule Pleroma.User.NotificationSettingTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.User.NotificationSetting alias Pleroma.User.NotificationSetting

View File

@ -5,7 +5,7 @@
defmodule Pleroma.UserRelationshipTest do defmodule Pleroma.UserRelationshipTest do
alias Pleroma.UserRelationship alias Pleroma.UserRelationship
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicyTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy alias Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Object alias Pleroma.Object

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicyTest do defmodule Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicyTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy alias Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicyTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy alias Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy
test "it clears content object" do test "it clears content object" do

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkupTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup alias Pleroma.Web.ActivityPub.MRF.NormalizeMarkup
@html_sample """ @html_sample """

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do defmodule Pleroma.Web.ActivityPub.MRF.TagPolicyTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Web.ActivityPub.MRF.TagPolicy alias Pleroma.Web.ActivityPub.MRF.TagPolicy

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidationTest do defmodule Pleroma.Web.ActivityPub.ObjectValidators.AcceptValidationTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.ActivityPub.ObjectValidator

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidationTest do defmodule Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidationTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Builder

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidatorTest do defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidatorTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNoteValidator
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator alias Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidationTest do defmodule Pleroma.Web.ActivityPub.ObjectValidators.BlockValidationTest do
use Pleroma.DataCase use Pleroma.DataCase, async: true
alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.ActivityPub.ObjectValidator

Some files were not shown because too many files have changed in this diff Show More