Compare commits

...

284 commits

Author SHA1 Message Date
Henry Jameson
8d82808d7a Merge remote-tracking branch 'origin/develop' into shigusegubu 2026-01-03 02:01:33 +02:00
lain
3d42219f12 Merge branch '2.10-mergeback' into 'develop'
Stable mergeback

See merge request pleroma/pleroma!4414
2025-12-31 14:56:45 +00:00
lain
3b99bbd955 Merge branch 'release/2.10' into 'stable'
Release/2.10

See merge request pleroma/pleroma!4413
2025-12-31 08:27:19 +00:00
Lain Soykaf
856bd7622e GitlabCI: Fix. 2025-12-31 11:40:27 +04:00
Lain Soykaf
e1e16656ce Merge in stable 2025-12-31 11:05:47 +04:00
Lain Soykaf
a5da6ce58e Changelog: Update changelog 2025-12-31 10:49:28 +04:00
Lain Soykaf
92fc8f0012 Merge branch 'release/2.10' into release/2.10-sec 2025-12-29 17:08:46 +04:00
Lain Soykaf
b9e333c307 Frontend: Actually use the correct build. 2025-12-29 17:08:20 +04:00
Lain Soykaf
e204bc150e Merge branch 'release/2.10' into release/2.10-sec 2025-12-29 09:49:53 +04:00
Lain Soykaf
c313c15d73 Mix: Fix version 2025-12-29 09:49:22 +04:00
Lain Soykaf
6c73ebe484 Merge branch 'phnt/mastoapi-misattribution-3381' into release/2.10-sec 2025-12-29 09:47:54 +04:00
Lain Soykaf
0127a10621 Changelog: Update changelog 2025-12-29 08:44:19 +04:00
Lain Soykaf
325c29c3fc Static: Update bundled frontend to 2.10 2025-12-29 08:32:29 +04:00
Lain Soykaf
19add4036d Mix: Bump version to 2.10 2025-12-29 08:23:14 +04:00
lain
d6888e24e4 Merge branch 'revert-cdd6df06' into 'develop'
Revert "Merge branch 'hackney-bump' into 'develop'"

See merge request pleroma/pleroma!4411
2025-12-26 05:08:43 +00:00
lain
23cb42a436 Revert "Merge branch 'hackney-bump' into 'develop'"
This reverts merge request !4409
2025-12-26 05:07:51 +00:00
Phantasm
38b3bff4e8
MastoAPI: Add more post attribution tests when fetched by Activity ID
Types returning 404:
- Accept
- Reject
- Delete
- Flag
- Follow
- Undo

Types returning posts:
- Create
- Update
- Like
- Announce
- EmojiReact
- Add/Remove
2025-12-25 20:40:21 +01:00
Phantasm
96de44b3d8
Tests AP Factory: fix featured collection factories
Internally it created Objects, tests passed Activities
2025-12-25 20:40:12 +01:00
lain
1a313fa30c Merge branch 'replies_collection' into 'develop'
Provide full replies collection in ActivityPub objects (ported from akkoma)

See merge request pleroma/pleroma!4370
2025-12-25 10:22:53 +00:00
lain
cdd6df0621 Merge branch 'hackney-bump' into 'develop'
Update Hackney

See merge request pleroma/pleroma!4409
2025-12-25 09:25:23 +00:00
Lain Soykaf
916c8c0581 ActivityPubController: Don't crash on unknown params 2025-12-25 13:04:09 +04:00
Lain Soykaf
e07b3d2442 ObjectView: Make the first reply collection a page, so it shows the actual items. 2025-12-25 12:54:09 +04:00
Lain Soykaf
8e94c5ca38 UserView: Followers != Follows 2025-12-25 12:53:36 +04:00
Lain Soykaf
fc15c25889 Transmogrifier: Only set replies on objects, not activities. 2025-12-25 12:50:55 +04:00
Lain Soykaf
4c537534ad NoteHandlingTest: Replies go on an object, not an activity. 2025-12-24 13:33:03 +04:00
Lain Soykaf
73b446bb07 ActivityPubControllerTest, UserViewTest: Add failing tests for reply collection related issues. 2025-12-24 12:20:11 +04:00
Mark Felder
3f9466e3a9 Update Hackney, the default HTTP client, to the latest release which supports Happy Eyeballs for improved IPv6 federation 2025-12-23 11:44:21 -08:00
Phantasm
07849927da
add changelogs 2025-12-23 18:38:34 +01:00
Phantasm
df375662d6
AP: simplify visible_for_user? conditions.
`true or true` returns `true`
2025-12-23 17:04:08 +01:00
Phantasm
7c93cd351b
MastoAPI StatusController: add tests for fetching context via Activity 2025-12-23 16:52:45 +01:00
Phantasm
ba8235ef50
lint 2025-12-23 16:51:59 +01:00
lain
2f48544937 Merge branch 'akkoma-fixes-1014-1018' into 'develop'
Status visibility checks for post interactions, stop leaking internal Activity representation (Akkoma PR 1014 and 1018)

Closes #3383

See merge request pleroma/pleroma!4400
2025-12-23 13:55:18 +00:00
Phantasm
b9601ae11a
MastoAPI: Add Announce and EmojiReact attribution tests
Introduces a new EmojiReact Activity factory
2025-12-23 00:17:16 +01:00
Phantasm
01ffaba3d2
MastoAPI: Fix unauth visibility checks when fetching by Activity FlakeID
- Adds another Pleroma.ActivityPub.Visibility.visible_for_user?/2 func
- Modifies existing tests to include a local Activity referencing a
  remote Object
- Changes Announce Activity test factory to reference Objects instead of
  Activities and use a different Actor for the Announce
- Changes ap_id of remote user in Announce test factory to match Objects
- Adds `object_local` option to Note factories that explicitly changes
  the domain in the URL to not match the endpoint URL in the test env
  to properly work with the new visibility func, since we don't store
  locality of Object unlike Activities
2025-12-23 00:07:16 +01:00
Phantasm
c2b40659e7
MastoAPI: Fix misattribution when fetching status by Activity FlakeID 2025-12-22 23:33:00 +01:00
lain
bd41d15100 Merge branch 'nginx-config-update' into 'develop'
Update Nginx config example

See merge request pleroma/pleroma!4277
2025-12-22 12:23:42 +00:00
Lain Soykaf
2b8a366f9b Nginx example: Add headers and use same paths we use in other places 2025-12-22 16:10:02 +04:00
Lain Soykaf
0f32134ea5 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into nginx-config-update 2025-12-22 13:51:25 +04:00
lain
1d366c0138 Merge branch 'transmogrifier/handle-as-public' into 'develop'
Transmogrifier: convert "as:Public" to full w3 URL

See merge request pleroma/pleroma!4394
2025-12-22 07:39:44 +00:00
lain
d19b992417 Merge branch 'webfinger-actual-fix' into 'develop'
Fix WebFinger for split-domain setups

See merge request pleroma/pleroma!4405
2025-12-22 07:38:55 +00:00
Lain Soykaf
e9d9724637 WebFinger: Tighten the requirements. 2025-12-21 17:46:39 +04:00
Lain Soykaf
f70d1a436b WebFingerTest: Add test for more webfinger spoofing. 2025-12-21 17:46:20 +04:00
lain
985a0a28c7 Merge branch 'docs-rum-idx' into 'develop'
Docs RUM: add OTP command, recommend vacuum after migration

See merge request pleroma/pleroma!4363
2025-12-21 11:36:39 +00:00
Lain Soykaf
ec58b6a4cc CommonFixes, Transmogrifier: Fix tests. 2025-12-21 15:19:38 +04:00
Lain Soykaf
4496dc81c4 TransmogrifierTest, CreateGenericValidatorTest: Add regression tests for addressing. 2025-12-21 15:19:05 +04:00
lain
1d44640655 Merge branch 'relayd-ipv6' into 'develop'
OpenBSD relayd: Fix IPv6 example

See merge request pleroma/pleroma!4408
2025-12-21 10:24:38 +00:00
Lain Soykaf
98f300c5ae Transmogrifier: Handle user updates. 2025-12-21 14:16:57 +04:00
Lain Soykaf
ed538603fb TransmogrifierTest: Add failing test for Update. 2025-12-21 14:04:19 +04:00
nicole mikołajczyk
45611c9881 Merge branch 'mastodon-quote-id-api' into 'develop'
Support `quoted_status_id` parameter in post creation request

See merge request pleroma/pleroma!4392
2025-12-17 20:52:08 +01:00
Phantasm
ed7ad7d96a
OpenBSD relayd: Fix IPv6 example
relayd has problems loading certs when IPv4 and IPv6 listens are in the
same relay block.
2025-12-17 19:11:20 +01:00
nicole mikołajczyk
e0ab2c9c9c Merge remote-tracking branch 'origin/develop' into mastodon-quote-id-api
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-12-17 13:43:45 +01:00
nicole mikołajczyk
c06fcc7f5d Merge branch 'order-favourites-reblogs' into 'develop'
Order favourites and reblogs list from newest to oldest

See merge request pleroma/pleroma!4399
2025-12-16 23:49:01 +01:00
nicole mikołajczyk
d41e2fbaaf Merge branch 'preferred-frontend' into 'develop'
Port Akkoma frontend preference code

See merge request pleroma/pleroma!4398
2025-12-16 20:54:00 +01:00
nicole mikołajczyk
8c9e130cc9 Merge branch 'description-improvement' into 'develop'
Use :list_behaviour_implementations for LanguageDetector and Translation providers

See merge request pleroma/pleroma!4407
2025-12-16 20:53:52 +01:00
nicole mikołajczyk
c6298be9f0 Merge branch 'scrobbles-scope' into 'develop'
Add `write:scrobbles` and `read:scrobbles` scope for scrobbling

See merge request pleroma/pleroma!4379
2025-12-16 20:53:32 +01:00
Phantasm
4b168691fe
add missing changelog 2025-12-16 20:42:34 +01:00
HJ
de022de4ce Merge branch 'scrubber-span-classes' into 'develop'
Allow "invisible" and "ellipsis" classes for span tags to match Mastodon behavior

See merge request pleroma/pleroma!4357
2025-12-16 16:56:11 +00:00
nicole mikołajczyk
d9baa0980d Merge branch 'normalize-actor-image-hrefs' into 'develop'
Add Actor images normalization from array of urls to string

See merge request pleroma/pleroma!4404
2025-12-16 10:49:51 +01:00
nicole mikołajczyk
c05d2d02c2 Use :list_behaviour_implementations for LanguageDetector and Translation providers
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-12-16 00:04:39 +01:00
nicole mikołajczyk
45af48520b this shouldn't be available outside the module
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-12-15 18:10:00 +01:00
nicole mikołajczyk
cacb2ce377 Update changelog
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-12-15 17:25:57 +01:00
nicole mikołajczyk
e5be1d04d6 Update tests, make the mastodon subdomain example not have the /.well-known/host-meta redirect, as the docs don't include it
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-12-15 17:01:56 +01:00
nicole mikołajczyk
3e2573f1c4 Fix WebFinger for split-domain set ups
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-12-15 17:01:53 +01:00
Phantasm
4985902b02
Add Actor images normalization from array of urls to string 2025-12-15 00:00:57 +01:00
Phantasm
3466b626d6
lint 2025-12-14 14:06:38 +01:00
Phantasm
d36d0abd27
API Docs: Switch some added 404 API response to ApiNotFoundError schema 2025-12-12 21:17:58 +01:00
Phantasm
49a5630c75
CommonAPI: Standardize visibility error, use helper function if possible 2025-12-12 18:05:58 +01:00
Phantasm
6f55763db4
add changelogs 2025-12-12 00:11:11 +01:00
Phantasm
53f23dd259
MastoAPI docs: Remove unused 403 respones 2025-12-12 00:04:28 +01:00
Phantasm
374305d5fe
AP C2S: Add reply test 2025-12-12 00:04:28 +01:00
Phantasm
fe7108cbc2
MastoAPI: Unify pin/bookmark/mute/fav not visible responses to 404
Also adds more tests for these interactions.
2025-12-12 00:04:27 +01:00
Phantasm
73a3f06f71
PleromaAPI: Change EmojiReact to invisible post response from 400 to 404 2025-12-12 00:03:59 +01:00
Phantasm
293628fb24
MastoAPI/CommonAPI: Return 404 when post not visible to user
Akkoma patches returned 403 and some of my previous commits returned 422.
This unifies the errors returned to 404 "Record not found", gaslighting
user just like we do for other endpoints and how Mastodon does it.
2025-12-11 23:32:21 +01:00
Phantasm
9d89156b84
AP C2S: Explicitly reject Updates to Actors that failed silently 2025-12-11 23:32:21 +01:00
Phantasm
63bdf4dc2b
C2S: New Add/Remove and Actor creation tests
Creating Actors via C2S doesn't make sense, thus it should fail.
Tests creating Actors with type: Application/Person/Service.

All Create Activities for new Actors currently fail with
`validator not set` in the pipeline.
2025-12-11 23:32:11 +01:00
Phantasm
426535bc38
CommonAPI: Forbid disallowed status (un)muting and unpinning
When a user tried to unpin a status not belonging to them, a full
MastoAPI response was sent back even if status was not visible to them.

Ditto with (un)mutting except ownership.
2025-12-11 23:30:04 +01:00
Phantasm
f914748510
Transmogrifier: make Listen Activity test more strict 2025-12-11 23:30:04 +01:00
Phantasm
3f16965178
Transmogrifier: update internal fields list according to constant 2025-12-11 23:30:04 +01:00
Phantasm
21b2fd1e05
AP C2S: reject Flag activities, add visibility refutes to some tests 2025-12-11 23:30:04 +01:00
Phantasm
7f3b3c2491
AP C2S: remove check for local user since user is already authenticated
Before a request arrives to update_outbox, it already passed through out
Plug authentication (:authenticate), so at this point all users should
be local.

Also adds Listen Activities to the list of allowed Activities that don't
need an existing normalized object referenced in them.
2025-12-11 23:30:04 +01:00
Phantasm
2b76243ec8
CommonAPI: Fail when user sends report with posts not visible to them 2025-12-11 23:30:03 +01:00
Phantasm
a4e480a636
lint and credo 2025-12-11 23:30:03 +01:00
Phantasm
b3887a6fa7
AP C2S: Validate visibility for C2S requests to /users/:nickname/outbox
A local user could previously send Announce/EmojiReact/Like activities
to their outbox referencing objects that aren't visible to them and they
would get processed as if can see them. Only requirement is knowing
the URI of the object and the users instance having C2S enabled (currently
disabled by default).
2025-12-11 23:30:03 +01:00
Phantasm
75353282ee
AP ObjectView: add test for Listen activities 2025-12-11 23:30:03 +01:00
Oneric
18d762c01b
Add voters key to internal object fields
It is inlined and used to keep track of who already voted for a poll.
This is expected to be confidential information and must no be exposed
2025-12-11 23:30:03 +01:00
Oneric
885ba3a46f
test: add more representation tests for perpare_outgoing
Port of commit 272799da6242dbf7387d2d42dfc98512cd7efd7e from
Akkoma PR 1018.

Changes from Akkoma commit:
- changed order of arguments in CommonAPI.(un)block, because Akkoma
  hasn't backported our change for the unified arg order yet

In particular this covers the case
e88f36f72b5317debafcc4209b91eb35ad8f0691 was meant to fix and
2025-12-11 23:30:03 +01:00
Oneric
a1662f05e0
fed/fetch: use same sanitisation logic as when delivering to inboxes
Port of commit 85171750f17725b71dcda098a5085b7f402cb061 from
Akkoma PR 1018.

Modifications from Akkoma patch:
- Pleroma.Web.ActivityPub.Utils.make_json_ld_header() calls had
  activity.data as argument.
- render() had Listen activities in activity_type, Akkoma only has
  Create activities there. Needs testing whether transmogrifier can
  handle this.

Original commit author: Oneric <oneric@oneric.stub>
Original commit message:
Duped code just means double the chance to mess up. This would have
prevented the leak of confidential info more minimally fixed in
6a8b8a14999f3ed82fdaedf6a53f9a391280df2f and  now furthermore
fixes the representation of Update activites which _need_ to have their
object inlined, as well as better interop for follow Accept and Reject
activities and all other special cases already handled in Transmogrifier.
It also means we get more thorough tests for free.

This also already adds JSON-LD context and does not add bogus Note-only
fields as happened before due to this views misuse of prepare_object
for activities. The doc of prepare_object clearly states it is only
intended for creatable objects, i.e. (for us) Notes and Questions.
2025-12-11 23:30:03 +01:00
Oneric
409698ca63
fed/out: ensure we never serve Updates for objects we deem static 2025-12-11 23:30:02 +01:00
Oneric
f8db412af4
fed/fetch: don't serve unsanitised object data for some activities
When the object associated with the activity was preloaded
(which happens automatically with Activity.normalize used in the
 controller) Object.normalize’s "id_only" option did not actually work.
This option and it’s usage were introduced to fix display of Undo
activities in e88f36f72b5317debafcc4209b91eb35ad8f0691.
For "Undo"s (and "Delete"s) there is no object preloaded
(since it is already gone from the database) thus this appeared
to work and for the particular case considered there in fact did.
Create activities use different rendering logic and thus remained
unaffected too.

However, for all other types of Activities (yes, including Update
which really _should_ include a properly sanitised, full object)
this new attempt at including "just the id", lead to it instead
including the full, unsanitised data of the referenced object.

This is obviously bad and can get worse due to access restrictions
on the activity being solely performed based on the addressing
of the activity itself, not of the (unintentionally) embedded
object.

Starting with the obvious, this leaks all "internal" fields
but as already mentioned in 8243fc0ef482a28daf2bcae2c64a9510bdb76489
all current "internal" fields from Constants.object_internal_fields
are already publicised via MastoAPI etc anyway. Assuming matching
addressing of the referenced object and activity this isn't problematic
with regard to confidentiality.
Except, the internal "voters" field recording who voted for a poll
is currently just omitted from Constants.object_internal_fields
and indeed confidential information (fix in subsequent commit).
Fortunately this list is for the poll as a whole and there are no
inlined lists for individual choices. While this thus leaks _who_
voted for a poll, it at least doesn't directly expose _what_ each voter
chose if there are multiple voters.

As alluded to before, the access restriction not being aware
of the misplaced object data into account makes the issue worse.
If the activity addressing is not a subset of the referenced object’s
addressing, this will leak private objects to unauthorised users.
This begs the question whether such mismatched addressing can occur.
For remote activities the answer is ofc a resounding YES,
but we only serve local ActivityPub objects and for the latter
it currently(!) seems like a "no".
For all intended interactions, the user interacting must already have
access to the object of interest and our ActivityPub Builder
already uses a subset of the original posts addressing for
posts not publicly accessible. This addressing creation logic
was last touched six years ago predating the introduction of this
exposure blunder.
The rather big caveat her being, until it was fixed just yesterday in
dff532ac723310903e58c5d28f897cc2d116594f it was indeed possible to
interact with posts one is not allowed to actually see. Combined, this
allowed unauthorised access to private posts. (The API ID of such
private posts can be obtained e.g. from replies one _is_ allowed to see)

During the time when ActivityPub C2S was supported there might have been
more ways to create activities with mismatched addressing and sneak a
peek on private posts. (The AP id can be obtained in an analogous way)

Replaces and fixes e88f36f72b5317debafcc4209b91eb35ad8f0691.
Since there never were any users of the
bugged "id_only" option it is removed.

This was reported by silverpill <silverpill@firemail.cc> as an
ActivityPub interop issue, since this blunder of course also
leads to invalid AP documents by adding an additional layer
in form of the "data" key and directly exposing the internal
Pleroma representation which is not always identical to valid AP.

Fixes: https://akkoma.dev/AkkomaGang/akkoma/issues/1017
2025-12-11 23:30:02 +01:00
Oneric
59fcb5c96e
api: ensure only visible posts are interactable
Port of Akkoma PR 1014 with a few changes:
- comments regarding akkomafe changed to Pleroma-FE when applicable
- different error message for replying to/interacting with invisible post
  in Pleroma.Web.CommonAPI.ActivityDraft.in_reply_to/1
- split "doesn't do funny things to other users favs" test into three:
  - can't unfavourite post that isn't favourited
  - can't unfavourite other user's favs
  - can't unfavourite other user's favs using their activity
- switched order of args for some CommonAPI function since Akkoma hasn't
  backported our old change for that

Pleroma.Web.CommonAPI.ActivityDraft.in_reply_to/1 now refactored to use
`with` statement as in Akkoma. Some defp in_reply_to/1 were therefore removed

Original PR author: Oneric
Original commit message:
It doesn't make sense to like, react, reply, etc to something you cannot
see and is unexpected for the author of the interacted with post and
might make them believe the reacting user actually _can_ see the post.

Wrt to fav, reblog, reaction indexes the missing visibility check was
also leaking some (presumably/hopefully) low-severity data.

Add full-API test for all modes of interactions with private posts.
2025-12-11 23:30:02 +01:00
nicole mikołajczyk
c8fc821a0e Merge branch 'nodeinfo-content-type' into 'develop'
Fix NodeInfo content-type

See merge request pleroma/pleroma!4401
2025-12-11 13:09:43 +01:00
lain
ed931a668f Merge branch 'url-encode-pt2' into 'develop'
Fix URL encoding of HTTP requests Pt2

