aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--config/config.exs2
-rw-r--r--docs/config.md2
-rw-r--r--lib/pleroma/activity.ex27
-rw-r--r--lib/pleroma/user.ex38
-rw-r--r--lib/pleroma/web/activity_pub/mrf.ex32
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex6
-rw-r--r--lib/pleroma/web/activity_pub/mrf/drop_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/keyword_policy.ex32
-rw-r--r--lib/pleroma/web/activity_pub/mrf/mediaproxy_warming_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/mention_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/noop_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/normalize_markup.ex2
-rw-r--r--lib/pleroma/web/activity_pub/mrf/reject_non_public.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/simple_policy.ex12
-rw-r--r--lib/pleroma/web/activity_pub/mrf/subchain_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/tag_policy.ex3
-rw-r--r--lib/pleroma/web/activity_pub/mrf/user_allowlist_policy.ex9
-rw-r--r--lib/pleroma/web/activity_pub/relay.ex17
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api.ex24
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex55
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex20
-rw-r--r--lib/pleroma/web/nodeinfo/nodeinfo_controller.ex54
-rw-r--r--lib/pleroma/web/web.ex4
-rw-r--r--test/support/mrf_module_mock.ex13
-rw-r--r--test/user_test.exs5
-rw-r--r--test/web/activity_pub/mrf/mrf_test.exs26
-rw-r--r--test/web/activity_pub/relay_test.exs62
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs137
-rw-r--r--test/web/mastodon_api/mastodon_api_test.exs103
-rw-r--r--test/web/node_info_test.exs8
35 files changed, 573 insertions, 150 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d998a4050..7548a546a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,6 +70,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Added synchronization of following/followers counters for external users
- Configuration: `enabled` option for `Pleroma.Emails.Mailer`, defaulting to `false`.
- Configuration: Pleroma.Plugs.RateLimiter `bucket_name`, `params` options.
+- Configuration: `user_bio_length` and `user_name_length` options.
- Addressable lists
- Twitter API: added rate limit for `/api/account/password_reset` endpoint.
- ActivityPub: Add an internal service actor for fetching ActivityPub objects.
diff --git a/config/config.exs b/config/config.exs
index 17799af59..758661120 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -253,6 +253,8 @@ config :pleroma, :instance,
skip_thread_containment: true,
limit_to_local_content: :unauthenticated,
dynamic_configuration: false,
+ user_bio_length: 5000,
+ user_name_length: 100,
external_user_synchronization: true
config :pleroma, :markup,
diff --git a/docs/config.md b/docs/config.md
index d1fa501ea..20311db54 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -127,6 +127,8 @@ config :pleroma, Pleroma.Emails.Mailer,
* `safe_dm_mentions`: If set to true, only mentions at the beginning of a post will be used to address people in direct messages. This is to prevent accidental mentioning of people when talking about them (e.g. "@friend hey i really don't like @enemy"). Default: `false`.
* `healthcheck`: If set to true, system data will be shown on ``/api/pleroma/healthcheck``.
* `remote_post_retention_days`: The default amount of days to retain remote posts when pruning the database.
+* `user_bio_length`: A user bio maximum length (default: `5000`)
+* `user_name_length`: A user name maximum length (default: `100`)
* `skip_thread_containment`: Skip filter out broken threads. The default is `false`.
* `limit_to_local_content`: Limit unauthenticated users to search for local statutes and users only. Possible values: `:unauthenticated`, `:all` and `false`. The default is `:unauthenticated`.
* `dynamic_configuration`: Allow transferring configuration to DB with the subsequent customization from Admin api.
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index 46552c7be..baf1e7722 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -224,6 +224,29 @@ defmodule Pleroma.Activity do
def get_create_by_object_ap_id(_), do: nil
+ def create_by_object_ap_id_with_object(ap_ids) when is_list(ap_ids) do
+ from(
+ activity in Activity,
+ where:
+ fragment(
+ "coalesce((?)->'object'->>'id', (?)->>'object') = ANY(?)",
+ activity.data,
+ activity.data,
+ ^ap_ids
+ ),
+ where: fragment("(?)->>'type' = 'Create'", activity.data),
+ inner_join: o in Object,
+ on:
+ fragment(
+ "(?->>'id') = COALESCE(?->'object'->>'id', ?->>'object')",
+ o.data,
+ activity.data,
+ activity.data
+ ),
+ preload: [object: o]
+ )
+ end
+
def create_by_object_ap_id_with_object(ap_id) when is_binary(ap_id) do
from(
activity in Activity,
@@ -263,8 +286,8 @@ defmodule Pleroma.Activity do
defp get_in_reply_to_activity_from_object(_), do: nil
- def get_in_reply_to_activity(%Activity{data: %{"object" => object}}) do
- get_in_reply_to_activity_from_object(Object.normalize(object))
+ def get_in_reply_to_activity(%Activity{} = activity) do
+ get_in_reply_to_activity_from_object(Object.normalize(activity))
end
def normalize(obj) when is_map(obj), do: get_by_ap_id_with_object(obj["id"])
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 7d18f099e..b67743846 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -152,10 +152,10 @@ defmodule Pleroma.User do
end
def remote_user_creation(params) do
- params =
- params
- |> Map.put(:info, params[:info] || %{})
+ bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
+ params = Map.put(params, :info, params[:info] || %{})
info_cng = User.Info.remote_user_creation(%User.Info{}, params[:info])
changes =
@@ -164,8 +164,8 @@ defmodule Pleroma.User do
|> validate_required([:name, :ap_id])
|> unique_constraint(:nickname)
|> validate_format(:nickname, @email_regex)
- |> validate_length(:bio, max: 5000)
- |> validate_length(:name, max: 100)
+ |> validate_length(:bio, max: bio_limit)
+ |> validate_length(:name, max: name_limit)
|> put_change(:local, false)
|> put_embed(:info, info_cng)
@@ -188,22 +188,23 @@ defmodule Pleroma.User do
end
def update_changeset(struct, params \\ %{}) do
+ bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
+
struct
|> cast(params, [:bio, :name, :avatar, :following])
|> unique_constraint(:nickname)
|> validate_format(:nickname, local_nickname_regex())
- |> validate_length(:bio, max: 5000)
- |> validate_length(:name, min: 1, max: 100)
+ |> validate_length(:bio, max: bio_limit)
+ |> validate_length(:name, min: 1, max: name_limit)
end
def upgrade_changeset(struct, params \\ %{}) do
- params =
- params
- |> Map.put(:last_refreshed_at, NaiveDateTime.utc_now())
+ bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
- info_cng =
- struct.info
- |> User.Info.user_upgrade(params[:info])
+ params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now())
+ info_cng = User.Info.user_upgrade(struct.info, params[:info])
struct
|> cast(params, [
@@ -216,8 +217,8 @@ defmodule Pleroma.User do
])
|> unique_constraint(:nickname)
|> validate_format(:nickname, local_nickname_regex())
- |> validate_length(:bio, max: 5000)
- |> validate_length(:name, max: 100)
+ |> validate_length(:bio, max: bio_limit)
+ |> validate_length(:name, max: name_limit)
|> put_embed(:info, info_cng)
end
@@ -244,6 +245,9 @@ defmodule Pleroma.User do
end
def register_changeset(struct, params \\ %{}, opts \\ []) do
+ bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
+
need_confirmation? =
if is_nil(opts[:need_confirmation]) do
Pleroma.Config.get([:instance, :account_activation_required])
@@ -264,8 +268,8 @@ defmodule Pleroma.User do
|> validate_exclusion(:nickname, Pleroma.Config.get([User, :restricted_nicknames]))
|> validate_format(:nickname, local_nickname_regex())
|> validate_format(:email, @email_regex)
- |> validate_length(:bio, max: 1000)
- |> validate_length(:name, min: 1, max: 100)
+ |> validate_length(:bio, max: bio_limit)
+ |> validate_length(:name, min: 1, max: name_limit)
|> put_change(:info, info_change)
changeset =
diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex
index caa2a3231..263ed11af 100644
--- a/lib/pleroma/web/activity_pub/mrf.ex
+++ b/lib/pleroma/web/activity_pub/mrf.ex
@@ -35,4 +35,36 @@ defmodule Pleroma.Web.ActivityPub.MRF do
def subdomain_match?(domains, host) do
Enum.any?(domains, fn domain -> Regex.match?(domain, host) end)
end
+
+ @callback describe() :: {:ok | :error, Map.t()}
+
+ def describe(policies) do
+ {:ok, policy_configs} =
+ policies
+ |> Enum.reduce({:ok, %{}}, fn
+ policy, {:ok, data} ->
+ {:ok, policy_data} = policy.describe()
+ {:ok, Map.merge(data, policy_data)}
+
+ _, error ->
+ error
+ end)
+
+ mrf_policies =
+ get_policies()
+ |> Enum.map(fn policy -> to_string(policy) |> String.split(".") |> List.last() end)
+
+ exclusions = Pleroma.Config.get([:instance, :mrf_transparency_exclusions])
+
+ base =
+ %{
+ mrf_policies: mrf_policies,
+ exclusions: length(exclusions) > 0
+ }
+ |> Map.merge(policy_configs)
+
+ {:ok, base}
+ end
+
+ def describe, do: get_policies() |> describe()
end
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
index 87fa514c3..de1eb4aa5 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_followbot_policy.ex
@@ -62,4 +62,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
@impl true
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
index 2da3eac2f..b90193ca0 100644
--- a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex
@@ -5,6 +5,8 @@
defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
alias Pleroma.User
+ @behaviour Pleroma.Web.ActivityPub.MRF
+
require Logger
# has the user successfully posted before?
@@ -22,6 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
defp contains_links?(_), do: false
+ @impl true
def filter(%{"type" => "Create", "actor" => actor, "object" => object} = message) do
with {:ok, %User{} = u} <- User.get_or_fetch_by_ap_id(actor),
{:contains_links, true} <- {:contains_links, contains_links?(object)},
@@ -45,4 +48,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do
# in all other cases, pass through
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
index b8d38aae6..f7831bc3e 100644
--- a/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/drop_policy.ex
@@ -12,4 +12,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.DropPolicy do
Logger.info("REJECTING #{inspect(object)}")
{:reject, object}
end
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
index 2d03df68a..3a3e72910 100644
--- a/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
+++ b/lib/pleroma/web/activity_pub/mrf/ensure_re_prepended.ex
@@ -39,4 +39,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrepended do
end
def filter(object), do: {:ok, object}
+
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index 377987cf2..9863454fa 100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
@@ -90,4 +90,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
@impl true
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{mrf_hellthread: Pleroma.Config.get([:mrf_hellthread])}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
index 4eec8b916..d6d1396bc 100644
--- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
@@ -96,4 +96,36 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
@impl true
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe do
+ # This horror is needed to convert regex sigils to strings
+ mrf_keyword =
+ Pleroma.Config.get(:mrf_keyword, [])
+ |> Enum.map(fn {key, value} ->
+ {key,
+ Enum.map(value, fn
+ {pattern, replacement} ->
+ %{
+ "pattern" =>
+ if not is_binary(pattern) do
+ inspect(pattern)
+ else
+ pattern
+ end,
+ "replacement" => replacement
+ }
+
+ pattern ->
+ if not is_binary(pattern) do
+ inspect(pattern)
+ else
+ pattern
+ end
+ end)}
+ end)
+ |> Enum.into(%{})
+
+ {:ok, %{mrf_keyword: mrf_keyword}}
+ end
end
diff --git a/lib/pleroma/web/activity_pub/mrf/mediaproxy_warming_policy.ex b/lib/pleroma/web/activity_pub/mrf/mediaproxy_warming_policy.ex
index 01d21a299..a179dd54d 100644
--- a/lib/pleroma/web/activity_pub/mrf/mediaproxy_warming_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/mediaproxy_warming_policy.ex
@@ -53,4 +53,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy do
@impl true
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
index 1842e1aeb..ce8bc4580 100644
--- a/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/mention_policy.ex
@@ -21,4 +21,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.MentionPolicy do
@impl true
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
index 86a48bda5..f67f48ab6 100644
--- a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
@@ -19,4 +19,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
@impl true
def filter(object), do: {:ok, object}
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/noop_policy.ex b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
index c47cb3298..878c57925 100644
--- a/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/noop_policy.ex
@@ -10,4 +10,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.NoOpPolicy do
def filter(object) do
{:ok, object}
end
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
index c269d0f89..daa4c88ad 100644
--- a/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
+++ b/lib/pleroma/web/activity_pub/mrf/normalize_markup.ex
@@ -21,4 +21,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.NormalizeMarkup do
end
def filter(object), do: {:ok, object}
+
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
index 457b6ee10..0ae9397ed 100644
--- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
+++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex
@@ -44,4 +44,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do
@impl true
def filter(object), do: {:ok, object}
+
+ @impl true
+ def describe, do: {:ok, %{mrf_rejectnonpublic: Pleroma.Config.get([:mrf_rejectnonpublic])}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
index f266457e3..8aa6852f0 100644
--- a/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/simple_policy.ex
@@ -177,4 +177,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
end
def filter(object), do: {:ok, object}
+
+ @impl true
+ def describe do
+ exclusions = Pleroma.Config.get([:instance, :mrf_transparency_exclusions])
+
+ mrf_simple =
+ Pleroma.Config.get(:mrf_simple)
+ |> Enum.map(fn {k, v} -> {k, Enum.reject(v, fn v -> v in exclusions end)} end)
+ |> Enum.into(%{})
+
+ {:ok, %{mrf_simple: mrf_simple}}
+ end
end
diff --git a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
index 765704389..566c1e191 100644
--- a/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
@@ -37,4 +37,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
@impl true
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
index 70edf4f7f..c1801d2ec 100644
--- a/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/tag_policy.ex
@@ -165,4 +165,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.TagPolicy do
@impl true
def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{}}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/user_allowlist_policy.ex b/lib/pleroma/web/activity_pub/mrf/user_allowlist_policy.ex
index e35d2c422..7389d6a96 100644
--- a/lib/pleroma/web/activity_pub/mrf/user_allowlist_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/user_allowlist_policy.ex
@@ -32,4 +32,13 @@ defmodule Pleroma.Web.ActivityPub.MRF.UserAllowListPolicy do
end
def filter(object), do: {:ok, object}
+
+ @impl true
+ def describe do
+ mrf_user_allowlist =
+ Config.get([:mrf_user_allowlist], [])
+ |> Enum.into(%{}, fn {k, v} -> {k, length(v)} end)
+
+ {:ok, %{mrf_user_allowlist: mrf_user_allowlist}}
+ end
end
diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex
index 1ebfcdd86..5f18cc64a 100644
--- a/lib/pleroma/web/activity_pub/relay.ex
+++ b/lib/pleroma/web/activity_pub/relay.ex
@@ -14,6 +14,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do
|> User.get_or_create_service_actor_by_ap_id()
end
+ @spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
def follow(target_instance) do
with %User{} = local_user <- get_actor(),
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance),
@@ -21,12 +22,17 @@ defmodule Pleroma.Web.ActivityPub.Relay do
Logger.info("relay: followed instance: #{target_instance}; id=#{activity.data["id"]}")
{:ok, activity}
else
+ {:error, _} = error ->
+ Logger.error("error: #{inspect(error)}")
+ error
+
e ->
Logger.error("error: #{inspect(e)}")
{:error, e}
end
end
+ @spec unfollow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
def unfollow(target_instance) do
with %User{} = local_user <- get_actor(),
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance),
@@ -34,20 +40,27 @@ defmodule Pleroma.Web.ActivityPub.Relay do
Logger.info("relay: unfollowed instance: #{target_instance}: id=#{activity.data["id"]}")
{:ok, activity}
else
+ {:error, _} = error ->
+ Logger.error("error: #{inspect(error)}")
+ error
+
e ->
Logger.error("error: #{inspect(e)}")
{:error, e}
end
end
+ @spec publish(any()) :: {:ok, Activity.t(), Object.t()} | {:error, any()}
def publish(%Activity{data: %{"type" => "Create"}} = activity) do
with %User{} = user <- get_actor(),
%Object{} = object <- Object.normalize(activity) do
ActivityPub.announce(user, object, nil, true, false)
else
- e -> Logger.error("error: #{inspect(e)}")
+ e ->
+ Logger.error("error: #{inspect(e)}")
+ {:error, inspect(e)}
end
end
- def publish(_), do: nil
+ def publish(_), do: {:error, "Not implemented"}
end
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex
index 46944dcbc..ac01d1ff3 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex
@@ -13,10 +13,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
alias Pleroma.User
alias Pleroma.Web.CommonAPI
+ @spec follow(User.t(), User.t(), map) :: {:ok, User.t()} | {:error, String.t()}
def follow(follower, followed, params \\ %{}) do
- options = cast_params(params)
- reblogs = options[:reblogs]
-
result =
if not User.following?(follower, followed) do
CommonAPI.follow(follower, followed)
@@ -24,19 +22,25 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
{:ok, follower, followed, nil}
end
- with {:ok, follower, followed, _} <- result do
- reblogs
- |> case do
- false -> CommonAPI.hide_reblogs(follower, followed)
- _ -> CommonAPI.show_reblogs(follower, followed)
- end
- |> case do
+ with {:ok, follower, _followed, _} <- result do
+ options = cast_params(params)
+
+ case reblogs_visibility(options[:reblogs], result) do
{:ok, follower} -> {:ok, follower}
_ -> {:ok, follower}
end
end
end
+ defp reblogs_visibility(false, {:ok, follower, followed, _}) do
+ CommonAPI.hide_reblogs(follower, followed)
+ end
+
+ defp reblogs_visibility(_, {:ok, follower, followed, _}) do
+ CommonAPI.show_reblogs(follower, followed)
+ end
+
+ @spec get_followers(User.t(), map()) :: list(User.t())
def get_followers(user, params \\ %{}) do
user
|> User.get_followers_query()
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 174e93468..c3c75bd9a 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -435,6 +435,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Map.put("local_only", local_only)
|> Map.put("blocking_user", user)
|> Map.put("muting_user", user)
+ |> Map.put("user", user)
|> ActivityPub.fetch_public_activities()
|> Enum.reverse()
@@ -536,8 +537,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> put_view(StatusView)
|> try_render("poll.json", %{object: object, for: user})
else
- nil -> render_error(conn, :not_found, "Record not found")
- false -> render_error(conn, :not_found, "Record not found")
+ error when is_nil(error) or error == false ->
+ render_error(conn, :not_found, "Record not found")
end
end
@@ -885,8 +886,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
- with %Activity{data: %{"object" => object}} <- Activity.get_by_id(id),
- %Object{data: %{"likes" => likes}} <- Object.normalize(object) do
+ with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+ %Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
q = from(u in User, where: u.ap_id in ^likes)
users =
@@ -902,8 +903,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
- with %Activity{data: %{"object" => object}} <- Activity.get_by_id(id),
- %Object{data: %{"announcements" => announces}} <- Object.normalize(object) do
+ with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+ %Object{data: %{"announcements" => announces}} <- Object.normalize(activity) do
q = from(u in User, where: u.ap_id in ^announces)
users =
@@ -944,6 +945,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Map.put("local_only", local_only)
|> Map.put("blocking_user", user)
|> Map.put("muting_user", user)
+ |> Map.put("user", user)
|> Map.put("tag", tags)
|> Map.put("tag_all", tag_all)
|> Map.put("tag_reject", tag_reject)
@@ -1350,6 +1352,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
params
|> Map.put("type", "Create")
|> Map.put("blocking_user", user)
+ |> Map.put("user", user)
|> Map.put("muting_user", user)
# we must filter the following list for the user to avoid leaking statuses the user
@@ -1690,45 +1693,35 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> String.replace("{{user}}", user)
with {:ok, %{status: 200, body: body}} <-
- HTTP.get(
- url,
- [],
- adapter: [
- recv_timeout: timeout,
- pool: :default
- ]
- ),
+ HTTP.get(url, [], adapter: [recv_timeout: timeout, pool: :default]),
{:ok, data} <- Jason.decode(body) do
data =
data
|> Enum.slice(0, limit)
|> Enum.map(fn x ->
- Map.put(
- x,
- "id",
- case User.get_or_fetch(x["acct"]) do
- {:ok, %User{id: id}} -> id
- _ -> 0
- end
- )
- end)
- |> Enum.map(fn x ->
- Map.put(x, "avatar", MediaProxy.url(x["avatar"]))
- end)
- |> Enum.map(fn x ->
- Map.put(x, "avatar_static", MediaProxy.url(x["avatar_static"]))
+ x
+ |> Map.put("id", fetch_suggestion_id(x))
+ |> Map.put("avatar", MediaProxy.url(x["avatar"]))
+ |> Map.put("avatar_static", MediaProxy.url(x["avatar_static"]))
end)
- conn
- |> json(data)
+ json(conn, data)
else
- e -> Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
+ e ->
+ Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
end
else
json(conn, [])
end
end
+ defp fetch_suggestion_id(attrs) do
+ case User.get_or_fetch(attrs["acct"]) do
+ {:ok, %User{id: id}} -> id
+ _ -> 0
+ end
+ end
+
def status_card(%{assigns: %{user: user}} = conn, %{"id" => status_id}) do
with %Activity{} = activity <- Activity.get_by_id(status_id),
true <- Visibility.visible_for_user?(activity, user) do
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 02819e116..492af1702 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -5,6 +5,8 @@
defmodule Pleroma.Web.MastodonAPI.StatusView do
use Pleroma.Web, :view
+ require Pleroma.Constants
+
alias Pleroma.Activity
alias Pleroma.HTML
alias Pleroma.Object
@@ -24,19 +26,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
defp get_replied_to_activities(activities) do
activities
|> Enum.map(fn
- %{data: %{"type" => "Create", "object" => object}} ->
- object = Object.normalize(object)
- object.data["inReplyTo"] != "" && object.data["inReplyTo"]
+ %{data: %{"type" => "Create"}} = activity ->
+ object = Object.normalize(activity)
+ object && object.data["inReplyTo"] != "" && object.data["inReplyTo"]
_ ->
nil
end)
|> Enum.filter(& &1)
- |> Activity.create_by_object_ap_id()
+ |> Activity.create_by_object_ap_id_with_object()
|> Repo.all()
|> Enum.reduce(%{}, fn activity, acc ->
object = Object.normalize(activity)
- Map.put(acc, object.data["id"], activity)
+ if object, do: Map.put(acc, object.data["id"], activity), else: acc
end)
end
@@ -88,6 +90,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblogged_activity =
Activity.create_by_object_ap_id(activity_object.data["id"])
|> Activity.with_preloaded_bookmark(opts[:for])
+ |> Activity.with_set_thread_muted_field(opts[:for])
|> Repo.one()
reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity))
@@ -142,6 +145,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
object = Object.normalize(activity)
user = get_user(activity.data["actor"])
+ user_follower_address = user.follower_address
like_count = object.data["like_count"] || 0
announcement_count = object.data["announcement_count"] || 0
@@ -157,7 +161,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
mentions =
(object.data["to"] ++ tag_mentions)
|> Enum.uniq()
- |> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end)
+ |> Enum.map(fn
+ Pleroma.Constants.as_public() -> nil
+ ^user_follower_address -> nil
+ ap_id -> User.get_cached_by_ap_id(ap_id)
+ end)
|> Enum.filter(& &1)
|> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end)
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index 54f89e65c..ee14cfd6b 100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
@@ -34,64 +34,18 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
def raw_nodeinfo do
stats = Stats.get_stats()
- exclusions = Config.get([:instance, :mrf_transparency_exclusions])
-
- mrf_simple =
- Config.get(:mrf_simple)
- |> Enum.map(fn {k, v} -> {k, Enum.reject(v, fn v -> v in exclusions end)} end)
- |> Enum.into(%{})
-
- # This horror is needed to convert regex sigils to strings
- mrf_keyword =
- Config.get(:mrf_keyword, [])
- |> Enum.map(fn {key, value} ->
- {key,
- Enum.map(value, fn
- {pattern, replacement} ->
- %{
- "pattern" =>
- if not is_binary(pattern) do
- inspect(pattern)
- else
- pattern
- end,
- "replacement" => replacement
- }
-
- pattern ->
- if not is_binary(pattern) do
- inspect(pattern)
- else
- pattern
- end
- end)}
- end)
- |> Enum.into(%{})
-
- mrf_policies =
- MRF.get_policies()
- |> Enum.map(fn policy -> to_string(policy) |> String.split(".") |> List.last() end)
-
quarantined = Config.get([:instance, :quarantined_instances], [])
staff_accounts =
User.all_superusers()
|> Enum.map(fn u -> u.ap_id end)
- mrf_user_allowlist =
- Config.get([:mrf_user_allowlist], [])
- |> Enum.into(%{}, fn {k, v} -> {k, length(v)} end)
-
federation_response =
if Config.get([:instance, :mrf_transparency]) do
- %{
- mrf_policies: mrf_policies,
- mrf_simple: mrf_simple,
- mrf_keyword: mrf_keyword,
- mrf_user_allowlist: mrf_user_allowlist,
- quarantined_instances: quarantined,
- exclusions: length(exclusions) > 0
- }
+ {:ok, data} = MRF.describe()
+
+ data
+ |> Map.merge(%{quarantined_instances: quarantined})
else
%{}
end
diff --git a/lib/pleroma/web/web.ex b/lib/pleroma/web/web.ex
index b42f6887e..687346554 100644
--- a/lib/pleroma/web/web.ex
+++ b/lib/pleroma/web/web.ex
@@ -58,10 +58,10 @@ defmodule Pleroma.Web do
rescue
error ->
Logger.error(
- "#{__MODULE__} failed to render #{inspect({view, template})}: #{inspect(error)}"
+ "#{__MODULE__} failed to render #{inspect({view, template})}\n" <>
+ Exception.format(:error, error, __STACKTRACE__)
)
- Logger.error(inspect(__STACKTRACE__))
nil
end
diff --git a/test/support/mrf_module_mock.ex b/test/support/mrf_module_mock.ex
new file mode 100644
index 000000000..12c7e22bc
--- /dev/null
+++ b/test/support/mrf_module_mock.ex
@@ -0,0 +1,13 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule MRFModuleMock do
+ @behaviour Pleroma.Web.ActivityPub.MRF
+
+ @impl true
+ def filter(message), do: {:ok, message}
+
+ @impl true
+ def describe, do: {:ok, %{mrf_module_mock: "some config data"}}
+end
diff --git a/test/user_test.exs b/test/user_test.exs
index 8440d456d..b363b322c 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -525,7 +525,10 @@ defmodule Pleroma.UserTest do
end
test "it restricts some sizes" do
- [bio: 5000, name: 100]
+ bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000)
+ name_limit = Pleroma.Config.get([:instance, :user_name_length], 100)
+
+ [bio: bio_limit, name: name_limit]
|> Enum.each(fn {field, size} ->
string = String.pad_leading(".", size)
cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
diff --git a/test/web/activity_pub/mrf/mrf_test.exs b/test/web/activity_pub/mrf/mrf_test.exs
index 1a888e18f..19e172939 100644
--- a/test/web/activity_pub/mrf/mrf_test.exs
+++ b/test/web/activity_pub/mrf/mrf_test.exs
@@ -57,4 +57,30 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do
refute MRF.subdomain_match?(regexes, "example.com")
end
end
+
+ describe "describe/0" do
+ test "it works as expected with noop policy" do
+ expected = %{
+ mrf_policies: ["NoOpPolicy"],
+ exclusions: false
+ }
+
+ {:ok, ^expected} = MRF.describe()
+ end
+
+ test "it works as expected with mock policy" do
+ config = Pleroma.Config.get([:instance, :rewrite_policy])
+ Pleroma.Config.put([:instance, :rewrite_policy], [MRFModuleMock])
+
+ expected = %{
+ mrf_policies: ["MRFModuleMock"],
+ mrf_module_mock: "some config data",
+ exclusions: false
+ }
+
+ {:ok, ^expected} = MRF.describe()
+
+ Pleroma.Config.put([:instance, :rewrite_policy], config)
+ end
+ end
end
diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs
index 21a63c493..e10b808f7 100644
--- a/test/web/activity_pub/relay_test.exs
+++ b/test/web/activity_pub/relay_test.exs
@@ -5,11 +5,71 @@
defmodule Pleroma.Web.ActivityPub.RelayTest do
use Pleroma.DataCase
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Relay
+ import Pleroma.Factory
+
test "gets an actor for the relay" do
user = Relay.get_actor()
+ assert user.ap_id == "#{Pleroma.Web.Endpoint.url()}/relay"
+ end
+
+ describe "follow/1" do
+ test "returns errors when user not found" do
+ assert Relay.follow("test-ap-id") == {:error, "Could not fetch by AP id"}
+ end
+
+ test "returns activity" do
+ user = insert(:user)
+ service_actor = Relay.get_actor()
+ assert {:ok, %Activity{} = activity} = Relay.follow(user.ap_id)
+ assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
+ assert user.ap_id in activity.recipients
+ assert activity.data["type"] == "Follow"
+ assert activity.data["actor"] == service_actor.ap_id
+ assert activity.data["object"] == user.ap_id
+ end
+ end
+
+ describe "unfollow/1" do
+ test "returns errors when user not found" do
+ assert Relay.unfollow("test-ap-id") == {:error, "Could not fetch by AP id"}
+ end
+
+ test "returns activity" do
+ user = insert(:user)
+ service_actor = Relay.get_actor()
+ ActivityPub.follow(service_actor, user)
+ assert {:ok, %Activity{} = activity} = Relay.unfollow(user.ap_id)
+ assert activity.actor == "#{Pleroma.Web.Endpoint.url()}/relay"
+ assert user.ap_id in activity.recipients
+ assert activity.data["type"] == "Undo"
+ assert activity.data["actor"] == service_actor.ap_id
+ assert activity.data["to"] == [user.ap_id]
+ end
+ end
+
+ describe "publish/1" do
+ test "returns error when activity not `Create` type" do
+ activity = insert(:like_activity)
+ assert Relay.publish(activity) == {:error, "Not implemented"}
+ end
+
+ test "returns error when activity not public" do
+ activity = insert(:direct_note_activity)
+ assert Relay.publish(activity) == {:error, false}
+ end
- assert user.ap_id =~ "/relay"
+ test "returns announce activity" do
+ service_actor = Relay.get_actor()
+ note = insert(:note_activity)
+ assert {:ok, %Activity{} = activity, %Object{} = obj} = Relay.publish(note)
+ assert activity.data["type"] == "Announce"
+ assert activity.data["actor"] == service_actor.ap_id
+ assert activity.data["object"] == obj.data["id"]
+ end
end
end
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index b023d1e4f..2febe8b3a 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
alias Ecto.Changeset
alias Pleroma.Activity
+ alias Pleroma.Config
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
@@ -85,11 +86,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
end
test "the public timeline when public is set to false", %{conn: conn} do
- public = Pleroma.Config.get([:instance, :public])
- Pleroma.Config.put([:instance, :public], false)
+ public = Config.get([:instance, :public])
+ Config.put([:instance, :public], false)
on_exit(fn ->
- Pleroma.Config.put([:instance, :public], public)
+ Config.put([:instance, :public], public)
end)
assert conn
@@ -250,7 +251,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
end
test "posting a status with OGP link preview", %{conn: conn} do
- Pleroma.Config.put([:rich_media, :enabled], true)
+ Config.put([:rich_media, :enabled], true)
conn =
conn
@@ -260,7 +261,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert %{"id" => id, "card" => %{"title" => "The Rock"}} = json_response(conn, 200)
assert Activity.get_by_id(id)
- Pleroma.Config.put([:rich_media, :enabled], false)
+ Config.put([:rich_media, :enabled], false)
end
test "posting a direct status", %{conn: conn} do
@@ -304,7 +305,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
test "option limit is enforced", %{conn: conn} do
user = insert(:user)
- limit = Pleroma.Config.get([:instance, :poll_limits, :max_options])
+ limit = Config.get([:instance, :poll_limits, :max_options])
conn =
conn
@@ -320,7 +321,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
test "option character limit is enforced", %{conn: conn} do
user = insert(:user)
- limit = Pleroma.Config.get([:instance, :poll_limits, :max_option_chars])
+ limit = Config.get([:instance, :poll_limits, :max_option_chars])
conn =
conn
@@ -339,7 +340,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
test "minimal date limit is enforced", %{conn: conn} do
user = insert(:user)
- limit = Pleroma.Config.get([:instance, :poll_limits, :min_expiration])
+ limit = Config.get([:instance, :poll_limits, :min_expiration])
conn =
conn
@@ -358,7 +359,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
test "maximum date limit is enforced", %{conn: conn} do
user = insert(:user)
- limit = Pleroma.Config.get([:instance, :poll_limits, :max_expiration])
+ limit = Config.get([:instance, :poll_limits, :max_expiration])
conn =
conn
@@ -1633,12 +1634,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
describe "media upload" do
setup do
- upload_config = Pleroma.Config.get([Pleroma.Upload])
- proxy_config = Pleroma.Config.get([:media_proxy])
+ upload_config = Config.get([Pleroma.Upload])
+ proxy_config = Config.get([:media_proxy])
on_exit(fn ->
- Pleroma.Config.put([Pleroma.Upload], upload_config)
- Pleroma.Config.put([:media_proxy], proxy_config)
+ Config.put([Pleroma.Upload], upload_config)
+ Config.put([:media_proxy], proxy_config)
end)
user = insert(:user)
@@ -2581,7 +2582,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
conn = get(conn, "/api/v1/instance")
assert result = json_response(conn, 200)
- email = Pleroma.Config.get([:instance, :email])
+ email = Config.get([:instance, :email])
# Note: not checking for "max_toot_chars" since it's optional
assert %{
"uri" => _,
@@ -2666,7 +2667,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
describe "pinned statuses" do
setup do
- Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
+ Config.put([:instance, :max_pinned_statuses], 1)
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
@@ -2766,10 +2767,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
describe "cards" do
setup do
- Pleroma.Config.put([:rich_media, :enabled], true)
+ Config.put([:rich_media, :enabled], true)
on_exit(fn ->
- Pleroma.Config.put([:rich_media, :enabled], false)
+ Config.put([:rich_media, :enabled], false)
end)
user = insert(:user)
@@ -2997,7 +2998,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
reporter: reporter,
target_user: target_user
} do
- max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
+ max_size = Config.get([:instance, :max_report_comment_size], 1000)
comment = String.pad_trailing("a", max_size + 1, "a")
error = %{"error" => "Comment must be up to #{max_size} characters"}
@@ -3126,15 +3127,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
conn: conn,
path: path
} do
- is_public = Pleroma.Config.get([:instance, :public])
- Pleroma.Config.put([:instance, :public], false)
+ is_public = Config.get([:instance, :public])
+ Config.put([:instance, :public], false)
conn = get(conn, path)
assert conn.status == 302
assert redirected_to(conn) == "/web/login"
- Pleroma.Config.put([:instance, :public], is_public)
+ Config.put([:instance, :public], is_public)
end
test "does not redirect logged in users to the login page", %{conn: conn, path: path} do
@@ -3876,8 +3877,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
- notify_email = Pleroma.Config.get([:instance, :notify_email])
- instance_name = Pleroma.Config.get([:instance, :name])
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
assert_email_sent(
from: {instance_name, notify_email},
@@ -3909,11 +3910,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
setup do
- setting = Pleroma.Config.get([:instance, :account_activation_required])
+ setting = Config.get([:instance, :account_activation_required])
unless setting do
- Pleroma.Config.put([:instance, :account_activation_required], true)
- on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
+ Config.put([:instance, :account_activation_required], true)
+ on_exit(fn -> Config.put([:instance, :account_activation_required], setting) end)
end
user = insert(:user)
@@ -3937,8 +3938,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|> json_response(:no_content)
email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
- notify_email = Pleroma.Config.get([:instance, :notify_email])
- instance_name = Pleroma.Config.get([:instance, :name])
+ notify_email = Config.get([:instance, :notify_email])
+ instance_name = Config.get([:instance, :name])
assert_email_sent(
from: {instance_name, notify_email},
@@ -3947,4 +3948,84 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
)
end
end
+
+ describe "GET /api/v1/suggestions" do
+ setup do
+ user = insert(:user)
+ other_user = insert(:user)
+ config = Config.get(:suggestions)
+ on_exit(fn -> Config.put(:suggestions, config) end)
+
+ host = Config.get([Pleroma.Web.Endpoint, :url, :host])
+ url500 = "http://test500?#{host}&#{user.nickname}"
+ url200 = "http://test200?#{host}&#{user.nickname}"
+
+ mock(fn
+ %{method: :get, url: ^url500} ->
+ %Tesla.Env{status: 500, body: "bad request"}
+
+ %{method: :get, url: ^url200} ->
+ %Tesla.Env{
+ status: 200,
+ body:
+ ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{
+ other_user.ap_id
+ }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}])
+ }
+ end)
+
+ [user: user, other_user: other_user]
+ end
+
+ test "returns empty result when suggestions disabled", %{conn: conn, user: user} do
+ Config.put([:suggestions, :enabled], false)
+
+ res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/suggestions")
+ |> json_response(200)
+
+ assert res == []
+ end
+
+ test "returns error", %{conn: conn, user: user} do
+ Config.put([:suggestions, :enabled], true)
+ Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
+
+ res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/suggestions")
+ |> json_response(500)
+
+ assert res == "Something went wrong"
+ end
+
+ test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
+ Config.put([:suggestions, :enabled], true)
+ Config.put([:suggestions, :third_party_engine], "http://test200?{{host}}&{{user}}")
+
+ res =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/suggestions")
+ |> json_response(200)
+
+ assert res == [
+ %{
+ "acct" => "yj455",
+ "avatar" => "https://social.heldscal.la/avatar/201.jpeg",
+ "avatar_static" => "https://social.heldscal.la/avatar/s/201.jpeg",
+ "id" => 0
+ },
+ %{
+ "acct" => other_user.ap_id,
+ "avatar" => "https://social.heldscal.la/avatar/202.jpeg",
+ "avatar_static" => "https://social.heldscal.la/avatar/s/202.jpeg",
+ "id" => other_user.id
+ }
+ ]
+ end
+ end
end
diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs
new file mode 100644
index 000000000..b4c0427c9
--- /dev/null
+++ b/test/web/mastodon_api/mastodon_api_test.exs
@@ -0,0 +1,103 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do
+ use Pleroma.Web.ConnCase
+
+ alias Pleroma.Notification
+ alias Pleroma.ScheduledActivity
+ alias Pleroma.User
+ alias Pleroma.Web.MastodonAPI.MastodonAPI
+ alias Pleroma.Web.TwitterAPI.TwitterAPI
+
+ import Pleroma.Factory
+
+ describe "follow/3" do
+ test "returns error when user deactivated" do
+ follower = insert(:user)
+ user = insert(:user, local: true, info: %{deactivated: true})
+ {:error, error} = MastodonAPI.follow(follower, user)
+ assert error == "Could not follow user: You are deactivated."
+ end
+
+ test "following for user" do
+ follower = insert(:user)
+ user = insert(:user)
+ {:ok, follower} = MastodonAPI.follow(follower, user)
+ assert User.following?(follower, user)
+ end
+
+ test "returns ok if user already followed" do
+ follower = insert(:user)
+ user = insert(:user)
+ {:ok, follower} = User.follow(follower, user)
+ {:ok, follower} = MastodonAPI.follow(follower, refresh_record(user))
+ assert User.following?(follower, user)
+ end
+ end
+
+ describe "get_followers/2" do
+ test "returns user followers" do
+ follower1_user = insert(:user)
+ follower2_user = insert(:user)
+ user = insert(:user)
+ {:ok, _follower1_user} = User.follow(follower1_user, user)
+ {:ok, follower2_user} = User.follow(follower2_user, user)
+
+ assert MastodonAPI.get_followers(user, %{"limit" => 1}) == [follower2_user]
+ end
+ end
+
+ describe "get_friends/2" do
+ test "returns user friends" do
+ user = insert(:user)
+ followed_one = insert(:user)
+ followed_two = insert(:user)
+ followed_three = insert(:user)
+
+ {:ok, user} = User.follow(user, followed_one)
+ {:ok, user} = User.follow(user, followed_two)
+ {:ok, user} = User.follow(user, followed_three)
+ res = MastodonAPI.get_friends(user)
+
+ assert length(res) == 3
+ assert Enum.member?(res, refresh_record(followed_three))
+ assert Enum.member?(res, refresh_record(followed_two))
+ assert Enum.member?(res, refresh_record(followed_one))
+ end
+ end
+
+ describe "get_notifications/2" do
+ test "returns notifications for user" do
+ user = insert(:user)
+ subscriber = insert(:user)
+
+ User.subscribe(subscriber, user)
+
+ {:ok, status} = TwitterAPI.create_status(user, %{"status" => "Akariiiin"})
+ {:ok, status1} = TwitterAPI.create_status(user, %{"status" => "Magi"})
+ {:ok, [notification]} = Notification.create_notifications(status)
+ {:ok, [notification1]} = Notification.create_notifications(status1)
+ res = MastodonAPI.get_notifications(subscriber)
+
+ assert Enum.member?(Enum.map(res, & &1.id), notification.id)
+ assert Enum.member?(Enum.map(res, & &1.id), notification1.id)
+ end
+ end
+
+ describe "get_scheduled_activities/2" do
+ test "returns user scheduled activities" do
+ user = insert(:user)
+
+ today =
+ NaiveDateTime.utc_now()
+ |> NaiveDateTime.add(:timer.minutes(6), :millisecond)
+ |> NaiveDateTime.to_iso8601()
+
+ attrs = %{params: %{}, scheduled_at: today}
+ {:ok, schedule} = ScheduledActivity.create(user, attrs)
+ assert MastodonAPI.get_scheduled_activities(user) == [schedule]
+ end
+ end
+end
diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs
index d7f848bfa..f6147c286 100644
--- a/test/web/node_info_test.exs
+++ b/test/web/node_info_test.exs
@@ -85,6 +85,9 @@ defmodule Pleroma.Web.NodeInfoTest do
end
test "it shows MRF transparency data if enabled", %{conn: conn} do
+ config = Pleroma.Config.get([:instance, :rewrite_policy])
+ Pleroma.Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])
+
option = Pleroma.Config.get([:instance, :mrf_transparency])
Pleroma.Config.put([:instance, :mrf_transparency], true)
@@ -98,11 +101,15 @@ defmodule Pleroma.Web.NodeInfoTest do
assert response["metadata"]["federation"]["mrf_simple"] == simple_config
+ Pleroma.Config.put([:instance, :rewrite_policy], config)
Pleroma.Config.put([:instance, :mrf_transparency], option)
Pleroma.Config.put(:mrf_simple, %{})
end
test "it performs exclusions from MRF transparency data if configured", %{conn: conn} do
+ config = Pleroma.Config.get([:instance, :rewrite_policy])
+ Pleroma.Config.put([:instance, :rewrite_policy], [Pleroma.Web.ActivityPub.MRF.SimplePolicy])
+
option = Pleroma.Config.get([:instance, :mrf_transparency])
Pleroma.Config.put([:instance, :mrf_transparency], true)
@@ -122,6 +129,7 @@ defmodule Pleroma.Web.NodeInfoTest do
assert response["metadata"]["federation"]["mrf_simple"] == expected_config
assert response["metadata"]["federation"]["exclusions"] == true
+ Pleroma.Config.put([:instance, :rewrite_policy], config)
Pleroma.Config.put([:instance, :mrf_transparency], option)
Pleroma.Config.put([:instance, :mrf_transparency_exclusions], exclusions)
Pleroma.Config.put(:mrf_simple, %{})