Merge remote-tracking branch 'origin/develop' into fork
This commit is contained in:
commit
d1daa9a0c8
20 changed files with 142 additions and 58 deletions
0
changelog.d/dialyzer.skip
Normal file
0
changelog.d/dialyzer.skip
Normal file
1
changelog.d/following-state.fix
Normal file
1
changelog.d/following-state.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Resolved edge case where the API can report you are following a user but the relationship is not fully established.
|
1
changelog.d/oban-uniques.change
Normal file
1
changelog.d/oban-uniques.change
Normal file
|
@ -0,0 +1 @@
|
|||
Adjust more Oban workers to enforce unique job constraints.
|
1
changelog.d/well-known.change
Normal file
1
changelog.d/well-known.change
Normal file
|
@ -0,0 +1 @@
|
|||
Accept application/activity+json for requests to .well-known/nodeinfo
|
|
@ -58,8 +58,12 @@ def refetch_object(%Object{data: %{"id" => id}} = object) do
|
|||
end
|
||||
end
|
||||
|
||||
@typep fetcher_errors ::
|
||||
:error | :reject | :allowed_depth | :fetch | :containment | :transmogrifier
|
||||
|
||||
# Note: will create a Create activity, which we need internally at the moment.
|
||||
@spec fetch_object_from_id(String.t(), list()) :: {:ok, Object.t()} | {:error | :reject, any()}
|
||||
@spec fetch_object_from_id(String.t(), list()) ::
|
||||
{:ok, Object.t()} | {fetcher_errors(), any()} | Pipeline.errors()
|
||||
def fetch_object_from_id(id, options \\ []) do
|
||||
with {_, nil} <- {:fetch_object, Object.get_cached_by_ap_id(id)},
|
||||
{_, true} <- {:allowed_depth, Federator.allowed_thread_distance?(options[:depth])},
|
||||
|
|
|
@ -93,9 +93,6 @@ def schedule_backup(backup) do
|
|||
else
|
||||
true ->
|
||||
{:error, "Backup is missing id. Please insert it into the Repo first."}
|
||||
|
||||
e ->
|
||||
{:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -122,14 +119,13 @@ def schedule_delete(backup) do
|
|||
end
|
||||
|
||||
defp permitted?(user) do
|
||||
with {_, %__MODULE__{inserted_at: inserted_at}} <- {:last, get_last(user)},
|
||||
days = Config.get([__MODULE__, :limit_days]),
|
||||
diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days),
|
||||
{_, true} <- {:diff, diff > days} do
|
||||
true
|
||||
with {_, %__MODULE__{inserted_at: inserted_at}} <- {:last, get_last(user)} do
|
||||
days = Config.get([__MODULE__, :limit_days])
|
||||
diff = Timex.diff(NaiveDateTime.utc_now(), inserted_at, :days)
|
||||
|
||||
diff > days
|
||||
else
|
||||
{:last, nil} -> true
|
||||
{:diff, false} -> false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -302,9 +298,6 @@ defp write(query, dir, name, fun) do
|
|||
)
|
||||
|
||||
acc
|
||||
|
||||
_ ->
|
||||
acc
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ defmodule Pleroma.User.Import do
|
|||
|
||||
require Logger
|
||||
|
||||
@spec perform(atom(), User.t(), list()) :: :ok | list() | {:error, any()}
|
||||
@spec perform(atom(), User.t(), String.t()) :: :ok | {:error, any()}
|
||||
def perform(:mute_import, %User{} = user, actor) do
|
||||
with {:ok, %User{} = muted_user} <- User.get_or_fetch(actor),
|
||||
{_, false} <- {:existing_mute, User.mutes_user?(user, muted_user)},
|
||||
|
@ -49,7 +49,7 @@ def perform(:follow_import, %User{} = user, actor) do
|
|||
|
||||
defp handle_error(op, user_id, error) do
|
||||
Logger.debug("#{op} failed for #{user_id} with: #{inspect(error)}")
|
||||
error
|
||||
{:error, error}
|
||||
end
|
||||
|
||||
def blocks_import(%User{} = user, [_ | _] = actors) do
|
||||
|
|
|
@ -22,22 +22,27 @@ defp mrf, do: Config.get([:pipeline, :mrf], MRF)
|
|||
defp activity_pub, do: Config.get([:pipeline, :activity_pub], ActivityPub)
|
||||
defp config, do: Config.get([:pipeline, :config], Config)
|
||||
|
||||
@spec common_pipeline(map(), keyword()) ::
|
||||
{:ok, Activity.t() | Object.t(), keyword()} | {:error | :reject, any()}
|
||||
@type results :: {:ok, Activity.t() | Object.t(), keyword()}
|
||||
@type errors :: {:error | :reject, any()}
|
||||
|
||||
# The Repo.transaction will wrap the result in an {:ok, _}
|
||||
# and only returns an {:error, _} if the error encountered was related
|
||||
# to the SQL transaction
|
||||
@spec common_pipeline(map(), keyword()) :: results() | errors()
|
||||
def common_pipeline(object, meta) do
|
||||
case Repo.transaction(fn -> do_common_pipeline(object, meta) end, Utils.query_timeout()) do
|
||||
{:ok, {:ok, activity, meta}} ->
|
||||
side_effects().handle_after_transaction(meta)
|
||||
{:ok, activity, meta}
|
||||
|
||||
{:ok, value} ->
|
||||
value
|
||||
{:ok, {:error, _} = error} ->
|
||||
error
|
||||
|
||||
{:ok, {:reject, _} = error} ->
|
||||
error
|
||||
|
||||
{:error, e} ->
|
||||
{:error, e}
|
||||
|
||||
{:reject, e} ->
|
||||
{:reject, e}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
require Pleroma.Constants
|
||||
require Logger
|
||||
|
||||
@spec block(User.t(), User.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec block(User.t(), User.t()) :: {:ok, Activity.t()} | Pipeline.errors()
|
||||
def block(blocked, blocker) do
|
||||
with {:ok, block_data, _} <- Builder.block(blocker, blocked),
|
||||
{:ok, block, _} <- Pipeline.common_pipeline(block_data, local: true) do
|
||||
|
@ -35,7 +35,7 @@ def block(blocked, blocker) do
|
|||
end
|
||||
|
||||
@spec post_chat_message(User.t(), User.t(), String.t(), list()) ::
|
||||
{:ok, Activity.t()} | {:error, any()}
|
||||
{:ok, Activity.t()} | Pipeline.errors()
|
||||
def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ []) do
|
||||
with maybe_attachment <- opts[:media_id] && Object.get_by_id(opts[:media_id]),
|
||||
:ok <- validate_chat_attachment_attribution(maybe_attachment, user),
|
||||
|
@ -58,7 +58,7 @@ def post_chat_message(%User{} = user, %User{} = recipient, content, opts \\ [])
|
|||
)} do
|
||||
{:ok, activity}
|
||||
else
|
||||
{:common_pipeline, {:reject, _} = e} -> e
|
||||
{:common_pipeline, e} -> e
|
||||
e -> e
|
||||
end
|
||||
end
|
||||
|
@ -99,7 +99,8 @@ defp validate_chat_content_length(content, _) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec unblock(User.t(), User.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec unblock(User.t(), User.t()) ::
|
||||
{:ok, Activity.t()} | {:ok, :no_activity} | Pipeline.errors() | {:error, :not_blocking}
|
||||
def unblock(blocked, blocker) do
|
||||
with {_, %Activity{} = block} <- {:fetch_block, Utils.fetch_latest_block(blocker, blocked)},
|
||||
{:ok, unblock_data, _} <- Builder.undo(blocker, block),
|
||||
|
@ -120,7 +121,9 @@ def unblock(blocked, blocker) do
|
|||
end
|
||||
|
||||
@spec follow(User.t(), User.t()) ::
|
||||
{:ok, User.t(), User.t(), Activity.t() | Object.t()} | {:error, :rejected}
|
||||
{:ok, User.t(), User.t(), Activity.t() | Object.t()}
|
||||
| {:error, :rejected}
|
||||
| Pipeline.errors()
|
||||
def follow(followed, follower) do
|
||||
timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout])
|
||||
|
||||
|
@ -145,7 +148,7 @@ def unfollow(unfollowed, follower) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec accept_follow_request(User.t(), User.t()) :: {:ok, User.t()} | {:error, any()}
|
||||
@spec accept_follow_request(User.t(), User.t()) :: {:ok, User.t()} | Pipeline.errors()
|
||||
def accept_follow_request(follower, followed) do
|
||||
with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, accept_data, _} <- Builder.accept(followed, follow_activity),
|
||||
|
@ -154,7 +157,7 @@ def accept_follow_request(follower, followed) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec reject_follow_request(User.t(), User.t()) :: {:ok, User.t()} | {:error, any()} | nil
|
||||
@spec reject_follow_request(User.t(), User.t()) :: {:ok, User.t()} | Pipeline.errors() | nil
|
||||
def reject_follow_request(follower, followed) do
|
||||
with %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed),
|
||||
{:ok, reject_data, _} <- Builder.reject(followed, follow_activity),
|
||||
|
@ -163,7 +166,8 @@ def reject_follow_request(follower, followed) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec delete(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec delete(String.t(), User.t()) ::
|
||||
{:ok, Activity.t()} | Pipeline.errors() | {:error, :not_found | String.t()}
|
||||
def delete(activity_id, user) do
|
||||
with {_, %Activity{data: %{"object" => _, "type" => "Create"}} = activity} <-
|
||||
{:find_activity, Activity.get_by_id(activity_id, filter: [])},
|
||||
|
@ -213,7 +217,7 @@ def delete(activity_id, user) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec repeat(String.t(), User.t(), map()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec repeat(String.t(), User.t(), map()) :: {:ok, Activity.t()} | {:error, :not_found}
|
||||
def repeat(id, user, params \\ %{}) do
|
||||
with %Activity{data: %{"type" => "Create"}} = activity <- Activity.get_by_id(id),
|
||||
object = %Object{} <- Object.normalize(activity, fetch: false),
|
||||
|
@ -231,7 +235,7 @@ def repeat(id, user, params \\ %{}) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec unrepeat(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec unrepeat(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, :not_found | String.t()}
|
||||
def unrepeat(id, user) do
|
||||
with {_, %Activity{data: %{"type" => "Create"}} = activity} <-
|
||||
{:find_activity, Activity.get_by_id(id)},
|
||||
|
@ -247,7 +251,8 @@ def unrepeat(id, user) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec favorite(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec favorite(String.t(), User.t()) ::
|
||||
{:ok, Activity.t()} | {:ok, :already_liked} | {:error, :not_found | String.t()}
|
||||
def favorite(id, %User{} = user) do
|
||||
case favorite_helper(user, id) do
|
||||
{:ok, _} = res ->
|
||||
|
@ -285,7 +290,8 @@ defp favorite_helper(user, id) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec unfavorite(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec unfavorite(String.t(), User.t()) ::
|
||||
{:ok, Activity.t()} | {:error, :not_found | String.t()}
|
||||
def unfavorite(id, user) do
|
||||
with {_, %Activity{data: %{"type" => "Create"}} = activity} <-
|
||||
{:find_activity, Activity.get_by_id(id)},
|
||||
|
@ -302,7 +308,7 @@ def unfavorite(id, user) do
|
|||
end
|
||||
|
||||
@spec react_with_emoji(String.t(), User.t(), String.t()) ::
|
||||
{:ok, Activity.t()} | {:error, any()}
|
||||
{:ok, Activity.t()} | {:error, String.t()}
|
||||
def react_with_emoji(id, user, emoji) do
|
||||
with %Activity{} = activity <- Activity.get_by_id(id),
|
||||
object <- Object.normalize(activity, fetch: false),
|
||||
|
@ -316,7 +322,7 @@ def react_with_emoji(id, user, emoji) do
|
|||
end
|
||||
|
||||
@spec unreact_with_emoji(String.t(), User.t(), String.t()) ::
|
||||
{:ok, Activity.t()} | {:error, any()}
|
||||
{:ok, Activity.t()} | {:error, String.t()}
|
||||
def unreact_with_emoji(id, user, emoji) do
|
||||
with %Activity{} = reaction_activity <- Utils.get_latest_reaction(id, user, emoji),
|
||||
{_, {:ok, _}} <- {:cancel_jobs, maybe_cancel_jobs(reaction_activity)},
|
||||
|
@ -329,7 +335,7 @@ def unreact_with_emoji(id, user, emoji) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec vote(Object.t(), User.t(), list()) :: {:ok, list(), Object.t()} | {:error, any()}
|
||||
@spec vote(Object.t(), User.t(), list()) :: {:ok, list(), Object.t()} | Pipeline.errors()
|
||||
def vote(%Object{data: %{"type" => "Question"}} = object, %User{} = user, choices) do
|
||||
with :ok <- validate_not_author(object, user),
|
||||
:ok <- validate_existing_votes(user, object),
|
||||
|
@ -540,7 +546,7 @@ def post(user, %{status: _} = data) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec update(Activity.t(), User.t(), map()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec update(Activity.t(), User.t(), map()) :: {:ok, Activity.t()} | {:error, nil}
|
||||
def update(orig_activity, %User{} = user, changes) do
|
||||
with orig_object <- Object.normalize(orig_activity),
|
||||
{:ok, new_object} <- make_update_data(user, orig_object, changes),
|
||||
|
@ -576,7 +582,7 @@ defp make_update_data(user, orig_object, changes) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec pin(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, term()}
|
||||
@spec pin(String.t(), User.t()) :: {:ok, Activity.t()} | Pipeline.errors()
|
||||
def pin(id, %User{} = user) do
|
||||
with %Activity{} = activity <- create_activity_by_id(id),
|
||||
true <- activity_belongs_to_actor(activity, user.ap_id),
|
||||
|
@ -616,7 +622,7 @@ defp activity_is_public(activity) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec unpin(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, term()}
|
||||
@spec unpin(String.t(), User.t()) :: {:ok, Activity.t()} | Pipeline.errors()
|
||||
def unpin(id, user) do
|
||||
with %Activity{} = activity <- create_activity_by_id(id),
|
||||
{:ok, unpin_data, _} <- Builder.unpin(user, activity.object),
|
||||
|
@ -631,7 +637,7 @@ def unpin(id, user) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec add_mute(Activity.t(), User.t(), map()) :: {:ok, Activity.t()} | {:error, any()}
|
||||
@spec add_mute(Activity.t(), User.t(), map()) :: {:ok, Activity.t()} | {:error, String.t()}
|
||||
def add_mute(activity, user, params \\ %{}) do
|
||||
expires_in = Map.get(params, :expires_in, 0)
|
||||
|
||||
|
|
|
@ -92,14 +92,13 @@ def render(
|
|||
User.get_follow_state(reading_user, target)
|
||||
end
|
||||
|
||||
followed_by =
|
||||
if following_relationships do
|
||||
case FollowingRelationship.find(following_relationships, target, reading_user) do
|
||||
%{state: :follow_accept} -> true
|
||||
_ -> false
|
||||
end
|
||||
else
|
||||
User.following?(target, reading_user)
|
||||
followed_by = FollowingRelationship.following?(target, reading_user)
|
||||
following = FollowingRelationship.following?(reading_user, target)
|
||||
|
||||
requested =
|
||||
cond do
|
||||
following -> false
|
||||
true -> match?(:follow_pending, follow_state)
|
||||
end
|
||||
|
||||
subscribing =
|
||||
|
@ -114,7 +113,7 @@ def render(
|
|||
# NOTE: adjust UserRelationship.view_relationships_option/2 on new relation-related flags
|
||||
%{
|
||||
id: to_string(target.id),
|
||||
following: follow_state == :follow_accept,
|
||||
following: following,
|
||||
followed_by: followed_by,
|
||||
blocking:
|
||||
UserRelationship.exists?(
|
||||
|
@ -150,7 +149,7 @@ def render(
|
|||
),
|
||||
subscribing: subscribing,
|
||||
notifying: subscribing,
|
||||
requested: follow_state == :follow_pending,
|
||||
requested: requested,
|
||||
domain_blocking: User.blocks_domain?(reading_user, target),
|
||||
showing_reblogs:
|
||||
not UserRelationship.exists?(
|
||||
|
|
|
@ -189,7 +189,7 @@ defmodule Pleroma.Web.Router do
|
|||
end
|
||||
|
||||
pipeline :well_known do
|
||||
plug(:accepts, ["json", "jrd", "jrd+json", "xml", "xrd+xml"])
|
||||
plug(:accepts, ["activity+json", "json", "jrd", "jrd+json", "xml", "xrd+xml"])
|
||||
end
|
||||
|
||||
pipeline :config do
|
||||
|
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
|||
alias Pleroma.User
|
||||
alias Pleroma.Web.Federator
|
||||
|
||||
use Oban.Worker, queue: :federator_incoming, max_attempts: 5
|
||||
use Oban.Worker, queue: :federator_incoming, max_attempts: 5, unique: [period: :infinity]
|
||||
|
||||
@impl true
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
defmodule Pleroma.Workers.RemoteFetcherWorker do
|
||||
alias Pleroma.Object.Fetcher
|
||||
|
||||
use Oban.Worker, queue: :background
|
||||
use Oban.Worker, queue: :background, unique: [period: :infinity]
|
||||
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "fetch_remote", "id" => id} = args}) do
|
||||
|
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Workers.RichMediaWorker do
|
|||
alias Pleroma.Web.RichMedia.Backfill
|
||||
alias Pleroma.Web.RichMedia.Card
|
||||
|
||||
use Oban.Worker, queue: :background, max_attempts: 3, unique: [period: 300]
|
||||
use Oban.Worker, queue: :background, max_attempts: 3, unique: [period: :infinity]
|
||||
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "expire", "url" => url} = _args}) do
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Workers.UserRefreshWorker do
|
||||
use Oban.Worker, queue: :background, max_attempts: 1, unique: [period: 300]
|
||||
use Oban.Worker, queue: :background, max_attempts: 1, unique: [period: :infinity]
|
||||
|
||||
alias Pleroma.User
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Workers.WebPusherWorker do
|
|||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.Push.Impl
|
||||
|
||||
use Oban.Worker, queue: :web_push
|
||||
use Oban.Worker, queue: :web_push, unique: [period: :infinity]
|
||||
|
||||
@impl true
|
||||
def perform(%Job{args: %{"op" => "web_push", "notification_id" => notification_id}}) do
|
||||
|
|
2
mix.lock
2
mix.lock
|
@ -22,7 +22,7 @@
|
|||
"cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"},
|
||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
|
||||
"cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
|
||||
"credo": {:hex, :credo, "1.7.3", "05bb11eaf2f2b8db370ecaa6a6bda2ec49b2acd5e0418bc106b73b07128c0436", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "35ea675a094c934c22fb1dca3696f3c31f2728ae6ef5a53b5d648c11180a4535"},
|
||||
"credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"},
|
||||
"crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
|
||||
"crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]},
|
||||
"csv": {:hex, :csv, "2.4.1", "50e32749953b6bf9818dbfed81cf1190e38cdf24f95891303108087486c5925e", [:mix], [{:parallel_stream, "~> 1.0.4", [hex: :parallel_stream, repo: "hexpm", optional: false]}], "hexpm", "54508938ac67e27966b10ef49606e3ad5995d665d7fc2688efb3eab1307c9079"},
|
||||
|
|
|
@ -41,6 +41,10 @@ defmodule Pleroma.HTMLTest do
|
|||
<span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
|
||||
"""
|
||||
|
||||
@mention_hashtags_sample """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
describe "StripTags scrubber" do
|
||||
test "works as expected" do
|
||||
expected = """
|
||||
|
@ -126,6 +130,15 @@ test "filters invalid microformats markup" do
|
|||
Pleroma.HTML.Scrubber.TwitterText
|
||||
)
|
||||
end
|
||||
|
||||
test "does allow mention hashtags" do
|
||||
expected = """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@mention_hashtags_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
end
|
||||
|
||||
describe "default scrubber" do
|
||||
|
@ -189,6 +202,15 @@ test "filters invalid microformats markup" do
|
|||
Pleroma.HTML.Scrubber.Default
|
||||
)
|
||||
end
|
||||
|
||||
test "does allow mention hashtags" do
|
||||
expected = """
|
||||
<a href="https://mastodon.example/tags/linux" class="mention hashtag" rel="tag">#<span>linux</span></a>
|
||||
"""
|
||||
|
||||
assert expected ==
|
||||
HTML.filter_tags(@mention_hashtags_sample, Pleroma.HTML.Scrubber.Default)
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_first_external_url_from_object" do
|
||||
|
|
|
@ -428,6 +428,45 @@ test "represent a relationship for the following and followed user" do
|
|||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "relationship does not indicate following if a FollowingRelationship is missing" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
|
||||
# Create a follow relationship with the real Follow Activity and Accept it
|
||||
assert {:ok, _, _, _} = CommonAPI.follow(other_user, user)
|
||||
assert {:ok, _} = CommonAPI.accept_follow_request(user, other_user)
|
||||
|
||||
assert %{data: %{"state" => "accept"}} =
|
||||
Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(user, other_user)
|
||||
|
||||
# Fetch the relationship and forcibly delete it to simulate
|
||||
# a Follow Accept that did not complete processing
|
||||
%{following_relationships: [relationship]} =
|
||||
Pleroma.UserRelationship.view_relationships_option(user, [other_user])
|
||||
|
||||
assert {:ok, _} = Pleroma.Repo.delete(relationship)
|
||||
|
||||
assert %{following_relationships: [], user_relationships: []} ==
|
||||
Pleroma.UserRelationship.view_relationships_option(user, [other_user])
|
||||
|
||||
expected =
|
||||
Map.merge(
|
||||
@blank_response,
|
||||
%{
|
||||
following: false,
|
||||
followed_by: false,
|
||||
muting: false,
|
||||
muting_notifications: false,
|
||||
subscribing: false,
|
||||
notifying: false,
|
||||
showing_reblogs: true,
|
||||
id: to_string(other_user.id)
|
||||
}
|
||||
)
|
||||
|
||||
test_relationship_rendering(user, other_user, expected)
|
||||
end
|
||||
|
||||
test "represent a relationship for the blocking and blocked user" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
|
|
@ -24,6 +24,19 @@ test "GET /.well-known/nodeinfo", %{conn: conn} do
|
|||
|> get(href)
|
||||
|> json_response(200)
|
||||
end)
|
||||
|
||||
accept_types = [
|
||||
"application/activity+json",
|
||||
"application/json",
|
||||
"application/jrd+json"
|
||||
]
|
||||
|
||||
for type <- accept_types do
|
||||
conn
|
||||
|> put_req_header("accept", type)
|
||||
|> get("/.well-known/nodeinfo")
|
||||
|> json_response(200)
|
||||
end
|
||||
end
|
||||
|
||||
test "nodeinfo shows staff accounts", %{conn: conn} do
|
||||
|
|
Loading…
Reference in a new issue