See merge request pleroma/pleroma!4364
2025-12-10 16:34:31 +00:00
Phantasm
7d8a188967
Disable Hackney URL encoding function
Hackney interferes with out URI encoding and implements older RFC 2396
instead of RFC 3986 which we and Elixir implement. As an example "'"
and "!" will get encoded by it and cause problems with our MediaProxy
making unexpected 302 redirects.

If an admin supplies a different function via *.secret.exs, we
don't override it.

https://github.com/benoitc/hackney/issues/399
2025-12-10 14:56:07 +01:00
Phantasm
73b337245b
Make URI encoding query quirks host-aware 2025-12-10 14:56:06 +01:00
Phantasm
0f7ad318d3
Add encode_url @spec and docs, and a check whether opts are booleans 2025-12-10 14:56:06 +01:00
Phantasm
07ba3bb829
Remove "support" for path encoding quirks
Currently there isn't any known quirk that would be needed
and this is just dead code that does nothing.
2025-12-10 14:56:06 +01:00
Phantasm
bcdd78fba5
Add changelog 2025-12-10 14:56:06 +01:00
Phantasm
0935823be9
Add test for mangling incorrect URL in MediaProxy link generation 2025-12-10 14:56:06 +01:00
Phantasm
bfe8372ad2
Remove "preserve ASCII encoding" test in MediaProxy
issue 580: Should not happen again, tested in HTTPTest
issue 1055: Fixed with quirk support in query encoding, tested
in HTTPTest
2025-12-10 14:56:06 +01:00
Phantasm
c31454fac1
Fix unicode URL encoding test 2025-12-10 14:56:05 +01:00
Phantasm
f290b15987
Move custom URI encoding functions to Pleroma.Utils.URIEncoding 2025-12-10 14:56:05 +01:00
Phantasm
6487c93c47
credo lint 2 2025-12-10 14:56:05 +01:00
Phantasm
f36851acbd
credo lint 2025-12-10 14:56:05 +01:00
Phantasm
cfd2c08ef6
lint 2025-12-10 14:56:05 +01:00
Phantasm
a0f73d0e2f
Reimplement URI.encode_query/2 to support quirks, add Guardian quirk
This solves the issue with Guardian rich media cards not loading, thanks
to them using "," and ":" in queries which get improperly encoded.
Guardian also needs specific ordering of the query keys, this also fixes
that.
2025-12-10 14:56:05 +01:00
Phantasm
1b438fd167
MediaProxy: fix query params test
Elixir and Erlang both add a traling = when encoding queries
2025-12-10 14:56:04 +01:00
Phantasm
d413f9bf70
MediaProxy: fix Pleroma.HTTP.encode_url not being available in test env 2025-12-10 14:56:04 +01:00
Phantasm
004ea90b29
MediaProxy: Fix 424 caused by inconsistent %-encoding from remote instances
Notably this would fail to redirect to original proxied file when
preview generation criteria haven't been met.
2025-12-10 14:56:04 +01:00
Phantasm
9445ab9096
ReverseProxy: Log request after potentional %-encoding 2025-12-10 14:56:04 +01:00
Phantasm
99a1c0890a
URI.encode_query needs an enum, add test for this case 2025-12-10 14:56:04 +01:00
Phantasm
80db6f1328
Fix character escaping test for Pleroma.Upload 2025-12-10 14:56:04 +01:00
Phantasm
0a8423fdf7
Add ability to bypass url decode/parse in Pleroma.HTTP, fix encode in Pleroma.Upload 2025-12-10 14:56:03 +01:00
Phantasm
619f247e38
Add more URL-encoding tests 2025-12-10 14:56:03 +01:00
Phantasm
0f3b1808fd
Check what chars to encode in the path segment of URIs, add list to Constants
https://datatracker.ietf.org/doc/html/rfc3986
2025-12-10 14:56:03 +01:00
HJ
cc14a7e33b Merge branch 'hj-develop-patch-37634' into 'develop'
Allow FediIndex

See merge request pleroma/pleroma!4391
2025-12-08 18:28:55 +00:00
nicole mikołajczyk
40695530a6 Merge branch 'changelog/fix-checker' into 'develop'
changelog-checker: Change changelog entry type

See merge request pleroma/pleroma!4402
2025-12-02 19:36:51 +01:00
nicole mikołajczyk
df1a3b5a70 changelog-checker: Change changelog entry type 2025-12-02 19:36:50 +01:00
nicole mikołajczyk
90686f96d6 Merge branch 'changelog/fix-checker' into 'develop'
Fix changelog checker

See merge request pleroma/pleroma!4395
2025-12-02 19:35:19 +01:00
nicole mikołajczyk
32ab9d628e Add changelog entry
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-12-02 14:39:51 +01:00
Oneric
c1aad0f141 Fix NodeInfo content-type
Fixes: https://akkoma.dev/AkkomaGang/akkoma/issues/852
2025-12-02 14:39:22 +01:00
nicole mikołajczyk
d7b0115124 Merge branch 'mastodon-quotes-updates' into 'develop'
Use Mastodon-compatible route for quotes list and param for quotes count

See merge request pleroma/pleroma!4367
2025-12-02 14:34:16 +01:00
nicole mikołajczyk
21f486c872 Order favourites and reblogs list from newest to oldest
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-30 00:26:30 +01:00
nicole mikołajczyk
ca03d94f52 Merge branch 'pin-chats' into 'develop'
Chats: pin/unpin chats

See merge request pleroma/pleroma!3637
2025-11-29 18:45:42 +01:00
nicole mikołajczyk
6b8bc3bb4c Merge branch 'blocked-muted-swagger' into 'develop'
Use separate schemas for muted/blocked accounts lists

See merge request pleroma/pleroma!4359
2025-11-29 18:45:33 +01:00
nicole mikołajczyk
f443b6d1d7 Merge branch 'lookup-restrict-unauthenticated' into 'develop'
Respect restrict_unauthenticated in /api/v1/accounts/lookup

See merge request pleroma/pleroma!4355
2025-11-29 18:13:53 +01:00
nicole mikołajczyk
2330c50666 Merge branch 'inlinequotes-mastodon' into 'develop'
MRF InlineQuotePolicy: Don't inline quoted post URL in Mastodon quotes

See merge request pleroma/pleroma!4371
2025-11-29 18:12:33 +01:00
Phantasm
5cb141a54e MRF InlineQuotePolicy: Don't inline quoted post URL in Mastodon quotes 2025-11-29 18:12:32 +01:00
nicole mikołajczyk
e74b6ed348 Merge branch 'scrubber-inline-quotes-mastodon' into 'develop'
Scrubber: Allow `quote-inline` class in <p> tags used by Mastodon quotes

See merge request pleroma/pleroma!4373
2025-11-29 17:27:01 +01:00
nicole mikołajczyk
26a058935a Merge branch 'filter-user-capabilities' into 'develop'
Allow filtering users with `accepts_chat_messages` capability

See merge request pleroma/pleroma!4372
2025-11-29 17:26:01 +01:00
nicole mikołajczyk
6e98c7a1ca Merge branch 'rich-media-user-agent' into 'develop'
Allow setting custom user-agent for fetching rich media content

See merge request pleroma/pleroma!4390
2025-11-29 17:25:18 +01:00
nicole mikołajczyk
428e038c58 Merge branch 'notification-view-deduplicate' into 'develop'
remove duplicated code from notificationview

See merge request pleroma/pleroma!4356
2025-11-29 17:21:44 +01:00
Atsuko Karagi
ef41378fa2 Respect restrict_unauthenticated in /api/v1/accounts/lookup
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-29 17:18:38 +01:00
nicole mikołajczyk
be0146afb3 Improve example
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-29 17:10:24 +01:00
nicole mikołajczyk
d2f6cc1445 Use separate schemas for muted/blocked accounts lists
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-29 17:10:24 +01:00
nicole mikołajczyk
f61fad0663 Pin/unpin chats
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-29 16:53:56 +01:00
nicole mikołajczyk
0dfcc24d30 Merge branch 'translation-provider-translatelocally' into 'develop'
Support translateLocally translation provider

See merge request pleroma/pleroma!4377
2025-11-29 16:50:42 +01:00
nicole mikołajczyk
ba8b5682cc Merge branch 'stream-marker-updates' into 'develop'
Stream marker updates

See merge request pleroma/pleroma!4354
2025-11-29 16:49:29 +01:00
nicole mikołajczyk
cc51ee8662 analysis
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-29 16:46:08 +01:00
nicole mikołajczyk
367d5c65f6 Merge branch 'outgoing_follow_requests' into 'develop'
Add /api/v1/pleroma/outgoing_follow_requests

See merge request pleroma/pleroma!4310
2025-11-28 16:36:40 +01:00
nicole mikołajczyk
78c4332218 spec, changelog
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 16:32:51 +01:00
nicole mikołajczyk
5c139be42e Add tests
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 16:30:03 +01:00
nicole mikołajczyk
a80776b260 make it work
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 16:10:02 +01:00
nicole mikołajczyk
f1586f0230 im bad at merge conflicts
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 16:01:00 +01:00
FloatingGhost
1fd94ed001 ensure only pickable frontends can be returned 2025-11-28 15:59:18 +01:00
nicole mikołajczyk
fd177a363b cleanup
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 15:59:07 +01:00
Paweł Świątkowski
8827e51170 Fix OpenAPI spec for preferred_frontend endpoint
The spec was copied from another endpoint, including the operation id,
leading to scrubbing the valid parameters from the request and simply
not working.

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 15:56:42 +01:00
FloatingGhost
bb44501a9e Add frontend preference route 2025-11-28 15:53:01 +01:00
FloatingGhost
004f9fa69b add selection UI 2025-11-28 15:45:05 +01:00
FloatingGhost
3a5e8e5e07 ensure we send the right files for preferred fe
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 15:39:30 +01:00
nicole mikołajczyk
13bc4ba639 Merge remote-tracking branch 'origin/develop' into translation-provider-translatelocally
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 15:07:43 +01:00
mkljczk
e458bd953a Add /api/v1/pleroma/outgoing_follow_requests
Signed-off-by: mkljczk <git@mkljczk.pl>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 14:59:55 +01:00
nicole mikołajczyk
5f4c948057 fix typo
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-28 14:53:22 +01:00
nicole mikołajczyk
0476cf4283 Merge branch 'rss-redirect' into 'develop'
Redirect /users/:nickname.rss to /users/:nickname/feed.rss instead of .atom

See merge request pleroma/pleroma!4375
2025-11-28 14:51:11 +01:00
nicole mikołajczyk
e81e0d64c1 Merge branch 'endorsements-api' into 'develop'
Support new Mastodon API for endorsed accounts

See merge request pleroma/pleroma!4361
2025-11-28 14:51:06 +01:00
nicole mikołajczyk
ec51aadc78 Merge branch 'instance-view-timeline-access' into 'develop'
Add `timelines_access` to InstanceView

See merge request pleroma/pleroma!4393
2025-11-28 14:50:46 +01:00
nicole mikołajczyk
9548c31ef9 Merge branch 'translation-provider-mozhi' into 'develop'
Support Mozhi as translation provider

See merge request pleroma/pleroma!4376
2025-11-28 14:48:21 +01:00
nicole mikołajczyk
4fc1a62264 Merge branch 'notification-cleanup' into 'develop'
Minor cleanup and comment fixes

See merge request pleroma/pleroma!4397
2025-11-28 14:40:30 +01:00
nicole mikołajczyk
dc85b27990 Minor cleanup and comment fixes
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-25 13:52:50 +01:00
nicole mikołajczyk
79e59cb753 Merge branch 'status-push-notification' into 'develop'
Send push notifications for statuses from subscribed accounts

See merge request pleroma/pleroma!4396
2025-11-22 17:52:23 +01:00
nicole mikołajczyk
9da1875c36 Send push notifications for statuses from subscribed accounts
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-22 16:51:21 +01:00
Mint
6ed9d681b9 Transmogrifier: convert "as:Public" to full w3 URL 2025-11-08 07:39:46 +03:00
Mint
aef26a615e Fix changelog checker 2025-11-07 19:47:54 +03:00
nicole mikołajczyk
b975dce9ba Add timelines_access to InstanceView
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-11-02 00:01:31 +01:00
nicole mikołajczyk
a893c69d20 Merge branch 'remote-url-fix' into 'develop'
Make `remote_url` link to unproxied URL

See merge request pleroma/pleroma!4365
2025-11-01 23:51:27 +01:00
nicole mikołajczyk
09df007aef Merge branch 'plaroma' into 'develop'
i don't think it's called plaroma lol

See merge request pleroma/pleroma!4378
2025-11-01 11:25:57 +01:00
nicole mikołajczyk
724cdc44fc Fix typo in Pleroma name in docs 2025-11-01 11:25:55 +01:00
nicole mikołajczyk
68b4de7558 Merge branch 'authorized-fetch-fix' into 'develop'
Fix fetching public keys with authorized fetch enabled

See merge request pleroma/pleroma!4383
2025-11-01 11:25:17 +01:00
nicole mikołajczyk
b6e16877e6 Merge branch 'local-nickname-regex-fix' into 'develop'
Use end-of-string in regex for local `get_by_nickname`

See merge request pleroma/pleroma!4358
2025-11-01 11:24:41 +01:00
nicole mikołajczyk
c1699c6e60 Support quoted_status_id parameter in post creation request
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-31 16:07:43 +01:00
HJ
a275ffacaf changelog 2025-10-29 16:49:37 +00:00
HJ
ca098a2bea Allow FediIndex 2025-10-29 16:47:59 +00:00
nicole mikołajczyk
32a940b86b Allow setting custom user-agent for fetching rich media content
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-26 23:32:54 +01:00
feld
5bc454c265 Merge branch 'merge-stable' into 'stable'
Merge CI changes to stable

See merge request pleroma/pleroma!4389
2025-10-24 05:52:24 +00:00
Mark Felder
929ed42a44 CI: Use the dotenv report method to capture the spec-build internal job id and pass it through to the spec-deploy job 2025-10-23 22:18:17 -07:00
Mark Felder
464fb3fb60 Fix branch names for pleroma/docs and pleroma/api-docs triggers 2025-10-23 22:17:27 -07:00
Mark Felder
ea38015c9c CI: use triggers for docs and api-docs deployments
This is a "bridge job" which is more efficient. We do not need a token or API call then to make the CI run in the target repos.
2025-10-23 22:17:25 -07:00
Mark Felder
a39f08242a CI: Allow running pipelines from web or directly for a tag 2025-10-23 22:16:26 -07:00
Mark Felder
aab65fe854 GitLab support for default artifacts setting is broken
https://gitlab.com/gitlab-org/gitlab/-/issues/404563
2025-10-23 22:14:30 -07:00
Mark Felder
5337a0e223 Enable expiration of CICD job artifacts
We have accumulated nearly 200GB of old artifacts that we do not need.
2025-10-23 22:14:30 -07:00
Mark Felder
d15f98bdec CI: Use the dotenv report method to capture the spec-build internal job id and pass it through to the spec-deploy job 2025-10-23 21:14:12 -07:00
Mark Felder
6f7e521488 CI: pass the variable CI_PIPELINE_ID through to the api-docs build job 2025-10-23 17:27:25 -07:00
Mark Felder
b6da3f490b Fix branch names for pleroma/docs and pleroma/api-docs triggers 2025-10-23 13:41:26 -07:00
feld
d54ec39448 Merge branch 'pipeline-fix' into 'develop'
CI: use triggers for docs and api-docs deployments

See merge request pleroma/pleroma!4388
2025-10-23 19:22:00 +00:00
Mark Felder
d09ec25454 CI: use triggers for docs and api-docs deployments
This is a "bridge job" which is more efficient. We do not need a token or API call then to make the CI run in the target repos.
2025-10-23 12:20:25 -07:00
Phantasm
d1b01ae707
docs rum: use relative path for optional migrations for OTP installs 2025-10-23 21:14:31 +02:00
feld
6026046b1c Merge branch 'expire-artifacts' into 'develop'
CI: Allow running pipelines from web or directly for a tag

See merge request pleroma/pleroma!4387
2025-10-23 18:46:25 +00:00
Mark Felder
a0225ddc79 CI: Allow running pipelines from web or directly for a tag 2025-10-23 11:44:11 -07:00
feld
6942244bb1 Merge branch 'expire-artifacts' into 'develop'
GitLab CI support for default artifacts setting is broken

See merge request pleroma/pleroma!4385
2025-10-23 18:34:39 +00:00
Mark Felder
a07305ca34 GitLab support for default artifacts setting is broken
https://gitlab.com/gitlab-org/gitlab/-/issues/404563
2025-10-23 11:34:11 -07:00
feld
3ab1c3ae8a Merge branch 'expire-artifacts' into 'develop'
Enable expiration of CICD job artifacts

See merge request pleroma/pleroma!4384
2025-10-22 20:41:49 +00:00
Mark Felder
4f31cadbcc Enable expiration of CICD job artifacts
We have accumulated nearly 200GB of old artifacts that we do not need.
2025-10-22 13:39:52 -07:00
nicole mikołajczyk
606c9ae4b1 Merge branch 'fix-lists-bcc' into 'develop'
Fix publisher when publishing to a list of users

See merge request pleroma/pleroma!4360
2025-10-21 21:56:26 +02:00
nicole mikołajczyk
b38fedf342 Fix fetching public keys with authorized fetch enabled
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-21 21:46:03 +02:00
nicole mikołajczyk
1610d39f36 Revert "User.get_or_fetch_public_key_for_ap_id/1 is no longer required."
This reverts commit c0a50b7c3e.
2025-10-21 21:41:33 +02:00
nicole mikołajczyk
bb1e643996 Update changelog
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-15 11:01:18 +02:00
nicole mikołajczyk
ed1cfd6f5e Support translateLocally translation provider
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-15 11:00:37 +02:00
nicole mikołajczyk
27223fc5bc Add write:scrobbles and read:scrobbles scope for scrobbling
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-15 10:59:53 +02:00
nicole mikołajczyk
d56433be69 List Mozhi in suggestions for translation providers
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-15 10:31:56 +02:00
nicole mikołajczyk
7e34d72860 Support Mozhi as translation provider
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-15 10:31:30 +02:00
nicole mikołajczyk
50e3cc67fc Redirect /users/:nickname.rss to /users/:nickname/feed.rss instead of .atom
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-15 10:27:31 +02:00
nicole mikołajczyk
f989626bad Fix publisher when publishing to a list of users
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-10 05:37:01 +02:00
Nicole Mikołajczyk
0b8b98f979 Add a failing test
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-10 05:36:46 +02:00
nicole mikołajczyk
2012e83e20 Allow filtering users with accepts_chat_messages capability
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-10 05:24:13 +02:00
nicole mikołajczyk
889938d76a Scrubber: Allow quote-inline class in <p> tags used by Mastodon quotes
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-10 05:21:49 +02:00
nicole mikołajczyk
4288e2780b Add changelog entry
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-09 20:16:04 +02:00
Oneric
03210f487d provide full replies collection in ActivityPub objects
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-09 15:15:16 +02:00
nicole mikołajczyk
5ce3c12c28 Merge branch 'develop' into 'endorsements-api'
# Conflicts:
#   test/pleroma/web/pleroma_api/controllers/account_controller_test.exs
2025-10-08 05:04:55 +02:00
nicole mikołajczyk
c5b100a9f8 Merge branch 'develop' into 'mastodon-quotes-updates'
# Conflicts:
#   docs/development/API/differences_in_mastoapi_responses.md
2025-10-08 05:02:14 +02:00
nicole mikołajczyk
9eb923bd43 Merge branch 'docs' into 'develop'
Update *Differences in Mastodon API responses from vanilla Mastodon*

See merge request pleroma/pleroma!4369
2025-09-29 13:02:28 +02:00
nicole mikołajczyk
94188a293c Update *Differences in Mastodon API responses from vanilla Mastodon*
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
2025-09-29 07:51:17 +02:00
nicole mikołajczyk
8f9a139ba1 Merge branch 'notification-type-update' into 'develop'
Add `update` to @notification_types

See merge request pleroma/pleroma!4368
2025-09-27 14:35:09 +02:00
mkljczk
aaaf18c1c5 Merge branch 'update-poll-voters-count' into 'develop'
Update voters count in remote polls when refreshing

See merge request pleroma/pleroma!4366
2025-09-27 12:49:46 +02:00
nicole mikołajczyk
e666ddc9ba Add update to @notification_types
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-27 12:40:26 +02:00
nicole mikołajczyk
ef9bcb373a Use Mastodon-compatible route for quotes list and param for quotes count
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-27 11:44:45 +02:00
nicole mikołajczyk
a06d09ab15 Update voters count in remote polls when refreshing
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-27 10:50:51 +02:00
mkljczk
dccb264c42 Merge branch 'typo' into 'develop'
Fix typo in test name

See merge request pleroma/pleroma!4362
2025-09-19 17:34:36 +02:00
nicole mikołajczyk
546c03b2c6 remote_url links to unproxied URL
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-19 16:27:34 +02:00
Phantasm
846e0ae2cd
docs rum: Update idx size, add command for OTP install, recommend vacuum 2025-09-13 23:26:56 +02:00
Phantasm
928fb6d2e6
docs rum: Remove warning about lower PostgreSQL now unsupported versions 2025-09-13 23:26:56 +02:00
feld
1efe48672d Merge branch 'ldap-wtf' into 'develop'
Remove redundant code from register_changeset_ldap

