Commit graph

18,396 commits

Author SHA1 Message Date
lain
a9bea940a4 Merge pull request 'Search: set gin_fuzzy_search_limit only for search queries' (#8038) from lambadalambda/pleroma:fix/gin-fuzzy-search-limit into develop 2026-10-29 09:00:15 +00:00
Lain Soykaf
fa8541309c
fix(search): set gin_fuzzy_search_limit only for search queries
The limit was a connection parameter, so it applied to every GIN index
scan, not only full-text search: recipient lookups and Oban job queries
could return incomplete, random results. Set it with SET LOCAL around
the search query only, configurable under Pleroma.Search.DatabaseSearch.

The default stays 500 for search: measured on a 74M-object database,
higher limits or none make searches for common words exceed the query
timeout. Remote fetches for URL queries run outside the transaction.

Based on Akkoma 811f0a468.

Co-authored-by: Oneric <oneric@oneric.stub>
2026-10-29 11:26:02 +04:00
lain
24038667b2 Merge pull request 'fix(http): treat an empty proxy_url as no proxy' (#8010) from lambadalambda/pleroma:fix/empty-proxy-url into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8010
2026-10-29 06:39:21 +00:00
lain
dca6c07631 Merge pull request 'Federation: always prefer the shared inbox' (#8029) from lambadalambda/pleroma:perf/shared-inbox into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8029
2026-10-29 05:41:18 +00:00
lain
a019cb7466 Merge pull request 'Mastodon API: add the quote entity to statuses' (#8035) from lambadalambda/pleroma:feature/mastodon-quote-entity into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8035
2026-10-28 16:41:29 +00:00
Lain Soykaf
3890fbc127
feat(api): add the Mastodon quote entity to statuses
Mastodon 4.4+ clients read quotes from a top-level quote object with
state and quoted_status; Pleroma only had pleroma.quote, so they did
not show quote posts. Quoted statuses get a shallow quote with only
quoted_status_id, as quotes are rendered one level deep.

Inspired by Akkoma 5b7209980, which can not use the shallow form because
Akkoma already had a top-level quote status.
2026-10-28 11:38:49 +04:00
lain
ecd20c7587 Merge pull request 'Federation: validate actor hosts and fetched object ids' (#8034) from lambadalambda/pleroma:fix/actor-containment into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8034
2026-10-28 07:19:42 +00:00
lain
24738790c3 Merge pull request 'MediaProxy: proxy network-path URLs (//host/path)' (#8027) from lambadalambda/pleroma:fix/media-proxy-network-path into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8027
2026-10-28 05:03:14 +00:00
Lain Soykaf
90e330e5b3
fix(containment): return nil for actor shapes without an id
Containment.get_actor raised on remote shapes it did not know, such as
an attributedTo object without an id. This crashed object fetches and
poll refetches. Return nil, so containment rejects the object.
2026-10-27 22:03:13 +04:00
Lain Soykaf
c81b1261dc
fix(federation): treat empty actor fields as missing
An empty inbox, collection or key id was rejected as being on another
host. Treat empty strings like null and only check fields with a value.
2026-10-27 22:02:31 +04:00
Lain Soykaf
f22caeff53
fix(user): update the known user when fetched from a display URL
A fetch from a display URL (e.g. https://host/@user) returns the
actor with its canonical id. make_user_from_ap_id looked the user up
by the fetch URL, did not find it and tried to insert a duplicate.
Look the user up by the fetched id.

Based on Akkoma 48b3a3579.
2026-10-27 21:58:46 +04:00
Lain Soykaf
f1337d8159
fix(fetcher): keep id and author fixed when refetching objects
refetch_object (used for poll updates) accepted whatever the remote
served. A hostile server could swap in another object or move the post
to another author.

The refetch now goes to the stored id without redirects, and the
returned id and actor must equal the stored ones.

Based on Akkoma 9061d148b and fee57eb37.
2026-10-27 21:58:46 +04:00
Lain Soykaf
20354e0aee
fix(fetcher): require fetched documents to have the fetched id
The fetcher accepted any document whose id was on the same host as the
fetch URL. Anyone who can place a JSON file on a host, for example
through an upload, could pass it off as another object or actor from
that host.

The id of a fetched document must now be the URL it came from (after
redirects), ignoring a trailing slash, the fragment, the host case and
differences that our URL encoding removes.
If it differs, as for Mastodon's /@user/123 display URLs, we refetch
once from that id, which must be on the same host. The refetch must
not redirect and must match exactly.

Test mocks that served a document under a different URL now serve it
from its own id.

Based on Akkoma 8684964c5 and 940792f8b.
2026-10-27 21:58:41 +04:00
Lain Soykaf
695dd340de
fix(federation): reject actors that point at other hosts
A remote actor could set its inbox or shared inbox to a third-party
host, so our signed deliveries went there. It could also claim
another actor's followers collection, which the visibility checks
trust.

Validate fetched actors and incoming actor Updates: inbox,
endpoints.sharedInbox, followers, following, featured and the
publicKey id must be on the same host as the actor id.

Based on Akkoma f07eb4cb5. The Bridgy fixture gets the key id that
current Bridgy Fed serves.
2026-10-27 21:37:20 +04:00
Lain Soykaf
5a5f4794d3
perf(federation): always prefer the shared inbox
Followers-only posts and DMs went to each recipient's personal inbox,
so a followers-only post was sent once per follower on the same server.
Mastodon, GoToSocial and Iceshrimp.NET always use the shared inbox.
Only activities with bcc or bto still go to personal inboxes.

Based on Akkoma a80444041.

Co-authored-by: Oneric <oneric@oneric.stub>
2026-10-27 20:45:32 +04:00
lain
d54ff52691 Merge pull request 'StatusView: handle attachments with zero width or height' (#8026) from lambadalambda/pleroma:fix/attachment-zero-size into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8026
2026-10-27 15:00:18 +00:00
lain
7ccdd47134 Merge pull request 'User: stop passing the ignored is_active key to User.Query' (#8025) from lambadalambda/pleroma:fix/user-query-is-active into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8025
2026-10-27 14:58:44 +00:00
Lain Soykaf
0006a478bb
chore: add changelog entry for network-path media proxy fix 2026-10-27 17:30:08 +04:00
Oneric
5cd6894a66
mediaproxy: proxy network-path references
Discovered-by: snow
Fixes: https://akkoma.dev/AkkomaGang/akkoma/issues/900
(cherry picked from commit bbf974adc82d09a2099fb1234729131929307911)
2026-10-27 17:30:08 +04:00
Lain Soykaf
283035ad4f
test(status_view): cover attachments with zero dimensions 2026-10-27 17:27:41 +04:00
Oneric
9443aba06c
api/view: handle explicitly zero dimensions in attachments
Some peertube videos are federated with explicitly zero dimensions
for their mp4 link leading to a division-by-zero exception here.
E.g.: https://spectra.video/videos/watch/66c12674-2013-47a4-9126-51ff8eb8d0a8
      (as of writing using peertube 8.1.1)

Reported by temp3 on IRC

(cherry picked from commit 6833281051aa86b3d82232be29497fed47bf5fb1)
2026-10-27 17:27:28 +04:00
Lain Soykaf
555d93bc33
fix(user): use deactivated: false for familiar followers
User.Query ignores is_active. The friends subquery already drops
deactivated users here, so this only removes the last ignored key.
Also add a changelog entry and a test.
2026-10-27 17:26:20 +04:00
Oneric
f5898ab0fb
Fix malformed is_active qualifiers in User.Query usages
While "is_active" is a property of users, it is not a recognised keyword
for the User.Query helper; instead "deactivated" with negated value must
be used.
This arose because originally the user property was also called
"deactivated" until it was renamed adn negated five years ago
in 860b5c7804. This included renaiming
the parameter in most but not all User.Query usages.
Notably the parameter in User.get_followers_query was renamed
but not in User.get_friends_query (friends == following).
The accepted query parameter in User.Query however was not changed.
This lead to the former mistakenly including deleted users causing
too large values to be reported in the ActivityPub follower, but not
following collection as reported in #1078.

In Masto API responses filtering by `User.is_visible` weeded out
the extra accounts before they got displayed to API users.

On the surface it might seem logical to align the name of the User.Query
parameter with the actual property name. However, User.Query already
accepts an "active" parameter which is an alias for limiting to accounts
which are neither deleted nor deactivated by moderators (both indicated
by is_active) and also are not newly created account requests still
pending an admin approval (is_approved) or necessary email confirmation
(is_confirmed); in short as the alias suggests whether the account is
active. Two highly similar parameter names like this would be much too
confusing.

The renamed "is_active" on the other hand does not actually suffice to
say whether an account is actually active, only whether it has (not yet)
ceased to be active (by its own volition or moderator action).
Meaning its "new" name is actively misleading. Arguably the rename
made things worse for no reason whatsoever and should not ever have
happened.

For now, we’ll just revert the incorrect query helper parameter renames.

Fixes: https://akkoma.dev/AkkomaGang/akkoma/ issues/ 1078
(cherry picked from commit a899663ddc0e3a2084a239eabd79608a94ac5493)
2026-10-27 17:24:58 +04:00
lain
c2bdfb6a34 Merge pull request 'Federation: do not deliver to instances rejected by SimplePolicy' (#8021) from lambadalambda/pleroma:fix/federation-reject-instances into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8021
2026-10-27 13:20:00 +00:00
lain
f4e8834e65 Merge pull request 'Filters: treat phrases as literal text' (#8020) from lambadalambda/pleroma:fix/filter-regex-escape into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8020
2026-10-27 12:39:47 +00:00
lain
a4ce628a50 Merge pull request 'Notifications: do not notify tagged users who cannot see the post' (#8022) from lambadalambda/pleroma:fix/mention-notify-access into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8022
2026-10-27 12:38:20 +00:00
lain
9d2c8d384e Merge branch 'develop' into fix/federation-reject-instances 2026-10-27 12:37:46 +00:00
lain
d15e62fa0a Merge pull request 'Tests: fix flaky RateLimiter tests' (#8024) from lambadalambda/pleroma:fix/rate-limiter-test-flake into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8024
2026-10-27 12:37:27 +00:00
lain
539db4b978 Merge pull request 'Notifications: do not crash on posts without content when filters exist' (#8023) from lambadalambda/pleroma:fix/notification-filter-nil-content into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8023
2026-10-27 12:36:46 +00:00
Lain Soykaf
985ad29724
test(rate_limiter): use windows that cannot expire during the test
The bucket entry expires one window after the first request. With a 50
or 80 ms window, a slow CI run could lose it between two requests, so
inspect_bucket/3 returned {0, 5} (seen on #8021 with Elixir 1.17). The
reset test expires the bucket itself, so a long window costs nothing.
2026-10-27 16:10:14 +04:00
lain
c5498c018d Merge pull request 'MRF ObjectAgePolicy: keep old DMs and followers-only posts private' (#8019) from lambadalambda/pleroma:fix/object-age-non-public into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8019
2026-10-27 12:03:58 +00:00
Lain Soykaf
21a5d1dca2
fix(notifications): skip the filter check for objects without content
Regex.match? raised on objects without content (for example posts with
only attachments), so no notifications were created for them when the
recipient had an irreversible filter.
2026-10-27 12:53:21 +04:00
Lain Soykaf
04fbb59932
fix(federation): cancel queued deliveries to blocked instances
Delivery jobs only checked reachability, so a job queued (or retrying)
before the admin rejected or quarantined an instance was still sent.
Check should_federate? again when the job runs.
2026-10-27 12:51:14 +04:00
Lain Soykaf
422a1d1475
fix(filters): honour whole_word
The whole_word field was stored and returned by the API, but the regex
always used word boundaries. As in Mastodon, a filter with whole_word
false now also matches inside words.
2026-10-27 12:50:04 +04:00
Lain Soykaf
cccbb39309
fix(notifications): handle unknown users when filtering tagged mentions
The access check from the previous commit crashed on tags of unknown
users in followers-only posts, so such posts failed to be received.
Also add tests for the check.
2026-10-27 12:39:02 +04:00
Lain Soykaf
a766335679
fix(federation): do not deliver to instances rejected by SimplePolicy
Public activities went to every inbox, so followers on an instance in
the SimplePolicy reject list still got our posts. With authorized fetch
mode on, signed fetches from those instances were also accepted, unless
the instance was in :instance, :rejected_instances too.

Check the SimplePolicy reject and accept lists for deliveries and signed
fetches, when the policy is enabled. Quarantine keeps its meaning (no
private activities). An inbox without a host no longer crashes.

Based on the Akkoma changes 90c4785b8, ca000f830, 03662501c and d2b0d8647.

Co-authored-by: FloatingGhost <hannah@coffee-and-dreams.uk>
Co-authored-by: Atsuko Karagi <atsuko.karagi@localhost>
2026-10-27 12:38:18 +04:00
Lain Soykaf
f975db8719
fix(filters): treat phrases as literal text in the regex
Phrases went into the Postgres and Elixir regexes as they were, so a
phrase like "(" broke the timeline and notification queries. The :re
form also put the word boundaries only around the whole alternation.

Escape each phrase and, as Mastodon does, add a word boundary only where
the phrase starts or ends with a word character.

Reported in Akkoma (d6209837b).
2026-10-27 12:36:09 +04:00
Lain Soykaf
0d93c903f7
test(mrf): cover ObjectAgePolicy with private, direct and unlisted posts 2026-10-27 12:35:16 +04:00
Oneric
df5e756862
Do not notify users unable to access post
Known implementations all intend to only tag users who are _also_ allowed to access the post,
but this is not guaranteed by ActivityPub semantics, thus recheck against the authorative
AP addressing fields.
An alternative worth considering is directly using the addressing fields to decide whom
to notify ignoring tags. However, MastoAPI later uses tags and thus this may lead to
confusing results if a recipient is addressed but not tagged and receives a notification about
being mentioned while the API claims they are not mentioned.

Addresses the receiving side of: https://akkoma.dev/AkkomaGang/akkoma/issues/1135

(cherry picked from commit 5cff1fac24bb3e6c22160202a7b846f8a62f2477)
2026-10-27 12:31:14 +04:00
Oneric
2a55239ca8
mrf/object_age: fix handling of non-public objects
Current logic unconditionally adds public adressing to "cc"
and follower adressing to "to" after attempting to strip it
from the other one. This creates serious problems:

First the bug prompting this investigation and fix,
unconditional addition creates duplicates when adressing
URIs already were in their intended final field; e.g.
this is prominently the case for all "unlisted" posts.
Since List.delete only removes the first occurence,
this then broke follower-adress stripping later on
making the policy ineffective.

It’s also just not safe in general wrt to non-public adressing:
e.g. pre-existing duplicates didn’t get fully stripped,
bespoke adressing modes with only one of public addressing
or follower addressing are mangled — and most importantly:
any belatedly received DM or follower-only post
also got public adressing added!
Shockingly this last point was actually asserted as "correct" in tests;
it appears to be a mistake from mindless match adjustments
while fixing crashes on nil adressing in
10c792110e.

Clean up this sloppy logic up, making sure no more duplicates are
added by us, all instances of relevant adresses are purged and only
readded when they actually existed to begin with.

(cherry picked from commit 932810c35ecba9d11fa4f11112c3444b62c45b65)
2026-10-27 12:27:09 +04:00
lain
90eb5e4015 Merge pull request 'ActivityPub: check OAuth scopes on C2S endpoints' (#8015) from lambadalambda/pleroma:fix/ap-c2s-oauth-scopes into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8015
2026-10-27 07:08:48 +00:00
lain
745926189f Merge pull request 'OAuth: require security scopes for /api/oauth_tokens' (#8013) from lambadalambda/pleroma:fix/oauth-tokens-scopes into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8013
2026-10-27 07:08:34 +00:00
lain
b9fcb8bbe0 Merge pull request 'Remove unrouted PleromaAPI token and password controllers' (#8014) from lambadalambda/pleroma:chore/remove-dead-pleroma-api-controllers into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8014
2026-10-27 07:06:53 +00:00
lain
6963c22fcf Merge pull request 'OAuth: support the profile scope' (#8012) from lambadalambda/pleroma:feature/oauth-profile-scope into develop
Reviewed-on: https://git.pleroma.social/pleroma/pleroma/pulls/8012
2026-10-27 07:06:03 +00:00
lain
70f9b8542f Merge pull request 'Merge stable 2.11.1 into develop' (#8017) from merge-stable-2.11.1 into develop 2026-10-26 19:36:51 +00:00
Lain Soykaf
15361ea917
Merge stable 2.11.1 into develop 2026-10-26 22:40:31 +04:00
lain
762058f2c5 Merge pull request 'Release 2.11.1' (#8016) from release/2.11.1 into stable 2026-10-26 18:39:46 +00:00
Lain Soykaf
006ad1c7d0
Prepare 2.11.1 release 2026-10-26 22:02:51 +04:00
Lain Soykaf
26486b041b
docs(http): update hackney comments for 4.9 2026-10-26 22:02:41 +04:00
Lain Soykaf
48ec8518a3
fix(http): drop the partial body from truncated-read errors
Hackney 4.9 returns {:error, {:closed, partial}}. RelMe caches errors,
so it would keep up to max_body bytes per URL.
2026-10-26 22:02:18 +04:00