Descriptions of MRF policies are gathered at compile-time and use
Pleroma.Docs.Generator.list_behaviour_implementations func, which
depends on modules implementing the queried behaviour to be loaded.
Otherwise descriptions for MRFs can be missing from the AdminAPI route.
Note: @behaviour cannot be injected in the __using__ macro. It causes a
loop in the compiler which leads to memory exhaustion. Hence why
@behaviour is still defined separately in the MRFs.
Elixir 1.19 started emitting warnings about our use of:
config :logger, :console and
config :logger, backends: []
which got split in 1.15 to :default_handler, :default_formatter, and
LoggerBackends.add(backend) respectively.
On Pleroma startup it is now necessary to add the additional logger
backends at runtime (done with configure_logger() in application.ex).
New config key :pleroma, :logger_backends: [] has replaced the older
backends array. The logger_backends package is now used to facilitate
usage of other logger backends besides the default one (:logger_std_h
from OTP).
Warnings were added to Pleroma startup to warn about the usage of
:logger, backends and additional logic was introduced to make addition
of ExSyslogger to admin's configuration less dumb.
Ref: https://hexdocs.pm/logger/1.15.0/Logger.html#module-backends-and-backwards-compatibility
It is no longer possible to match regexes. Instead at least match that
the sources of the regexes (regexes themselves) are the same.
Notice the +1 Reference number below.
2) test subdomain_match/2 wildcard domains with one subdomain (Pleroma.Web.ActivityPub.MRFTest)
test/pleroma/web/activity_pub/mrf_test.exs:36
Assertion with == failed
code: assert regexes == [~r/^(.*\.)*unsafe.tld$/i]
left: [%Regex{opts: [:caseless], re_pattern: {:re_pattern, 1, 0, 0, #Reference<0.378940835.3277193222.129648>}, source: "^(.*\\.)*unsafe.tld$"}]
right: [%Regex{opts: [:caseless], re_pattern: {:re_pattern, 1, 0, 0, #Reference<0.378940835.3277193222.129649>}, source: "^(.*\\.)*unsafe.tld$"}]
stacktrace:
test/pleroma/web/activity_pub/mrf_test.exs:39: (test)
It is not possible match regexes anymore as this worked by accident
previously. Instead, at least check that the sources of the regex (the
regex itself) match.
Notice the +1 difference in the regex Reference below.
1) test to_elixir_types/1 complex keyword with sigil (Pleroma.ConfigDBTest)
test/pleroma/config_db_test.exs:460
Assertion with == failed
code: assert ConfigDB.to_elixir_types([
%{"tuple" => [":federated_timeline_removal", []]},
%{"tuple" => [":reject", ["~r/comp[lL][aA][iI][nN]er/"]]},
%{"tuple" => [":replace", []]}
]) == [federated_timeline_removal: [], reject: [~r/comp[lL][aA][iI][nN]er/], replace: []]
left: [federated_timeline_removal: [], reject: [%Regex{opts: [], re_pattern: {:re_pattern, 0, 0, 0, #Reference<0.230935836.591265794.259515>}, source: "comp[lL][aA][iI][nN]er"}], replace: []]
right: [federated_timeline_removal: [], reject: [%Regex{opts: [], re_pattern: {:re_pattern, 0, 0, 0, #Reference<0.230935836.591265794.259516>}, source: "comp[lL][aA][iI][nN]er"}], replace: []]
stacktrace:
test/pleroma/config_db_test.exs:461: (test)
warning: a struct for Pleroma.Marker is expected on struct update:
%Pleroma.Marker{refresh_record(marker) | unread_count: 2}
but got type:
dynamic()
where "marker" was given the type:
# type: dynamic()
# from: test/pleroma/marker_test.exs:35:14
marker = Pleroma.Factory.insert(:marker, user: user)
you must assign "refresh_record(marker)" to variable and pattern match on "%Pleroma.Marker{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
43 │ ) == [%Marker{refresh_record(marker) | unread_count: 2}]
│ ~
│
└─ test/pleroma/marker_test.exs:43:20: Pleroma.MarkerTest."test get_markers/2 returns user markers"/1
warning: a struct for Pleroma.Web.OAuth.Token is expected on struct update:
%Pleroma.Web.OAuth.Token{Pleroma.Factory.insert(:oauth_token) | user: user}
but got type:
dynamic()
you must assign "Pleroma.Factory.insert(:oauth_token)" to variable and pattern match on "%Pleroma.Web.OAuth.Token{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
27 │ token = %Pleroma.Web.OAuth.Token{insert(:oauth_token) | user: user}
│ ~
│
└─ test/pleroma/repo_test.exs:27:15: Pleroma.RepoTest."test get_assoc/2 get assoc from preloaded data"/1
warning: a struct for Plug.Upload is expected on struct update:
%Plug.Upload{image | filename: "../../../../../nested/file.jpg"}
but got type:
dynamic()
where "image" was given the type:
# type: dynamic()
# from: test/pleroma/web/mastodon_api/controllers/media_controller_test.exs:132:42
%{conn: conn, image: image}
when defining the variable "image", you must also pattern match on "%Plug.Upload{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
133 │ image = %Plug.Upload{
│ ~
│
└─ test/pleroma/web/mastodon_api/controllers/media_controller_test.exs:133:15: Pleroma.Web.MastodonAPI.MediaControllerTest."test Upload media Do not allow nested filename"/1
warning: a struct for Pleroma.Web.CommonAPI.ActivityDraft is expected on struct update:
%Pleroma.Web.CommonAPI.ActivityDraft{draft | object: object}
but got type:
dynamic()
where "draft" was given the type:
# type: dynamic()
# from: lib/pleroma/web/common_api/activity_draft.ex:91:22
draft
when defining the variable "draft", you must also pattern match on "%Pleroma.Web.CommonAPI.ActivityDraft{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
102 │ %__MODULE__{draft | object: object}
│ ~
│
└─ lib/pleroma/web/common_api/activity_draft.ex:102:5: Pleroma.Web.CommonAPI.ActivityDraft.listen_object/1
warning: a struct for OpenApiSpex.Cast.Error is expected on struct update:
%OpenApiSpex.Cast.Error{err | name: err.value}
but got type:
dynamic(%{..., name: nil, reason: :invalid_enum})
where "err" was given the type:
# type: dynamic(%{..., name: nil, reason: :invalid_enum})
# from: lib/pleroma/web/api_spec/render_error.ex:20:45
%{name: nil, reason: :invalid_enum} = err
when defining the variable "err", you must also pattern match on "%OpenApiSpex.Cast.Error{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
21 │ %OpenApiSpex.Cast.Error{err | name: err.value}
│ ~
│
└─ lib/pleroma/web/api_spec/render_error.ex:21:11: Pleroma.Web.ApiSpec.RenderError.call/2
warning: a struct for Plug.Conn is expected on struct update:
%Plug.Conn{conn | query_params: query_params}
but got type:
dynamic()
where "conn" was given the type:
# type: dynamic()
# from: lib/pleroma/web/api_spec/cast_and_validate.ex:109:43
conn
when defining the variable "conn", you must also pattern match on "%Plug.Conn{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
133 │ conn = %Conn{conn | query_params: query_params}
│ ~
│
└─ lib/pleroma/web/api_spec/cast_and_validate.ex:133:16: Pleroma.Web.ApiSpec.CastAndValidate.cast_and_validate/6
warning: a struct for Pleroma.Upload is expected on struct update:
%Pleroma.Upload{
upload
| path:
case upload.path do
x when x === false or x === nil ->
<<to_string(upload.id)::binary, "/", to_string(upload.name)::binary>>
x ->
x
end
}
but got type:
dynamic()
where "upload" was given the type:
# type: dynamic()
# from: lib/pleroma/upload.ex:95:24
{:ok, upload} <- prepare_upload(upload, opts)
when defining the variable "upload", you must also pattern match on "%Pleroma.Upload{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
96 │ upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
│ ~
│
└─ lib/pleroma/upload.ex:96:19: Pleroma.Upload.store/2
warning: a struct for Pleroma.MFA.Settings is expected on struct update:
%Pleroma.MFA.Settings{settings | enabled: false}
but got type:
dynamic()
where "settings" was given the type:
# type: dynamic()
# from: lib/pleroma/mfa/changeset.ex:11:14
settings = Pleroma.MFA.fetch_settings(Ecto.Changeset.apply_changes(changeset))
when defining the variable "settings", you must also pattern match on "%Pleroma.MFA.Settings{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
17 │ put_change(changeset, %Settings{settings | enabled: false})
│ ~
│
└─ lib/pleroma/mfa/changeset.ex:17:29: Pleroma.MFA.Changeset.disable/2
---
warning: a struct for Pleroma.MFA.Settings is expected on struct update:
%Pleroma.MFA.Settings{
settings
| totp: %Pleroma.MFA.Settings.TOTP{confirmed: false, delivery_type: "app", secret: nil}
}
but got type:
dynamic()
where "settings" was given the type:
# type: dynamic()
# from: lib/pleroma/mfa/changeset.ex:23:74
%Pleroma.User{multi_factor_authentication_settings: settings} = user
when defining the variable "settings", you must also pattern match on "%Pleroma.MFA.Settings{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
25 │ |> put_change(%Settings{settings | totp: %Settings.TOTP{}})
│ ~
│
└─ lib/pleroma/mfa/changeset.ex:25:19: Pleroma.MFA.Changeset.disable_totp/1
warning: a struct for Pleroma.Marker is expected on struct update:
%Pleroma.Marker{marker | user: user}
but got type:
dynamic()
where "marker" was given the type:
# type: dynamic()
# from: lib/pleroma/marker.ex
{:ok, marker}
when defining the variable "marker", you must also pattern match on "%Pleroma.Marker{}".
hint: given pattern matching is enough to catch typing errors, you may optionally convert the struct update into a map update. For example, instead of:
user = some_function()
%User{user | name: "John Doe"}
it is enough to write:
%User{} = user = some_function()
%{user | name: "John Doe"}
typing violation found at:
│
81 │ {:ok, marker} -> %__MODULE__{marker | user: user}
│ ~
│
└─ lib/pleroma/marker.ex:81:24: Pleroma.Marker.get_marker/2
Drop follow_redirect/force_redirect from the HTTP options used when warming MediaProxy, relying on Tesla middleware instead (Hackney redirect handling can crash behind CONNECT proxies).
Also add a regression assertion in the policy test and document the upstream Hackney issues in ReverseProxy redirect handling.
Exercises Pleroma.ReverseProxy.Client.Hackney with follow_redirect enabled behind an HTTPS CONNECT proxy, ensuring the client follows a relative redirect and can stream the final body.
Hackney 1.25 crashes when follow_redirect is enabled behind an HTTPS CONNECT proxy and the Location header is relative (hackney_http_connect transport).
This test demonstrates the failure and verifies Tesla-level redirects work when hackney redirects are disabled.
Reproduces the Hackney 1.25 pooled redirect cleanup issue which can surface as :req_not_found when the adapter returns a Ref and the body is later fetched.
Hackney 1.25.x has redirect handling issues behind CONNECT proxies and with pools.
Disable hackney-level redirects and rely on Tesla.Middleware.FollowRedirects instead.
Also default to with_body: true so redirects can be followed reliably.