See merge request pleroma/pleroma!4412
2025-09-12 16:51:54 +00:00
nicole mikołajczyk
32bc8ec580 Stream marker updates
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-07 23:48:01 +02:00
nicole mikołajczyk
c3c57ef6c4 remove duplicated code from notificationview
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-07 23:15:50 +02:00
nicole mikołajczyk
3be0d206bd Allow "invisible" and "ellipsis" classes for span tags to match Mastodon behavior
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-07 22:52:11 +02:00
nicole mikołajczyk
abdb511992 Fix typo in test name
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-07 22:41:25 +02:00
nicole mikołajczyk
cb7086cb18 Use end-of-string in regex for local get_by_nickname
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-09-07 22:37:48 +02:00
lain
d1d7dd1827 Merge branch 'from/upstream-develop/tusooa/report-anon' into 'develop'
Anonymize reports

Closes #2661 and #1024

See merge request pleroma/pleroma!3806
2025-09-05 12:15:19 +00:00
Lain Soykaf
5503247b15 PublisherTest: Linting. 2025-09-05 15:17:17 +04:00
Lain Soykaf
b023e1591c PublisherTest: Mock -> Mox 2025-09-05 15:04:33 +04:00
Lain Soykaf
3de250da23 PublisherTest: Use mox instead of mock. 2025-09-05 14:18:12 +04:00
Lain Soykaf
ae0c0260fd Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into pleroma-from/upstream-develop/tusooa/report-anon 2025-09-05 12:04:30 +04:00
Lain Soykaf
71785d7ff7 PublisherTest: Add test for signature replacement 2025-09-05 09:52:12 +04:00
lain
8de659d3fd Merge branch 'pleroma-fe-2.9.2' into 'develop'
Update Pleroma-FE version to 2.9.2

See merge request pleroma/pleroma!4404
2025-09-05 05:17:49 +00:00
Lain Soykaf
5bf1a384c7 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into pleroma-from/upstream-develop/tusooa/report-anon 2025-09-04 18:10:41 +04:00
Lain Soykaf
ffc93a10ab Mix: Remove double lazarus 2025-09-04 15:49:57 +04:00
Lain Soykaf
bbf4c6998d Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into pleroma-fe-2.9.2 2025-09-04 15:48:58 +04:00
Lain Soykaf
ff580a58ca Add changelog 2025-09-04 15:48:24 +04:00
Lain Soykaf
e2a9a4183f Update Pleroma-FE version to 2.9.2 2025-09-04 15:24:03 +04:00
lain
aaaed87899 Merge branch 'lazarus' into 'develop'
Add Oban.Plugins.Lazarus

See merge request pleroma/pleroma!4269
2025-08-30 08:33:57 +00:00
Lain Soykaf
348291cc3b Merge branch 'lazarus' of git.pleroma.social:pleroma/pleroma into lazarus 2025-08-30 10:21:55 +04:00
Lain Soykaf
0c4b5a9258 Mix, Gitlab, Docs: Require Elixir 1.15 2025-08-30 10:21:28 +04:00
Mark Felder
52323e1612 Add Oban.Plugins.Lazarus 2025-08-29 09:16:23 -07:00
Lain Soykaf
a5dbf8dead Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into lazarus 2025-08-27 15:27:37 +04:00
feld
14caaa8f23 Merge branch 'moderation-log-fix-3385' into 'develop'
Fix ModerationLog FunctionClauseError for unknown actions

Closes #3385

See merge request pleroma/pleroma!4384
2025-08-27 10:43:35 +00:00
lain
2980788c8e Merge branch 'admin-api-revocation' into 'develop'
Admin api revocation fix

Closes #3390

See merge request pleroma/pleroma!4382
2025-08-27 10:33:36 +00:00
lain
49376e6b75 Merge branch 'repost-repeat-filtering-3391' into 'develop'
Add only_reblogs parameter to account statuses API

Closes #3391

See merge request pleroma/pleroma!4385
2025-08-27 10:27:25 +00:00
lain
7e770d73c9 Merge branch 'update-dockerfile' into 'develop'
Dockerfile: Sync with CI, make more resilient

See merge request pleroma/pleroma!4401
2025-08-27 10:25:55 +00:00
Lain Soykaf
b9f623608a Dockerfile: Sync with CI, make more resilient 2025-08-27 14:07:21 +04:00
lain
91c0746b54 Merge branch 'update-docker-images-building-otp' into 'develop'
[CI] Upgrade Docker images building OTP

Closes #3389

See merge request pleroma/pleroma!4400
2025-08-27 10:06:18 +00:00
Codimp
933fe4fcf6 [CI] Upgrade Docker images building OTP 2025-08-27 10:06:18 +00:00
Lain Soykaf
8428a1bed3 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into lazarus 2025-08-27 11:43:32 +04:00
lain
c7ac7300ba Merge branch 'deps-update-2025-08' into 'develop'
mix.lock: mix deps.update --all

See merge request pleroma/pleroma!4398
2025-08-27 05:13:31 +00:00
Haelwenn (lanodan) Monnier
f78db5aaca
mix.lock: mix deps.update --all
Except gettext, due to API changes, that should be in dedicated MR
2025-08-15 04:22:54 +02:00
vaartis
7071e65a76 Merge branch 'docs/client_link_update' into 'develop'
clients.md: Update Source Code and Contact links

See merge request pleroma/pleroma!4317
2025-08-11 08:50:37 +00:00
Lain Soykaf
3a1581c945 add changelog 2025-08-01 10:39:42 -07:00
Lain Soykaf
bde52824d3 Fix ModerationLog FunctionClauseError for unknown actions
Add catchall clause to handle log entries with unknown actions or
malformed data. Prevents HTTP 500 errors in admin moderation log view.

Fixes #3385
2025-08-01 10:39:39 -07:00
Lain Soykaf
b13d5c2f88 Add changelog entry for only_reblogs parameter 2025-07-23 14:03:48 +04:00
Lain Soykaf
991c5e0c44 Add ActivityPub test for only_reblogs filtering 2025-07-23 14:02:49 +04:00
Lain Soykaf
f1cb334cd3 Document only_reblogs parameter in API differences 2025-07-23 14:00:57 +04:00
Lain Soykaf
331f21111c Add only_reblogs parameter to account statuses API
Implement filtering to show only reblogs/reposts in user status queries.
This complements the existing exclude_reblogs parameter. Supports both
boolean and "1" string values for consistency with other API parameters.
2025-07-23 13:30:25 +04:00
Lain Soykaf
606d64ceb6 Add changelog entry for admin self-revocation fix 2025-07-20 21:37:41 +04:00
Lain Soykaf
c38ce20a5d AdminApiController: Reorder functions to fix admin revocation 2025-07-20 21:33:39 +04:00
Lain Soykaf
28a2e3650d AdminAPI: Add (failing) test for admin self-revocation 2025-07-20 21:32:57 +04:00
Ekaterina Vaartis
871e9e8492 Make unaddressed_message? condsider [] as empty 2025-06-19 23:52:18 +03:00
Ekaterina Vaartis
1df7d428bc Update preparing and tests for current codebase 2025-06-18 22:10:04 +03:00
tusooa
9d62fca315 Add changelog for anonymizing reports 2025-06-18 19:14:42 +03:00
tusooa
58afb15eab Make ActivityPub.Publisher aware of the actor change by Transmogrifier 2025-06-18 19:14:37 +03:00
tusooa
b5c97e9ee0 Put strip and anonymize process in prepare_outgoing
It is not useful to call maybe_federate() with the processed
activity, because it will only record the activity id, and put
it into the queue. When the job is invoked, it reads from the database
for the activity. This means the changes we just made will be
discarded.

In this commit, I moved the stripping and anonymizing procedures
to Transmogrifier.prepare_outgoing, which is called after the
federator reads the activity from the database.
2025-06-18 19:03:05 +03:00
tusooa
1121f099e9 Ensure actor in Activity is also anonymized 2025-06-18 19:02:26 +03:00
tusooa
58ec4fd1ee Anonymize reporter before federating 2025-06-18 19:02:26 +03:00
tusooa
27d271b4ef Add maybe_anonymize_reporter/1 2025-06-18 19:02:25 +03:00
mkljczk
1f2d4dd634 Remove redundant code from register_changeset_ldap 2025-05-08 15:04:02 +02:00
Nicole Mikołajczyk
065200e92e Support new Mastodon API for endorsed accounts
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
2025-05-06 15:22:18 +02:00
NPL
c0c4bfd8cf clients.md: Update Source Code and Contact links 2025-01-23 12:33:32 +00:00
Mark Felder
045dfaf2af Fix nginx location for serving media directly 2024-10-30 10:48:23 -04:00
Mark Felder
503e43da5d Document the /uploads location more thoroughly 2024-09-25 15:36:20 -04:00
Mark Felder
2870140db2 The /media route has not existed for some years now 2024-09-25 15:27:30 -04:00
Mark Felder
90e0911cdb Provide full uploads config for a subdomain 2024-09-25 15:19:57 -04:00
Mark Felder
6b596ca8e2 Update the example Nginx config 2024-09-25 15:13:38 -04:00
Mark Felder
f06a7b51e2 Annotate the Nginx media upload limit 2024-09-25 15:13:33 -04:00
Mark Felder
887a45488b Provide example of configuring a dedicated media and proxy subdomain 2024-09-25 15:05:42 -04:00
Mark Felder
16796c292f Provide HTTP/3 config example 2024-09-25 14:44:48 -04:00
Mark Felder
537d4d19c5 Move to the new method to enable http2 instead of on the listen socket statement 2024-09-25 14:42:18 -04:00
Mark Felder
f53c34c5d6 Move Pleroma cache to /var/tmp
/tmp is increasingly becoming tmpfs on a lot of distros and in cloud environments, so putting the cache there by default will be problematic
2024-09-25 14:37:50 -04:00
Mark Felder
2c2de55b05 Add Oban.Plugins.Lazarus 2024-09-17 14:24:12 -04:00
632 changed files with 7519 additions and 1314 deletions

View file

@ -1,4 +1,4 @@
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.14.5-otp-25
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15.8-otp-26
variables: &global_variables
# Only used for the release
@ -16,9 +16,15 @@ workflow:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "develop"
- if: $CI_COMMIT_BRANCH == "stable"
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
# Default artifacts configuration
.default_artifacts: &default_artifacts
expire_in: 30 days
cache: &global_cache_policy
key: $CI_JOB_IMAGE-$CI_COMMIT_SHORT_SHA
paths:
@ -56,6 +62,7 @@ check-changelog:
before_script: ''
after_script: ''
cache: {}
artifacts: *default_artifacts
script:
- apk add git
- sh ./tools/check-changelog
@ -71,8 +78,9 @@ check-changelog:
.using-ci-base:
tags:
- amd64
artifacts: *default_artifacts
build-1.14.5-otp-25:
build-1.15.8-otp-26:
extends:
- .build_changes_policy
- .using-ci-base
@ -101,8 +109,12 @@ spec-build:
artifacts:
paths:
- spec.json
reports:
dotenv: build.env
expire_in: 42 years
script:
- mix pleroma.openapi_spec spec.json
- echo "SPEC_BUILD_JOB_ID=$CI_JOB_ID" >> build.env
benchmark:
extends:
@ -120,7 +132,7 @@ benchmark:
- mix ecto.migrate
- mix pleroma.load_testing
unit-testing-1.14.5-otp-25:
unit-testing-1.15.8-otp-26:
extends:
- .build_changes_policy
- .using-ci-base
@ -153,6 +165,7 @@ unit-testing-1.14.5-otp-25:
- su testuser -c "HOME=/home/testuser mix pleroma.test_runner --cover --preload-modules"
coverage: '/^Line total: ([^ ]*%)$/'
artifacts:
expire_in: 30 days
reports:
coverage_report:
coverage_format: cobertura
@ -171,6 +184,7 @@ unit-testing-1.18.3-otp-27:
formatting-1.15:
extends: .build_changes_policy
artifacts: *default_artifacts
image: &formatting_elixir elixir:1.15-alpine
stage: lint
cache: *testing_cache_policy
@ -185,6 +199,7 @@ formatting-1.15:
cycles-1.15:
extends: .build_changes_policy
artifacts: *default_artifacts
image: *formatting_elixir
stage: lint
cache: {}
@ -208,7 +223,7 @@ dialyzer:
- .using-ci-base
stage: lint
allow_failure: true
when: manual
when: manual
cache: *testing_cache_policy
tags:
- feld
@ -217,15 +232,14 @@ dialyzer:
docs-deploy:
stage: deploy
cache: *testing_cache_policy
image: alpine:latest
trigger:
project: pleroma/docs
branch: master
strategy: depend
only:
- stable@pleroma/pleroma
- develop@pleroma/pleroma
before_script:
- apk add curl
script:
- curl --fail-with-body -X POST -F"token=$DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" https://git.pleroma.social/api/v4/projects/673/trigger/pipeline
review_app:
image: alpine:3.9
stage: deploy
@ -241,6 +255,7 @@ review_app:
except:
- master
- develop
artifacts: *default_artifacts
script:
- echo "$CI_ENVIRONMENT_SLUG"
- mkdir -p ~/.ssh
@ -257,21 +272,19 @@ review_app:
spec-deploy:
stage: deploy
artifacts:
paths:
- spec.json
trigger:
project: pleroma/api-docs
branch: master
strategy: depend
only:
- develop@pleroma/pleroma
image: alpine:latest
before_script:
- apk add curl
script:
- curl --fail-with-body -X POST -F"token=$API_DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline
variables:
SPEC_BUILD_JOB_ID: $SPEC_BUILD_JOB_ID
stop_review_app:
image: alpine:3.9
stage: deploy
artifacts: *default_artifacts
before_script:
- apk update && apk add openssh-client git
when: manual
@ -290,7 +303,7 @@ stop_review_app:
amd64:
stage: release
image:
name: hexpm/elixir-amd64:1.17.3-erlang-26.2.5.6-ubuntu-focal-20241011
name: hexpm/elixir-amd64:1.17.3-erlang-27.3.4.2-ubuntu-noble-20250716
only: &release-only
- stable@pleroma/pleroma
- develop@pleroma/pleroma
@ -317,7 +330,7 @@ amd64:
VIX_COMPILATION_MODE: PLATFORM_PROVIDED_LIBVIPS
DEBIAN_FRONTEND: noninteractive
before_script: &before-release
- apt-get update && apt-get install -y cmake libmagic-dev libvips-dev erlang-dev git
- apt-get update && apt-get install -y cmake libmagic-dev libvips-dev erlang-dev git build-essential
- echo "import Config" > config/prod.secret.exs
- mix local.hex --force
- mix local.rebar --force
@ -333,7 +346,7 @@ amd64-musl:
artifacts: *release-artifacts
only: *release-only
image:
name: hexpm/elixir-amd64:1.17.3-erlang-26.2.5.6-alpine-3.17.9
name: hexpm/elixir-amd64:1.17.3-erlang-27.3.4.2-alpine-3.22.1
tags:
- amd64
cache: *release-cache
@ -377,7 +390,7 @@ arm64:
tags:
- arm
image:
name: hexpm/elixir-arm64:1.17.3-erlang-26.2.5.6-ubuntu-focal-20241011
name: hexpm/elixir-arm64:1.17.3-erlang-27.3.4.2-ubuntu-noble-20250716
cache: *release-cache
variables: *release-variables
before_script: *before-release
@ -390,7 +403,7 @@ arm64-musl:
tags:
- arm
image:
name: hexpm/elixir-arm64:1.17.3-erlang-26.2.5.6-alpine-3.17.9
name: hexpm/elixir-arm64:1.17.3-erlang-27.3.4.2-alpine-3.22.1
cache: *release-cache
variables: *release-variables
before_script: *before-release-musl

View file

