Merge branch 'develop' into gitlab-mr-iid-4426

This commit is contained in:
lain 2026-05-14 06:56:57 +00:00
commit c7c453ca21
34 changed files with 1574 additions and 115 deletions

View file

@ -0,0 +1 @@
Switch native captcha to the published pleroma_captcha Hex package.

View file

@ -0,0 +1 @@
Ensure Host header is present and matches instance URI

View file

@ -0,0 +1 @@
Handle reports with just actor ap id as the object

View file

@ -0,0 +1 @@
Update majic to 1.2.0.

View file

@ -0,0 +1 @@
Use the Hex package for oban_plugins_lazarus.

View file

@ -0,0 +1 @@
Reject incoming reports when both the reporter and reported account are remote

View file

@ -0,0 +1 @@
Use upstream Hex releases for the `remote_ip` dependency and expose client IP ranges for remote IP resolution.

View file

@ -0,0 +1 @@
Improve user search / autocompletion ordering.

View file

@ -738,6 +738,7 @@ config :pleroma, Pleroma.Workers.PurgeExpiredActivity, enabled: true, min_lifeti
config :pleroma, Pleroma.Web.Plugs.RemoteIp, config :pleroma, Pleroma.Web.Plugs.RemoteIp,
enabled: true, enabled: true,
headers: ["x-forwarded-for"], headers: ["x-forwarded-for"],
clients: [],
proxies: [], proxies: [],
reserved: [ reserved: [
"127.0.0.0/8", "127.0.0.0/8",

View file

@ -2910,7 +2910,7 @@ config :pleroma, :config_description, [
key: Pleroma.Web.Plugs.RemoteIp, key: Pleroma.Web.Plugs.RemoteIp,
type: :group, type: :group,
description: """ description: """
`Pleroma.Web.Plugs.RemoteIp` is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration. `Pleroma.Web.Plugs.RemoteIp` is a shim to call [`RemoteIp`](https://hex.pm/packages/remote_ip) but with runtime configuration.
**If your instance is not behind at least one reverse proxy, you should not enable this plug.** **If your instance is not behind at least one reverse proxy, you should not enable this plug.**
""", """,
children: [ children: [
@ -2926,6 +2926,12 @@ config :pleroma, :config_description, [
A list of strings naming the HTTP headers to use when deriving the true client IP. Default: `["x-forwarded-for"]`. A list of strings naming the HTTP headers to use when deriving the true client IP. Default: `["x-forwarded-for"]`.
""" """
}, },
%{
key: :clients,
type: {:list, :string},
description:
"A list of client IPs or subnets in CIDR notation. These will not be treated as proxies or reserved ranges. Defaults to `[]`. IPv4 entries without a bitmask will be assumed to be /32 and IPv6 /128."
},
%{ %{
key: :proxies, key: :proxies,
type: {:list, :string}, type: {:list, :string},

View file

@ -104,7 +104,7 @@ defmodule Pleroma.Signature do
|> put_req_header("(request-target)", request_target) |> put_req_header("(request-target)", request_target)
|> put_req_header("@request-target", request_target) |> put_req_header("@request-target", request_target)
@http_signatures_impl.validate_conn(conn) @http_signatures_impl.validate_conn(conn) == true
end end
@spec validate_signature(Plug.Conn.t()) :: boolean() @spec validate_signature(Plug.Conn.t()) :: boolean()

View file

@ -4,6 +4,7 @@
defmodule Pleroma.User.Search do defmodule Pleroma.User.Search do
alias Pleroma.EctoType.ActivityPub.ObjectValidators.Uri, as: UriType alias Pleroma.EctoType.ActivityPub.ObjectValidators.Uri, as: UriType
alias Pleroma.Instances.Instance
alias Pleroma.Pagination alias Pleroma.Pagination
alias Pleroma.User alias Pleroma.User
@ -88,12 +89,13 @@ defmodule Pleroma.User.Search do
|> filter_invisible_users() |> filter_invisible_users()
|> filter_internal_users() |> filter_internal_users()
|> filter_blocked_domains(for_user) |> filter_blocked_domains(for_user)
|> filter_unreachable_users()
|> fts_search(query_string) |> fts_search(query_string)
|> select_top_users(top_user_ids) |> select_top_users(top_user_ids)
|> trigram_rank(query_string) |> trigram_rank(query_string)
|> boost_search_rank(for_user, top_user_ids) |> boost_search_rank(for_user, top_user_ids)
|> subquery() |> subquery()
|> order_by(desc: :search_rank) |> order_by_search_rank(for_user)
|> maybe_restrict_local(for_user) |> maybe_restrict_local(for_user)
|> maybe_restrict_accepting_chat_messages(capabilities) |> maybe_restrict_accepting_chat_messages(capabilities)
|> filter_deactivated_users() |> filter_deactivated_users()
@ -196,6 +198,14 @@ defmodule Pleroma.User.Search do
defp filter_blocked_domains(query, _), do: query defp filter_blocked_domains(query, _), do: query
defp filter_unreachable_users(query) do
from(u in query,
left_join: i in Instance,
on: i.host == fragment("substring(? from '.*://([^/]*)')", u.ap_id),
where: is_nil(i.unreachable_since)
)
end
defp maybe_resolve(true, user, query) do defp maybe_resolve(true, user, query) do
case {limit(), user} do case {limit(), user} do
{:all, _} -> :noop {:all, _} -> :noop
@ -236,6 +246,16 @@ defmodule Pleroma.User.Search do
from(u in subquery(query), from(u in subquery(query),
select_merge: %{ select_merge: %{
search_type:
fragment(
"""
CASE WHEN (?) THEN 2
WHEN (?) THEN 1
ELSE 0 END
""",
u.id in ^top_user_ids,
u.id in ^friends_ids or u.id in ^followers_ids
),
search_rank: search_rank:
fragment( fragment(
""" """
@ -261,6 +281,14 @@ defmodule Pleroma.User.Search do
defp boost_search_rank(query, _for_user, top_user_ids) do defp boost_search_rank(query, _for_user, top_user_ids) do
from(u in subquery(query), from(u in subquery(query),
select_merge: %{ select_merge: %{
search_type:
fragment(
"""
CASE WHEN (?) THEN 2
ELSE 0 END
""",
u.id in ^top_user_ids
),
search_rank: search_rank:
fragment( fragment(
""" """
@ -273,4 +301,22 @@ defmodule Pleroma.User.Search do
} }
) )
end end
defp order_by_search_rank(query, %User{}) do
order_by(
query,
[u],
desc: u.search_type,
desc_nulls_last:
fragment(
"CASE WHEN ? = 1 THEN COALESCE(?, ?) ELSE NULL END",
u.search_type,
u.last_status_at,
u.last_active_at
),
desc: u.search_rank
)
end
defp order_by_search_rank(query, _), do: order_by(query, desc: :search_rank)
end end

View file

@ -303,7 +303,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end end
end end
def inbox(%{assigns: %{valid_signature: true}} = conn, %{"nickname" => nickname} = params) do def inbox(
%{
assigns: %{valid_signature: true, valid_host_header: true}
} = conn,
%{"nickname" => nickname} = params
) do
with {:recipient_exists, %User{} = recipient} <- with {:recipient_exists, %User{} = recipient} <-
{:recipient_exists, User.get_cached_by_nickname(nickname)}, {:recipient_exists, User.get_cached_by_nickname(nickname)},
{:sender_exists, {:ok, %User{} = actor}} <- {:sender_exists, {:ok, %User{} = actor}} <-
@ -342,7 +347,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end end
end end
def inbox(%{assigns: %{valid_signature: true}} = conn, params) do def inbox(%{assigns: %{valid_signature: true, valid_host_header: true}} = conn, params) do
Federator.incoming_ap_doc(params) Federator.incoming_ap_doc(params)
json(conn, "ok") json(conn, "ok")
end end

View file

@ -430,6 +430,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end) end)
end end
defp reject_third_party_report(%User{local: false}, %User{local: false} = account) do
{:reject, "[Transmogrifier] third-party report: #{account.ap_id}"}
end
defp reject_third_party_report(_, _), do: :ok
def handle_incoming(data, options \\ []) do def handle_incoming(data, options \\ []) do
data data
|> fix_recursive(&strip_internal_fields/1) |> fix_recursive(&strip_internal_fields/1)
@ -444,9 +450,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
) do ) do
with context <- data["context"] || Utils.generate_context_id(), with context <- data["context"] || Utils.generate_context_id(),
content <- data["content"] || "", content <- data["content"] || "",
objects <- List.wrap(objects),
%User{} = actor <- User.get_cached_by_ap_id(actor), %User{} = actor <- User.get_cached_by_ap_id(actor),
# Reduce the object list to find the reported user. # Reduce the object list to find the reported user.
%User{} = account <- get_reported(objects), %User{} = account <- get_reported(objects),
:ok <- reject_third_party_report(actor, account),
# Remove the reported user from the object list. # Remove the reported user from the object list.
statuses <- Enum.filter(objects, fn ap_id -> ap_id != account.ap_id end) do statuses <- Enum.filter(objects, fn ap_id -> ap_id != account.ap_id end) do
%{ %{

View file

@ -0,0 +1,63 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2026 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.EnsureHostMatchesPlug do
@moduledoc "Ensures Host header matches instance"
alias Pleroma.Web.Endpoint
import Plug.Conn
def init(options), do: options
@spec call(Plug.Conn.t(), Plug.opts()) :: Plug.Conn.t()
def call(%Plug.Conn{assigns: %{valid_signature: true}} = conn, _opts) do
# Host header is scheme-less, URI.parse needs the //
host_header = get_req_header(conn, "host")
host_uri = URI.parse("//#{host_header}")
instance_uri = URI.parse(Endpoint.url())
case host_header do
[host] ->
cond do
host == "" ->
resp(conn, 400, "Host header not provided") |> halt()
true ->
if host_matches?(host_uri, instance_uri),
do: assign(conn, :valid_host_header, true),
else: resp(conn, 400, "Host header does not match this instance") |> halt()
end
[_head | _rest] ->
conn
|> resp(400, "More than one Host header provided")
|> halt()
[] ->
conn
|> resp(400, "Host header not provided")
|> halt()
end
end
# Host header may not be provided, but signature verification failed anyway
def call(conn, _opts), do: conn
defp case_insensitive_compare(checked, authority) do
String.downcase(checked) == String.downcase(authority)
end
# Host header did not provide port
# Host header is scheme-less, URI.parse does not provide default port
defp host_matches?(%URI{host: req_host, port: nil}, %URI{host: instance_host}),
do: case_insensitive_compare(req_host, instance_host)
# Host header provided a port
# Any port specified in the Endpoint url configuration is valid here
defp host_matches?(%URI{host: req_host, port: port}, %URI{host: instance_host, port: port}),
do: case_insensitive_compare(req_host, instance_host)
defp host_matches?(_, _), do: false
end

View file

@ -4,7 +4,7 @@
defmodule Pleroma.Web.Plugs.RemoteIp do defmodule Pleroma.Web.Plugs.RemoteIp do
@moduledoc """ @moduledoc """
This is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration. This is a shim to call [`RemoteIp`](https://hex.pm/packages/remote_ip) but with runtime configuration.
""" """
alias Pleroma.Config alias Pleroma.Config
@ -17,15 +17,29 @@ defmodule Pleroma.Web.Plugs.RemoteIp do
def call(%{remote_ip: original_remote_ip} = conn, _) do def call(%{remote_ip: original_remote_ip} = conn, _) do
if Config.get([__MODULE__, :enabled]) do if Config.get([__MODULE__, :enabled]) do
%{remote_ip: new_remote_ip} = conn = RemoteIp.call(conn, remote_ip_opts()) new_remote_ip = remote_ip(conn) || original_remote_ip
conn = %{conn | remote_ip: new_remote_ip}
assign(conn, :remote_ip_found, original_remote_ip != new_remote_ip) assign(conn, :remote_ip_found, original_remote_ip != new_remote_ip)
else else
conn conn
end end
end end
defp remote_ip(conn) do
opts = remote_ip_opts()
# Do not use RemoteIp.from/2 here: upstream remote_ip always applies its
# built-in reserved ranges. Pleroma keeps :reserved configurable, so reuse
# only the header parsing and apply Pleroma's own block classification.
conn.req_headers
|> RemoteIp.Headers.take(opts[:headers])
|> RemoteIp.Headers.parse()
|> Enum.reverse()
|> Enum.find(&client?(&1, opts))
end
defp remote_ip_opts do defp remote_ip_opts do
headers = Config.get([__MODULE__, :headers], []) |> MapSet.new()
reserved = Config.get([__MODULE__, :reserved], []) reserved = Config.get([__MODULE__, :reserved], [])
proxies = proxies =
@ -33,6 +47,26 @@ defmodule Pleroma.Web.Plugs.RemoteIp do
|> Enum.concat(reserved) |> Enum.concat(reserved)
|> Enum.map(&InetHelper.parse_cidr/1) |> Enum.map(&InetHelper.parse_cidr/1)
{headers, proxies} clients =
Config.get([__MODULE__, :clients], [])
|> Enum.map(&InetHelper.parse_cidr/1)
[
headers: Config.get([__MODULE__, :headers], []),
clients: clients,
proxies: proxies
]
end
defp client?(ip, opts) do
client_ip?(ip, opts[:clients]) || !proxy_ip?(ip, opts[:proxies])
end
defp client_ip?(ip, clients) do
Enum.any?(clients, &InetCidr.contains?(&1, ip))
end
defp proxy_ip?(ip, proxies) do
Enum.any?(proxies, &InetCidr.contains?(&1, ip))
end end
end end

View file

@ -216,6 +216,7 @@ defmodule Pleroma.Web.Router do
pipeline :http_signature do pipeline :http_signature do
plug(Pleroma.Web.Plugs.HTTPSignaturePlug) plug(Pleroma.Web.Plugs.HTTPSignaturePlug)
plug(Pleroma.Web.Plugs.MappedSignatureToIdentityPlug) plug(Pleroma.Web.Plugs.MappedSignatureToIdentityPlug)
plug(Pleroma.Web.Plugs.EnsureHostMatchesPlug)
end end
pipeline :inbox_guard do pipeline :inbox_guard do

View file

@ -8,6 +8,7 @@ defmodule Pleroma.Workers.SignatureRetryWorker do
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.Federator alias Pleroma.Web.Federator
alias Pleroma.Web.Plugs.EnsureHostMatchesPlug
alias Pleroma.Web.Plugs.MappedSignatureToIdentityPlug alias Pleroma.Web.Plugs.MappedSignatureToIdentityPlug
require Logger require Logger
@ -48,6 +49,7 @@ defmodule Pleroma.Workers.SignatureRetryWorker do
{:ok, _public_key} <- Signature.refetch_public_key(conn_data), {:ok, _public_key} <- Signature.refetch_public_key(conn_data),
{:signature, true} <- {:signature, validate_signature(conn_data)}, {:signature, true} <- {:signature, validate_signature(conn_data)},
{:same_actor, true} <- {:same_actor, validate_same_actor(conn_data)}, {:same_actor, true} <- {:same_actor, validate_same_actor(conn_data)},
{:host_header, true} <- {:host_header, validate_host_header(conn_data)},
{:ok, res} <- Federator.perform(:incoming_ap_doc, params) do {:ok, res} <- Federator.perform(:incoming_ap_doc, params) do
unless Instances.reachable?(params["actor"]) do unless Instances.reachable?(params["actor"]) do
domain = URI.parse(params["actor"]).host domain = URI.parse(params["actor"]).host
@ -103,6 +105,16 @@ defmodule Pleroma.Workers.SignatureRetryWorker do
end end
end end
defp validate_host_header(conn_data) do
case EnsureHostMatchesPlug.call(conn_data, []) do
%Plug.Conn{assigns: %{valid_signature: true, valid_host_header: true}} ->
true
_ ->
false
end
end
defp validate_same_actor(conn_data) do defp validate_same_actor(conn_data) do
case MappedSignatureToIdentityPlug.call(conn_data, []) do case MappedSignatureToIdentityPlug.call(conn_data, []) do
%Plug.Conn{assigns: %{valid_signature: true}} -> %Plug.Conn{assigns: %{valid_signature: true}} ->
@ -170,6 +182,10 @@ defmodule Pleroma.Workers.SignatureRetryWorker do
{:same_actor, false} -> {:same_actor, false} ->
{:cancel, :actor_signature_mismatch} {:cancel, :actor_signature_mismatch}
# Host header from request not for us
{:host_header, false} ->
{:cancel, :host_header_mismatch}
# Origin / URL validation failed somewhere possibly due to spoofing # Origin / URL validation failed somewhere possibly due to spoofing
{:error, :origin_containment_failed} -> {:error, :origin_containment_failed} ->
{:cancel, :origin_containment_failed} {:cancel, :origin_containment_failed}
@ -234,6 +250,7 @@ defmodule Pleroma.Workers.SignatureRetryWorker do
defp log_signature_retry_rejection({:cancel, reason}, context) defp log_signature_retry_rejection({:cancel, reason}, context)
when reason in [ when reason in [
:actor_signature_mismatch, :actor_signature_mismatch,
:host_header_mismatch,
:invalid_signature, :invalid_signature,
:invalid_signature_retry_metadata, :invalid_signature_retry_metadata,
:missing_signature_retry_metadata, :missing_signature_retry_metadata,

15
mix.exs
View file

@ -136,9 +136,7 @@ defmodule Pleroma.Mixfile do
{:tzdata, "~> 1.0.5"}, {:tzdata, "~> 1.0.5"},
{:plug_cowboy, "~> 2.7"}, {:plug_cowboy, "~> 2.7"},
{:oban, "~> 2.19.4"}, {:oban, "~> 2.19.4"},
{:oban_plugins_lazarus, {:oban_plugins_lazarus, "~> 0.1.1"},
git: "https://git.pleroma.social/pleroma/elixir-libraries/oban_plugins_lazarus.git",
ref: "e49fc355baaf0e435208bf5f534d31e26e897711"},
{:oban_web, "~> 2.11"}, {:oban_web, "~> 2.11"},
{:gettext, "~> 0.24"}, {:gettext, "~> 0.24"},
{:bcrypt_elixir, "~> 2.3"}, {:bcrypt_elixir, "~> 2.3"},
@ -183,14 +181,11 @@ defmodule Pleroma.Mixfile do
{:plug_static_index_html, "~> 1.0.0"}, {:plug_static_index_html, "~> 1.0.0"},
{:flake_id, "~> 0.1.0"}, {:flake_id, "~> 0.1.0"},
{:concurrent_limiter, "~> 0.1.1"}, {:concurrent_limiter, "~> 0.1.1"},
{:remote_ip, {:remote_ip, "~> 1.2.0"},
git: "https://git.pleroma.social/pleroma/remote_ip.git", {:inet_cidr, "~> 1.0"},
ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"}, {:captcha, "~> 1.0.3", hex: :pleroma_captcha},
{:captcha,
git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
ref: "e7b7cc34cc16b383461b966484c297e4ec9aeef6"},
{:restarter, path: "./restarter"}, {:restarter, path: "./restarter"},
{:majic, "~> 1.1"}, {:majic, "~> 1.2"},
{:open_api_spex, "~> 3.22"}, {:open_api_spex, "~> 3.22"},
{:ecto_psql_extras, "~> 0.8"}, {:ecto_psql_extras, "~> 0.8"},
{:vix, "~> 0.36"}, {:vix, "~> 0.36"},

View file

@ -10,7 +10,7 @@
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"cachex": {:hex, :cachex, "3.6.0", "14a1bfbeee060dd9bec25a5b6f4e4691e3670ebda28c8ba2884b12fe30b36bf8", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "ebf24e373883bc8e0c8d894a63bbe102ae13d918f790121f5cfe6e485cc8e2e2"}, "cachex": {:hex, :cachex, "3.6.0", "14a1bfbeee060dd9bec25a5b6f4e4691e3670ebda28c8ba2884b12fe30b36bf8", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "ebf24e373883bc8e0c8d894a63bbe102ae13d918f790121f5cfe6e485cc8e2e2"},
"calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.1.201603 or ~> 0.5.20 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"}, "calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.1.201603 or ~> 0.5.20 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"},
"captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "e7b7cc34cc16b383461b966484c297e4ec9aeef6", [ref: "e7b7cc34cc16b383461b966484c297e4ec9aeef6"]}, "captcha": {:hex, :pleroma_captcha, "1.0.3", "6cc1440e91a092653fe909f028cc4c5d83ea858b1439e3b9a85e446382e2b9a3", [:make, :mix], [], "hexpm", "477f62c1a845a9458c546658223295f958f98136acef89c05beb278b1b6f4a14"},
"castore": {:hex, :castore, "1.0.15", "8aa930c890fe18b6fe0a0cff27b27d0d4d231867897bd23ea772dee561f032a3", [:mix], [], "hexpm", "96ce4c69d7d5d7a0761420ef743e2f4096253931a3ba69e5ff8ef1844fe446d3"}, "castore": {:hex, :castore, "1.0.15", "8aa930c890fe18b6fe0a0cff27b27d0d4d231867897bd23ea772dee561f032a3", [:mix], [], "hexpm", "96ce4c69d7d5d7a0761420ef743e2f4096253931a3ba69e5ff8ef1844fe446d3"},
"cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"}, "cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"},
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
@ -65,7 +65,7 @@
"http_signatures": {:hex, :http_signatures, "0.1.3", "19f26aee35b4684e37efdce3ac4638605e6e41a04368186bd39d2b6138a60ea9", [:mix], [{:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "20313a65516db88006f85b090f6f76cc5b04e9609b45943657e6781eb91174f4"}, "http_signatures": {:hex, :http_signatures, "0.1.3", "19f26aee35b4684e37efdce3ac4638605e6e41a04368186bd39d2b6138a60ea9", [:mix], [{:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "20313a65516db88006f85b090f6f76cc5b04e9609b45943657e6781eb91174f4"},
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"inet_cidr": {:hex, :inet_cidr, "1.0.8", "d26bb7bdbdf21ae401ead2092bf2bb4bf57fe44a62f5eaa5025280720ace8a40", [:mix], [], "hexpm", "d5b26da66603bb56c933c65214c72152f0de9a6ea53618b56d63302a68f6a90e"}, "inet_cidr": {:hex, :inet_cidr, "1.0.9", "e0ef72a2942529da78c8e4147d53f2ef5f6f5293335c3637b0fdf83c012cc816", [:mix], [], "hexpm", "172da15ff7cf635b1feaf14f5818be28c811b37cc5fb7c5f7c01058c1c1066cc"},
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"joken": {:hex, :joken, "2.6.2", "5daaf82259ca603af4f0b065475099ada1b2b849ff140ccd37f4b6828ca6892a", [:mix], [{:jose, "~> 1.11.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5134b5b0a6e37494e46dbf9e4dad53808e5e787904b7c73972651b51cce3d72b"}, "joken": {:hex, :joken, "2.6.2", "5daaf82259ca603af4f0b065475099ada1b2b849ff140ccd37f4b6828ca6892a", [:mix], [{:jose, "~> 1.11.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5134b5b0a6e37494e46dbf9e4dad53808e5e787904b7c73972651b51cce3d72b"},
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"}, "jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
@ -73,7 +73,7 @@
"linkify": {:hex, :linkify, "0.5.3", "5f8143d8f61f5ff08d3aeeff47ef6509492b4948d8f08007fbf66e4d2246a7f2", [:mix], [], "hexpm", "3ef35a1377d47c25506e07c1c005ea9d38d700699d92ee92825f024434258177"}, "linkify": {:hex, :linkify, "0.5.3", "5f8143d8f61f5ff08d3aeeff47ef6509492b4948d8f08007fbf66e4d2246a7f2", [:mix], [], "hexpm", "3ef35a1377d47c25506e07c1c005ea9d38d700699d92ee92825f024434258177"},
"logger_backends": {:hex, :logger_backends, "1.0.0", "09c4fad6202e08cb0fbd37f328282f16539aca380f512523ce9472b28edc6bdf", [:mix], [], "hexpm", "1faceb3e7ec3ef66a8f5746c5afd020e63996df6fd4eb8cdb789e5665ae6c9ce"}, "logger_backends": {:hex, :logger_backends, "1.0.0", "09c4fad6202e08cb0fbd37f328282f16539aca380f512523ce9472b28edc6bdf", [:mix], [], "hexpm", "1faceb3e7ec3ef66a8f5746c5afd020e63996df6fd4eb8cdb789e5665ae6c9ce"},
"mail": {:hex, :mail, "0.3.1", "cb0a14e4ed8904e4e5a08214e686ccf6f9099346885db17d8c309381f865cc5c", [:mix], [], "hexpm", "1db701e89865c1d5fa296b2b57b1cd587587cca8d8a1a22892b35ef5a8e352a6"}, "mail": {:hex, :mail, "0.3.1", "cb0a14e4ed8904e4e5a08214e686ccf6f9099346885db17d8c309381f865cc5c", [:mix], [], "hexpm", "1db701e89865c1d5fa296b2b57b1cd587587cca8d8a1a22892b35ef5a8e352a6"},
"majic": {:hex, :majic, "1.1.1", "16092a3a3376cc5e13d207e82ec06e05a5561170465e50cc11cc4df8a5747938", [:make, :mix], [{:elixir_make, "~> 0.8.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7fbb0372f0447b3f777056177d6ab3f009742e68474f850521ff56b84bd85b96"}, "majic": {:hex, :majic, "1.2.0", "414b69c1460ece692fa892a0ed6669b8db6a44c42bb3071cb723854f22e7bd78", [:make, :mix], [{:elixir_make, "~> 0.8.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0bd0c65f8e4dcc595757d957577f6151b59246da9614ba87debfdc641ccc0514"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"}, "makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"},
@ -96,7 +96,7 @@
"oban": {:hex, :oban, "2.19.4", "045adb10db1161dceb75c254782f97cdc6596e7044af456a59decb6d06da73c1", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fcc6219e6464525b808d97add17896e724131f498444a292071bf8991c99f97"}, "oban": {:hex, :oban, "2.19.4", "045adb10db1161dceb75c254782f97cdc6596e7044af456a59decb6d06da73c1", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fcc6219e6464525b808d97add17896e724131f498444a292071bf8991c99f97"},
"oban_live_dashboard": {:hex, :oban_live_dashboard, "0.1.1", "8aa4ceaf381c818f7d5c8185cc59942b8ac82ef0cf559881aacf8d3f8ac7bdd3", [:mix], [{:oban, "~> 2.15", [hex: :oban, repo: "hexpm", optional: false]}, {:phoenix_live_dashboard, "~> 0.7", [hex: :phoenix_live_dashboard, repo: "hexpm", optional: false]}], "hexpm", "16dc4ce9c9a95aa2e655e35ed4e675652994a8def61731a18af85e230e1caa63"}, "oban_live_dashboard": {:hex, :oban_live_dashboard, "0.1.1", "8aa4ceaf381c818f7d5c8185cc59942b8ac82ef0cf559881aacf8d3f8ac7bdd3", [:mix], [{:oban, "~> 2.15", [hex: :oban, repo: "hexpm", optional: false]}, {:phoenix_live_dashboard, "~> 0.7", [hex: :phoenix_live_dashboard, repo: "hexpm", optional: false]}], "hexpm", "16dc4ce9c9a95aa2e655e35ed4e675652994a8def61731a18af85e230e1caa63"},
"oban_met": {:hex, :oban_met, "1.0.5", "bb633ab06448dab2ef9194f6688d33b3d07fc3f2ad793a1a08f4dfbb2cc9fe50", [:mix], [{:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}], "hexpm", "64664d50805bbfd3903aeada1f3c39634652a87844797ee400b0bcc95a28f5ea"}, "oban_met": {:hex, :oban_met, "1.0.5", "bb633ab06448dab2ef9194f6688d33b3d07fc3f2ad793a1a08f4dfbb2cc9fe50", [:mix], [{:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}], "hexpm", "64664d50805bbfd3903aeada1f3c39634652a87844797ee400b0bcc95a28f5ea"},
"oban_plugins_lazarus": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/oban_plugins_lazarus.git", "e49fc355baaf0e435208bf5f534d31e26e897711", [ref: "e49fc355baaf0e435208bf5f534d31e26e897711"]}, "oban_plugins_lazarus": {:hex, :oban_plugins_lazarus, "0.1.1", "a5141d569e5b9f3bec8f4a958231d2c538af097d3c1ad06274f096fc06956821", [:mix], [{:oban, "< 3.0.0", [hex: :oban, repo: "hexpm", optional: false]}], "hexpm", "7e9c51bc44d33f71c0a52cf0cd5c8d4c70380ede065c1042013f5123f2fc9729"},
"oban_web": {:hex, :oban_web, "2.11.6", "53933cb4253c4d9f1098ee311c06f07935259f0e564dcf2d66bae4cc98e317fe", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}, {:oban_met, "~> 1.0", [hex: :oban_met, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "576d94b705688c313694c2c114ca21aa0f8f2ad1b9ca45c052c5ba316d3e8d10"}, "oban_web": {:hex, :oban_web, "2.11.6", "53933cb4253c4d9f1098ee311c06f07935259f0e564dcf2d66bae4cc98e317fe", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}, {:oban_met, "~> 1.0", [hex: :oban_met, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "576d94b705688c313694c2c114ca21aa0f8f2ad1b9ca45c052c5ba316d3e8d10"},
"octo_fetch": {:hex, :octo_fetch, "0.4.0", "074b5ecbc08be10b05b27e9db08bc20a3060142769436242702931c418695b19", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "cf8be6f40cd519d7000bb4e84adcf661c32e59369ca2827c4e20042eda7a7fc6"}, "octo_fetch": {:hex, :octo_fetch, "0.4.0", "074b5ecbc08be10b05b27e9db08bc20a3060142769436242702931c418695b19", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "cf8be6f40cd519d7000bb4e84adcf661c32e59369ca2827c4e20042eda7a7fc6"},
"open_api_spex": {:hex, :open_api_spex, "3.22.0", "fbf90dc82681dc042a4ee79853c8e989efbba73d9e87439085daf849bbf8bc20", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "dd751ddbdd709bb4a5313e9a24530da6e66594773c7242a0c2592cbd9f589063"}, "open_api_spex": {:hex, :open_api_spex, "3.22.0", "fbf90dc82681dc042a4ee79853c8e989efbba73d9e87439085daf849bbf8bc20", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "dd751ddbdd709bb4a5313e9a24530da6e66594773c7242a0c2592cbd9f589063"},
@ -132,7 +132,7 @@
"quic": {:hex, :quic, "0.10.2", "4b390507a85f65ce47808f3df1a864e0baf9adb7a1b4ea9f4dcd66fe9d0cb166", [:rebar3], [], "hexpm", "7c196a66973c877a59768a5687f0a0610ff11817254d0a4e45cc4e3a16b1d00b"}, "quic": {:hex, :quic, "0.10.2", "4b390507a85f65ce47808f3df1a864e0baf9adb7a1b4ea9f4dcd66fe9d0cb166", [:rebar3], [], "hexpm", "7c196a66973c877a59768a5687f0a0610ff11817254d0a4e45cc4e3a16b1d00b"},
"ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"}, "ranch": {:hex, :ranch, "2.2.0", "25528f82bc8d7c6152c57666ca99ec716510fe0925cb188172f41ce93117b1b0", [:make, :rebar3], [], "hexpm", "fa0b99a1780c80218a4197a59ea8d3bdae32fbff7e88527d7d8a4787eff4f8e7"},
"recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"}, "recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"},
"remote_ip": {:git, "https://git.pleroma.social/pleroma/remote_ip.git", "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8", [ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"]}, "remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"},
"rustler": {:hex, :rustler, "0.30.0", "cefc49922132b072853fa9b0ca4dc2ffcb452f68fb73b779042b02d545e097fb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "9ef1abb6a7dda35c47cfc649e6a5a61663af6cf842a55814a554a84607dee389"}, "rustler": {:hex, :rustler, "0.30.0", "cefc49922132b072853fa9b0ca4dc2ffcb452f68fb73b779042b02d545e097fb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "9ef1abb6a7dda35c47cfc649e6a5a61663af6cf842a55814a554a84607dee389"},
"sleeplocks": {:hex, :sleeplocks, "1.1.3", "96a86460cc33b435c7310dbd27ec82ca2c1f24ae38e34f8edde97f756503441a", [:rebar3], [], "hexpm", "d3b3958552e6eb16f463921e70ae7c767519ef8f5be46d7696cc1ed649421321"}, "sleeplocks": {:hex, :sleeplocks, "1.1.3", "96a86460cc33b435c7310dbd27ec82ca2c1f24ae38e34f8edde97f756503441a", [:rebar3], [], "hexpm", "d3b3958552e6eb16f463921e70ae7c767519ef8f5be46d7696cc1ed649421321"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-22 02:09+0300\n" "POT-Creation-Date: 2022-07-22 02:09+0300\n"
"PO-Revision-Date: 2024-10-13 21:03+0000\n" "PO-Revision-Date: 2025-12-27 07:08+0000\n"
"Last-Translator: Codimp <contact@lithio.fr>\n" "Last-Translator: Codimp <contact@lithio.fr>\n"
"Language-Team: French <https://translate.pleroma.social/projects/pleroma/" "Language-Team: French <https://translate.pleroma.social/projects/pleroma/"
"pleroma-backend-domain-config_descriptions/fr/>\n" "pleroma-backend-domain-config_descriptions/fr/>\n"
@ -280,7 +280,7 @@ msgstr ""
"Rejeter, Enlever de TWKN ou marquer comme contenu sensible les messages avec " "Rejeter, Enlever de TWKN ou marquer comme contenu sensible les messages avec "
"des mots-croisillons (sans mettre le # du début)\n" "des mots-croisillons (sans mettre le # du début)\n"
"\n" "\n"
"Note: cette politique MRF est toujours activée. Si vous voulez la " "Note : cette politique MRF est toujours activée. Si vous voulez la "
"désactiver, vous devez configurer des listes vides.\n" "désactiver, vous devez configurer des listes vides.\n"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
@ -402,7 +402,7 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-:shout" msgctxt "config description at :pleroma-:shout"
msgid "Pleroma shout settings" msgid "Pleroma shout settings"
msgstr "" msgstr "Paramètre de Pleroma shout"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -416,7 +416,7 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-:streamer" msgctxt "config description at :pleroma-:streamer"
msgid "Settings for notifications streamer" msgid "Settings for notifications streamer"
msgstr "" msgstr "Paramètres des streamers de notifications"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -429,12 +429,14 @@ msgstr "Paramètres liés au schémas d'URI"
msgctxt "config description at :pleroma-:web_cache_ttl" msgctxt "config description at :pleroma-:web_cache_ttl"
msgid "The expiration time for the web responses cache. Values should be in milliseconds or `nil` to disable expiration." msgid "The expiration time for the web responses cache. Values should be in milliseconds or `nil` to disable expiration."
msgstr "" msgstr ""
"Temps d'expiration pour le cache des réponses web. Les valeurs doivent être "
"en millisecondes ou `nil`pour désactiver l'expiration."
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-:welcome" msgctxt "config description at :pleroma-:welcome"
msgid "Welcome messages settings" msgid "Welcome messages settings"
msgstr "" msgstr "Paramètres de messages de bienvenue"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -458,133 +460,146 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Captcha" msgctxt "config description at :pleroma-Pleroma.Captcha"
msgid "Captcha-related settings" msgid "Captcha-related settings"
msgstr "" msgstr "Paramètres liés au Captcha"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Captcha.Kocaptcha" msgctxt "config description at :pleroma-Pleroma.Captcha.Kocaptcha"
msgid "Kocaptcha is a very simple captcha service with a single API endpoint, the source code is here: https://github.com/koto-bank/kocaptcha. The default endpoint (https://captcha.kotobank.ch) is hosted by the developer." msgid "Kocaptcha is a very simple captcha service with a single API endpoint, the source code is here: https://github.com/koto-bank/kocaptcha. The default endpoint (https://captcha.kotobank.ch) is hosted by the developer."
msgstr "" msgstr ""
"Kocaptcha est un service de captcha très simple avec une API n'utilisant "
"qu'une seule ressource, le code source est ici : https://github.com/"
"koto-bank/kocaptcha. La ressource par défaut (https://captcha.kotobank.ch) "
"est hébergée par son développeur."
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Emails.Mailer" msgctxt "config description at :pleroma-Pleroma.Emails.Mailer"
msgid "Mailer-related settings" msgid "Mailer-related settings"
msgstr "" msgstr "Paramètres liés à l'envoyeur d'email"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Emails.NewUsersDigestEmail" msgctxt "config description at :pleroma-Pleroma.Emails.NewUsersDigestEmail"
msgid "New users admin email digest" msgid "New users admin email digest"
msgstr "" msgstr "Email à l'administrateur de résumé des nouveaux utilisateurs"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Emails.UserEmail" msgctxt "config description at :pleroma-Pleroma.Emails.UserEmail"
msgid "Email template settings" msgid "Email template settings"
msgstr "" msgstr "Paramètres de template d'email"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Formatter" msgctxt "config description at :pleroma-Pleroma.Formatter"
msgid "Configuration for Pleroma's link formatter which parses mentions, hashtags, and URLs." msgid "Configuration for Pleroma's link formatter which parses mentions, hashtags, and URLs."
msgstr "" msgstr ""
"Configuration du formateur de lien Pleroma qui interprète les mentions, "
"hashtags et URLs."
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.ScheduledActivity" msgctxt "config description at :pleroma-Pleroma.ScheduledActivity"
msgid "Scheduled activities settings" msgid "Scheduled activities settings"
msgstr "" msgstr "Paramètres des activités planifiées"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Upload" msgctxt "config description at :pleroma-Pleroma.Upload"
msgid "Upload general settings" msgid "Upload general settings"
msgstr "" msgstr "Paramètres généraux d'upload"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Upload.Filter.AnonymizeFilename" msgctxt "config description at :pleroma-Pleroma.Upload.Filter.AnonymizeFilename"
msgid "Filter replaces the filename of the upload" msgid "Filter replaces the filename of the upload"
msgstr "" msgstr "Filtre de remplacement du nom de fichier de l'upload"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Upload.Filter.Mogrify" msgctxt "config description at :pleroma-Pleroma.Upload.Filter.Mogrify"
msgid "Uploads mogrify filter settings" msgid "Uploads mogrify filter settings"
msgstr "" msgstr "Paramètres de filtre mogrify pour les uploads"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Uploaders.Local" msgctxt "config description at :pleroma-Pleroma.Uploaders.Local"
msgid "Local uploader-related settings" msgid "Local uploader-related settings"
msgstr "" msgstr "Paramètres liés aux uploads locaux"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Uploaders.S3" msgctxt "config description at :pleroma-Pleroma.Uploaders.S3"
msgid "S3 uploader-related settings" msgid "S3 uploader-related settings"
msgstr "" msgstr "Paramètres liés à l'uploader S3"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.User.Backup" msgctxt "config description at :pleroma-Pleroma.User.Backup"
msgid "Account Backup" msgid "Account Backup"
msgstr "" msgstr "Sauvegarde de Comptes"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Web.MediaProxy.Invalidation.Http" msgctxt "config description at :pleroma-Pleroma.Web.MediaProxy.Invalidation.Http"
msgid "HTTP invalidate settings" msgid "HTTP invalidate settings"
msgstr "" msgstr "Paramètres d'invalidation HTTP"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Web.MediaProxy.Invalidation.Script" msgctxt "config description at :pleroma-Pleroma.Web.MediaProxy.Invalidation.Script"
msgid "Invalidation script settings" msgid "Invalidation script settings"
msgstr "" msgstr "Paramètres du script d'invalidation"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Web.Metadata" msgctxt "config description at :pleroma-Pleroma.Web.Metadata"
msgid "Metadata-related settings" msgid "Metadata-related settings"
msgstr "" msgstr "Paramètres liés aux métadonnées"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Web.Plugs.RemoteIp" msgctxt "config description at :pleroma-Pleroma.Web.Plugs.RemoteIp"
msgid "`Pleroma.Web.Plugs.RemoteIp` is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration.\n**If your instance is not behind at least one reverse proxy, you should not enable this plug.**\n" msgid "`Pleroma.Web.Plugs.RemoteIp` is a shim to call [`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) but with runtime configuration.\n**If your instance is not behind at least one reverse proxy, you should not enable this plug.**\n"
msgstr "" msgstr ""
"`Pleroma.Web.Plugs.RemoteIp` est un shim pour invoquer "
"[`RemoteIp`](https://git.pleroma.social/pleroma/remote_ip) mais avec une "
"configuration au runtime.\n"
"**Si votre instance n'est pas derrière au moins un proxy inverse, vous ne "
"devriez pas activer ce plug.**\n"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Web.Preload" msgctxt "config description at :pleroma-Pleroma.Web.Preload"
msgid "Preload-related settings" msgid "Preload-related settings"
msgstr "" msgstr "Paramètres liés au préchargement"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :pleroma-Pleroma.Workers.PurgeExpiredActivity" msgctxt "config description at :pleroma-Pleroma.Workers.PurgeExpiredActivity"
msgid "Expired activities settings" msgid "Expired activities settings"
msgstr "" msgstr "Paramètres des activités expirées"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :prometheus-Pleroma.Web.Endpoint.MetricsExporter" msgctxt "config description at :prometheus-Pleroma.Web.Endpoint.MetricsExporter"
msgid "Prometheus app metrics endpoint configuration" msgid "Prometheus app metrics endpoint configuration"
msgstr "" msgstr "Configuration des endpoints de métriques Prometheus"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config description at :web_push_encryption-:vapid_details" msgctxt "config description at :web_push_encryption-:vapid_details"
msgid "Web Push Notifications configuration. You can use the mix task mix web_push.gen.keypair to generate it." msgid "Web Push Notifications configuration. You can use the mix task mix web_push.gen.keypair to generate it."
msgstr "" msgstr ""
"Configuration des notifications Web Push. Vous pouvez utiliser la tâche mix "
"web_push.gen.keypair pour le générer."
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :ex_aws-:s3" msgctxt "config label at :ex_aws-:s3"
msgid "S3" msgid "S3"
msgstr "" msgstr "S3"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -596,13 +611,13 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :logger-:ex_syslogger" msgctxt "config label at :logger-:ex_syslogger"
msgid "ExSyslogger" msgid "ExSyslogger"
msgstr "" msgstr "ExSyslogger"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:activitypub" msgctxt "config label at :pleroma-:activitypub"
msgid "ActivityPub" msgid "ActivityPub"
msgstr "" msgstr "ActivityPub"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -620,151 +635,151 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:connections_pool" msgctxt "config label at :pleroma-:connections_pool"
msgid "Connections pool" msgid "Connections pool"
msgstr "" msgstr "Pool de connexions"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:email_notifications" msgctxt "config label at :pleroma-:email_notifications"
msgid "Email notifications" msgid "Email notifications"
msgstr "" msgstr "Notifications email"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:emoji" msgctxt "config label at :pleroma-:emoji"
msgid "Emoji" msgid "Emoji"
msgstr "" msgstr "Emoji"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:features" msgctxt "config label at :pleroma-:features"
msgid "Features" msgid "Features"
msgstr "" msgstr "Fonctionnalités"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:feed" msgctxt "config label at :pleroma-:feed"
msgid "Feed" msgid "Feed"
msgstr "" msgstr "Flux"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:frontend_configurations" msgctxt "config label at :pleroma-:frontend_configurations"
msgid "Frontend configurations" msgid "Frontend configurations"
msgstr "" msgstr "Configurations des frontends"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:frontends" msgctxt "config label at :pleroma-:frontends"
msgid "Frontends" msgid "Frontends"
msgstr "" msgstr "Frontends"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:gopher" msgctxt "config label at :pleroma-:gopher"
msgid "Gopher" msgid "Gopher"
msgstr "" msgstr "Gopher"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:hackney_pools" msgctxt "config label at :pleroma-:hackney_pools"
msgid "Hackney pools" msgid "Hackney pools"
msgstr "" msgstr "Bacs (pools) d'Hackney"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:http" msgctxt "config label at :pleroma-:http"
msgid "HTTP" msgid "HTTP"
msgstr "" msgstr "HTTP"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:http_security" msgctxt "config label at :pleroma-:http_security"
msgid "HTTP security" msgid "HTTP security"
msgstr "" msgstr "Sécurité HTTP"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:instance" msgctxt "config label at :pleroma-:instance"
msgid "Instance" msgid "Instance"
msgstr "" msgstr "Instance"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:instances_favicons" msgctxt "config label at :pleroma-:instances_favicons"
msgid "Instances favicons" msgid "Instances favicons"
msgstr "" msgstr "Favicons des instances"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:ldap" msgctxt "config label at :pleroma-:ldap"
msgid "LDAP" msgid "LDAP"
msgstr "" msgstr "LDAP"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:majic_pool" msgctxt "config label at :pleroma-:majic_pool"
msgid "Majic pool" msgid "Majic pool"
msgstr "" msgstr "Bac (pool) de Majic"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:manifest" msgctxt "config label at :pleroma-:manifest"
msgid "Manifest" msgid "Manifest"
msgstr "" msgstr "Manifeste"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:markup" msgctxt "config label at :pleroma-:markup"
msgid "Markup Settings" msgid "Markup Settings"
msgstr "" msgstr "Paramètres des Balises"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:media_preview_proxy" msgctxt "config label at :pleroma-:media_preview_proxy"
msgid "Media preview proxy" msgid "Media preview proxy"
msgstr "" msgstr "Proxy de prévisualisation média"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:media_proxy" msgctxt "config label at :pleroma-:media_proxy"
msgid "Media proxy" msgid "Media proxy"
msgstr "" msgstr "Proxy média"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:modules" msgctxt "config label at :pleroma-:modules"
msgid "Modules" msgid "Modules"
msgstr "" msgstr "Modules"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:mrf" msgctxt "config label at :pleroma-:mrf"
msgid "MRF" msgid "MRF"
msgstr "" msgstr "MRF"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:mrf_activity_expiration" msgctxt "config label at :pleroma-:mrf_activity_expiration"
msgid "MRF Activity Expiration Policy" msgid "MRF Activity Expiration Policy"
msgstr "" msgstr "Politique MRF d'Expiration des Activités"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:mrf_follow_bot" msgctxt "config label at :pleroma-:mrf_follow_bot"
msgid "MRF FollowBot Policy" msgid "MRF FollowBot Policy"
msgstr "" msgstr "Politique MRF FollowBot"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:mrf_hashtag" msgctxt "config label at :pleroma-:mrf_hashtag"
msgid "MRF Hashtag" msgid "MRF Hashtag"
msgstr "" msgstr "Politique MRF hashtag"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgctxt "config label at :pleroma-:mrf_hellthread" msgctxt "config label at :pleroma-:mrf_hellthread"
msgid "MRF Hellthread" msgid "MRF Hellthread"
msgstr "" msgstr "MRF Hellthread"
#: lib/pleroma/docs/translator.ex:5 #: lib/pleroma/docs/translator.ex:5
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format

View file

@ -8,16 +8,15 @@
## to merge POT files into PO files. ## to merge POT files into PO files.
msgid "" msgid ""
msgstr "" msgstr ""
"PO-Revision-Date: 2020-05-12 15:52+0000\n" "PO-Revision-Date: 2025-12-27 07:08+0000\n"
"Last-Translator: Haelwenn (lanodan) Monnier " "Last-Translator: Codimp <contact@lithio.fr>\n"
"<contact+translate.pleroma.social@hacktivis.me>\n"
"Language-Team: French <https://translate.pleroma.social/projects/pleroma/" "Language-Team: French <https://translate.pleroma.social/projects/pleroma/"
"pleroma/fr/>\n" "pleroma-backend-domain-errors/fr/>\n"
"Language: fr\n" "Language: fr\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.0.4\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.13.1\n"
msgid "can't be blank" msgid "can't be blank"
msgstr "ne peut être vide" msgstr "ne peut être vide"
@ -357,7 +356,7 @@ msgstr "Ne peut poster dans la boite d'émission de %{nickname} en tant que %{as
#: lib/pleroma/web/common_api/common_api.ex:335 #: lib/pleroma/web/common_api/common_api.ex:335
#, elixir-format #, elixir-format
msgid "conversation is already muted" msgid "conversation is already muted"
msgstr "la conversation est déjà baillonée" msgstr "la conversation est déjà silenciée"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:192 #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:192
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:317 #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:317
@ -421,7 +420,7 @@ msgstr "Erreur interne"
#: lib/pleroma/web/oauth/fallback_controller.ex:29 #: lib/pleroma/web/oauth/fallback_controller.ex:29
#, elixir-format #, elixir-format
msgid "Invalid Username/Password" msgid "Invalid Username/Password"
msgstr "Nom d'utilisateur/mot de passe invalide" msgstr "Nom d'utilisateur·ice/mot de passe invalide"
#: lib/pleroma/captcha/captcha.ex:107 #: lib/pleroma/captcha/captcha.ex:107
#, elixir-format #, elixir-format

View file

@ -3,16 +3,16 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-08-15 15:40+0000\n" "POT-Creation-Date: 2021-08-15 15:40+0000\n"
"PO-Revision-Date: 2021-09-03 06:45+0000\n" "PO-Revision-Date: 2025-07-31 05:58+0000\n"
"Last-Translator: @liimee <alt3753.7@gmail.com>\n" "Last-Translator: Neko Nekowazarashi <kodra@nekoweb.my.id>\n"
"Language-Team: Indonesian <https://translate.pleroma.social/projects/pleroma/" "Language-Team: Indonesian <https://translate.pleroma.social/projects/pleroma/"
"pleroma/id/>\n" "pleroma-backend-domain-errors/id/>\n"
"Language: id\n" "Language: id\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 4.6.2\n" "X-Generator: Weblate 4.13.1\n"
## This file is a PO Template file. ## This file is a PO Template file.
## ##
@ -41,7 +41,7 @@ msgstr "memiliki format yang tidak valid"
## From Ecto.Changeset.validate_subset/3 ## From Ecto.Changeset.validate_subset/3
msgid "has an invalid entry" msgid "has an invalid entry"
msgstr "" msgstr "ada yang tidak valid"
## From Ecto.Changeset.validate_exclusion/3 ## From Ecto.Changeset.validate_exclusion/3
msgid "is reserved" msgid "is reserved"
@ -49,7 +49,7 @@ msgstr ""
## From Ecto.Changeset.validate_confirmation/3 ## From Ecto.Changeset.validate_confirmation/3
msgid "does not match confirmation" msgid "does not match confirmation"
msgstr "" msgstr "tidak sama dengan konfirmasi"
## From Ecto.Changeset.no_assoc_constraint/3 ## From Ecto.Changeset.no_assoc_constraint/3
msgid "is still associated with this entry" msgid "is still associated with this entry"
@ -61,19 +61,19 @@ msgstr ""
## From Ecto.Changeset.validate_length/3 ## From Ecto.Changeset.validate_length/3
msgid "should be %{count} character(s)" msgid "should be %{count} character(s)"
msgid_plural "should be %{count} character(s)" msgid_plural "should be %{count} character(s)"
msgstr[0] "harus memiliki %{count} karakter" msgstr[0] "harus ada %{count} karakter"
msgid "should have %{count} item(s)" msgid "should have %{count} item(s)"
msgid_plural "should have %{count} item(s)" msgid_plural "should have %{count} item(s)"
msgstr[0] "harus memiliki %{count} item" msgstr[0] "harus ada %{count} item"
msgid "should be at least %{count} character(s)" msgid "should be at least %{count} character(s)"
msgid_plural "should be at least %{count} character(s)" msgid_plural "should be at least %{count} character(s)"
msgstr[0] "harus memiliki sekurang-kurangnya %{count} karakter" msgstr[0] "harus ada sekurang-kurangnya %{count} karakter"
msgid "should have at least %{count} item(s)" msgid "should have at least %{count} item(s)"
msgid_plural "should have at least %{count} item(s)" msgid_plural "should have at least %{count} item(s)"
msgstr[0] "harus memiliki sekurang-kurangnya %{count} item" msgstr[0] "harus ada sekurang-kurangnya %{count} item"
msgid "should be at most %{count} character(s)" msgid "should be at most %{count} character(s)"
msgid_plural "should be at most %{count} character(s)" msgid_plural "should be at most %{count} character(s)"
@ -112,7 +112,7 @@ msgstr "Sudah memilih"
#: lib/pleroma/web/oauth/oauth_controller.ex:359 #: lib/pleroma/web/oauth/oauth_controller.ex:359
#, elixir-format #, elixir-format
msgid "Bad request" msgid "Bad request"
msgstr "Permintaan buruk (bad request)" msgstr "Permintaan buruk"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426 #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426
#, elixir-format #, elixir-format
@ -133,7 +133,7 @@ msgstr "Tidak dapat mencari pengguna"
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61 #: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61
#, elixir-format #, elixir-format
msgid "Can't get favorites" msgid "Can't get favorites"
msgstr "Tidak dapat mendapatkan favorit" msgstr "Tidak dapat mengambil favorit"
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438 #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438
#, elixir-format #, elixir-format
@ -143,7 +143,7 @@ msgstr "Tidak dapat menyukai objek"
#: lib/pleroma/web/common_api/utils.ex:563 #: lib/pleroma/web/common_api/utils.ex:563
#, elixir-format #, elixir-format
msgid "Cannot post an empty status without attachments" msgid "Cannot post an empty status without attachments"
msgstr "Tidak dapat memposting status kosong tanpa lampiran" msgstr "Tidak dapat mempos status kosong tanpa lampiran"
#: lib/pleroma/web/common_api/utils.ex:511 #: lib/pleroma/web/common_api/utils.ex:511
#, elixir-format #, elixir-format
@ -206,7 +206,7 @@ msgstr "CAPTCHA tidak valid"
#: lib/pleroma/web/oauth/oauth_controller.ex:568 #: lib/pleroma/web/oauth/oauth_controller.ex:568
#, elixir-format #, elixir-format
msgid "Invalid credentials" msgid "Invalid credentials"
msgstr "Kredensian tidak valid" msgstr "Kredensial tidak valid"
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38 #: lib/pleroma/plugs/ensure_authenticated_plug.ex:38
#, elixir-format #, elixir-format
@ -279,12 +279,12 @@ msgstr ""
#: lib/pleroma/web/ostatus/ostatus_controller.ex:149 #: lib/pleroma/web/ostatus/ostatus_controller.ex:149
#, elixir-format #, elixir-format
msgid "Something went wrong" msgid "Something went wrong"
msgstr "Sesuatu yang salah terjadi" msgstr "Ada sesuatu yang salah"
#: lib/pleroma/web/common_api/activity_draft.ex:107 #: lib/pleroma/web/common_api/activity_draft.ex:107
#, elixir-format #, elixir-format
msgid "The message visibility must be direct" msgid "The message visibility must be direct"
msgstr "Visibilitas pesan harus langsung" msgstr "Ketampakan pesan harus langsung"
#: lib/pleroma/web/common_api/utils.ex:573 #: lib/pleroma/web/common_api/utils.ex:573
#, elixir-format #, elixir-format
@ -294,7 +294,7 @@ msgstr "Status lebih dari batas karakter"
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31 #: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31
#, elixir-format #, elixir-format
msgid "This resource requires authentication." msgid "This resource requires authentication."
msgstr "" msgstr "Autentikasi diperlukan untuk hal ini."
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206 #: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206
#, elixir-format #, elixir-format
@ -314,7 +314,7 @@ msgstr ""
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485 #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485
#, elixir-format #, elixir-format
msgid "You can't revoke your own admin status." msgid "You can't revoke your own admin status."
msgstr "" msgstr "Anda tidak dapat mencabut status admin Anda."
#: lib/pleroma/web/oauth/oauth_controller.ex:221 #: lib/pleroma/web/oauth/oauth_controller.ex:221
#: lib/pleroma/web/oauth/oauth_controller.ex:308 #: lib/pleroma/web/oauth/oauth_controller.ex:308
@ -382,7 +382,7 @@ msgstr "Gagal"
#: lib/pleroma/web/oauth/oauth_controller.ex:410 #: lib/pleroma/web/oauth/oauth_controller.ex:410
#, elixir-format #, elixir-format
msgid "Failed to authenticate: %{message}." msgid "Failed to authenticate: %{message}."
msgstr "Gagal mengotentikasi: %{message}." msgstr "Gagal mengautentikasi: %{message}."
#: lib/pleroma/web/oauth/oauth_controller.ex:441 #: lib/pleroma/web/oauth/oauth_controller.ex:441
#, elixir-format #, elixir-format
@ -392,7 +392,7 @@ msgstr "Gagal menyiapkan akun pengguna."
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38 #: lib/pleroma/plugs/oauth_scopes_plug.ex:38
#, elixir-format #, elixir-format
msgid "Insufficient permissions: %{permissions}." msgid "Insufficient permissions: %{permissions}."
msgstr "" msgstr "Izin tidak cukup: %{permissions}."
#: lib/pleroma/plugs/uploaded_media.ex:104 #: lib/pleroma/plugs/uploaded_media.ex:104
#, elixir-format #, elixir-format
@ -418,12 +418,12 @@ msgstr ""
#: lib/pleroma/web/oauth/oauth_controller.ex:172 #: lib/pleroma/web/oauth/oauth_controller.ex:172
#, elixir-format #, elixir-format
msgid "This action is outside the authorized scopes" msgid "This action is outside the authorized scopes"
msgstr "" msgstr "Tindakan ini diluar jangkauan yang terotorisasi"
#: lib/pleroma/web/oauth/fallback_controller.ex:14 #: lib/pleroma/web/oauth/fallback_controller.ex:14
#, elixir-format #, elixir-format
msgid "Unknown error, please check the details and try again." msgid "Unknown error, please check the details and try again."
msgstr "Kesalahan tidak dikenal, harap periksa keterangannya dan coba lagi." msgstr "Kesalahan tidak dikenal, harap periksa detailnya dan coba lagi."
#: lib/pleroma/web/oauth/oauth_controller.ex:119 #: lib/pleroma/web/oauth/oauth_controller.ex:119
#: lib/pleroma/web/oauth/oauth_controller.ex:158 #: lib/pleroma/web/oauth/oauth_controller.ex:158
@ -444,7 +444,7 @@ msgstr ""
#: lib/pleroma/web/uploader_controller.ex:23 #: lib/pleroma/web/uploader_controller.ex:23
#, elixir-format #, elixir-format
msgid "bad request" msgid "bad request"
msgstr "permintaan buruk (bad request)" msgstr "permintaan buruk"
#: lib/pleroma/web/twitter_api/twitter_api.ex:103 #: lib/pleroma/web/twitter_api/twitter_api.ex:103
#, elixir-format #, elixir-format
@ -469,7 +469,7 @@ msgstr "CAPTCHA Tidak Valid (Parameter kurang: %{name})"
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92 #: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92
#, elixir-format #, elixir-format
msgid "List not found" msgid "List not found"
msgstr "" msgstr "Daftar tidak ditemukan"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123 #: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123
#, elixir-format #, elixir-format
@ -480,7 +480,7 @@ msgstr "Parameter kurang: %{name}"
#: lib/pleroma/web/oauth/oauth_controller.ex:321 #: lib/pleroma/web/oauth/oauth_controller.ex:321
#, elixir-format #, elixir-format
msgid "Password reset is required" msgid "Password reset is required"
msgstr "" msgstr "Diperlukan atur ulang kata sandi"
#: lib/pleroma/tests/auth_test_controller.ex:9 #: lib/pleroma/tests/auth_test_controller.ex:9
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6 #: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6
@ -522,7 +522,7 @@ msgstr ""
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28 #: lib/pleroma/plugs/ensure_authenticated_plug.ex:28
#, elixir-format #, elixir-format
msgid "Two-factor authentication enabled, you must use a access token." msgid "Two-factor authentication enabled, you must use a access token."
msgstr "Otentikasi dua-faktor diaktifkan, Anda harus menggunakan token akses." msgstr "Autentikasi dua langkah diaktifkan, Anda harus menggunakan token akses."
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210 #: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210
#, elixir-format #, elixir-format
@ -552,7 +552,7 @@ msgstr ""
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61 #: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
#, elixir-format #, elixir-format
msgid "Web push subscription is disabled on this Pleroma instance" msgid "Web push subscription is disabled on this Pleroma instance"
msgstr "" msgstr "Langganan push web dinonaktifkan untuk peladen Pleroma ini"
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451 #: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451
#, elixir-format #, elixir-format
@ -562,7 +562,7 @@ msgstr "Anda tidak bisa mencabut status admin/moderator Anda sendiri."
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126 #: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126
#, elixir-format #, elixir-format
msgid "authorization required for timeline view" msgid "authorization required for timeline view"
msgstr "" msgstr "Otorisasi diperlukan untuk tampilan linimasa"
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24 #: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24
#, elixir-format #, elixir-format
@ -572,7 +572,7 @@ msgstr "Akses ditolak"
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282 #: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282
#, elixir-format #, elixir-format
msgid "This API requires an authenticated user" msgid "This API requires an authenticated user"
msgstr "" msgstr "API ini memerlukan pengguna terautentikasi"
#: lib/pleroma/plugs/user_is_admin_plug.ex:21 #: lib/pleroma/plugs/user_is_admin_plug.ex:21
#, elixir-format #, elixir-format

View file

@ -0,0 +1,163 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-08-11 18:40+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Translate Toolkit 3.7.2\n"
## This file is a PO Template file.
##
## `msgid`s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run `mix gettext.extract` to bring this file up to
## date. Leave `msgstr`s empty as changing them here as no
## effect: edit them in PO (`.po`) files instead.
msgid "eperm"
msgstr ""
msgid "eacces"
msgstr ""
msgid "eagain"
msgstr ""
msgid "ebadf"
msgstr ""
msgid "ebadmsg"
msgstr ""
msgid "ebusy"
msgstr ""
msgid "edeadlk"
msgstr ""
msgid "edeadlock"
msgstr ""
msgid "edquot"
msgstr ""
msgid "eexist"
msgstr ""
msgid "efault"
msgstr ""
msgid "efbig"
msgstr ""
msgid "eftype"
msgstr ""
msgid "eintr"
msgstr ""
msgid "einval"
msgstr ""
msgid "eio"
msgstr ""
msgid "eisdir"
msgstr ""
msgid "eloop"
msgstr ""
msgid "emfile"
msgstr ""
msgid "emlink"
msgstr ""
msgid "emultihop"
msgstr ""
msgid "enametoolong"
msgstr ""
msgid "enfile"
msgstr ""
msgid "enobufs"
msgstr ""
msgid "enodev"
msgstr ""
msgid "enolck"
msgstr ""
msgid "enolink"
msgstr ""
msgid "enoent"
msgstr ""
msgid "enomem"
msgstr ""
msgid "enospc"
msgstr ""
msgid "enosr"
msgstr ""
msgid "enostr"
msgstr ""
msgid "enosys"
msgstr ""
msgid "enotblk"
msgstr ""
msgid "enotdir"
msgstr ""
msgid "enotsup"
msgstr ""
msgid "enxio"
msgstr ""
msgid "eopnotsupp"
msgstr ""
msgid "eoverflow"
msgstr ""
msgid "epipe"
msgstr ""
msgid "erange"
msgstr ""
msgid "erofs"
msgstr ""
msgid "espipe"
msgstr ""
msgid "esrch"
msgstr ""
msgid "estale"
msgstr ""
msgid "etxtbsy"
msgstr ""
msgid "exdev"
msgstr ""

View file

@ -0,0 +1,574 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-08-11 18:40+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Translate Toolkit 3.7.2\n"
## This file is a PO Template file.
##
## "msgid"s here are often extracted from source code.
## Add new translations manually only if they're dynamic
## translations that can't be statically extracted.
##
## Run "mix gettext.extract" to bring this file up to
## date. Leave "msgstr"s empty as changing them here as no
## effect: edit them in PO (.po) files instead.
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
#, elixir-autogen, elixir-format
msgctxt "remote follow authorization button"
msgid "Authorize"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:2
#, elixir-autogen, elixir-format
msgctxt "remote follow error"
msgid "Error fetching user"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "remote follow header"
msgid "Remote follow"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "placeholder text for auth code entry"
msgid "Authentication code"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:10
#, elixir-autogen, elixir-format
msgctxt "placeholder text for password entry"
msgid "Password"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "placeholder text for username entry"
msgid "Username"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:13
#, elixir-autogen, elixir-format
msgctxt "remote follow authorization button for login"
msgid "Authorize"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:12
#, elixir-autogen, elixir-format
msgctxt "remote follow authorization button for mfa"
msgid "Authorize"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:2
#, elixir-autogen, elixir-format
msgctxt "remote follow error"
msgid "Error following account"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "remote follow header, need login"
msgid "Log in to follow"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "remote follow mfa header"
msgid "Two-factor authentication"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "remote follow success"
msgid "Account followed!"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:7
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:7
#, elixir-autogen, elixir-format
msgctxt "placeholder text for account id"
msgid "Your account ID, e.g. lain@quitter.se"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "remote follow authorization button for following with a remote account"
msgid "Follow"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:2
#, elixir-autogen, elixir-format
msgctxt "remote follow error"
msgid "Error: %{error}"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "remote follow header"
msgid "Remotely follow %{nickname}"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:12
#, elixir-autogen, elixir-format
msgctxt "password reset button"
msgid "Reset"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "password reset failed homepage link"
msgid "Homepage"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "password reset failed message"
msgid "Password reset failed"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "password reset form confirm password prompt"
msgid "Confirmation"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "password reset form password prompt"
msgid "Password"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "password reset invalid token message"
msgid "Invalid Token"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:2
#, elixir-autogen, elixir-format
msgctxt "password reset successful homepage link"
msgid "Homepage"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "password reset successful message"
msgid "Password changed!"
msgstr ""
#: lib/pleroma/web/templates/feed/feed/tag.atom.eex:12
#: lib/pleroma/web/templates/feed/feed/tag.rss.eex:8
#, elixir-autogen, elixir-format
msgctxt "tag feed description"
msgid "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse."
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "oauth authorization exists page title"
msgid "Authorization exists"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:32
#, elixir-autogen, elixir-format
msgctxt "oauth authorize approve button"
msgid "Approve"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:30
#, elixir-autogen, elixir-format
msgctxt "oauth authorize cancel button"
msgid "Cancel"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:23
#, elixir-autogen, elixir-format
msgctxt "oauth authorize message"
msgid "Application <strong>%{client_name}</strong> is requesting access to your account."
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "oauth authorized page title"
msgid "Successfully authorized"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "oauth external provider page title"
msgid "Sign in with external provider"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:13
#, elixir-autogen, elixir-format
msgctxt "oauth external provider sign in button"
msgid "Sign in with %{strategy}"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:54
#, elixir-autogen, elixir-format
msgctxt "oauth login button"
msgid "Log In"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:51
#, elixir-autogen, elixir-format
msgctxt "oauth login password prompt"
msgid "Password"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:47
#, elixir-autogen, elixir-format
msgctxt "oauth login username prompt"
msgid "Username"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:39
#, elixir-autogen, elixir-format
msgctxt "oauth register nickname prompt"
msgid "Pleroma Handle"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:37
#, elixir-autogen, elixir-format
msgctxt "oauth register nickname unchangeable warning"
msgid "Choose carefully! You won't be able to change this later. You will be able to change your display name, though."
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:18
#, elixir-autogen, elixir-format
msgctxt "oauth register page email prompt"
msgid "Email"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:10
#, elixir-autogen, elixir-format
msgctxt "oauth register page fill form prompt"
msgid "If you'd like to register a new account, please provide the details below."
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:35
#, elixir-autogen, elixir-format
msgctxt "oauth register page login button"
msgid "Proceed as existing user"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:31
#, elixir-autogen, elixir-format
msgctxt "oauth register page login password prompt"
msgid "Password"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:24
#, elixir-autogen, elixir-format
msgctxt "oauth register page login prompt"
msgid "Alternatively, sign in to connect to existing account."
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:27
#, elixir-autogen, elixir-format
msgctxt "oauth register page login username prompt"
msgid "Name or email"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:14
#, elixir-autogen, elixir-format
msgctxt "oauth register page nickname prompt"
msgid "Nickname"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:22
#, elixir-autogen, elixir-format
msgctxt "oauth register page register button"
msgid "Proceed as new user"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "oauth register page title"
msgid "Registration Details"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:36
#, elixir-autogen, elixir-format
msgctxt "oauth register page title"
msgid "This is the first time you visit! Please enter your Pleroma handle."
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex:2
#, elixir-autogen, elixir-format
msgctxt "oauth scopes message"
msgid "The following permissions will be granted"
msgstr ""
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:2
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:2
#, elixir-autogen, elixir-format
msgctxt "oauth token code message"
msgid "Token code is <br>%{token}"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:12
#, elixir-autogen, elixir-format
msgctxt "mfa auth code prompt"
msgid "Authentication code"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "mfa auth page title"
msgid "Two-factor authentication"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:23
#, elixir-autogen, elixir-format
msgctxt "mfa auth page use recovery code link"
msgid "Enter a two-factor recovery code"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:20
#, elixir-autogen, elixir-format
msgctxt "mfa auth verify code button"
msgid "Verify"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "mfa recover page title"
msgid "Two-factor recovery"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:12
#, elixir-autogen, elixir-format
msgctxt "mfa recover recovery code prompt"
msgid "Recovery code"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:23
#, elixir-autogen, elixir-format
msgctxt "mfa recover use 2fa code link"
msgid "Enter a two-factor code"
msgstr ""
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:20
#, elixir-autogen, elixir-format
msgctxt "mfa recover verify recovery code button"
msgid "Verify"
msgstr ""
#: lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "static fe profile page remote follow button"
msgid "Remote follow"
msgstr ""
#: lib/pleroma/web/templates/email/digest.html.eex:163
#, elixir-autogen, elixir-format
msgctxt "digest email header line"
msgid "Hey %{nickname}, here is what you've missed!"
msgstr ""
#: lib/pleroma/web/templates/email/digest.html.eex:544
#, elixir-autogen, elixir-format
msgctxt "digest email receiver address"
msgid "The email address you are subscribed as is <a href='mailto:%{@user.email}' style='color: %{color};text-decoration: none;'>%{email}</a>. "
msgstr ""
#: lib/pleroma/web/templates/email/digest.html.eex:538
#, elixir-autogen, elixir-format
msgctxt "digest email sending reason"
msgid "You have received this email because you have signed up to receive digest emails from <b>%{instance}</b> Pleroma instance."
msgstr ""
#: lib/pleroma/web/templates/email/digest.html.eex:547
#, elixir-autogen, elixir-format
msgctxt "digest email unsubscribe action"
msgid "To unsubscribe, please go %{here}."
msgstr ""
#: lib/pleroma/web/templates/email/digest.html.eex:547
#, elixir-autogen, elixir-format
msgctxt "digest email unsubscribe action link text"
msgid "here"
msgstr ""
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "mailer unsubscribe failed message"
msgid "UNSUBSCRIBE FAILURE"
msgstr ""
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex:1
#, elixir-autogen, elixir-format
msgctxt "mailer unsubscribe successful message"
msgid "UNSUBSCRIBE SUCCESSFUL"
msgstr ""
#: lib/pleroma/web/templates/email/digest.html.eex:385
#, elixir-format
msgctxt "new followers count header"
msgid "%{count} New Follower"
msgid_plural "%{count} New Followers"
msgstr[0] ""
msgstr[1] ""
#: lib/pleroma/emails/user_email.ex:356
#, elixir-autogen, elixir-format
msgctxt "account archive email body - self-requested"
msgid "<p>You requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
msgstr ""
#: lib/pleroma/emails/user_email.ex:384
#, elixir-autogen, elixir-format
msgctxt "account archive email subject"
msgid "Your account archive is ready"
msgstr ""
#: lib/pleroma/emails/user_email.ex:188
#, elixir-autogen, elixir-format
msgctxt "approval pending email body"
msgid "<h3>Awaiting Approval</h3>\n<p>Your account at %{instance_name} is being reviewed by staff. You will receive another email once your account is approved.</p>\n"
msgstr ""
#: lib/pleroma/emails/user_email.ex:202
#, elixir-autogen, elixir-format
msgctxt "approval pending email subject"
msgid "Your account is awaiting approval"
msgstr ""
#: lib/pleroma/emails/user_email.ex:158
#, elixir-autogen, elixir-format
msgctxt "confirmation email body"
msgid "<h3>Thank you for registering on %{instance_name}</h3>\n<p>Email confirmation is required to activate the account.</p>\n<p>Please click the following link to <a href=\"%{confirmation_url}\">activate your account</a>.</p>\n"
msgstr ""
#: lib/pleroma/emails/user_email.ex:174
#, elixir-autogen, elixir-format
msgctxt "confirmation email subject"
msgid "%{instance_name} account confirmation"
msgstr ""
#: lib/pleroma/emails/user_email.ex:310
#, elixir-autogen, elixir-format
msgctxt "digest email subject"
msgid "Your digest from %{instance_name}"
msgstr ""
#: lib/pleroma/emails/user_email.ex:81
#, elixir-autogen, elixir-format
msgctxt "password reset email body"
msgid "<h3>Reset your password at %{instance_name}</h3>\n<p>Someone has requested password change for your account at %{instance_name}.</p>\n<p>If it was you, visit the following link to proceed: <a href=\"%{password_reset_url}\">reset password</a>.</p>\n<p>If it was someone else, nothing to worry about: your data is secure and your password has not been changed.</p>\n"
msgstr ""
#: lib/pleroma/emails/user_email.ex:98
#, elixir-autogen, elixir-format
msgctxt "password reset email subject"
msgid "Password reset"
msgstr ""
#: lib/pleroma/emails/user_email.ex:215
#, elixir-autogen, elixir-format
msgctxt "successful registration email body"
msgid "<h3>Hello @%{nickname},</h3>\n<p>Your account at %{instance_name} has been registered successfully.</p>\n<p>No further action is required to activate your account.</p>\n"
msgstr ""
#: lib/pleroma/emails/user_email.ex:231
#, elixir-autogen, elixir-format
msgctxt "successful registration email subject"
msgid "Account registered on %{instance_name}"
msgstr ""
#: lib/pleroma/emails/user_email.ex:119
#, elixir-autogen, elixir-format
msgctxt "user invitation email body"
msgid "<h3>You are invited to %{instance_name}</h3>\n<p>%{inviter_name} invites you to join %{instance_name}, an instance of Pleroma federated social networking platform.</p>\n<p>Click the following link to register: <a href=\"%{registration_url}\">accept invitation</a>.</p>\n"
msgstr ""
#: lib/pleroma/emails/user_email.ex:136
#, elixir-autogen, elixir-format
msgctxt "user invitation email subject"
msgid "Invitation to %{instance_name}"
msgstr ""
#: lib/pleroma/emails/user_email.ex:53
#, elixir-autogen, elixir-format
msgctxt "welcome email html body"
msgid "Welcome to %{instance_name}!"
msgstr ""
#: lib/pleroma/emails/user_email.ex:41
#, elixir-autogen, elixir-format
msgctxt "welcome email subject"
msgid "Welcome to %{instance_name}!"
msgstr ""
#: lib/pleroma/emails/user_email.ex:65
#, elixir-autogen, elixir-format
msgctxt "welcome email text body"
msgid "Welcome to %{instance_name}!"
msgstr ""
#: lib/pleroma/emails/user_email.ex:368
#, elixir-autogen, elixir-format
msgctxt "account archive email body - admin requested"
msgid "<p>Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
msgstr ""
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:123
#, elixir-autogen, elixir-format
msgctxt "remote follow error message - unknown error"
msgid "Something went wrong."
msgstr ""
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:67
#, elixir-autogen, elixir-format
msgctxt "remote follow error message - user not found"
msgid "Could not find user"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:8
#, elixir-autogen, elixir-format
msgctxt "status interact authorization button"
msgid "Interact"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:2
#, elixir-autogen, elixir-format
msgctxt "status interact error"
msgid "Error: %{error}"
msgstr ""
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:95
#, elixir-autogen, elixir-format
msgctxt "status interact error message - status not found"
msgid "Could not find status"
msgstr ""
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:144
#, elixir-autogen, elixir-format
msgctxt "status interact error message - unknown error"
msgid "Something went wrong."
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "status interact header"
msgid "Interacting with %{nickname}'s %{status_link}"
msgstr ""
#: lib/pleroma/web/templates/twitter_api/util/status_interact.html.eex:4
#, elixir-autogen, elixir-format
msgctxt "status interact header - status link text"
msgid "status"
msgstr ""

View file

@ -0,0 +1,16 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.DependencyVersionTest do
use ExUnit.Case, async: true
test "uses majic 1.2" do
majic_version =
:majic
|> Application.spec(:vsn)
|> to_string()
assert Version.match?(majic_version, "~> 1.2")
end
end

View file

@ -11,6 +11,7 @@ defmodule Pleroma.SignatureTest do
import Mock import Mock
alias Pleroma.Signature alias Pleroma.Signature
alias Pleroma.StubbedHTTPSignaturesMock, as: HTTPSignaturesMock
setup do setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end) mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
@ -103,6 +104,18 @@ defmodule Pleroma.SignatureTest do
end end
end end
describe "validate_signature/1" do
test "treats HTTP signature errors as failed validation" do
conn = %Plug.Conn{method: "GET", request_path: "/inbox", req_headers: []}
Mox.expect(HTTPSignaturesMock, :validate_conn, fn _conn ->
{:error, :request_target_header}
end)
assert Signature.validate_signature(conn) == false
end
end
describe "key_id_to_actor_id/1" do describe "key_id_to_actor_id/1" do
test "it properly deduces the actor id for misskey" do test "it properly deduces the actor id for misskey" do
assert Signature.key_id_to_actor_id("https://example.com/users/1234/publickey") == assert Signature.key_id_to_actor_id("https://example.com/users/1234/publickey") ==

View file

@ -0,0 +1,195 @@
# Pleroma: A lightweight social networking server
# Copyright © Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.User.SearchTest do
use Pleroma.DataCase, async: false
import Pleroma.Factory
alias Pleroma.Instances
alias Pleroma.Repo
alias Pleroma.User
describe "search/2 mention suggestions" do
test "prioritizes followed/follower users before others" do
user = insert(:user)
related =
insert(:user,
local: false,
nickname: "hj@real.example",
ap_id: "https://real.example/users/hj",
last_status_at: ~N[2020-01-01 00:00:00]
)
other = insert(:user, nickname: "hj", last_status_at: ~N[2020-01-02 00:00:00])
{:ok, _related, _user} = User.follow(related, user)
results = User.search("hj", for_user: user) |> Enum.map(& &1.id)
assert results == [related.id, other.id]
end
test "orders followed/follower users by most recent activity" do
user = insert(:user)
older =
insert(:user,
local: false,
nickname: "ali@remote.example",
ap_id: "https://remote.example/users/ali",
last_status_at: ~N[2020-01-01 00:00:00]
)
newer =
insert(:user,
local: false,
nickname: "alia@remote.example",
ap_id: "https://remote.example/users/alia",
last_status_at: ~N[2020-01-02 00:00:00]
)
{:ok, _user, _older} = User.follow(user, older)
{:ok, _user, _newer} = User.follow(user, newer)
assert [newer.id, older.id] ==
User.search("ali", for_user: user)
|> Enum.map(& &1.id)
end
test "groups followed/follower users first and sorts them by recency" do
user = insert(:user)
following_newest =
insert(:user,
local: false,
nickname: "mentiontesta@related.example",
ap_id: "https://related.example/users/mentiontesta",
last_status_at: ~N[2020-01-03 00:00:00]
)
follower_middle =
insert(:user,
local: false,
nickname: "mentiontestb@related.example",
ap_id: "https://related.example/users/mentiontestb",
last_status_at: ~N[2020-01-02 00:00:00]
)
mutual_oldest =
insert(:user,
local: false,
nickname: "mentiontestc@related.example",
ap_id: "https://related.example/users/mentiontestc",
last_status_at: ~N[2020-01-01 00:00:00]
)
unrelated_newer =
insert(:user,
local: false,
nickname: "mentiontestd@unrelated.example",
ap_id: "https://unrelated.example/users/mentiontestd",
last_status_at: ~N[2020-01-04 00:00:00]
)
{:ok, _user, _following_newest} = User.follow(user, following_newest)
{:ok, _follower_middle, _user} = User.follow(follower_middle, user)
{:ok, _user, _mutual_oldest} = User.follow(user, mutual_oldest)
{:ok, _mutual_oldest, _user} = User.follow(mutual_oldest, user)
results = User.search("mentiontest", for_user: user)
assert Enum.map(results, & &1.id) ==
[following_newest.id, follower_middle.id, mutual_oldest.id, unrelated_newer.id]
end
test "uses last_active_at when last_status_at is missing" do
user = insert(:user)
older =
insert(:user,
local: false,
nickname: "activefallbacka@remote.example",
ap_id: "https://remote.example/users/activefallbacka",
last_status_at: nil,
last_active_at: ~N[2020-01-01 00:00:00]
)
newer =
insert(:user,
local: false,
nickname: "activefallbackb@remote.example",
ap_id: "https://remote.example/users/activefallbackb",
last_status_at: nil,
last_active_at: ~N[2020-01-02 00:00:00]
)
{:ok, _user, _older} = User.follow(user, older)
{:ok, _user, _newer} = User.follow(user, newer)
assert [newer.id, older.id] ==
User.search("activefallback", for_user: user)
|> Enum.map(& &1.id)
end
test "does not return deactivated users even if related" do
user = insert(:user)
active =
insert(:user,
local: false,
nickname: "deactivatedtesta@remote.example",
ap_id: "https://remote.example/users/deactivatedtesta",
last_status_at: ~N[2020-01-02 00:00:00]
)
deactivated =
insert(:user,
local: false,
nickname: "deactivatedtestb@remote.example",
ap_id: "https://remote.example/users/deactivatedtestb",
last_status_at: ~N[2020-01-03 00:00:00]
)
{:ok, _user, _active} = User.follow(user, active)
{:ok, _user, _deactivated} = User.follow(user, deactivated)
Repo.update!(Ecto.Changeset.change(deactivated, is_active: false))
results = User.search("deactivatedtest", for_user: user) |> Enum.map(& &1.id)
assert results == [active.id]
end
test "does not return users from unreachable instances" do
user = insert(:user)
{:ok, _instance} = Instances.set_unreachable("dead.example")
dead =
insert(:user,
local: false,
nickname: "ali@dead.example",
ap_id: "https://dead.example/users/ali",
last_status_at: ~N[2020-01-02 00:00:00]
)
alive =
insert(:user,
local: false,
nickname: "ali@alive.example",
ap_id: "https://alive.example/users/ali",
last_status_at: ~N[2020-01-02 00:00:00]
)
{:ok, _user, _alive} = User.follow(user, alive)
{:ok, _user, _dead} = User.follow(user, dead)
results = User.search("ali", for_user: user) |> Enum.map(& &1.id)
assert results == [alive.id]
end
end
end

View file

@ -950,6 +950,50 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
refute Activity.get_by_ap_id(data["id"]) refute Activity.get_by_ap_id(data["id"])
end end
test "does not process post with Host header not for us", %{conn: conn} do
alice = insert(:user, local: false, ap_id: "https://one.com/users/alice")
object_id = "https://one.com/objects/inbox-forged-note"
data = %{
"type" => "Create",
"actor" => alice.ap_id,
"id" => "https://one.com/activities/inbox-forged-create",
"context" => "https://one.com/contexts/inbox-forged-create",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => [],
"object" => %{
"type" => "Note",
"id" => object_id,
"actor" => alice.ap_id,
"attributedTo" => alice.ap_id,
"context" => "https://one.com/contexts/inbox-forged-create",
"content" => "forged post",
"published" => "2024-07-25T13:33:31Z",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => []
}
}
# Plug will complain when replacing raw host header with put_req_header.
# The Plug way is updating conn.host, but that isn't the raw header
# and that isn't used in the EnsureHostMatchesPlug, because it doesn't include the port.
conn =
conn
|> assign_valid_signature_for_actor(alice)
|> delete_req_header("host")
|> put_req_header("content-type", "application/activity+json")
conn = %{conn | req_headers: conn.req_headers ++ [{"host", "invalid.example.com"}]}
conn = post(conn, "/inbox", data)
assert "Host header does not match this instance" == conn.resp_body
assert 400 == conn.status
assert true == conn.halted
refute Activity.get_by_ap_id(data["id"])
refute Object.get_by_ap_id(object_id)
end
test "accept follow activity", %{conn: conn} do test "accept follow activity", %{conn: conn} do
clear_config([:instance, :federating], true) clear_config([:instance, :federating], true)
relay = Relay.get_actor() relay = Relay.get_actor()

View file

@ -86,6 +86,43 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert activity.data["cc"] == [user.ap_id] assert activity.data["cc"] == [user.ap_id]
end end
test "it rejects Flag activities when both reporter and reported account are remote" do
reporter = insert(:user, local: false, domain: "mastodon.cat")
reported = insert(:user, local: false, domain: "nicecrew.digital")
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"actor" => reporter.ap_id,
"content" => "blocked AND reported!!!",
"object" => [reported.ap_id, "https://nicecrew.digital/objects/report-status"],
"type" => "Flag"
}
assert {:reject, reason} = Transmogrifier.handle_incoming(message)
assert reason =~ "third-party report"
refute "Flag" |> Pleroma.Activity.Queries.by_type() |> Pleroma.Repo.one()
end
test "it accepts Flag activities with just actor id as object" do
user = insert(:user)
other_user = insert(:user)
message = %{
"@context" => "https://www.w3.org/ns/activitystreams",
"cc" => [user.ap_id],
"object" => user.ap_id,
"type" => "Flag",
"content" => "blocked AND reported!!!",
"actor" => other_user.ap_id
}
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
assert activity.data["content"] == "blocked AND reported!!!"
assert activity.data["actor"] == other_user.ap_id
assert activity.data["cc"] == [user.ap_id]
end
test "it accepts Move activities" do test "it accepts Move activities" do
old_user = insert(:user) old_user = insert(:user)
new_user = insert(:user) new_user = insert(:user)

View file

@ -0,0 +1,121 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2026 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.EnsureHostMatchesPlugTest do
use Pleroma.Web.ConnCase
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Plugs.EnsureHostMatchesPlug
import Plug.Conn
import Tesla.Mock
setup do
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
:ok
end
defp set_host(conn, host), do: %{conn | req_headers: conn.req_headers ++ [{"host", host}]}
describe "EnsureHostMatchesPlug" do
setup do
conn = build_conn(:post, "/cofe") |> assign(:valid_signature, true)
[conn: conn]
end
test "gracefully handles no Host header", %{conn: conn} do
conn = EnsureHostMatchesPlug.call(conn, %{})
assert conn.status == 400
assert conn.halted == true
assert conn.resp_body == "Host header not provided"
end
test "gracefully handles empty Host header", %{conn: conn} do
conn =
conn
|> set_host("")
|> EnsureHostMatchesPlug.call(%{})
assert conn.status == 400
assert conn.halted == true
assert conn.resp_body == "Host header not provided"
end
test "it rejects Host header not matching Endpoint URL", %{conn: conn} do
conn =
conn
|> set_host("invalid.example.com")
|> EnsureHostMatchesPlug.call(%{})
assert conn.status == 400
assert conn.halted == true
assert conn.resp_body == "Host header does not match this instance"
end
test "it rejects Host header not matching Endpoint with port", %{conn: conn} do
endpoint = URI.parse(Endpoint.url())
conn =
conn
|> set_host("invalid.example.com:#{endpoint.port}")
|> EnsureHostMatchesPlug.call(%{})
assert conn.status == 400
assert conn.halted == true
assert conn.resp_body == "Host header does not match this instance"
end
test "it rejects Host header not matching Endpoint port", %{conn: conn} do
endpoint = URI.parse(Endpoint.url())
conn =
conn
|> set_host("#{endpoint.host}:25")
|> EnsureHostMatchesPlug.call(%{})
assert conn.status == 400
assert conn.halted == true
assert conn.resp_body == "Host header does not match this instance"
end
test "it rejects multiple Host headers", %{conn: conn} do
conn =
conn
|> set_host("host1.example.com")
|> set_host("host2.example.com")
|> EnsureHostMatchesPlug.call(%{})
assert conn.status == 400
assert conn.halted == true
assert conn.resp_body == "More than one Host header provided"
end
test "it works for Host header without port", %{conn: conn} do
endpoint = URI.parse(Endpoint.url())
conn =
conn
|> set_host("#{endpoint.host}")
|> EnsureHostMatchesPlug.call(%{})
assert conn.halted == false
assert Map.get(conn.assigns, :valid_host_header, nil)
end
test "it works for Host header with port same as Endpoint", %{
conn: conn
} do
endpoint = URI.parse(Endpoint.url())
conn =
conn
|> set_host("#{endpoint.host}:#{endpoint.port}")
|> EnsureHostMatchesPlug.call(%{})
assert conn.halted == false
assert Map.get(conn.assigns, :valid_host_header, nil)
end
end
end

View file

@ -106,4 +106,38 @@ defmodule Pleroma.Web.Plugs.RemoteIpTest do
assert conn.remote_ip == {1, 1, 1, 1} assert conn.remote_ip == {1, 1, 1, 1}
end end
test "reserved ranges are configurable" do
clear_config([RemoteIp, :reserved], [])
conn =
conn(:get, "/")
|> put_req_header("x-forwarded-for", "1.1.1.1, 10.0.0.3")
|> RemoteIp.call(nil)
assert conn.remote_ip == {10, 0, 0, 3}
end
test "clients override reserved ranges" do
clear_config([RemoteIp, :clients], ["10.0.0.0/8"])
conn =
conn(:get, "/")
|> put_req_header("x-forwarded-for", "1.1.1.1, 10.0.0.3")
|> RemoteIp.call(nil)
assert conn.remote_ip == {10, 0, 0, 3}
end
test "clients override proxies" do
clear_config([RemoteIp, :clients], ["10.0.0.3"])
clear_config([RemoteIp, :proxies], ["10.0.0.0/8"])
conn =
conn(:get, "/")
|> put_req_header("x-forwarded-for", "1.1.1.1, 10.0.0.3")
|> RemoteIp.call(nil)
assert conn.remote_ip == {10, 0, 0, 3}
end
end end

View file

@ -16,12 +16,13 @@ defmodule Pleroma.Workers.SignatureRetryWorkerTest do
alias Pleroma.Signature alias Pleroma.Signature
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.UserView alias Pleroma.Web.ActivityPub.UserView
alias Pleroma.Web.Endpoint
alias Pleroma.Web.Federator alias Pleroma.Web.Federator
alias Pleroma.Workers.SignatureRetryWorker alias Pleroma.Workers.SignatureRetryWorker
defp signature_headers_for(%User{} = signer) do defp signature_headers_for(%User{} = signer) do
[ [
{"host", "local.test"}, {"host", "#{URI.parse(Endpoint.url()).host}"},
{"date", "Thu, 25 Jul 2024 13:33:31 GMT"}, {"date", "Thu, 25 Jul 2024 13:33:31 GMT"},
{"digest", "SHA-256=fake-digest"}, {"digest", "SHA-256=fake-digest"},
{"content-type", "application/activity+json"}, {"content-type", "application/activity+json"},
@ -245,6 +246,66 @@ defmodule Pleroma.Workers.SignatureRetryWorkerTest do
refute Activity.get_by_ap_id(create["id"]) refute Activity.get_by_ap_id(create["id"])
end end
test "cancels when the Host header does not match Endpoint" do
alice = insert(:user, local: false, ap_id: "https://one.com/users/alice")
create = %{
"type" => "Create",
"actor" => alice.ap_id,
"id" => "https://one.com/activities/invalid-signature-create",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => [],
"object" => %{
"type" => "Note",
"id" => "https://one.com/objects/invalid-signature-note",
"actor" => alice.ap_id,
"attributedTo" => alice.ap_id,
"content" => "forged post",
"published" => "2024-07-25T13:33:31Z",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"cc" => []
}
}
expect_signature_from(alice)
headers =
[
{"host", "invalid.example.com"},
{"date", "Thu, 25 Jul 2024 13:33:31 GMT"},
{"digest", "SHA-256=fake-digest"},
{"content-type", "application/activity+json"},
{
"signature",
"keyId=\"#{alice.ap_id}#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"fake-signature\""
}
]
assert {:ok, oban_job} =
Federator.incoming_failed_signature_ap_doc(%{
method: "POST",
req_headers: headers,
request_path: "/inbox",
params: create,
query_string: ""
})
log =
capture_log([level: :warning], fn ->
assert {:cancel, :host_header_mismatch} = SignatureRetryWorker.perform(oban_job)
end)
assert log =~ "Failed-signature inbox retry rejected"
assert log =~ "reason=:host_header_mismatch"
assert log =~ "payload_actor=\"https://one.com/users/alice\""
assert log =~ "signature_actor=\"https://one.com/users/alice\""
assert log =~ "activity_id=\"https://one.com/activities/invalid-signature-create\""
assert log =~ "type=\"Create\""
assert log =~ "request_path=\"/inbox\""
refute Activity.get_by_ap_id(create["id"])
end
test "processes the activity after refetching a valid matching signature" do test "processes the activity after refetching a valid matching signature" do
alice = insert(:user, local: false, ap_id: "https://one.com/users/alice") alice = insert(:user, local: false, ap_id: "https://one.com/users/alice")
@ -309,11 +370,11 @@ defmodule Pleroma.Workers.SignatureRetryWorkerTest do
"content-type" => "application/activity+json", "content-type" => "application/activity+json",
date: date, date: date,
digest: digest, digest: digest,
host: "local.test" host: "#{URI.parse(Endpoint.url()).host}"
}) })
req_headers = [ req_headers = [
["host", "local.test"], ["host", "#{URI.parse(Endpoint.url()).host}"],
["date", date], ["date", date],
["digest", digest], ["digest", digest],
["content-type", "application/activity+json"], ["content-type", "application/activity+json"],

View file

@ -119,7 +119,10 @@ defmodule Pleroma.Web.ConnCase do
DataCase.stub_pipeline() DataCase.stub_pipeline()
Mox.verify_on_exit!() Mox.verify_on_exit!()
endpoint = URI.parse(Pleroma.Web.Endpoint.url())
conn = Phoenix.ConnTest.build_conn()
conn = %{conn | req_headers: [{"host", "#{endpoint.host}:#{endpoint.port}"}]}
{:ok, conn: Phoenix.ConnTest.build_conn()} {:ok, conn: conn}
end end
end end