@ -4,9 +4,113 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 2.10
### Security
- Admin API: Fixed self-revocation vulnerability where admins could accidentally revoke their own admin status via the single-user permission endpoint
- Fix bypass of the restrict unauthenticated setting by requesting local Activities
### Changed
- Add new activity actor/type index. Greatly speeds up retrieval of rare types (like "Listen")
- Use separate schemas for muted/blocked accounts lists
- Docs: Restore DB schema before data to avoid long restore times
- Return 404 with a better error message instead of 400 when receiving an activity for a deactivated user
- Deleting an instance queues individual jobs for each user that needs to be deleted from the server.
- Update Dockerfile to use Elixir 1.17.3, Erlang 26.2.5.6, and Alpine 3.17.9 to match CI release builds
- Docs RUM index: Add OTP install command, update index size expectation and recommend VACUUM FULL
- Support new Mastodon API for endorsed accounts
- Allow FediIndex crawler bot by default
- Update Cowboy, Gun, and Plug family of dependencies
- Hashtag searches return real results based on words in your query
- Support `quoted_status_id` parameter in post creation request
- Use Mastodon-compatible route for quotes list and param for quotes count
- Updated the example Nginx configuration
- Oban Notifier was changed to Oban.Notifiers.PG for performance and scalability benefits
- Updated relayd/httpd config files to be on par with nginx
- Order favourites and reblogs list from newest to oldest
- Update Pleroma-FE to 2.9.2
- Updated Postgrex library to 0.20.0
- Improved the logic of how we determine if a server is unreachable.
- Relax alsoKnownAs requirements to just URI, not necessarily HTTP(S)
- Redirect /users/:nickname.rss to /users/:nickname/feed.rss instead of .atom
- Add `write:scrobbles` and `read:scrobbles` scope for scrobbling
- Change scrobble external link param name to use snake case
- Allow "invisible" and "ellipsis" classes for span tags to match Mastodon behavior
- Change SMTP example to use the Mua adapter that works with OTP>25
- Updated Tesla to 1.15.3
- Truncate the length of Rich Media title and description fields
- Don't require an Accept header for WebFinger queries and default to JSON.
### Added
- Support Dislike activity, as sent by Mitra and Friendica, by changing it into a thumbs-down EmojiReact
- Support Mitra-style emoji likes.
- Added a way to upload new packs from a URL or ZIP file via Admin API
- Add `duration` to the block endpoint, which makes block expire
- Expose markup configuration in InstanceView
- Allow filtering users with `accepts_chat_messages` capability
- Add `timelines_access` to InstanceView
- Implement language detection with fastText
- Added MRF.QuietReply which prevents replies to public posts from being published to the timelines
- Oban.Plugins.Lazarus to help recover stuck jobs from an unclean shutdown of Pleroma
- Add /api/v1/pleroma/outgoing_follow_requests
- Allow users to select preferred frontend
- Provide full replies collection in ActivityPub objects
- Allow anonymizing reports sent to remote servers
- Add only_reblogs parameter to account statuses API for filtering to show only reblogs/reposts
- Allow setting custom user-agent for fetching rich media content
- Scrubber: Allow `quote-inline` class in <p> tags used by Mastodon quotes
- Add `base_urls` to the /api/v1/instance pleroma metadata which provides information about the base URLs for media_proxy and uploads when configured
- Stream marker updates
- Allow Terms of Service panel behaviour to be configurable
- Support translation providers (DeepL, LibreTranslate)
- Support Mozhi translation provider
- Support translateLocally translation provider
### Fixed
- AP C2S: Reject interactions with statuses not visible to Actor
- Fix AssignAppUser migration OOM
- Fix fetching public keys with authorized fetch enabled
- Fix building "captcha" library with OpenBSD make
- Use JSON for DeepL API requests
- Elixir 1.18: Fixed warnings and new deprecations
- Fix endorsement state display in relationship view
- Fix publisher when publishing to a list of users
- Fix reports being rejected when the activity had an empty CC or TO field (instead of not having them at all)
- Set PATH in the FreeBSD rc script to avoid failures starting the service
- Improved performance of status search queries using the default GIN index
- Use end-of-string in regex for local `get_by_nickname`
- Respect restrict_unauthenticated in /api/v1/accounts/lookup
- MastodonAPI: Reject interactions with statuses not visible to user
- Fix ModerationLog FunctionClauseError for unknown actions
- MRF InlineQuotePolicy: Don't inline quoted post URL in Mastodon quote posts
- Fix NodeInfo content-type
- Add Actor images normalization from array of urls to string
- Add `update` to @notification_types
- replaced depracated flags and functions, renamed service to fit other service files
- Allow to pin/unpip chats
- Fix federation issue where Public visibility information in cc field was lost when sent to remote servers, causing posts to appear with inconsistent visibility across instances
- OpenBSD relayd: Fix IPv6 example
- Fix release builds
- `remote_url` links to unproxied URL
- Send push notifications for statuses from subscribed accounts
- Backport [Elixir PR 14242](https://github.com/elixir-lang/elixir/pull/14242) fixing racy mkdir and lack of error handling of parent directory creation
- Transmogrifier: convert "as:Public" to full w3 URL
- Update voters count in remote polls when refreshing
- Fix sometimes incorrect URI percent encoding
- Fix HTTP client making invalid requests due to no percent encoding processing or validation.
- ObjectView: Do not leak unsanitized internal representation of non-Create/non-Undo Activities on fetches
- Fix WebFinger for split-domain setups
- Enforce an exact domain match for WebFinger resolution
- MastodonAPI: Fix misattribution of statuses when fetched via non-Announce Activity ID
## 2.9.1
### Security
- Fix authorization checks for C2S Update activities to prevent unauthorized modifications of other users' content.
- Fix content-type spoofing vulnerability that could allow users to upload ActivityPub objects as attachments
- Reject cross-domain redirects when fetching ActivityPub objects to prevent bypassing domain-based security controls.
@ -16,27 +120,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Validate Content-Type headers when fetching remote ActivityPub objects to prevent spoofing attacks.
### Changed
- Include `pl-fe` in available frontends
### Fixed
- Remove trailing ` from end of line 75 which caused issues copy-pasting
## 2.9.0
### Security
- Require HTTP signatures (if enabled) for routes used by both C2S and S2S AP API
- Fix several spoofing vectors
### Changed
- Performance: Use 301 (permanent) redirect instead of 302 (temporary) when redirecting small images in media proxy. This allows browsers to cache the redirect response.
- Performance: Use 301 (permanent) redirect instead of 302 (temporary) when redirecting small images in media proxy. This allows browsers to cache the redirect response.
### Added
- Include "published" in actor view
- Link to exported outbox/followers/following collections in backup actor.json
- Hashtag following
- Allow to specify post language
### Fixed
- Verify a local Update sent through AP C2S so users can only update their own objects
- Fix Mastodon incoming edits with inlined "likes"
- Allow incoming "Listen" activities
@ -46,11 +156,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix blurhash generation crashes
### Removed
- Retire MRFs DNSRBL, FODirectReply, and QuietReply
## 2.8.0
### Changed
- Metadata: Do not include .atom feed links for remote accounts
- Bumped `fast_html` to v2.3.0, which notably allows to use system-installed lexbor with passing `WITH_SYSTEM_LEXBOR=1` environment variable at build-time
- Dedupe upload filter now uses a three-level sharding directory structure
@ -71,6 +183,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Worker configuration is no longer available. This only affects custom max_retries values for a couple Oban queues.
### Added
- Add metadata provider for ActivityPub alternate links
- Added support for argon2 passwords and their conversion for migration from Akkoma fork to upstream.
- Respect :restrict_unauthenticated for hashtag rss/atom feeds
@ -88,6 +201,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Include session scopes in TokenView
### Fixed
- Verify a local Update sent through AP C2S so users can only update their own objects
- Fixed malformed follow requests that cause them to appear stuck pending due to the recipient being unable to process them.
- Fix incoming Block activities being rejected
@ -105,14 +219,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Make vapid_config return empty array, fixing preloading for instances without push notifications configured
### Removed
- Remove stub for /api/v1/accounts/:id/identity_proofs (deprecated by Mastodon 3.5.0)
## 2.7.1
### Changed
- Accept `application/activity+json` for requests to `/.well-known/nodeinfo`
### Fixed
- Truncate remote user fields, avoids them getting rejected
- Improve the `FollowValidator` to successfully incoming activities with an errant `cc` field.
- Resolved edge case where the API can report you are following a user but the relationship is not fully established.
@ -122,16 +239,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 2.7.0
### Security
- HTTP Security: By default, don't allow unsafe-eval. The setting needs to be changed to allow Flash emulation.
- Fix webfinger spoofing.
- Use proper workers for fetching pins instead of an ad-hoc task, fixing a potential fetch loop
### Changed
- Update to Phoenix 1.7
- Elixir Logger configuration is now longer permitted through AdminFE and ConfigDB
- Refactor the user backups code and improve test coverage
- Invalid activities delivered to the inbox will be rejected with a 400 Bad Request
- Support Bandit as an alternative to Cowboy for the HTTP server.
- Support Bandit as an alternative to Cowboy for the HTTP server.
- Update Bandit to 1.5.2
- Replace eblurhash with rinpatch_blurhash. This also removes a dependency on ImageMagick.
- Elixir 1.13 is the minimum required version.
@ -170,6 +289,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Refactor the Mastodon /api/v1/streaming websocket handler to use Phoenix.Socket.Transport
### Added
- Uploader: Add support for uploading attachments using IPFS
- Add NSFW-detecting MRF
- Add DNSRBL MRF
@ -215,6 +335,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Support honk-style attachment summaries as alt-text.
### Fixed
- Fix Emoji object IDs not always being valid
- Remove checking ImageMagick's commands for Pleroma.Upload.Filter.AnalyzeMetadata
- Ensure that StripLocation actually removes everything resembling GPS data from PNGs
@ -257,7 +378,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix Optimistic Inbox for failed signatures
- MediaProxy Preview failures prevented when encountering certain video files
- pleroma_ctl: Use realpath(1) instead of readlink(1)
- ReceiverWorker: Make sure non-{:ok, _} is returned as {:error, …}
- ReceiverWorker: Make sure non-{:ok, \_} is returned as {:error, …}
- Harden Rich Media parsing against very slow or malicious URLs
- Rich Media Preview cache eviction when the activity is updated.
- Parsing of RichMedia TTLs for Amazon URLs when query parameters are nil
@ -269,32 +390,41 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fix validate_webfinger when running a different domain for Webfinger
### Removed
- Mastodon API: Remove deprecated GET /api/v1/statuses/:id/card endpoint https://github.com/mastodon/mastodon/pull/11213
- Removed support for multiple federator modules as we only support ActivityPub
## 2.6.2
### Security
- MRF StealEmojiPolicy: Sanitize shortcodes (thanks to Hazel K for the report
## 2.6.1
### Changed
- - Document maximum supported version of Erlang & Elixir
### Added
- [docs] add frontends management documentation
### Fixed
- TwitterAPI: Return proper error when healthcheck is disabled
- Fix eblurhash and elixir-captcha not using system cflags
## 2.6.0
### Security
- Preload: Make generated JSON html-safe. It already was html safe because it only consists of config data that is base64 encoded, but this will keep it safe it that ever changes.
- CommonAPI: Prevent users from accessing media of other users by creating a status with reused attachment ID
- Disable XML entity resolution completely to fix a dos vulnerability
### Added
- Support for Image activities, namely from Hubzilla
- Add OAuth scope descriptions
- Allow lang attribute in status text
@ -305,6 +435,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add unified streaming endpoint
### Fixed
- rel="me" was missing its cache
- MediaProxy responses now return a sandbox CSP header
- Filter context activities using Visibility.visible_for_user?
@ -326,6 +457,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Show more informative errors when profile exceeds char limits
### Removed
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
- remove BBS/SSH feature, replaced by an external bridge.
- Remove a few unused indexes.
@ -335,56 +467,67 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 2.5.4
## Security
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
## 2.5.3
### Security
- Emoji pack loader sanitizes pack names
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
## 2.5.5
## Security
- Prevent users from accessing media of other users by creating a status with reused attachment ID
## 2.5.4
## Security
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem
## 2.5.3
### Security
- Emoji pack loader sanitizes pack names
- Reduced permissions of config files and directories, distros requiring greater permissions like group-read need to pre-create the directories
## 2.5.2
### Security
- `/proxy` endpoint now sets a Content-Security-Policy (sandbox)
- WebSocket endpoint now respects unauthenticated restrictions for streams of public posts
- OEmbed HTML tags are now filtered
### Changed
- docs: Be more explicit about the level of compatibility of OTP releases
- Set default background worker timeout to 15 minutes
### Fixed
- Atom/RSS formatting (HTML truncation, published, missing summary)
- Remove `static_fe` pipeline for `/users/:nickname/feed`
- Stop oban from retrying if validating errors occur when processing incoming data
- Make sure object refetching as used by already received polls follows MRF rules
### Removed
- BREAKING: Support for passwords generated with `crypt(3)` (Gnu Social migration artifact)
## 2.5.1
### Added
- Allow customizing instance languages
### Fixed
- Security: uploading HTTP endpoint can no longer create directories in the upload dir (internal APIs, like backup, still can do it.)
- ~ character in urls in Markdown posts are handled properly
- Exiftool upload filter will now ignore SVG files
@ -405,6 +548,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Quack, the logging backend that pushes to Slack channels
### Changed
- **Breaking:** Elixir >=1.11 is now required (was >= 1.9)
- Allow users to remove their emails if instance does not need email to register
- Uploadfilter `Pleroma.Upload.Filter.Exiftool` has been renamed to `Pleroma.Upload.Filter.Exiftool.StripLocation`
@ -415,6 +559,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- CSP now includes wasm-unsafe-eval
### Added
- `activeMonth` and `activeHalfyear` fields in NodeInfo usage.users object
- Experimental support for Finch. Put `config :tesla, :adapter, {Tesla.Adapter.Finch, name: MyFinch}` in your secrets file to use it. Reverse Proxy will still use Hackney.
- `ForceMentionsInPostContent` MRF policy
@ -436,6 +581,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Possibility to discover users like `user@example.org`, while Pleroma is working on `pleroma.example.org`. Additional configuration required.
### Fixed
- Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies
- Handle Reject for already-accepted Follows properly
- Display OpenGraph data on alternative notice routes.
@ -458,6 +604,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 2.4.5 - 2022-11-27
## Fixed
- Image `class` attributes not being scrubbed, allowing to exploit frontend special classes [!3792](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3792)
- Delete report notifs when demoting from superuser [!3642](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3642)
- Validate `mediaType` only by it's format rather than using a list [!3597](https://git.pleroma.social/pleroma/pleroma/-/merge_requests/3597)
@ -472,17 +619,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 2.4.4 - 2022-08-19
### Security
- Streaming API sessions will now properly disconnect if the corresponding token is revoked
## 2.4.3 - 2022-05-06
### Security
- Private `/objects/` and `/activities/` leaking if cached by authenticated user
- SweetXML library DTD bomb
## 2.4.2 - 2022-01-10
### Fixed
- Federation issues caused by HTTP pool checkout timeouts
- Compatibility with Elixir 1.13
@ -493,12 +643,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## 2.4.1 - 2021-08-29
### Changed
- Make `mix pleroma.database set_text_search_config` run concurrently and indefinitely
### Added
- AdminAPI: Missing configuration description for StealEmojiPolicy
### Fixed
- MastodonAPI: Stream out Create activities
- MRF ObjectAgePolicy: Fix pattern matching on "published"
- TwitterAPI: Make `change_password` and `change_email` require params on body instead of query
@ -537,6 +690,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Pinned posts federation
### Fixed
- Don't crash so hard when email settings are invalid.
- Checking activated Upload Filters for required commands.
- Remote users can no longer reappear after being deleted.
@ -554,6 +708,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fixed some Markdown issues, including trailing slash in links.
### Removed
- **Breaking**: Remove deprecated `/api/qvitter/statuses/notifications/read` (replaced by `/api/v1/pleroma/notifications/read`)
## [2.3.0] - 2021-03-01
@ -672,6 +827,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [2.2.1] - 2020-12-22
### Changed
- Updated Pleroma FE
### Fixed
@ -724,7 +880,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **Breaking:** `Pleroma.Workers.Cron.ClearOauthTokenWorker` setting from Oban `:crontab` (moved to scheduled jobs).
- **Breaking:** `Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker` setting from Oban `:crontab` (moved to scheduled jobs).
- Removed `:managed_config` option. In practice, it was accidentally removed with 2.0.0 release when frontends were
switched to a new configuration mechanism, however it was not officially removed until now.
switched to a new configuration mechanism, however it was not officially removed until now.
### Added
@ -755,8 +911,10 @@ switched to a new configuration mechanism, however it was not officially removed
1. Install libmagic and development headers (`libmagic-dev` on Ubuntu/Debian, `file-dev` on Alpine Linux)
2. Run database migrations (inside Pleroma directory):
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
3. Restart Pleroma
## [2.1.2] - 2020-09-17
@ -784,6 +942,7 @@ switched to a new configuration mechanism, however it was not officially removed
## [2.1.1] - 2020-09-08
### Security
- Fix possible DoS in Mastodon API user search due to an error in match clauses, leading to an infinite recursion and subsequent OOM with certain inputs.
- Fix metadata leak for accounts and statuses on private instances.
- Fix possible DoS in Admin API search using an atom leak vulnerability. Authentication with admin rights was required to exploit.
@ -794,6 +953,7 @@ switched to a new configuration mechanism, however it was not officially removed
- Improved error message when cmake is not available at build stage.
### Added
- Rich media failure tracking (along with `:failure_backoff` option).
<details>
@ -803,6 +963,7 @@ switched to a new configuration mechanism, however it was not officially removed
</details>
### Fixed
- Default HTTP adapter not respecting pool setting, leading to possible OOM.
- Fixed uploading webp images when the Exiftool Upload Filter is enabled by skipping them
- Mastodon API: Search parameter `following` now correctly returns the followings rather than the followers
@ -908,6 +1069,7 @@ switched to a new configuration mechanism, however it was not officially removed
</details>
### Fixed
- Fix list pagination and other list issues.
- Support pagination in conversations API
- **Breaking**: SimplePolicy `:reject` and `:accept` allow deletions again
@ -928,9 +1090,11 @@ switched to a new configuration mechanism, however it was not officially removed
## [2.0.7] - 2020-06-13
### Security
- Fix potential DoSes exploiting atom leaks in rich media parser and the `UserAllowListPolicy` MRF policy
### Fixed
- CSP: not allowing images/media from every host when mediaproxy is disabled
- CSP: not adding mediaproxy base url to image/media hosts
- StaticFE missing the CSS file
@ -942,28 +1106,36 @@ switched to a new configuration mechanism, however it was not officially removed
## [2.0.6] - 2020-06-09
### Security
- CSP: harden `image-src` and `media-src` when MediaProxy is used
### Fixed
- AP C2S: Fix pagination in inbox/outbox
- Various compilation errors on OTP 23
- Mastodon API streaming: Repeats from muted threads not being filtered
### Changed
- Various database performance improvements
### Upgrade notes
1. Run database migrations (inside Pleroma directory):
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
2. Restart Pleroma
## [2.0.5] - 2020-05-13
### Security
- Fix possible private status leaks in Mastodon Streaming API
### Fixed
- Crashes when trying to block a user if block federation is disabled
- Not being able to start the instance without `erlang-eldap` installed
- Users with bios over the limit getting rejected
@ -976,9 +1148,11 @@ switched to a new configuration mechanism, however it was not officially removed
## [2.0.4] - 2020-05-10
### Security
- AP C2S: Fix a potential DoS by creating nonsensical objects that break timelines
### Fixed
- Peertube user lookups not working
- `InsertSkeletonsForDeletedUsers` migration failing on some instances
- Healthcheck reporting the number of memory currently used, rather than allocated in total
@ -990,6 +1164,7 @@ switched to a new configuration mechanism, however it was not officially removed
#### Apache only
1. Remove the following line from your config:
```
SSLCertificateFile /etc/letsencrypt/live/${servername}/cert.pem
```
@ -1001,11 +1176,13 @@ switched to a new configuration mechanism, however it was not officially removed
## [2.0.3] - 2020-05-02
### Security
- Disallow re-registration of previously deleted users, which allowed viewing direct messages addressed to them
- Mastodon API: Fix `POST /api/v1/follow_requests/:id/authorize` allowing to force a follow from a local user even if they didn't request to follow
- CSP: Sandbox uploads
### Fixed
- Notifications from blocked domains
- Potential federation issues with Mastodon versions before 3.0.0
- HTTP Basic Authentication permissions issue
@ -1016,6 +1193,7 @@ switched to a new configuration mechanism, however it was not officially removed
- `blob:` urls not being allowed by CSP
### Added
- NodeInfo: ObjectAgePolicy settings to the `federation` list.
- Follow request notifications
<details>
@ -1027,19 +1205,24 @@ switched to a new configuration mechanism, however it was not officially removed
1. Restart Pleroma
2. Run database migrations (inside Pleroma directory):
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
3. Reset status visibility counters (inside Pleroma directory):
- OTP: `./bin/pleroma_ctl refresh_counter_cache`
- From Source: `mix pleroma.refresh_counter_cache`
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
3. Reset status visibility counters (inside Pleroma directory):
- OTP: `./bin/pleroma_ctl refresh_counter_cache`
- From Source: `mix pleroma.refresh_counter_cache`
## [2.0.2] - 2020-04-08
### Added
- Support for Funkwhale's `Audio` activity
- Admin API: `PATCH /api/pleroma/admin/users/:nickname/update_credentials`
### Fixed
- Blocked/muted users still generating push notifications
- Input textbox for bio ignoring newlines
- OTP: Inability to use PostgreSQL databases with SSL
@ -1047,13 +1230,17 @@ switched to a new configuration mechanism, however it was not officially removed
- Incorrect URL for Funkwhale channels
### Upgrade notes
1. Restart Pleroma
## [2.0.1] - 2020-03-15
### Security
- Static-FE: Fix remote posts not being sanitized
### Fixed
- Rate limiter crashes when there is no explicitly specified ip in the config
- 500 errors when no `Accept` header is present if Static-FE is enabled
- Instance panel not being updated immediately due to wrong `Cache-Control` headers
@ -1064,24 +1251,33 @@ switched to a new configuration mechanism, however it was not officially removed
- Mastodon Streaming API: hashtag timelines not working
### Changed
- BBCode and Markdown formatters will no longer return any `\n` and only use `<br/>` for newlines
- Mastodon API: Allow registration without email if email verification is not enabled
### Upgrade notes
#### Nginx only
1. Remove `proxy_ignore_headers Cache-Control;` and `proxy_hide_header Cache-Control;` from your config.
#### Everyone
1. Run database migrations (inside Pleroma directory):
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
- OTP: `./bin/pleroma_ctl migrate`
- From Source: `mix ecto.migrate`
2. Restart Pleroma
## [2.0.0] - 2019-03-08
### Security
- Mastodon API: Fix being able to request enormous amount of statuses in timelines leading to DoS. Now limited to 40 per request.
### Removed
- **Breaking**: Removed 1.0+ deprecated configurations `Pleroma.Upload, :strip_exif` and `:instance, :dedupe_media`
- **Breaking**: OStatus protocol support
- **Breaking**: MDII uploader
@ -1093,6 +1289,7 @@ switched to a new configuration mechanism, however it was not officially removed
</details>
### Changed
- **Breaking:** Pleroma won't start if it detects unapplied migrations
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
- **Breaking:** `Pleroma.Plugs.RemoteIp` and `:rate_limiter` enabled by default. Please ensure your reverse proxy forwards the real IP!
@ -1142,6 +1339,7 @@ switched to a new configuration mechanism, however it was not officially removed
</details>
### Added
- `:chat_limit` option to limit chat characters.
- `cleanup_attachments` option to remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
- Refreshing poll results for remote polls
@ -1209,6 +1407,7 @@ switched to a new configuration mechanism, however it was not officially removed
</details>
### Fixed
- Report emails now include functional links to profiles of remote user accounts
- Not being able to log in to some third-party apps when logged in to MastoFE
- MRF: `Delete` activities being exempt from MRF policies
@ -1228,7 +1427,9 @@ switched to a new configuration mechanism, however it was not officially removed
</details>
## [1.1.9] - 2020-02-10
### Fixed
- OTP: Inability to set the upload limit (again)
- Not being able to pin polls
- Streaming API: incorrect handling of reblog mutes
@ -1236,98 +1437,132 @@ switched to a new configuration mechanism, however it was not officially removed
- OpenGraph provider: html entities in descriptions
## [1.1.8] - 2020-01-10
### Fixed
- Captcha generation issues
- Returned Kocaptcha endpoint to configuration
- Captcha validity is now 5 minutes
## [1.1.7] - 2019-12-13
### Fixed
- OTP: Inability to set the upload limit
- OTP: Inability to override node name/distribution type to run 2 Pleroma instances on the same machine
### Added
- Integrated captcha provider
### Changed
- Captcha enabled by default
- Default Captcha provider changed from `Pleroma.Captcha.Kocaptcha` to `Pleroma.Captcha.Native`
- Better `Cache-Control` header for static content
### Bundled Pleroma-FE Changes
#### Added
- Icons in the navigation panel
#### Fixed
- Improved support unauthenticated view of private instances
#### Removed
- Whitespace hack on empty post content
## [1.1.6] - 2019-11-19
### Fixed
- Not being able to log into to third party apps when the browser is logged into mastofe
- Email confirmation not being required even when enabled
- Mastodon API: conversations API crashing when one status is malformed
### Bundled Pleroma-FE Changes
#### Added
- About page
- Meme arrows
#### Fixed
- Image modal not closing unless clicked outside of image
- Attachment upload spinner not being centered
- Showing follow counters being 0 when they are actually hidden
## [1.1.5] - 2019-11-09
### Fixed
- Polls having different numbers in timelines/notifications/poll api endpoints due to cache desyncronization
- Pleroma API: OAuth token endpoint not being found when ".json" suffix is appended
### Changed
- Frontend bundle updated to [044c9ad0](https://git.pleroma.social/pleroma/pleroma-fe/commit/044c9ad0562af059dd961d50961a3880fca9c642)
## [1.1.4] - 2019-11-01
### Fixed
- Added a migration that fills up empty user.info fields to prevent breakage after previous unsafe migrations.
- Failure to migrate from pre-1.0.0 versions
- Mastodon API: Notification stream not including follow notifications
## [1.1.3] - 2019-10-25
### Fixed
- Blocked users showing up in notifications collapsed as if they were muted
- `pleroma_ctl` not working on Debian's default shell
## [1.1.2] - 2019-10-18
### Fixed
- `pleroma_ctl` trying to connect to a running instance when generating the config, which of course doesn't exist.
## [1.1.1] - 2019-10-18
### Fixed
- One of the migrations between 1.0.0 and 1.1.0 wiping user info of the relay user because of unexpected behavior of postgresql's `jsonb_set`, resulting in inability to post in the default configuration. If you were affected, please run the following query in postgres console, the relay user will be recreated automatically:
```
delete from users where ap_id = 'https://your.instance.hostname/relay';
```
- Bad user search matches
## [1.1.0] - 2019-10-14
**Breaking:** The stable branch has been changed from `master` to `stable`. If you want to keep using 1.0, the `release/1.0` branch will receive security updates for 6 months after 1.1 release.
**OTP Note:** `pleroma_ctl` in 1.0 defaults to `master` and doesn't support specifying arbitrary branches, making `./pleroma_ctl update` fail. To fix this, fetch a version of `pleroma_ctl` from 1.1 using the command below and proceed with the update normally:
```
curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/develop/rel/files/bin/pleroma_ctl'
```
### Security
- Mastodon API: respect post privacy in `/api/v1/statuses/:id/{favourited,reblogged}_by`
### Removed
- **Breaking:** GNU Social API with Qvitter extensions support
- Emoji: Remove longfox emojis.
- Remove `Reply-To` header from report emails for admins.
- ActivityPub: The `/objects/:uuid/likes` endpoint.
### Changed
- **Breaking:** Configuration: A setting to explicitly disable the mailer was added, defaulting to true, if you are using a mailer add `config :pleroma, Pleroma.Emails.Mailer, enabled: true` to your config
- **Breaking:** Configuration: `/media/` is now removed when `base_url` is configured, append `/media/` to your `base_url` config to keep the old behaviour if desired
- **Breaking:** `/api/pleroma/notifications/read` is moved to `/api/v1/pleroma/notifications/read` and now supports `max_id` and responds with Mastodon API entities.
@ -1341,10 +1576,11 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- Mastodon API: `pleroma.thread_muted` key in the Status entity
- AdminAPI: Add "godmode" while fetching user statuses (i.e. admin can see private statuses)
- Improve digest email template
Pagination: (optional) return `total` alongside with `items` when paginating
Pagination: (optional) return `total` alongside with `items` when paginating
- The `Pleroma.FlakeId` module has been replaced with the `flake_id` library.
### Fixed
- Following from Osada
- Favorites timeline doing database-intensive queries
- Metadata rendering errors resulting in the entire page being inaccessible
@ -1377,6 +1613,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances
### Added
- Expiring/ephemeral activities. All activities can have expires_at value set, which controls when they should be deleted automatically.
- Mastodon API: in post_status, the expires_in parameter lets you set the number of seconds until an activity expires. It must be at least one hour.
- Mastodon API: all status JSON responses contain a `pleroma.expires_at` item which states when an activity will expire. The value is only shown to the user who created the activity. To everyone else it's empty.
@ -1420,24 +1657,33 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- Reverse Proxy: Do not retry failed requests to limit pressure on the peer
### Changed
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
- Admin API: changed json structure for saving config settings.
- RichMedia: parsers and their order are configured in `rich_media` config.
- RichMedia: add the rich media ttl based on image expiration time.
## [1.0.7] - 2019-09-26
### Fixed
- Broken federation on Erlang 22 (previous versions of hackney http client were using an option that got deprecated)
### Changed
- ActivityPub: The first page in inboxes/outboxes is no longer embedded.
## [1.0.6] - 2019-08-14
### Fixed
- MRF: fix use of unserializable keyword lists in describe() implementations
- ActivityPub S2S: POST requests are now signed with `(request-target)` pseudo-header.
## [1.0.5] - 2019-08-13
### Fixed
- Mastodon API: follower/following counters not being nullified, when `hide_follows`/`hide_followers` is set
- Mastodon API: `muted` in the Status entity, using author's account to determine if the thread was muted
- Mastodon API: return the actual profile URL in the Account entity's `url` property when appropriate
@ -1448,6 +1694,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- Fix internal server error when using the healthcheck API.
### Added
- **Breaking:** MRF describe API, which adds support for exposing configuration information about MRF policies to NodeInfo.
Custom modules will need to be updated by adding, at the very least, `def describe, do: {:ok, %{}}` to the MRF policy modules.
- Relays: Added a task to list relay subscriptions.
@ -1459,21 +1706,28 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- Configuration: `federation_incoming_replies_max_depth` option
### Removed
- Federation: Remove `likes` from objects.
- **Breaking:** ActivityPub: The `accept_blocks` configuration setting.
## [1.0.4] - 2019-08-01
### Fixed
- Invalid SemVer version generation, when the current branch does not have commits ahead of tag/checked out on a tag
## [1.0.3] - 2019-07-31
### Security
- OStatus: eliminate the possibility of a protocol downgrade attack.
- OStatus: prevent following locked accounts, bypassing the approval process.
- TwitterAPI: use CommonAPI to handle remote follows instead of OStatus.
## [1.0.2] - 2019-07-28
### Fixed
- Not being able to pin unlisted posts
- Mastodon API: represent poll IDs as strings
- MediaProxy: fix matching filenames
@ -1484,19 +1738,25 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- ActivityPub S2S: remote user deletions now work the same as local user deletions.
### Changed
- Configuration: OpenGraph and TwitterCard providers enabled by default
- Configuration: Filter.AnonymizeFilename added ability to retain file extension with custom text
## [1.0.1] - 2019-07-14
### Security
- OStatus: fix an object spoofing vulnerability.
## [1.0.0] - 2019-06-29
### Security
- Mastodon API: Fix display names not being sanitized
- Rich media: Do not crawl private IP ranges
### Added
- Digest email for inactive users
- Add a generic settings store for frontends / clients to use.
- Explicit addressing option for posting.
@ -1561,6 +1821,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- Configuration: default syslog tag "Pleroma" is now lowercased to "pleroma"
### Changed
- **Breaking:** bind to 127.0.0.1 instead of 0.0.0.0 by default
- **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer
- Thread containment / test for complete visibility will be skipped by default.
@ -1602,6 +1863,7 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- Rich Media: crawl only https URLs.
### Fixed
- Follow requests don't get 'stuck' anymore.
- Added an FTS index on objects. Running `vacuum analyze` and setting a larger `work_mem` is recommended.
- Followers counter not being updated when a follower is blocked
@ -1637,31 +1899,48 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel
- MRF: Simple policy now properly delists imported or relayed statuses
## Removed
- Configuration: `config :pleroma, :fe` in favor of the more flexible `config :pleroma, :frontend_configurations`
## [0.9.99999] - 2019-05-31
### Security
- Mastodon API: Fix lists leaking private posts
## [0.9.9999] - 2019-04-05
### Security
- Mastodon API: Fix content warnings skipping HTML sanitization
## [0.9.999] - 2019-03-13
Frontend changes only.
### Added
- Added floating action button for posting status on mobile
### Changed
- Changed user-settings icon to a pencil
### Fixed
- Keyboard shortcuts activating when typing a message
- Gaps when scrolling down on a timeline after showing new
## [0.9.99] - 2019-03-08
### Changed
- Update the frontend to the 0.9.99 tag
### Fixed
- Sign the date header in federation to fix Mastodon federation.
## [0.9.9] - 2019-02-22
This is our first stable release.

View file

@ -1,10 +1,10 @@
# https://hub.docker.com/r/hexpm/elixir/tags
ARG ELIXIR_IMG=hexpm/elixir
ARG ELIXIR_VER=1.14.5
ARG ERLANG_VER=25.3.2.14
ARG ELIXIR_VER=1.17.3
ARG ERLANG_VER=26.2.5.6
ARG ALPINE_VER=3.17.9
FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} as build
FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} AS build
COPY . .
@ -15,6 +15,7 @@ RUN apk add git gcc g++ musl-dev make cmake file-dev vips-dev &&\
echo "import Config" > config/prod.secret.exs &&\
mix local.hex --force &&\
mix local.rebar --force &&\
mix deps.clean --all &&\
mix deps.get --only prod &&\
mkdir release &&\
mix release --path release

View file

@ -1 +0,0 @@
Add new activity actor/type index. Greatly speeds up retrieval of rare types (like "Listen")

View file

@ -1 +0,0 @@
Fix 'Create a user' description in admin api docs

View file

@ -1 +0,0 @@
Fix AssignAppUser migration OOM

View file

@ -1 +0,0 @@
- Fix building "captcha" library with OpenBSD make

View file

@ -1 +0,0 @@
Docs: Restore DB schema before data to avoid long restore times

View file

@ -1 +0,0 @@
Return 404 with a better error message instead of 400 when receiving an activity for a deactivated user

View file

@ -1 +0,0 @@
Use JSON for DeepL API requests

View file

@ -1 +0,0 @@
Deleting an instance queues individual jobs for each user that needs to be deleted from the server.

View file

@ -1 +0,0 @@
Support Dislike activity, as sent by Mitra and Friendica, by changing it into a thumbs-down EmojiReact

View file

@ -1 +0,0 @@
Elixir 1.18: Fixed warnings and new deprecations

View file

@ -1 +0,0 @@
Added a way to upload new packs from a URL or ZIP file via Admin API

View file

@ -1 +0,0 @@
Support Mitra-style emoji likes.

View file

@ -1 +0,0 @@
Fix endorsement state display in relationship view

View file

@ -1 +0,0 @@
Add `duration` to the block endpoint, which makes block expire

View file

@ -1 +0,0 @@
Expose markup configuration in InstanceView

View file

@ -1 +0,0 @@
Set PATH in the FreeBSD rc script to avoid failures starting the service

View file

@ -1 +0,0 @@
Improved performance of status search queries using the default GIN index

View file

@ -1 +0,0 @@
Update Cowboy, Gun, and Plug family of dependencies

View file

@ -1 +0,0 @@
Hashtag searches return real results based on words in your query

View file

@ -1 +0,0 @@
Implement language detection with fastText

View file

@ -1 +0,0 @@
Added MRF.QuietReply which prevents replies to public posts from being published to the timelines

View file

@ -1 +0,0 @@
Oban Notifier was changed to Oban.Notifiers.PG for performance and scalability benefits

View file

@ -1 +0,0 @@
Updated relayd/httpd config files to be on par with nginx

View file

@ -1 +0,0 @@
replaced depracated flags and functions, renamed service to fit other service files

View file

@ -1 +0,0 @@
Updated Postgrex library to 0.20.0

View file

@ -1 +0,0 @@
Fix federation issue where Public visibility information in cc field was lost when sent to remote servers, causing posts to appear with inconsistent visibility across instances

View file

@ -1 +0,0 @@
Improved the logic of how we determine if a server is unreachable.

View file

@ -1 +0,0 @@
Relax alsoKnownAs requirements to just URI, not necessarily HTTP(S)

View file

@ -1 +0,0 @@
Fix release builds

View file

@ -1 +0,0 @@
Change scrobble external link param name to use snake case

View file

@ -1 +0,0 @@
Add `base_urls` to the /api/v1/instance pleroma metadata which provides information about the base URLs for media_proxy and uploads when configured

View file

@ -1 +0,0 @@
Change SMTP example to use the Mua adapter that works with OTP>25

View file

@ -1 +0,0 @@
Updated Tesla to 1.15.3

View file

@ -1 +0,0 @@
Backport [Elixir PR 14242](https://github.com/elixir-lang/elixir/pull/14242) fixing racy mkdir and lack of error handling of parent directory creation

View file

@ -1 +0,0 @@
Allow Terms of Service panel behaviour to be configurable

View file

@ -1 +0,0 @@
Support translation providers (DeepL, LibreTranslate)

View file

@ -1 +0,0 @@
Truncate the length of Rich Media title and description fields

View file

View file

@ -1 +0,0 @@
Fix HTTP client making invalid requests due to no percent encoding processing or validation.

View file

@ -1 +0,0 @@
Enforce an exact domain match for WebFinger resolution

View file

@ -1 +0,0 @@
Don't require an Accept header for WebFinger queries and default to JSON.

View file

@ -362,7 +362,9 @@ config :pleroma, :activitypub,
note_replies_output_limit: 5,
sign_object_fetches: true,
authorized_fetch_mode: false,
client_api_enabled: false
client_api_enabled: false,
anonymize_reporter: false,
anonymize_reporter_local_nickname: ""
config :pleroma, :streamer,
workers: 3,
@ -613,7 +615,7 @@ config :pleroma, Oban,
search_indexing: [limit: 10, paused: true],
slow: 5
],
plugins: [{Oban.Plugins.Pruner, max_age: 900}],
plugins: [Oban.Plugins.Lazarus, {Oban.Plugins.Pruner, max_age: 900}],
crontab: [
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker},

View file

@ -1797,6 +1797,23 @@ config :pleroma, :config_description, [
key: :client_api_enabled,
type: :boolean,
description: "Allow client to server ActivityPub interactions"
},
%{
key: :anonymize_reporter,
type: :boolean,
label: "Anonymize local reports",
description:
"If true, replace local reporters with the designated local user for the copy to be sent to remote servers"
},
%{
key: :anonymize_reporter_local_nickname,
type: :string,
label: "Anonymized reporter",
description:
"The nickname of the designated local user that replaces the actual reporter in the copy to be sent to remote servers",
suggestions: [
"lain"
]
}
]
},
@ -2114,6 +2131,11 @@ config :pleroma, :config_description, [
description:
"Amount of milliseconds after which the HTTP request is forcibly terminated.",
suggestions: [5_000]
},
%{
key: :user_agent,
type: :string,
description: "Custom User-Agent header to be used when fetching rich media content."
}
]
},
@ -3311,6 +3333,12 @@ config :pleroma, :config_description, [
description:
"A map containing available frontends and parameters for their installation.",
children: frontend_options
},
%{
key: :pickable,
type: {:list, :string},
description:
"A list containing all frontends users can pick as their preference, format is :name/:ref, e.g pleroma-fe/stable."
}
]
},
@ -3517,9 +3545,7 @@ config :pleroma, :config_description, [
%{
key: :provider,
type: :module,
suggestions: [
Pleroma.Language.LanguageDetector.Fasttext
]
suggestions: {:list_behaviour_implementations, Pleroma.Language.LanguageDetector.Provider}
},
%{
group: {:subgroup, Pleroma.Language.LanguageDetector.Fasttext},
@ -3539,10 +3565,7 @@ config :pleroma, :config_description, [
%{
key: :provider,
type: :module,
suggestions: [
Pleroma.Language.Translation.Deepl,
Pleroma.Language.Translation.Libretranslate
]
suggestions: {:list_behaviour_implementations, Pleroma.Language.Translation.Provider}
},
%{
group: {:subgroup, Pleroma.Language.Translation.Deepl},
@ -3571,6 +3594,27 @@ config :pleroma, :config_description, [
label: "LibreTranslate API Key",
type: :string,
suggestions: ["YOUR_API_KEY"]
},
%{
group: {:subgroup, Pleroma.Language.Translation.TranslateLocally},
key: :intermediary_language,
label:
"translateLocally intermediary language (used when direct source->target model is not available)",
type: :string,
suggestions: ["en"]
},
%{
group: {:subgroup, Pleroma.Language.Translation.Mozhi},
key: :base_url,
label: "Mozhi instance URL",
type: :string
},
%{
group: {:subgroup, Pleroma.Language.Translation.Mozhi},
key: :engine,
label: "Engine used for Mozhi",
type: :string,
suggestions: ["libretranslate"]
}
]
}

View file

@ -170,6 +170,10 @@ config :pleroma, Pleroma.Upload.Filter.Mogrify, config_impl: Pleroma.StaticStubb
config :pleroma, Pleroma.Upload.Filter.Mogrify, mogrify_impl: Pleroma.MogrifyMock
config :pleroma, Pleroma.Signature, http_signatures_impl: Pleroma.StubbedHTTPSignaturesMock
config :pleroma, Pleroma.Web.ActivityPub.Publisher, signature_impl: Pleroma.SignatureMock
config :pleroma, Pleroma.Web.ActivityPub.Publisher,
transmogrifier_impl: Pleroma.Web.ActivityPub.TransmogrifierMock
peer_module =
if String.to_integer(System.otp_release()) >= 25 do

View file

@ -28,6 +28,7 @@ Feel free to contact us to be added to this list!
### AndStatus
- Homepage: <http://andstatus.org/>
- Source Code: <https://github.com/andstatus/andstatus/>
- Contact: [@AndStatus@mastodon.social](https://mastodon.social/@AndStatus)
- Platforms: Android
- Features: MastoAPI, ActivityPub (Client-to-Server)
@ -40,8 +41,8 @@ Feel free to contact us to be added to this list!
### Fedilab
- Homepage: <https://fedilab.app/>
- Source Code: <https://framagit.org/tom79/fedilab/>
- Contact: [@fedilab@framapiaf.org](https://framapiaf.org/users/fedilab)
- Source Code: <https://codeberg.org/tom79/Fedilab>
- Contact: [@apps@toot.fedilab.app](https://toot.fedilab.app/@apps)
- Platforms: Android
- Features: MastoAPI, Streaming Ready, Moderation, Text Formatting
@ -51,8 +52,8 @@ Feel free to contact us to be added to this list!
- Features: MastoAPI, No Streaming
### Husky
- Source code: <https://git.mentality.rip/FWGS/Husky>
- Contact: [@Husky@enigmatic.observer](https://enigmatic.observer/users/Husky)
- Source code: <https://github.com/captainepoch/husky>
- Contact: [@husky@stereophonic.space](https://stereophonic.space/users/husky)
- Platforms: Android
- Features: MastoAPI, No Streaming, Emoji Reactions, Text Formatting, FE Stickers
@ -65,7 +66,7 @@ Feel free to contact us to be added to this list!
### Tusky
- Homepage: <https://tuskyapp.github.io/>
- Source Code: <https://github.com/tuskyapp/Tusky>
- Contact: [@ConnyDuck@mastodon.social](https://mastodon.social/users/ConnyDuck)
- Contact: [@Tusky@mastodon.social](https://mastodon.social/@Tusky)
- Platforms: Android
- Features: MastoAPI, No Streaming
@ -76,10 +77,10 @@ Feel free to contact us to be added to this list!
- Platform: Android
- Features: MastoAPI, No Streaming
### Indigenous
- Homepage: <https://indigenous.realize.be/>
- Source Code: <https://github.com/swentel/indigenous-android/>
- Contact: [@swentel@realize.be](https://realize.be)
### IndiePass
- Homepage: <https://indiepass.app/>
- Source Code: <https://github.com/IndiePass/indiepass-android>
- Contact: [@marksuth@mastodon.social](https://mastodon.social/@marksuth)
- Platforms: Android
- Features: MastoAPI, No Streaming

View file

@ -904,21 +904,31 @@ config :logger, :console,
### RUM indexing for full text search
!!! warning
It is recommended to use PostgreSQL v11 or newer. We have seen some minor issues with lower PostgreSQL versions.
* `rum_enabled`: If RUM indexes should be used. Defaults to `false`.
RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. While they may eventually be mainlined, for now they have to be installed as a PostgreSQL extension from https://github.com/postgrespro/rum.
RUM indexes are an alternative indexing scheme that is not included in PostgreSQL by default. While they may eventually be mainlined, for now they have to be installed as a PostgreSQL extension from [https://github.com/postgrespro/rum](https://github.com/postgrespro/rum).
Their advantage over the standard GIN indexes is that they allow efficient ordering of search results by timestamp, which makes search queries a lot faster on larger servers, by one or two orders of magnitude. They take up around 3 times as much space as GIN indexes.
Their advantage over the standard GIN indexes is that they allow efficient ordering of search results by timestamp, which makes search queries a lot faster on larger servers, by one or two orders of magnitude. They take up around 3-4 times as much space as GIN indexes.
To enable them, both the `rum_enabled` flag has to be set and the following special migration has to be run:
`mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`
* Source install:
- Stop Pleroma
- `mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`
* OTP install:
- Stop Pleroma
- `pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/`
This will probably take a long time.
!!! note
It is recommended to `VACUUM FULL` the objects table after the migration has completed, to do that run:
```
# sudo -Hu postgres vacuumdb --full --analyze -t objects <pleroma DB name>
```
Now you can start Pleroma back up.
## Alternative client protocols
### BBS / SSH access

View file

@ -16,7 +16,9 @@ location /proxy {
```
Also add the following on top of the configuration, outside of the `server` block:
```
proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off;
# Note: The cache directory must exist and be writable by nginx.
# If nginx runs in a chroot, create it inside the chroot.
proxy_cache_path /var/tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g inactive=720m use_temp_path=off;
```
If you came here from one of the installation guides, take a look at the example configuration `/installation/pleroma.nginx`, where this part is already included.

View file

@ -66,9 +66,9 @@ Returned data:
"username": "somenick",
...
},
"id" : "1",
"unread" : 2,
"last_message" : {...}, // The last message in that chat
"id": "1",
"unread": 2,
"last_message": {...}, // The last message in that chat
"updated_at": "2020-04-21T15:11:46.000Z"
}
```
@ -93,8 +93,8 @@ Returned data:
"username": "somenick",
...
},
"id" : "1",
"unread" : 0,
"id": "1",
"unread": 0,
"updated_at": "2020-04-21T15:11:46.000Z"
}
```
@ -111,7 +111,7 @@ The modified chat message
### Getting a list of Chats
`GET /api/v1/pleroma/chats`
`GET /api/v2/pleroma/chats`
This will return a list of chats that you have been involved in, sorted by their
last update (so new chats will be at the top).
@ -119,6 +119,7 @@ last update (so new chats will be at the top).
Parameters:
- with_muted: Include chats from muted users (boolean).
- pinned: Include only pinned chats (boolean).
Returned data:
@ -130,16 +131,16 @@ Returned data:
"username": "somenick",
...
},
"id" : "1",
"unread" : 2,
"last_message" : {...}, // The last message in that chat
"id": "1",
"unread": 2,
"last_message": {...}, // The last message in that chat
"updated_at": "2020-04-21T15:11:46.000Z"
}
]
```
The recipient of messages that are sent to this chat is given by their AP ID.
No pagination is implemented for now.
The usual pagination options are implemented.
### Getting the messages for a Chat
@ -226,6 +227,32 @@ Deleting a chat message for given Chat id works like this:
Returned data is the deleted message.
### Pinning a chat
Pinning a chat works like this:
`POST /api/v1/pleroma/chats/:id/pin`
Returned data:
```json
{
"account": {
"id": "someflakeid",
"username": "somenick",
...
},
"id": "1",
"unread": 0,
"updated_at": "2020-04-21T15:11:46.000Z",
"pinned": true,
}
```
To unpin a pinned chat, use:
`POST /api/v1/pleroma/chats/:id/unpin`
### Notifications
There's a new `pleroma:chat_mention` notification, which has this form. It is not given out in the notifications endpoint by default, you need to explicitly request it with `include_types[]=pleroma:chat_mention`:

View file

@ -39,11 +39,13 @@ Has these additional fields under the `pleroma` object:
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
- `parent_visible`: If the parent of this post is visible to the user or not.
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
- `quotes_count`: the count of status quotes.
- `non_anonymous`: true if the source post specifies the poll results are not anonymous. Currently only implemented by Smithereen.
- `bookmark_folder`: the ID of the folder bookmark is stored within (if any).
- `list_id`: the ID of the list the post is addressed to (if any, only returned to author).
Has these additional fields under the `poll.pleroma` object:
- `non_anonymous`: true if the source post specifies the poll results are not anonymous. Currently only implemented by Smithereen.
The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
- `content_type`: The content type of the status source.
@ -88,6 +90,7 @@ The `id` parameter can also be the `nickname` of the user. This only works in th
- `only_media`: include only statuses with media attached
- `with_muted`: include statuses/reactions from muted accounts
- `exclude_reblogs`: exclude reblogs
- `only_reblogs`: include only reblogs
- `exclude_replies`: exclude replies
- `exclude_visibilities`: exclude visibilities
@ -97,6 +100,9 @@ Endpoints which accept `with_relationships` parameter:
- `/api/v1/accounts/:id/followers`
- `/api/v1/accounts/:id/following`
- `/api/v1/mutes`
- `/api/v1/blocks`
- `/api/v1/search`
- `/api/v2/search`
Has these additional fields under the `pleroma` object:

View file

@ -684,6 +684,7 @@ Audio scrobbling in Pleroma is **deprecated**.
### Creates a new Listen activity for an account
* Method `POST`
* Authentication: required
* OAuth scope: `write:scrobbles`
* Params:
* `title`: the title of the media playing
* `album`: the album of the media playing [optional]

View file

@ -14,7 +14,7 @@ Note: This article is potentially outdated because at this time we may not have
- PostgreSQL 11.0以上 (Ubuntu16.04では9.5しか提供されていないので,[](https://www.postgresql.org/download/linux/ubuntu/)こちらから新しいバージョンを入手してください)
- `postgresql-contrib` 11.0以上 (同上)
- Elixir 1.14 以上 ([Debianのリポジトリからインストールしないこと ここからインストールすること!](https://elixir-lang.org/install.html#unix-and-unix-like)。または [asdf](https://github.com/asdf-vm/asdf) をpleromaユーザーでインストールしてください)
- Elixir 1.15 以上 ([Debianのリポジトリからインストールしないこと ここからインストールすること!](https://elixir-lang.org/install.html#unix-and-unix-like)。または [asdf](https://github.com/asdf-vm/asdf) をpleromaユーザーでインストールしてください)
- `erlang-dev`
- `erlang-nox`
- `git`

View file

@ -1,7 +1,7 @@
## Required dependencies
* PostgreSQL >=11.0
* Elixir >=1.14.0 <1.19
* Elixir >=1.15.0 <1.19
* Erlang OTP >=23.0.0 (supported: <28)
* git
* file / libmagic

View file

@ -16,7 +16,7 @@ Note: the packages are not required with the current default settings of Pleroma
It is required for the following Pleroma features:
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Pleroma.Upload/filters` in `config/config.exs`)
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
## `ffmpeg`
@ -33,5 +33,5 @@ It is required for the following Pleroma features:
It is required for the following Pleroma features:
* `Pleroma.Upload.Filters.Exiftool.StripLocation` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
* `Pleroma.Upload.Filters.Exiftool.ReadDescription` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
* `Pleroma.Upload.Filters.Exiftool.StripLocation` upload filter (related config: `Pleroma.Upload/filters` in `config/config.exs`)
* `Pleroma.Upload.Filters.Exiftool.ReadDescription` upload filter (related config: `Pleroma.Upload/filters` in `config/config.exs`)

View file

@ -56,7 +56,6 @@ http protocol pleroma { # Protocol for upstream Pleroma server
relay wwwtls {
listen on $ext_inet port https tls # Comment to disable listening on IPv4
#listen on $ext_inet6 port https tls # Comment to disable listening on IPv6
protocol pleroma
@ -66,3 +65,16 @@ relay wwwtls {
# Example:
#forward to <httpd_server> port 8080
}
# Uncomment relay block to enable IPv6
#relay wwwtls6 {
# listen on $ext_inet6 port https tls
# protocol pleroma
# forward to <pleroma_server> port 4000 check tcp timeout 500 # Adjust timeout accordingly when relayd returns 502 while Pleroma is running without problems.
# # When serving multiple services, add the forwards here.
# # Example:
# #forward to <httpd_server> port 8080
#}

View file

@ -6,7 +6,9 @@
# 3. Copy this file to /etc/nginx/sites-available/ and then add a symlink to it
# in /etc/nginx/sites-enabled/ and run 'nginx -s reload' or restart nginx.
proxy_cache_path /tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g
# Note: The cache directory must exist and be writable by nginx.
# If nginx runs in a chroot, create it inside the chroot.
proxy_cache_path /var/tmp/pleroma-media-cache levels=1:2 keys_zone=pleroma_media_cache:10m max_size=10g
inactive=720m use_temp_path=off;
# this is explicitly IPv4 since Pleroma.Web.Endpoint binds on IPv4 only
@ -41,8 +43,21 @@ ssl_session_cache shared:ssl_session_cache:10m;
server {
server_name example.tld;
listen 443 ssl http2;
listen [::]:443 ssl http2;
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
# Optional HTTP/3 support
# Note: requires you open UDP port 443
#
# listen 443 quic reuseport;
# listen [::]:443 quic reuseport;
# http3 on;
# quic_retry on;
# ssl_early_data on;
# quic_gso on;
# add_header Alt-Svc 'h3=":443"; ma=86400';
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
@ -67,8 +82,14 @@ server {
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/activity+json application/atom+xml;
# the nginx default is 1m, not enough for large media uploads
# Nginx media upload limitation
# Ensure that this value matches or exceeds your Pleroma upload limit:
#
# config :pleroma, :instance,
# upload_limit: 16_000_000
#
client_max_body_size 16m;
ignore_invalid_headers off;
proxy_http_version 1.1;
@ -94,7 +115,9 @@ server {
# proxy_pass http://phoenix/notice/$1;
# }
location ~ ^/(media|proxy) {
# Remove this location if you choose to use a dedicated subdomain
# for mediaproxy
location /proxy {
proxy_cache pleroma_media_cache;
slice 1m;
proxy_cache_key $host$uri$is_args$args$slice_range;
@ -106,4 +129,95 @@ server {
chunked_transfer_encoding on;
proxy_pass http://phoenix;
}
# Nginx can serve the local file uploads directly reducing work for
# the backend. Make sure to change this to a "deny all" if you use
# a dedicated subdomain. It will break access to uploads that have already
# federated if you are converting an existing installation, so weigh the risks
# carefully.
#
# location /media/ {
# alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment
# allow all;
# add_header X-Content-Type-Options "nosniff";
# add_header Content-Security-Policy "sandbox";
# }
}
# It is strongly recommended that you host your media and the mediaproxy on a dedicated subdomain for security reasons.
# The following Pleroma settings will be required to enable this capability:
#
# config :pleroma, :media_proxy,
# base_url: "https://media.example.tld/"
#
# # Assuming default media upload deployment (e.g., not S3 which will require a different domain anyway) --
# config :pleroma, Pleroma.Upload,
# base_url: "https://media.example.tld/media/",
#
# config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads"
#
# And then uncomment and configure the following server.
# Make sure your certificate was issued to support both domains or use a dedicated certificate:
#
# server {
# server_name media.example.tld;
#
# listen 443 ssl;
# listen [::]:443 ssl;
# http2 on;
#
# # Optional HTTP/3 support
# # Note: requires you open UDP port 443
# #
# # listen 443 quic reuseport;
# # listen [::]:443 quic reuseport;
# # http3 on;
# # quic_retry on;
# # ssl_early_data on;
# # quic_gso on;
# # add_header Alt-Svc 'h3=":443"; ma=86400';
#
# ssl_session_timeout 1d;
# ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
# ssl_session_tickets off;
#
# ssl_trusted_certificate /etc/letsencrypt/live/example.tld/chain.pem;
# ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem;
#
# ssl_protocols TLSv1.2 TLSv1.3;
# ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
# ssl_prefer_server_ciphers off;
# # In case of an old server with an OpenSSL version of 1.0.2 or below,
# # leave only prime256v1 or comment out the following line.
# ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
# ssl_stapling on;
# ssl_stapling_verify on;
#
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
# proxy_set_header Host $http_host;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#
# location /media/ { # <-- make sure this path matches your Pleroma.Upload :base_url
# alias /var/lib/pleroma/uploads/; # <-- make sure this is correct for your deployment
# allow all;
# add_header X-Content-Type-Options "nosniff";
# add_header Content-Security-Policy "sandbox";
# }
#
# location /proxy {
# proxy_cache pleroma_media_cache;
# slice 1m;
# proxy_cache_key $host$uri$is_args$args$slice_range;
# proxy_set_header Range $slice_range;
# proxy_cache_valid 200 206 301 304 1h;
# proxy_cache_lock on;
# proxy_ignore_client_abort on;
# proxy_buffering on;
# chunked_transfer_encoding on;
# proxy_pass http://phoenix;
# }
# }

View file

@ -7,7 +7,7 @@ defmodule Pleroma.Activity.Queries do
Contains queries for Activity.
"""
import Ecto.Query, only: [from: 2, where: 3]
import Ecto.Query, only: [from: 2]
@type query :: Ecto.Queryable.t() | Pleroma.Activity.t()
@ -70,22 +70,6 @@ defmodule Pleroma.Activity.Queries do
)
end
@spec by_object_in_reply_to_id(query, String.t(), keyword()) :: query
def by_object_in_reply_to_id(query, in_reply_to_id, opts \\ []) do
query =
if opts[:skip_preloading] do
Activity.with_joined_object(query)
else
Activity.with_preloaded_object(query)
end
where(
query,
[activity, object: o],
fragment("(?)->>'inReplyTo' = ?", o.data, ^to_string(in_reply_to_id))
)
end
@spec by_type(query, String.t()) :: query
def by_type(query \\ Activity, activity_type) do
from(

View file

@ -25,6 +25,8 @@ defmodule Pleroma.Chat do
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
field(:recipient, :string)
field(:pinned, :boolean)
timestamps()
end
@ -94,4 +96,16 @@ defmodule Pleroma.Chat do
order_by: [desc: c.updated_at]
)
end
def pin(%__MODULE__{} = chat) do
chat
|> cast(%{pinned: true}, [:pinned])
|> Repo.update()
end
def unpin(%__MODULE__{} = chat) do
chat
|> cast(%{pinned: false}, [:pinned])
|> Repo.update()
end
end

View file

@ -21,7 +21,8 @@ defmodule Pleroma.Constants do
"pleroma_internal",
"generator",
"rules",
"language"
"language",
"voters"
]
)

View file

@ -157,6 +157,16 @@ defmodule Pleroma.FollowingRelationship do
|> Repo.all()
end
def get_outgoing_follow_requests(%User{id: id}) do
__MODULE__
|> join(:inner, [r], f in assoc(r, :following))
|> where([r], r.state == ^:follow_pending)
|> where([r], r.follower_id == ^id)
|> where([r, f], f.is_active == true)
|> select([r, f], f)
|> Repo.all()
end
def following?(%User{id: follower_id}, %User{id: followed_id}) do
__MODULE__
|> where(follower_id: ^follower_id, following_id: ^followed_id, state: ^:follow_accept)

View file

@ -131,31 +131,4 @@ defmodule Pleroma.HTTP do
defp default_middleware,
do: [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.EncodeUrl]
def encode_url(url) when is_binary(url) do
URI.parse(url)
|> then(fn parsed ->
path = encode_path(parsed.path)
query = encode_query(parsed.query)
%{parsed | path: path, query: query}
end)
|> URI.to_string()
end
defp encode_path(nil), do: nil
defp encode_path(path) when is_binary(path) do
path
|> URI.decode()
|> URI.encode()
end
defp encode_query(nil), do: nil
defp encode_query(query) when is_binary(query) do
query
|> URI.decode_query()
|> URI.encode_query()
end
end

View file

@ -16,7 +16,12 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do
config_opts = Pleroma.Config.get([:http, :adapter], [])
url_encoding =
Keyword.new()
|> Keyword.put(:path_encode_fun, fn path -> path end)
@defaults
|> Keyword.merge(url_encoding)
|> Keyword.merge(config_opts)
|> Keyword.merge(connection_opts)
|> add_scheme_opts(uri)

View file

@ -0,0 +1,109 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Language.Translation.Mozhi do
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
alias Pleroma.Language.Translation.Provider
use Provider
@behaviour Provider
@name "Mozhi"
@impl Provider
def configured?, do: not_empty_string(base_url()) and not_empty_string(engine())
@impl Provider
def translate(content, source_language, target_language) do
endpoint =
base_url()
|> URI.merge("/api/translate")
|> URI.to_string()
case Pleroma.HTTP.get(
endpoint <>
"?" <>
URI.encode_query(%{
engine: engine(),
text: content,
from: source_language,
to: target_language
}),
[{"Accept", "application/json"}]
) do
{:ok, %{status: 200} = res} ->
%{
"translated-text" => content,
"source_language" => source_language
} = Jason.decode!(res.body)
{:ok,
%{
content: content,
detected_source_language: source_language,
provider: @name
}}
_ ->
{:error, :internal_server_error}
end
end
@impl Provider
def supported_languages(type) when type in [:source, :target] do
path =
case type do
:source -> "/api/source_languages"
:target -> "/api/target_languages"
end
endpoint =
base_url()
|> URI.merge(path)
|> URI.to_string()
case Pleroma.HTTP.get(
endpoint <>
"?" <>
URI.encode_query(%{
engine: engine()
}),
[{"Accept", "application/json"}]
) do
{:ok, %{status: 200} = res} ->
languages =
Jason.decode!(res.body)
|> Enum.map(fn %{"Id" => language} -> language end)
{:ok, languages}
_ ->
{:error, :internal_server_error}
end
end
@impl Provider
def languages_matrix do
with {:ok, source_languages} <- supported_languages(:source),
{:ok, target_languages} <- supported_languages(:target) do
{:ok,
Map.new(source_languages, fn language -> {language, target_languages -- [language]} end)}
else
{:error, error} -> {:error, error}
end
end
@impl Provider
def name, do: @name
defp base_url do
Pleroma.Config.get([__MODULE__, :base_url])
end
defp engine do
Pleroma.Config.get([__MODULE__, :engine])
end
end

View file

@ -0,0 +1,129 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Language.Translation.TranslateLocally do
alias Pleroma.Language.Translation.Provider
use Provider
@behaviour Provider
@name "translateLocally"
@impl Provider
def missing_dependencies do
if Pleroma.Utils.command_available?("translateLocally") do
[]
else
["translateLocally"]
end
end
@impl Provider
def configured?, do: is_map(models())
@impl Provider
def translate(content, source_language, target_language) do
model =
models()
|> Map.get(source_language, %{})
|> Map.get(target_language)
models =
if model do
[model]
else
[
models()
|> Map.get(source_language, %{})
|> Map.get(intermediary_language()),
models()
|> Map.get(intermediary_language(), %{})
|> Map.get(target_language)
]
end
translated_content =
Enum.reduce(models, content, fn model, content ->
text_path = Path.join(System.tmp_dir!(), "translateLocally-#{Ecto.UUID.generate()}")
File.write(text_path, content)
translated_content =
case System.cmd("translateLocally", ["-m", model, "-i", text_path, "--html"]) do
{content, _} -> content
_ -> nil
end
File.rm(text_path)
translated_content
end)
{:ok,
%{
content: translated_content,
detected_source_language: source_language,
provider: @name
}}
end
@impl Provider
def supported_languages(:source) do
languages =
languages_matrix()
|> elem(1)
|> Map.keys()
{:ok, languages}
end
@impl Provider
def supported_languages(:target) do
languages =
languages_matrix()
|> elem(1)
|> Map.values()
|> List.flatten()
|> Enum.uniq()
{:ok, languages}
end
@impl Provider
def languages_matrix do
languages =
models()
|> Map.to_list()
|> Enum.map(fn {key, value} -> {key, Map.keys(value)} end)
|> Enum.into(%{})
matrix =
if intermediary_language() do
languages
|> Map.to_list()
|> Enum.map(fn {key, value} ->
with_intermediary =
(((value ++ languages[intermediary_language()])
|> Enum.uniq()) --
[key])
|> Enum.sort()
{key, with_intermediary}
end)
|> Enum.into(%{})
else
languages
end
{:ok, matrix}
end
@impl Provider
def name, do: @name
defp models, do: Pleroma.Config.get([__MODULE__, :models])
defp intermediary_language, do: Pleroma.Config.get([__MODULE__, :intermediary_language])
end

View file

@ -575,6 +575,12 @@ defmodule Pleroma.ModerationLog do
"@#{actor_nickname} requested account backup for @#{user_nickname}"
end
def get_log_entry_message(%ModerationLog{data: data}) do
actor_name = get_in(data, ["actor", "nickname"]) || "unknown"
action = data["action"] || "unknown"
"@#{actor_name} performed action #{action}"
end
defp nicknames_to_string(nicknames) do
nicknames
|> Enum.map(&"@#{&1}")

View file

@ -74,6 +74,7 @@ defmodule Pleroma.Notification do
reblog
poll
status
update
}
def changeset(%Notification{} = notification, attrs) do
@ -281,10 +282,15 @@ defmodule Pleroma.Notification do
select: n.id
)
Multi.new()
|> Multi.update_all(:ids, query, set: [seen: true, updated_at: NaiveDateTime.utc_now()])
|> Marker.multi_set_last_read_id(user, "notifications")
|> Repo.transaction()
{:ok, %{marker: marker}} =
Multi.new()
|> Multi.update_all(:ids, query, set: [seen: true, updated_at: NaiveDateTime.utc_now()])
|> Marker.multi_set_last_read_id(user, "notifications")
|> Repo.transaction()
Streamer.stream(["user", "user:notification"], marker)
{:ok, %{marker: marker}}
end
@spec read_one(User.t(), String.t()) ::
@ -525,9 +531,7 @@ defmodule Pleroma.Notification do
%Activity{data: %{"type" => "Create"}} = activity,
local_only
) do
notification_enabled_ap_ids =
[]
|> Utils.maybe_notify_subscribers(activity)
notification_enabled_ap_ids = Utils.get_notified_subscribers(activity)
potential_receivers =
User.get_users_from_set(notification_enabled_ap_ids, local_only: local_only)

View file

@ -126,7 +126,7 @@ defmodule Pleroma.Object do
Logger.debug("Backtrace: #{inspect(Process.info(:erlang.self(), :current_stacktrace))}")
end
def normalize(_, options \\ [fetch: false, id_only: false])
def normalize(_, options \\ [fetch: false])
# If we pass an Activity to Object.normalize(), we can try to use the preloaded object.
# Use this whenever possible, especially when walking graphs in an O(N) loop!
@ -155,9 +155,6 @@ defmodule Pleroma.Object do
def normalize(ap_id, options) when is_binary(ap_id) do
cond do
Keyword.get(options, :id_only) ->
ap_id
Keyword.get(options, :fetch) ->
case Fetcher.fetch_object_from_id(ap_id, options) do
{:ok, object} -> object
@ -401,28 +398,6 @@ defmodule Pleroma.Object do
String.starts_with?(id, Pleroma.Web.Endpoint.url() <> "/")
end
def replies(object, opts \\ []) do
object = Object.normalize(object, fetch: false)
query =
Object
|> where(
[o],
fragment("(?)->>'inReplyTo' = ?", o.data, ^object.data["id"])
)
|> order_by([o], asc: o.id)
if opts[:self_only] do
actor = object.data["actor"]
where(query, [o], fragment("(?)->>'actor' = ?", o.data, ^actor))
else
query
end
end
def self_replies(object, opts \\ []),
do: replies(object, Keyword.put(opts, :self_only, true))
def tags(%Object{data: %{"tag" => tags}}) when is_list(tags), do: tags
def tags(_), do: []

View file

@ -5,6 +5,7 @@
defmodule Pleroma.Object.Updater do
require Pleroma.Constants
alias Pleroma.Maps
alias Pleroma.Object
alias Pleroma.Repo
@ -115,6 +116,7 @@ defmodule Pleroma.Object.Updater do
# Choices are the same, but counts are different
to_be_updated
|> Map.put(key, updated_object[key])
|> Maps.put_if_present("votersCount", updated_object["votersCount"])
else
# Choices (or vote type) have changed, do not allow this
_ -> to_be_updated

View file

@ -95,13 +95,30 @@ defmodule Pleroma.Pagination do
offset: :integer,
limit: :integer,
skip_extra_order: :boolean,
skip_order: :boolean
skip_order: :boolean,
order_asc: :boolean
}
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
changeset.changes
end
defp order_statement(query, table_binding, :asc) do
order_by(
query,
[{u, table_position(query, table_binding)}],
fragment("? asc nulls last", u.id)
)
end
defp order_statement(query, table_binding, :desc) do
order_by(
query,
[{u, table_position(query, table_binding)}],
fragment("? desc nulls last", u.id)
)
end
defp restrict(query, :min_id, %{min_id: min_id}, table_binding) do
where(query, [{q, table_position(query, table_binding)}], q.id > ^min_id)
end
@ -119,19 +136,16 @@ defmodule Pleroma.Pagination do
defp restrict(%{order_bys: [_ | _]} = query, :order, %{skip_extra_order: true}, _), do: query
defp restrict(query, :order, %{min_id: _}, table_binding) do
order_by(
query,
[{u, table_position(query, table_binding)}],
fragment("? asc nulls last", u.id)
)
order_statement(query, table_binding, :asc)
end
defp restrict(query, :order, _options, table_binding) do
order_by(
query,
[{u, table_position(query, table_binding)}],
fragment("? desc nulls last", u.id)
)
defp restrict(query, :order, %{max_id: _}, table_binding) do
order_statement(query, table_binding, :desc)
end
defp restrict(query, :order, options, table_binding) do
dir = if options[:order_asc], do: :asc, else: :desc
order_statement(query, table_binding, dir)
end
defp restrict(query, :offset, %{offset: offset}, _table_binding) do
@ -151,11 +165,9 @@ defmodule Pleroma.Pagination do
defp restrict(query, _, _, _), do: query
defp enforce_order(result, %{min_id: _}) do
result
|> Enum.reverse()
end
defp enforce_order(result, %{min_id: _, order_asc: true}), do: result
defp enforce_order(result, %{min_id: _}), do: Enum.reverse(result)
defp enforce_order(result, %{max_id: _, order_asc: true}), do: Enum.reverse(result)
defp enforce_order(result, _), do: result
defp table_position(%Ecto.Query{} = query, binding_name) do

View file

@ -3,6 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.ReverseProxy do
alias Pleroma.Utils.URIEncoding
@range_headers ~w(range if-range)
@keep_req_headers ~w(accept accept-encoding cache-control if-modified-since) ++
~w(if-unmodified-since if-none-match) ++ @range_headers
@ -155,11 +157,12 @@ defmodule Pleroma.ReverseProxy do
end
defp request(method, url, headers, opts) do
Logger.debug("#{__MODULE__} #{method} #{url} #{inspect(headers)}")
method = method |> String.downcase() |> String.to_existing_atom()
url = maybe_encode_url(url)
Logger.debug("#{__MODULE__} #{method} #{url} #{inspect(headers)}")
case client().request(method, url, headers, "", opts) do
{:ok, code, headers, client} when code in @valid_resp_codes ->
{:ok, code, downcase_headers(headers), client}
@ -459,9 +462,9 @@ defmodule Pleroma.ReverseProxy do
# Also do it for test environment
defp maybe_encode_url(url) do
case Application.get_env(:tesla, :adapter) do
Tesla.Adapter.Hackney -> Pleroma.HTTP.encode_url(url)
{Tesla.Adapter.Finch, _} -> Pleroma.HTTP.encode_url(url)
Tesla.Mock -> Pleroma.HTTP.encode_url(url)
Tesla.Adapter.Hackney -> URIEncoding.encode_url(url)
{Tesla.Adapter.Finch, _} -> URIEncoding.encode_url(url)
Tesla.Mock -> URIEncoding.encode_url(url)
_ -> url
end
end

View file

@ -7,6 +7,11 @@ defmodule Pleroma.ReverseProxy.Client.Hackney do
@impl true
def request(method, url, headers, body, opts \\ []) do
opts =
Keyword.put_new(opts, :path_encode_fun, fn path ->
path
end)
:hackney.request(method, url, headers, body, opts)
end

View file

@ -3,6 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Signature do
@behaviour Pleroma.Signature.API
@behaviour HTTPSignatures.Adapter
alias Pleroma.EctoType.ActivityPub.ObjectValidators
@ -53,7 +54,7 @@ defmodule Pleroma.Signature do
def fetch_public_key(conn) do
with {:ok, actor_id} <- get_actor_id(conn),
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
{:ok, public_key} <- User.get_or_fetch_public_key_for_ap_id(actor_id) do
{:ok, public_key}
else
e ->

View file

@ -0,0 +1,14 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Signature.API do
@moduledoc """
Behaviour for signing requests and producing HTTP Date headers.
This is used to allow tests to replace the signing implementation with Mox.
"""
@callback sign(user :: Pleroma.User.t(), headers :: map()) :: String.t()
@callback signed_date() :: String.t()
end

View file

@ -17,7 +17,7 @@ defmodule Pleroma.Tesla.Middleware.EncodeUrl do
@impl Tesla.Middleware
def call(%Tesla.Env{url: url} = env, next, _) do
url = Pleroma.HTTP.encode_url(url)
url = Pleroma.Utils.URIEncoding.encode_url(url)
env = %{env | url: url}

View file

@ -35,6 +35,7 @@ defmodule Pleroma.Upload do
"""
alias Ecto.UUID
alias Pleroma.Maps
alias Pleroma.Utils.URIEncoding
alias Pleroma.Web.ActivityPub.Utils
require Logger
@ -230,11 +231,18 @@ defmodule Pleroma.Upload do
tmp_path
end
# Encoding the whole path here is fine since the path is in a
# UUID/<file name> form.
# The file at this point isn't %-encoded, so the path shouldn't
# be decoded first like Pleroma.Utils.URIEncoding.encode_url/1 does.
defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do
encode_opts = [bypass_decode: true, bypass_parse: true]
path =
URI.encode(path, &char_unescaped?/1) <>
URIEncoding.encode_url(path, encode_opts) <>
if Pleroma.Config.get([__MODULE__, :link_name], false) do
"?name=#{URI.encode(name, &char_unescaped?/1)}"
enum = %{name: name}
"?#{URI.encode_query(enum)}"
else
""
end

View file

@ -233,8 +233,8 @@ defmodule Pleroma.User do
for {_relationship_type, [{_outgoing_relation, outgoing_relation_target}, _]} <-
@user_relationships_config do
# `def blocked_users_relation/2`, `def muted_users_relation/2`,
# `def reblog_muted_users_relation/2`, `def notification_muted_users/2`,
# `def subscriber_users/2`, `def endorsed_users_relation/2`
# `def reblog_muted_users_relation/2`, `def notification_muted_users_relation/2`,
# `def subscriber_users_relation/2`, `def endorsed_users_relation/2`
def unquote(:"#{outgoing_relation_target}_relation")(user, restrict_deactivated? \\ false) do
target_users_query = assoc(user, unquote(outgoing_relation_target))
@ -288,6 +288,7 @@ defmodule Pleroma.User do
defdelegate following?(follower, followed), to: FollowingRelationship
defdelegate following_ap_ids(user), to: FollowingRelationship
defdelegate get_follow_requests(user), to: FollowingRelationship
defdelegate get_outgoing_follow_requests(user), to: FollowingRelationship
defdelegate search(query, opts \\ []), to: User.Search
@doc """
@ -801,13 +802,6 @@ defmodule Pleroma.User do
when is_nil(password) do
params = Map.put_new(params, :accepts_chat_messages, true)
params =
if Map.has_key?(params, :email) do
Map.put_new(params, :email, params[:email])
else
params
end
struct
|> cast(params, [
:name,
@ -1364,7 +1358,7 @@ defmodule Pleroma.User do
@spec get_by_nickname(String.t()) :: User.t() | nil
def get_by_nickname(nickname) do
Repo.get_by(User, nickname: nickname) ||
if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()})i, nickname) do
if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()}$)i, nickname) do
Repo.get_by(User, nickname: local_nickname(nickname))
end
end
@ -2314,6 +2308,15 @@ defmodule Pleroma.User do
def public_key(_), do: {:error, "key not found"}
def get_or_fetch_public_key_for_ap_id(ap_id) do
with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id),
{:ok, public_key} <- public_key(user) do
{:ok, public_key}
else
_ -> :error
end
end
def get_public_key_for_ap_id(ap_id) do
with %User{} = user <- get_cached_by_ap_id(ap_id),
{:ok, public_key} <- public_key(user) do

View file

@ -16,6 +16,7 @@ defmodule Pleroma.User.Search do
following = Keyword.get(opts, :following, false)
result_limit = Keyword.get(opts, :limit, @limit)
offset = Keyword.get(opts, :offset, 0)
capabilities = Keyword.get(opts, :capabilities, [])
for_user = Keyword.get(opts, :for_user)
@ -32,7 +33,7 @@ defmodule Pleroma.User.Search do
results =
query_string
|> search_query(for_user, following, top_user_ids)
|> search_query(for_user, following, top_user_ids, capabilities)
|> Pagination.fetch_paginated(%{"offset" => offset, "limit" => result_limit}, :offset)
results
@ -80,7 +81,7 @@ defmodule Pleroma.User.Search do
end
end
defp search_query(query_string, for_user, following, top_user_ids) do
defp search_query(query_string, for_user, following, top_user_ids, capabilities) do
for_user
|> base_query(following)
|> filter_blocked_user(for_user)
@ -94,6 +95,7 @@ defmodule Pleroma.User.Search do
|> subquery()
|> order_by(desc: :search_rank)
|> maybe_restrict_local(for_user)
|> maybe_restrict_accepting_chat_messages(capabilities)
|> filter_deactivated_users()
end
@ -214,6 +216,14 @@ defmodule Pleroma.User.Search do
end
end
defp maybe_restrict_accepting_chat_messages(query, capabilities) do
if "accepts_chat_messages" in capabilities do
from(q in query, where: q.accepts_chat_messages == true)
else
query
end
end
defp limit, do: Pleroma.Config.get([:instance, :limit_to_local_content], :unauthenticated)
defp restrict_local(q), do: where(q, [u], u.local == true)

View file

@ -0,0 +1,142 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2025 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Utils.URIEncoding do
@moduledoc """
Utility functions for dealing with URI encoding of paths and queries
with support for query-encoding quirks.
"""
require Pleroma.Constants
# We don't always want to decode the path first, like is the case in
# Pleroma.Upload.url_from_spec/3.
@doc """
Wraps URI encoding/decoding functions from Elixir's standard library to fix usually unintended side-effects.
Supports two URL processing options in the optional 2nd argument with the default being `false`:
* `bypass_parse` - Bypasses `URI.parse` stage, useful when it's not desirable to parse to URL first
before encoding it. Supports only encoding as the Path segment of a URI.
* `bypass_decode` - Bypasses `URI.decode` stage for the Path segment of a URI. Used when a URL
has to be double %-encoded for internal reasons.
Options must be specified as a Keyword with tuples with booleans, otherwise
`{:error, :invalid_opts}` is returned. Example:
`encode_url(url, [bypass_parse: true, bypass_decode: true])`
"""
@spec encode_url(String.t(), Keyword.t()) :: String.t() | {:error, :invalid_opts}
def encode_url(url, opts \\ []) when is_binary(url) and is_list(opts) do
bypass_parse = Keyword.get(opts, :bypass_parse, false)
bypass_decode = Keyword.get(opts, :bypass_decode, false)
with true <- is_boolean(bypass_parse),
true <- is_boolean(bypass_decode) do
cond do
bypass_parse ->
encode_path(url, bypass_decode)
true ->
URI.parse(url)
|> then(fn parsed ->
path = encode_path(parsed.path, bypass_decode)
query = encode_query(parsed.query, parsed.host)
%{parsed | path: path, query: query}
end)
|> URI.to_string()
end
else
_ -> {:error, :invalid_opts}
end
end
defp encode_path(nil, _bypass_decode), do: nil
# URI.encode/2 deliberately does not encode all chars that are forbidden
# in the path component of a URI. It only encodes chars that are forbidden
# in the whole URI. A predicate in the 2nd argument is used to fix that here.
# URI.encode/2 uses the predicate function to determine whether each byte
# (in an integer representation) should be encoded or not.
defp encode_path(path, bypass_decode) when is_binary(path) do
path =
cond do
bypass_decode ->
path
true ->
URI.decode(path)
end
path
|> URI.encode(fn byte ->
URI.char_unreserved?(byte) ||
Enum.any?(
Pleroma.Constants.uri_path_allowed_reserved_chars(),
fn char ->
char == byte
end
)
end)
end
# Order of kv pairs in query is not preserved when using URI.decode_query.
# URI.query_decoder/2 returns a stream which so far appears to not change order.
# Immediately switch to a list to prevent breakage for sites that expect
# the order of query keys to be always the same.
defp encode_query(query, host) when is_binary(query) do
query
|> URI.query_decoder()
|> Enum.to_list()
|> do_encode_query(host)
end
defp encode_query(nil, _), do: nil
# Always uses www_form encoding.
# Taken from Elixir's URI module.
defp do_encode_query(enumerable, host) do
Enum.map_join(enumerable, "&", &maybe_apply_query_quirk(&1, host))
end
# https://git.pleroma.social/pleroma/pleroma/-/issues/1055
defp maybe_apply_query_quirk({key, value}, "i.guim.co.uk" = _host) do
case key do
"precrop" ->
query_encode_kv_pair({key, value}, ~c":,")
key ->
query_encode_kv_pair({key, value})
end
end
defp maybe_apply_query_quirk({key, value}, _), do: query_encode_kv_pair({key, value})
# Taken from Elixir's URI module and modified to support quirks.
defp query_encode_kv_pair({key, value}, rules \\ []) when is_list(rules) do
cond do
length(rules) > 0 ->
# URI.encode_query/2 does not appear to follow spec and encodes all parts
# of our URI path Constant. This appears to work outside of edge-cases
# like The Guardian Rich Media Cards, keeping behavior same as with
# URI.encode_query/2 unless otherwise specified via rules.
(URI.encode_www_form(Kernel.to_string(key)) <>
"=" <>
URI.encode(value, fn byte ->
URI.char_unreserved?(byte) ||
Enum.any?(
rules,
fn char ->
char == byte
end
)
end))
|> String.replace("%20", "+")
true ->
URI.encode_www_form(Kernel.to_string(key)) <>
"=" <> URI.encode_www_form(Kernel.to_string(value))
end
end
end

View file

@ -414,10 +414,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
with flag_data <- make_flag_data(params, additional),
{:ok, activity} <- insert(flag_data, local),
{:ok, stripped_activity} <- strip_report_status_data(activity),
_ <- notify_and_stream(activity),
:ok <-
maybe_federate(stripped_activity) do
:ok <- maybe_federate(activity) do
User.all_users_with_privilege(:reports_manage_reports)
|> Enum.filter(fn user -> user.ap_id != actor end)
|> Enum.filter(fn user -> not is_nil(user.email) end)
@ -501,6 +499,28 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> Repo.all()
end
def fetch_objects_for_replies_collection(parent_ap_id, opts \\ %{}) do
opts =
opts
|> Map.put(:order_asc, true)
|> Map.put(:id_type, :integer)
from(o in Object,
where:
fragment("?->>'inReplyTo' = ?", o.data, ^parent_ap_id) and
fragment(
"(?->'to' \\? ?::text OR ?->'cc' \\? ?::text)",
o.data,
^Pleroma.Constants.as_public(),
o.data,
^Pleroma.Constants.as_public()
) and
fragment("?->>'type' <> 'Answer'", o.data),
select: %{id: o.id, ap_id: fragment("?->>'id'", o.data)}
)
|> Pagination.fetch_paginated(opts, :keyset)
end
@spec fetch_latest_direct_activity_id_for_context(String.t(), keyword() | map()) ::
Ecto.UUID.t() | nil
def fetch_latest_direct_activity_id_for_context(context, opts \\ %{}) do
@ -1065,6 +1085,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
from(activity in query, where: fragment("?->>'type' != 'Announce'", activity.data))
end
defp restrict_reblogs(query, %{only_reblogs: true}) do
from(activity in query, where: fragment("?->>'type' = 'Announce'", activity.data))
end
defp restrict_reblogs(query, _), do: query
defp restrict_muted(query, %{with_muted: true}), do: query
@ -1567,7 +1591,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp get_actor_url(_url), do: nil
defp normalize_image(%{"url" => url} = data) do
defp normalize_image(%{"url" => url} = data) when is_binary(url) do
%{
"type" => "Image",
"url" => [%{"href" => url}]
@ -1575,6 +1599,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> maybe_put_description(data)
end
defp normalize_image(%{"url" => urls}) when is_list(urls) do
url = urls |> List.first()
%{"url" => url}
|> normalize_image()
end
defp normalize_image(urls) when is_list(urls), do: urls |> List.first() |> normalize_image()
defp normalize_image(_), do: nil

View file

@ -31,6 +31,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
@federating_only_actions [:internal_fetch, :relay, :relay_following, :relay_followers]
@object_replies_known_param_keys ["page", "min_id", "max_id", "since_id", "limit"]
plug(FederatingPlug when action in @federating_only_actions)
plug(
@ -95,6 +97,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
def object_replies(%{assigns: assigns, query_params: params} = conn, _all_params) do
object_ap_id = conn.path_info |> Enum.reverse() |> tl() |> Enum.reverse()
object_ap_id = Endpoint.url() <> "/" <> Enum.join(object_ap_id, "/")
# Most other API params are converted to atoms by OpenAPISpex 3.x
# and therefore helper functions assume atoms. For consistency,
# also convert our params to atoms here.
params =
params
|> Map.take(@object_replies_known_param_keys)
|> Enum.into(%{}, fn {k, v} -> {String.to_existing_atom(k), v} end)
|> Map.put(:object_ap_id, object_ap_id)
|> Map.put(:order_asc, true)
|> Map.put(:conn, conn)
with %Object{} = object <- Object.get_cached_by_ap_id(object_ap_id),
user <- Map.get(assigns, :user, nil),
{_, true} <- {:visible?, Visibility.visible_for_user?(object, user)} do
conn
|> maybe_skip_cache(user)
|> set_cache_ttl_for(object)
|> put_resp_content_type("application/activity+json")
|> put_view(ObjectView)
|> render("object_replies.json", render_params: params)
else
{:visible?, false} -> {:error, :not_found}
nil -> {:error, :not_found}
end
end
def track_object_fetch(conn, nil), do: conn
def track_object_fetch(conn, object_id) do
@ -257,8 +289,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> put_view(UserView)
|> render("activity_collection_page.json", %{
activities: activities,
pagination: ControllerHelper.get_pagination_fields(conn, activities),
iri: "#{user.ap_id}/outbox"
pagination: ControllerHelper.get_pagination_fields(conn, activities)
})
end
end
@ -404,8 +435,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> put_view(UserView)
|> render("activity_collection_page.json", %{
activities: activities,
pagination: ControllerHelper.get_pagination_fields(conn, activities),
iri: "#{user.ap_id}/inbox"
pagination: ControllerHelper.get_pagination_fields(conn, activities)
})
end
@ -482,6 +512,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
{:ok, activity}
end
# We currently lack a Flag ObjectValidator since both CommonAPI and Transmogrifier
# both send it straight to ActivityPub.flag and C2S currently has to go through
# the normal pipeline which requires an ObjectValidator.
# TODO: Add a Flag Activity ObjectValidator
defp check_allowed_action(_, %{"type" => "Flag"}) do
{:error, "Flag activities aren't currently supported in C2S"}
end
# It would respond with 201 and silently fail with:
# Could not decode featured collection at fetch #{user.ap_id} \
# {:error, "Trying to fetch local resource"}
defp check_allowed_action(%{ap_id: ap_id}, %{"type" => "Update", "object" => %{"id" => ap_id}}),
do: {:error, "Updating profile is not currently supported in C2S"}
defp check_allowed_action(_, activity), do: {:ok, activity}
defp validate_visibility(%User{} = user, %{"type" => type, "object" => object} = activity) do
with {_, %Object{} = normalized_object} <-
{:normalize, Object.normalize(object, fetch: false)},
{_, true} <- {:visibility, Visibility.visible_for_user?(normalized_object, user)} do
{:ok, activity}
else
{:normalize, _} ->
if type in ["Create", "Listen"] do
# Creating new object via C2S; user is local and authenticated
# via the :authenticate Plug pipeline.
{:ok, activity}
else
{:error, "No such object found"}
end
{:visibility, _} ->
{:forbidden, "You can't interact with this object"}
end
end
def update_outbox(
%{assigns: %{user: %User{nickname: nickname, ap_id: actor} = user}} = conn,
%{"nickname" => nickname} = params
@ -493,6 +559,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> Map.put("actor", actor)
with {:ok, params} <- fix_user_message(user, params),
{:ok, params} <- check_allowed_action(user, params),
{:ok, params} <- validate_visibility(user, params),
{:ok, activity, _} <- Pipeline.common_pipeline(params, local: true),
%Activity{data: activity_data} <- Activity.normalize(activity) do
conn

View file

@ -18,6 +18,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
content =~ quote_url -> true
# Does the content already have a .quote-inline span?
content =~ "<span class=\"quote-inline\">" -> true
# Does the content already have a .quote-inline p? (Mastodon)
content =~ "<p class=\"quote-inline\">" -> true
# No inline quote found
true -> false
end

View file

@ -56,20 +56,24 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
defp fix_tag(%{"tag" => tag} = data) when is_map(tag), do: Map.put(data, "tag", [tag])
defp fix_tag(data), do: Map.drop(data, ["tag"])
# legacy internal *oma format
defp fix_replies(%{"replies" => replies} = data) when is_list(replies), do: data
defp fix_replies(%{"replies" => %{"first" => %{"items" => replies}}} = data)
when is_list(replies),
do: Map.put(data, "replies", replies)
defp fix_replies(%{"replies" => %{"first" => %{"orderedItems" => replies}}} = data)
when is_list(replies),
do: Map.put(data, "replies", replies)
defp fix_replies(%{"replies" => %{"items" => replies}} = data) when is_list(replies),
do: Map.put(data, "replies", replies)
# TODO: Pleroma does not have any support for Collections at the moment.
# If the `replies` field is not something the ObjectID validator can handle,
# the activity/object would be rejected, which is bad behavior.
defp fix_replies(%{"replies" => replies} = data) when not is_list(replies),
do: Map.drop(data, ["replies"])
defp fix_replies(%{"replies" => %{"orderedItems" => replies}} = data) when is_list(replies),
do: Map.put(data, "replies", replies)
defp fix_replies(data), do: data
defp fix_replies(data), do: Map.delete(data, "replies")
def fix_attachments(%{"attachment" => attachment} = data) when is_map(attachment),
do: Map.put(data, "attachment", [attachment])

View file

@ -20,7 +20,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
require Pleroma.Constants
def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
{:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback)
# Fix as:Public/Public before ObjectID casting drops it, but keep `field_fallback`
# semantics (only used when the field is missing).
recipients =
%{field => message[field] || field_fallback}
|> Transmogrifier.fix_addressing_list(field)
|> Transmogrifier.fix_addressing_public(field)
|> Map.fetch!(field)
{:ok, data} = ObjectValidators.Recipients.cast(recipients)
data =
Enum.reject(data, fn x ->

View file

@ -13,7 +13,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Publisher.Prepared
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Workers.PublisherWorker
require Pleroma.Constants
@ -26,6 +25,18 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
ActivityPub outgoing federation module.
"""
@signature_impl Application.compile_env(
:pleroma,
[__MODULE__, :signature_impl],
Pleroma.Signature
)
@transmogrifier_impl Application.compile_env(
:pleroma,
[__MODULE__, :transmogrifier_impl],
Pleroma.Web.ActivityPub.Transmogrifier
)
@doc """
Enqueue publishing a single activity.
"""
@ -68,7 +79,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
Determine if an activity can be represented by running it through Transmogrifier.
"""
def representable?(%Activity{} = activity) do
with {:ok, _data} <- Transmogrifier.prepare_outgoing(activity.data) do
with {:ok, _data} <- @transmogrifier_impl.prepare_outgoing(activity.data) do
true
else
_e ->
@ -91,7 +102,17 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
Logger.debug("Federating #{ap_id} to #{inbox}")
uri = %{path: path} = URI.parse(inbox)
{:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
{:ok, data} = @transmogrifier_impl.prepare_outgoing(activity.data)
{actor, data} =
with {_, false} <- {:actor_changed?, data["actor"] != activity.data["actor"]} do
{actor, data}
else
{:actor_changed?, true} ->
# If prepare_outgoing changes the actor, re-get it from the db
new_actor = User.get_cached_by_ap_id(data["actor"])
{new_actor, data}
end
param_cc = Map.get(params, :cc, [])
@ -115,10 +136,10 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
date = Pleroma.Signature.signed_date()
date = @signature_impl.signed_date()
signature =
Pleroma.Signature.sign(actor, %{
@signature_impl.sign(actor, %{
"(request-target)": "post #{path}",
host: signature_host(uri),
"content-length": byte_size(json),
@ -310,17 +331,21 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
Repo.checkout(fn ->
Enum.each([priority_inboxes, other_inboxes], fn inboxes ->
Enum.each(inboxes, fn inbox ->
%User{ap_id: ap_id} = Enum.find(recipients, fn actor -> actor.inbox == inbox end)
{%User{ap_id: ap_id}, priority} =
get_user_with_priority(inbox, priority_recipients, recipients)
# Get all the recipients on the same host and add them to cc. Otherwise, a remote
# instance would only accept a first message for the first recipient and ignore the rest.
cc = get_cc_ap_ids(ap_id, recipients)
__MODULE__.enqueue_one(%{
inbox: inbox,
cc: cc,
activity_id: activity.id
})
__MODULE__.enqueue_one(
%{
inbox: inbox,
cc: cc,
activity_id: activity.id
},
priority: priority
)
end)
end)
end)
@ -382,4 +407,15 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
end
def gather_nodeinfo_protocol_names, do: ["activitypub"]
defp get_user_with_priority(inbox, priority_recipients, recipients) do
[{priority_recipients, 0}, {recipients, 1}]
|> Enum.find_value(fn {recipients, priority} ->
with %User{} = user <- Enum.find(recipients, fn actor -> actor.inbox == inbox end) do
{user, priority}
else
_ -> nil
end
end)
end
end

View file

@ -6,6 +6,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
@moduledoc """
A module to handle coding from internal to wire ActivityPub and back.
"""
@behaviour Pleroma.Web.ActivityPub.Transmogrifier.API
alias Pleroma.Activity
alias Pleroma.EctoType.ActivityPub.ObjectValidators
alias Pleroma.Maps
@ -22,7 +23,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Federator
import Ecto.Query
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
require Pleroma.Constants
@ -103,6 +103,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
@doc """
Bovine compatibility
https://codeberg.org/bovine/bovine/issues/53
"""
def fix_addressing_public(map, field) do
addrs = Map.get(map, field, []) |> List.wrap()
Map.put(
map,
field,
Enum.map(addrs, fn
"Public" -> Pleroma.Constants.as_public()
"as:Public" -> Pleroma.Constants.as_public()
x -> x
end)
)
end
# if directMessage flag is set to true, leave the addressing alone
def fix_explicit_addressing(%{"directMessage" => true} = object, _follower_collection),
do: object
@ -160,6 +178,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> fix_addressing_list("cc")
|> fix_addressing_list("bto")
|> fix_addressing_list("bcc")
|> fix_addressing_public("to")
|> fix_addressing_public("cc")
|> fix_addressing_public("bto")
|> fix_addressing_public("bcc")
|> fix_explicit_addressing(follower_collection)
|> fix_implicit_addressing(follower_collection)
end
@ -739,48 +761,26 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def set_quote_url(obj), do: obj
@doc """
Serialized Mastodon-compatible `replies` collection containing _self-replies_.
Based on Mastodon's ActivityPub::NoteSerializer#replies.
Inline first page of the `replies` collection,
containing any replies in chronological order.
"""
def set_replies(obj_data) do
replies_uris =
with limit when limit > 0 <-
Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0),
%Object{} = object <- Object.get_cached_by_ap_id(obj_data["id"]) do
object
|> Object.self_replies()
|> select([o], fragment("?->>'id'", o.data))
|> limit(^limit)
|> Repo.all()
else
_ -> []
end
set_replies(obj_data, replies_uris)
def set_replies(%{"type" => type} = obj_data)
when type in Pleroma.Constants.status_object_types() do
with obj_ap_id when is_binary(obj_ap_id) <- obj_data["id"],
limit when limit > 0 <-
Pleroma.Config.get([:activitypub, :note_replies_output_limit], 0),
collection <-
Pleroma.Web.ActivityPub.ObjectView.render("object_replies.json", %{
render_params: %{object_ap_id: obj_data["id"], limit: limit, skip_ap_ctx: true}
}) do
Map.put(obj_data, "replies", collection)
else
0 -> Map.put(obj_data, "replies", obj_data["id"] <> "/replies")
_ -> obj_data
end
end
defp set_replies(obj, []) do
obj
end
defp set_replies(obj, replies_uris) do
replies_collection = %{
"type" => "Collection",
"items" => replies_uris
}
Map.merge(obj, %{"replies" => replies_collection})
end
def replies(%{"replies" => %{"first" => %{"items" => items}}}) when not is_nil(items) do
items
end
def replies(%{"replies" => %{"items" => items}}) when not is_nil(items) do
items
end
def replies(_), do: []
def set_replies(obj_data), do: obj_data
# Prepares the object of an outgoing create activity.
def prepare_object(object) do
@ -850,6 +850,27 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, data}
end
def prepare_outgoing(%{"type" => "Update", "object" => %{"type" => objtype} = object} = data)
when objtype in Pleroma.Constants.actor_types() do
object =
object
|> maybe_fix_user_object()
|> strip_internal_fields()
data =
data
|> Map.put("object", object)
|> strip_internal_fields()
|> Map.merge(Utils.make_json_ld_header(object))
|> Map.delete("bcc")
{:ok, data}
end
def prepare_outgoing(%{"type" => "Update", "object" => %{}} = data) do
raise "Requested to serve an Update for non-updateable object type: #{inspect(data)}"
end
def prepare_outgoing(%{"type" => "Announce", "actor" => ap_id, "object" => object_id} = data) do
object =
object_id
@ -909,6 +930,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
end
def prepare_outgoing(%{"type" => "Flag"} = data) do
with {:ok, stripped_activity} <- Utils.strip_report_status_data(data),
stripped_activity <- Utils.maybe_anonymize_reporter(stripped_activity),
stripped_activity <- Map.merge(stripped_activity, Utils.make_json_ld_header()) do
{:ok, stripped_activity}
end
end
def prepare_outgoing(%{"type" => _type} = data) do
data =
data

View file

@ -0,0 +1,11 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.Transmogrifier.API do
@moduledoc """
Behaviour for the subset of Transmogrifier used by Publisher.
"""
@callback prepare_outgoing(map()) :: {:ok, map()} | {:error, term()}
end

View file

@ -82,7 +82,11 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def unaddressed_message?(params),
do:
[params["to"], params["cc"], params["bto"], params["bcc"]]
|> Enum.all?(&is_nil(&1))
|> Enum.all?(fn
nil -> true
[] -> true
_ -> false
end)
@spec recipient_in_message(User.t(), User.t(), map()) :: boolean()
def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params),
@ -859,8 +863,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
def update_report_state(_, _), do: {:error, "Unsupported state"}
def strip_report_status_data(activity) do
[actor | reported_activities] = activity.data["object"]
def strip_report_status_data(%Activity{} = activity) do
with {:ok, new_data} <- strip_report_status_data(activity.data) do
{:ok, %{activity | data: new_data}}
end
end
def strip_report_status_data(data) do
[actor | reported_activities] = data["object"]
stripped_activities =
Enum.reduce(reported_activities, [], fn act, acc ->
@ -870,9 +880,36 @@ defmodule Pleroma.Web.ActivityPub.Utils do
end
end)
new_data = put_in(activity.data, ["object"], [actor | stripped_activities])
new_data = put_in(data, ["object"], [actor | stripped_activities])
{:ok, %{activity | data: new_data}}
{:ok, new_data}
end
def get_anonymized_reporter do
with true <- Pleroma.Config.get([:activitypub, :anonymize_reporter]),
nickname when is_binary(nickname) <-
Pleroma.Config.get([:activitypub, :anonymize_reporter_local_nickname]),
%User{ap_id: ap_id, local: true} <- User.get_cached_by_nickname(nickname) do
ap_id
else
_ -> nil
end
end
def maybe_anonymize_reporter(%Activity{data: data} = activity) do
new_data = maybe_anonymize_reporter(data)
%Activity{activity | actor: new_data["actor"], data: new_data}
end
def maybe_anonymize_reporter(activity) do
ap_id = get_anonymized_reporter()
if is_binary(ap_id) do
activity
|> Map.put("actor", ap_id)
else
activity
end
end
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do

View file

@ -0,0 +1,59 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# Copyright © 2025 Akkoma Authors <https://akkoma.dev/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.CollectionViewHelper do
alias Pleroma.Web.ActivityPub.Utils
def collection_page_offset(collection, iri, page, show_items \\ true, total \\ nil) do
offset = (page - 1) * 10
items = Enum.slice(collection, offset, 10)
items = Enum.map(items, fn user -> user.ap_id end)
total = total || length(collection)
map = %{
"id" => "#{iri}?page=#{page}",
"type" => "OrderedCollectionPage",
"partOf" => iri,
"totalItems" => total,
"orderedItems" => if(show_items, do: items, else: [])
}
if offset + 10 < total do
Map.put(map, "next", "#{iri}?page=#{page + 1}")
else
map
end
end
defp maybe_omit_next(pagination, _items, nil), do: pagination
defp maybe_omit_next(pagination, items, limit) when is_binary(limit) do
case Integer.parse(limit) do
{limit, ""} -> maybe_omit_next(pagination, items, limit)
_ -> maybe_omit_next(pagination, items, nil)
end
end
defp maybe_omit_next(pagination, items, limit) when is_number(limit) do
if Enum.count(items) < limit, do: Map.delete(pagination, "next"), else: pagination
end
def collection_page_keyset(
display_items,
pagination,
limit \\ nil,
skip_ap_context \\ false
) do
%{
"type" => "OrderedCollectionPage",
"orderedItems" => display_items
}
|> Map.merge(pagination)
|> maybe_omit_next(display_items, limit)
|> then(fn m ->
if skip_ap_context, do: m, else: Map.merge(m, Utils.make_json_ld_header())
end)
end
end

View file

@ -6,7 +6,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
use Pleroma.Web, :view
alias Pleroma.Activity
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.CollectionViewHelper
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ControllerHelper
def render("object.json", %{object: %Object{} = object}) do
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(object.data)
@ -15,26 +18,94 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
Map.merge(base, additional)
end
def render("object.json", %{object: %Activity{data: %{"type" => activity_type}} = activity})
when activity_type in ["Create", "Listen"] do
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(activity.data)
object = Object.normalize(activity, fetch: false)
additional =
Transmogrifier.prepare_object(activity.data)
|> Map.put("object", Transmogrifier.prepare_object(object.data))
Map.merge(base, additional)
def render("object.json", %{object: %Activity{} = activity}) do
{:ok, ap_data} = Transmogrifier.prepare_outgoing(activity.data)
ap_data
end
def render("object.json", %{object: %Activity{} = activity}) do
base = Pleroma.Web.ActivityPub.Utils.make_json_ld_header(activity.data)
object_id = Object.normalize(activity, id_only: true)
def render("object_replies.json", %{
conn: conn,
render_params: %{object_ap_id: object_ap_id, page: "true"} = params
}) do
params = Map.put_new(params, :limit, 40)
additional =
Transmogrifier.prepare_object(activity.data)
|> Map.put("object", object_id)
items = ActivityPub.fetch_objects_for_replies_collection(object_ap_id, params)
display_items = map_reply_collection_items(items)
Map.merge(base, additional)
pagination = ControllerHelper.get_pagination_fields(conn, items, %{}, :asc)
CollectionViewHelper.collection_page_keyset(display_items, pagination, params[:limit])
end
def render(
"object_replies.json",
%{
render_params: %{object_ap_id: object_ap_id} = params
} = opts
) do
params =
params
|> Map.drop([:max_id, :min_id, :since_id, :object_ap_id])
|> Map.put_new(:limit, 40)
|> Map.put(:total, true)
%{total: total, items: items} =
ActivityPub.fetch_objects_for_replies_collection(object_ap_id, params)
display_items = map_reply_collection_items(items)
first_pagination = reply_collection_first_pagination(items, opts)
col_ap =
%{
"id" => object_ap_id <> "/replies",
"type" => "OrderedCollection",
"totalItems" => total
}
col_ap =
if total > 0 do
first_page =
CollectionViewHelper.collection_page_keyset(
display_items,
first_pagination,
params[:limit],
true
)
Map.put(col_ap, "first", first_page)
else
col_ap
end
if params[:skip_ap_ctx] do
col_ap
else
Map.merge(col_ap, Pleroma.Web.ActivityPub.Utils.make_json_ld_header())
end
end
defp map_reply_collection_items(items), do: Enum.map(items, fn %{ap_id: ap_id} -> ap_id end)
defp reply_collection_first_pagination(items, %{conn: %Plug.Conn{} = conn}) do
pagination = ControllerHelper.get_pagination_fields(conn, items, %{"page" => true}, :asc)
Map.put(pagination, "id", Phoenix.Controller.current_url(conn, %{"page" => true}))
end
defp reply_collection_first_pagination(items, %{render_params: %{object_ap_id: object_ap_id}}) do
%{
"id" => object_ap_id <> "/replies?page=true",
"partOf" => object_ap_id <> "/replies"
}
|> then(fn m ->
case items do
[] ->
m
i ->
next_id = object_ap_id <> "/replies?page=true&min_id=#{List.last(i)[:id]}"
Map.put(m, "next", next_id)
end
end)
end
end

View file

@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.CollectionViewHelper
alias Pleroma.Web.ActivityPub.ObjectView
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
@ -164,7 +165,13 @@ defmodule Pleroma.Web.ActivityPub.UserView do
0
end
collection(following, "#{user.ap_id}/following", page, showing_items, total)
CollectionViewHelper.collection_page_offset(
following,
"#{user.ap_id}/following",
page,
showing_items,
total
)
|> Map.merge(Utils.make_json_ld_header())
end
@ -189,7 +196,12 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"totalItems" => total,
"first" =>
if showing_items do
collection(following, "#{user.ap_id}/following", 1, !user.hide_follows)
CollectionViewHelper.collection_page_offset(
following,
"#{user.ap_id}/following",
1,
!user.hide_follows
)
else
"#{user.ap_id}/following?page=1"
end
@ -212,7 +224,13 @@ defmodule Pleroma.Web.ActivityPub.UserView do
0
end
collection(followers, "#{user.ap_id}/followers", page, showing_items, total)
CollectionViewHelper.collection_page_offset(
followers,
"#{user.ap_id}/followers",
page,
showing_items,
total
)
|> Map.merge(Utils.make_json_ld_header())
end
@ -236,7 +254,12 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"type" => "OrderedCollection",
"first" =>
if showing_items do
collection(followers, "#{user.ap_id}/followers", 1, showing_items, total)
CollectionViewHelper.collection_page_offset(
followers,
"#{user.ap_id}/followers",
1,
showing_items
)
else
"#{user.ap_id}/followers?page=1"
end
@ -256,7 +279,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
def render("activity_collection_page.json", %{
activities: activities,
iri: iri,
pagination: pagination
}) do
collection =
@ -265,13 +287,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
data
end)
%{
"type" => "OrderedCollectionPage",
"partOf" => iri,
"orderedItems" => collection
}
|> Map.merge(Utils.make_json_ld_header())
|> Map.merge(pagination)
CollectionViewHelper.collection_page_keyset(collection, pagination)
end
def render("featured.json", %{
@ -299,27 +315,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
Map.put(map, "totalItems", total)
end
def collection(collection, iri, page, show_items \\ true, total \\ nil) do
offset = (page - 1) * 10
items = Enum.slice(collection, offset, 10)
items = Enum.map(items, fn user -> user.ap_id end)
total = total || length(collection)
map = %{
"id" => "#{iri}?page=#{page}",
"type" => "OrderedCollectionPage",
"partOf" => iri,
"totalItems" => total,
"orderedItems" => if(show_items, do: items, else: [])
}
if offset < total do
Map.put(map, "next", "#{iri}?page=#{page + 1}")
else
map
end
end
defp maybe_make_image(func, description, key, user) do
if image = func.(user, no_default: true) do
%{

View file

@ -73,6 +73,22 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
|> Pleroma.List.member?(user)
end
def visible_for_user?(%Activity{object: %Object{} = object} = activity, nil) do
activity_visibility? = restrict_unauthenticated_access?(activity)
activity_public? = public?(activity) and not local_public?(activity)
object_visibility? = restrict_unauthenticated_access?(object)
object_public? = public?(object) and not local_public?(object)
# Activity could be local, but object might not (Announce/Like)
cond do
activity_visibility? or object_visibility? ->
false
true ->
activity_public? and object_public?
end
end
def visible_for_user?(%{__struct__: module} = message, nil)
when module in [Activity, Object] do
if restrict_unauthenticated_access?(message),

Some files were not shown because too many files have changed in this diff Show more