Compare commits

...

465 Commits

Author SHA1 Message Date
Haelwenn fb4aa9f725 Merge branch 'release/2.6.2' into 'stable'
Security Release 2.6.2

See merge request pleroma/pleroma!4074
2024-02-20 08:43:07 +00:00
Haelwenn (lanodan) Monnier be075a4336
Security release 2.6.2 2024-02-20 09:16:36 +01:00
Haelwenn (lanodan) Monnier ac977bdb1c
StealEmojiPolicy: Sanitize shortcodes
Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3245
2024-02-20 09:14:02 +01:00
tusooa 6722b7f395 Merge branch 'release/2.6.1' into 'stable'
Release: 2.6.1

See merge request pleroma/pleroma!3999
2023-12-16 00:36:08 +00:00
Haelwenn f07b134add Fix formatting of changelog 2023-12-15 23:52:37 +00:00
tusooa 948f01f19a
Bundle 2.6.1 frontend 2023-12-14 20:32:49 -05:00
tusooa ad6a6aa07b
Bump version to 2.6.1 2023-12-14 20:14:41 -05:00
Haelwenn (lanodan) Monnier b1ea63b4c6
changelog.d/system-cflags.fix: New entry 2023-12-14 20:13:25 -05:00
Haelwenn (lanodan) Monnier 41f6e8f7f4
mix: Bump elixir-captcha for system-CFLAGS 2023-12-14 20:13:20 -05:00
Haelwenn (lanodan) Monnier 08839602bd
mix: cherry-pick eblurhash latest git for system-CFLAGS 2023-12-14 20:13:00 -05:00
Haelwenn (lanodan) Monnier 35090f6eac
TwitterAPI: Return proper error when healthcheck is disabled 2023-12-14 20:11:01 -05:00
Haelwenn (lanodan) Monnier 272271d939
docs: clang is also supported 2023-12-14 07:29:54 -05:00
Haelwenn (lanodan) Monnier 1b22f13488
docs: Put a max version on erlang and elixir
Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3194
2023-12-14 07:29:54 -05:00
Henry Jameson e635ee8b39
changelog 2023-12-14 07:28:52 -05:00
Henry Jameson 57445e65cb
update, add images 2023-12-14 07:28:52 -05:00
Henry Jameson 476fd01f8d
Initial draft on frontends management 2023-12-14 07:28:43 -05:00
tusooa 6f654d534a Merge branch 'release/2.6.0' into 'stable'
Release/2.6.0

See merge request pleroma/pleroma!3924
2023-11-01 00:43:35 +00:00
tusooa ad45b06b3f Merge branch 'stable' into 'release/2.6.0'
# Conflicts:
#   .gitlab-ci.yml
#   lib/pleroma/web/common_api/utils.ex
#   lib/pleroma/web/xml.ex
#   mix.exs
#   test/pleroma/web/activity_pub/transmogrifier/emoji_react_handling_test.exs
#   test/pleroma/web/common_api/utils_test.exs
#   test/pleroma/web/mastodon_api/update_credentials_test.exs
#   test/pleroma/web/xml_test.exs
2023-10-31 01:07:43 +00:00
tusooa ab894d98f4
Bundle 2.6.0 frontend 2023-10-29 12:59:03 -04:00
tusooa 6a13c2d180
Add collect-changelog script 2023-10-25 20:45:23 -04:00
tusooa a2a69709b5
Bump version to 2.6.0 2023-10-24 19:57:31 -04:00
Haelwenn e3ea311cd5 Merge branch 'tusooa/2810-punycode-mention' into 'develop'
Fix mentioning punycode domains when using Markdown

Closes #2810

See merge request pleroma/pleroma!3925
2023-10-18 01:20:00 +00:00
tusooa df0b56576a
Fix other quotation mark conversion tests 2023-10-16 21:35:37 -04:00
tusooa b748efe66a
Fix mentioning punycode domains when using Markdown 2023-10-16 21:35:25 -04:00
tusooa 340c881296 Merge branch 'tusooa/3018-unified-stream' into 'develop'
Unified streaming endpoint

Closes #3018

See merge request pleroma/pleroma!3864
2023-10-15 21:35:30 +00:00
tusooa eb33a03d0a
Explain the encode-decode roundtrip 2023-10-15 17:20:26 -04:00
tusooa 3e7d2e29b3
Add changelog 2023-10-15 17:20:26 -04:00
tusooa 840dd01035
Fix duplicated schema names 2023-10-15 17:20:26 -04:00
tusooa 32de0683c4
Fix unsubscribe event type in streaming doc 2023-10-15 17:20:26 -04:00
tusooa c13f0a8460
Add meta-info and query strings to streaming doc 2023-10-15 17:20:26 -04:00
tusooa f393a15dd1
Fix some specs about server-sent events in streaming 2023-10-15 17:20:26 -04:00
tusooa 8829dcaee4
Document client-sent events in streaming 2023-10-15 17:20:25 -04:00
tusooa dcef33f5f0
Document server-sent events of streaming 2023-10-15 17:20:25 -04:00
tusooa 844d1a14e0
Start writing api docs for streaming endpoint 2023-10-15 17:20:25 -04:00
tusooa 314360e5e3
Add test to cover edit streaming 2023-10-15 17:20:25 -04:00
tusooa 26f5caebae
Add test to cover notifications streaming 2023-10-15 17:20:25 -04:00
tusooa 4cf109d3c4
Add test to cover rendering update with user 2023-10-15 17:20:25 -04:00
tusooa 050227f118
Add test to cover error: bad_topic 2023-10-15 17:20:25 -04:00
tusooa eebc605bc2
Clear up debug statement 2023-10-15 17:20:25 -04:00
tusooa 949c4f01c6
Fix NotificationTest 2023-10-15 17:20:25 -04:00
tusooa 7f12ad6dcc
Fix docs wording 2023-10-15 17:20:25 -04:00
tusooa 9572be1e5f
Add tests for list streams 2023-10-15 17:20:25 -04:00
tusooa 2d43067946
Document the streaming endpoint 2023-10-15 17:20:25 -04:00
tusooa a348c2e4dd
Use pleroma: instead of pleroma. for ws events 2023-10-15 17:20:25 -04:00
tusooa 7d005e8c93
Return stream attribute in server-sent events 2023-10-15 17:20:23 -04:00
tusooa 21395aa509
Allow authenticating via client-sent events 2023-10-15 17:19:49 -04:00
tusooa 273cda63ad
Allow subscribing to streams 2023-10-15 17:19:49 -04:00
tusooa 2b5636bf12
Allow unified streaming endpoint 2023-10-15 17:19:40 -04:00
tusooa 14b1b9c9b0 Merge branch 'tusooa/quote' into 'develop'
Quoting

See merge request pleroma/pleroma!3921
2023-10-15 20:48:16 +00:00
tusooa 08608afca5
Fix quote_visible attribute 2023-09-13 19:20:33 -04:00
tusooa a8b2f9205d
Expose quote_id parameter on the api 2023-09-13 19:20:32 -04:00
tusooa 875b46d97d
Do not mention original poster when quoting 2023-09-13 19:20:32 -04:00
tusooa 87353e5ad1
Fix config descriptions for mrf inline quote 2023-09-13 19:20:32 -04:00
tusooa 8596f92654
Fix TransmogrifierTest 2023-09-13 19:20:32 -04:00
tusooa 8b98a98dfb
Make InlineQuotePolicy history aware 2023-09-13 19:20:32 -04:00
tusooa e349e92a44
Add mrf to force link tag of quoting posts 2023-09-13 19:20:30 -04:00
tusooa 479a6f11db
Keep incoming Link tag 2023-09-13 19:19:44 -04:00
tusooa e9cd004ba1
Parse object link as quoteUrl 2023-09-13 19:19:42 -04:00
tusooa 163e563733
Allow more flexibility in InlineQuotePolicy 2023-09-13 19:19:05 -04:00
tusooa 762794eed9
Fix CommonAPITest 2023-09-13 19:19:05 -04:00
tusooa d244c9d298
Add changelog 2023-09-13 19:19:05 -04:00
tusooa 9bcec87aba
Allow local quote and private self-quote 2023-09-13 19:19:05 -04:00
tusooa b0a7e795e7
Unify logic for normalizing quoteUri 2023-09-13 19:19:05 -04:00
Alex Gleason f9697e68c2
InlineQuotePolicy: skip objects which already have an .inline-quote span 2023-09-13 19:19:05 -04:00
Alex Gleason 79fca39faf
Actually, don't send _misskey_quote anymore 2023-09-13 19:19:05 -04:00
Alex Gleason 4075eecca0
InlineQuotePolicy: improve the way Markdown quotes are displayed by other software 2023-09-13 19:19:05 -04:00
Alex Gleason 817e308c0d
Handle Fedibird's new quoteUri field 2023-09-13 19:19:05 -04:00
Alex Gleason 3c8319fe9f
Transmogrifier: federate quotes with _misskey_quote field 2023-09-13 19:19:04 -04:00
Alex Gleason cf8e425883
StatusView: return quote post inside a reblog 2023-09-13 19:19:04 -04:00
Alex Gleason 93e4972b50
Add InlineQuotePolicy as a default MRF 2023-09-13 19:19:04 -04:00
Alex Gleason bee7e41959
InlineQuotePolicy: don't add line breaks to markdown posts 2023-09-13 19:19:04 -04:00
Alex Gleason 74e0a4555f
StatusView: add `quote_visible` param 2023-09-13 19:19:04 -04:00
Alex Gleason 6f11f11519
StatusView: fix quote visibility 2023-09-13 19:19:04 -04:00
Alex Gleason 59326247aa
CommonAPI: disallow quoting private posts through the API 2023-09-13 19:19:04 -04:00
Alex Gleason 57ef1d1211
Add InlineQuotePolicy to force quote URLs inline 2023-09-13 19:19:04 -04:00
Alex Gleason 36a5578d2b
Scrubber.Default: allow span.quote-inline for quote post compatibility 2023-09-13 19:19:04 -04:00
Alex Gleason 1f19dd76f6
ActivityDraft: mix format, defensive actor ID 2023-09-13 19:19:04 -04:00
Alex Gleason 54a9897938
ActivityDraft: mention the OP of a quoted post 2023-09-13 19:19:04 -04:00
Alex Gleason 80ab2572a4
Return quote_url through the API, don't render quotes more than 1 level deep 2023-09-13 19:19:04 -04:00
Alex Gleason db46abce47
@context: add quoteUrl 2023-09-13 19:19:04 -04:00
Alex Gleason 5716f88a1d
InstanceView: add "quote_posting" feature 2023-09-13 19:19:03 -04:00
Alex Gleason f4ccdfd503
Fix typos 2023-09-13 19:19:03 -04:00
Alex Gleason 9600973917
mix format 2023-09-13 19:19:03 -04:00
Alex Gleason cbd1760efa
TransmogrifierTest: prepare an outgoing quote post 2023-09-13 19:19:03 -04:00
Alex Gleason 3a8b5d90df
StatusControllerTest: test creating a quote post 2023-09-13 19:19:03 -04:00
Alex Gleason c20e90e898
BuilderTest: build quote post 2023-09-13 19:19:03 -04:00
Alex Gleason d4fea8b559
ActivityDraft: allow quoting 2023-09-13 19:19:03 -04:00
Alex Gleason 6ac19c3999
ActivityDraft: create quote posts 2023-09-13 19:19:03 -04:00
Alex Gleason 0d9c443e51
StatusView: render the whole quoted status 2023-09-13 19:19:03 -04:00
Alex Gleason ce5eb31723
StatusView: show quoted posts through the API, probably 2023-09-13 19:19:03 -04:00
Alex Gleason cc4badaf60
Transmogrifier: fix quoteUrl here too 2023-09-13 19:19:03 -04:00
Alex Gleason b022d6635d
Transmogrifier: fetch quoted post 2023-09-13 19:19:03 -04:00
Alex Gleason 795736af16
ObjectValidators: improve quoteUrl compatibility 2023-09-13 19:19:03 -04:00
Alex Gleason 7deda1fa18
Quote post: add fixtures 2023-09-13 19:19:02 -04:00
Alex Gleason 31eb3dc245
ObjectValidators: accept "quoteUrl" field 2023-09-13 19:19:02 -04:00
Haelwenn f966abe4fb Merge branch 'release/2.5.5' into 'stable'
Release 2.5.5

See merge request pleroma/pleroma!3949
2023-09-03 12:12:44 +00:00
Haelwenn (lanodan) Monnier 385492577d mix: version 2.5.5 2023-09-03 11:19:26 +02:00
Mint 535a5ecad0 CommonAPI: Prevent users from accessing media of other users
commit 1afde067b1 upstream.
2023-09-03 11:19:13 +02:00
Haelwenn a94cf2ad4f Merge branch 'check-attachment-attribution' into 'develop'
Prevent users from attaching other users' attachments

See merge request pleroma/pleroma!3947
2023-09-03 09:09:27 +00:00
Mint 1afde067b1 CommonAPI: Prevent users from accessing media of other users 2023-09-03 10:41:37 +02:00
Haelwenn 9da4f89b7b Merge branch 'tusooa/lint' into 'develop'
Make lint happy

See merge request pleroma/pleroma!3944
2023-08-31 22:24:30 +00:00
tusooa 3c5ecca377
Skip changelog 2023-08-30 20:37:45 -04:00
tusooa 3d09bc320e
Make lint happy 2023-08-30 20:36:52 -04:00
Haelwenn 1e685c8302 Merge branch 'csp-flash' into 'develop'
allow https: so that flash works across instances without need for media proxy

See merge request pleroma/pleroma!3879
2023-08-16 13:37:49 +00:00
Haelwenn d838d1990b Apply lanodan's suggestion(s) to 1 file(s) 2023-08-16 13:34:32 +00:00
tusooa b729a8b140 Merge branch 'fix-dockerfile-perms' into 'develop'
Fix config ownership in dockerfile to pass restriction test

See merge request pleroma/pleroma!3931
2023-08-10 00:42:29 +00:00
Cat pony Black c298e0165c Fix config ownership in dockerfile to pass restriction test 2023-08-08 19:07:48 +02:00
Haelwenn 4e355b8595 Merge branch 'disable-xml-entities-completely' into 'develop'
Completely disable xml entity resolution

See merge request pleroma/pleroma!3932
2023-08-06 08:27:27 +00:00
mae 48b1e9bdc7 Completely disable xml entity resolution 2023-08-05 14:17:04 +02:00
Haelwenn 17c336de66 Merge branch 'docs/gentoo-otp-intro' into 'develop'
gentoo_otp_en.md: Indicate which install method it covers

See merge request pleroma/pleroma!3928
2023-08-05 11:04:32 +00:00
Haelwenn d0f7a5c4f5 Merge branch 'mergeback/2.5.4' into 'develop'
Mergeback: 2.5.4

See merge request pleroma/pleroma!3930
2023-08-05 08:13:03 +00:00
Haelwenn 1f4be2b349 Merge branch 'releases/2.5.4' into 'stable'
Release 2.5.4

See merge request pleroma/pleroma!3929
2023-08-05 08:12:25 +00:00
Haelwenn (lanodan) Monnier 4099ddb3dc Mergeback release 2.5.4 2023-08-05 08:58:05 +02:00
Haelwenn (lanodan) Monnier b631180b38 Release 2.5.4 2023-08-05 08:27:42 +02:00
Mark Felder cc848b78dc Document and test that XXE processing is disabled
https://vuln.be/post/xxe-in-erlang-and-elixir/
2023-08-05 08:23:04 +02:00
FloatingGhost 77d57c974a Add unit test for external entity loading 2023-08-05 08:23:04 +02:00
Mae fc10e07ffb Prevent XML parser from loading external entities 2023-08-05 08:23:04 +02:00
Mark Felder 6d48b0f1a9 Document and test that XXE processing is disabled
https://vuln.be/post/xxe-in-erlang-and-elixir/
2023-08-05 08:14:27 +02:00
FloatingGhost 307692cee8 Add unit test for external entity loading 2023-08-05 08:14:27 +02:00
Mae ca0859b90f Prevent XML parser from loading external entities 2023-08-04 22:35:13 -04:00
Haelwenn (lanodan) Monnier 0e321698d2 gentoo_otp_en.md: Indicate which install method it covers 2023-08-04 17:11:20 +02:00
Haelwenn ff2f3862ab Merge branch 'release/2.5.3' into 'stable'
Release 2.5.3

See merge request pleroma/pleroma!3926
2023-08-04 09:45:48 +00:00
Haelwenn 1062185ba0 Merge branch 'mergeback/2.5.3' into 'develop'
Mergeback: 2.5.3

Closes #3135

See merge request pleroma/pleroma!3927
2023-08-04 09:38:01 +00:00
Haelwenn (lanodan) Monnier 6a0fd77c48 Release 2.5.53 2023-08-04 09:50:28 +02:00
Haelwenn (lanodan) Monnier 65ef8f19c5 release_runtime_provider_test: chmod config for hardened permissions
Git doesn't manages file permissions precisely enough for us.
2023-08-04 09:50:28 +02:00
Haelwenn (lanodan) Monnier 9f0ad901ed changelog: Entry for config permissions restrictions
Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3135
2023-08-04 09:50:28 +02:00
Haelwenn (lanodan) Monnier 69caedc591 instance gen: Reduce permissions of pleroma directories and config files 2023-08-04 09:50:28 +02:00
Haelwenn (lanodan) Monnier 8cc8100120 Config: Restrict permissions of OTP config file 2023-08-04 09:50:28 +02:00
Haelwenn (lanodan) Monnier 57f7453748 Release 2.5.3 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 5ac2b7417d test: Fix warnings 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier c37561214a Force the use of amd64 runners for jobs using ci-base 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 76e408e42d release_runtime_provider_test: chmod config for hardened permissions
Git doesn't manages file permissions precisely enough for us.
2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 22df32b3f5 changelog: Entry for config permissions restrictions
Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3135
2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier bd7381f2f4 instance gen: Reduce permissions of pleroma directories and config files 2023-08-04 09:49:53 +02:00
Haelwenn (lanodan) Monnier 4befb3b1d0 Config: Restrict permissions of OTP config file 2023-08-04 09:49:53 +02:00
Mark Felder 2c79509453 Resolve information disclosure vulnerability through emoji pack archive download endpoint
The pack name has been sanitized so an attacker cannot upload a media
file called pack.json with their own handcrafted list of emoji files as
arbitrary files on the filesystem and then call the emoji pack archive
download endpoint with a pack name crafted to the location of the media
file they uploaded which tricks Pleroma into generating a zip file of
the target files the attacker wants to download.

The attack only works if the Pleroma instance does not have the
AnonymizeFilename upload filter enabled, which is currently the default.

Reported by: graf@poast.org
2023-08-04 08:40:27 +02:00
Mark Felder 18a0c923d0 Resolve information disclosure vulnerability through emoji pack archive download endpoint
The pack name has been sanitized so an attacker cannot upload a media
file called pack.json with their own handcrafted list of emoji files as
arbitrary files on the filesystem and then call the emoji pack archive
download endpoint with a pack name crafted to the location of the media
file they uploaded which tricks Pleroma into generating a zip file of
the target files the attacker wants to download.

The attack only works if the Pleroma instance does not have the
AnonymizeFilename upload filter enabled, which is currently the default.

Reported by: graf@poast.org
2023-08-04 08:39:55 +02:00
Haelwenn 819fccb7d1 Merge branch 'tusooa/3154-attachment-type-check' into 'develop'
Restrict attachments to only uploaded files only

Closes #3154

See merge request pleroma/pleroma!3923
2023-08-03 10:01:32 +00:00
tusooa b08cbe76f1 Merge branch 'fix/2927-disallow-unauthenticated-access' into 'develop'
/api/v1/statuses/:id/context: filter context activities using Visibility.visible_for_user?/2

See merge request pleroma/pleroma!3801
2023-07-28 15:05:46 +00:00
faried nawaz 11ce81d4af add changelog entry 2023-07-28 18:49:05 +05:00
Faried Nawaz e5e76ec445 cleaner ecto query to handle restrict_unauthenticated for activities
This fix is for this case:

  config :pleroma, :restrict_unauthenticated,
    activities: %{local: true, remote: true}
2023-07-28 18:45:59 +05:00
faried nawaz dc4de79d43 status context: perform visibility check on activities around a status
issue #2927
2023-07-28 18:45:59 +05:00
tusooa ea4225a646
Restrict attachments to only uploaded files only 2023-07-18 18:39:59 -04:00
Haelwenn 93ad16cca0 Merge branch '2023-06-deps-update' into 'develop'
2023-06 deps update + de-override plug

See merge request pleroma/pleroma!3911
2023-07-17 20:37:47 +00:00
Haelwenn e38207162b Merge branch 'tusooa/2775-emoji-policy' into 'develop'
EmojiPolicy

Closes #2775

See merge request pleroma/pleroma!3842
2023-07-07 16:27:30 +00:00
tusooa 1459d64508
Make regex-to-string descriptor reusable 2023-07-07 07:09:35 -04:00
tusooa ba3aa4f86d
Fix edge cases 2023-07-07 06:58:32 -04:00
tusooa 0d914e17be
Add changelog 2023-07-07 06:58:32 -04:00
tusooa d670dbdbd3
Test that unicode emoji reactions are not affected 2023-07-07 06:58:32 -04:00
tusooa ef8a6c539a
Make EmojiPolicy aware of custom emoji reactions 2023-07-07 06:58:31 -04:00
tusooa 20d193c91d
Improve config examples for EmojiPolicy 2023-07-07 06:58:31 -04:00
tusooa 18a8378beb
Update config cheatsheet 2023-07-07 06:58:31 -04:00
tusooa f50422c380
Move emoji_policy.ex to the right place 2023-07-07 06:58:31 -04:00
tusooa 7eb8abf7bb
EmojiPolicy: Implement delist 2023-07-07 06:58:31 -04:00
tusooa 80ce6482f6
EmojiPolicy: implement remove by shortcode 2023-07-07 06:58:31 -04:00
tusooa 28ff828caa
Add emoji policy to remove emojis matching certain urls
https://git.pleroma.social/pleroma/pleroma/-/issues/2775
2023-07-07 06:58:22 -04:00
tusooa 7da6a82dbd Merge branch 'deprecate-scrobbles' into 'develop'
Deprecate audio scrobbling

See merge request pleroma/pleroma!3919
2023-07-04 02:46:10 +00:00
Haelwenn 624a5ccb2e Merge branch 'hotfix/docs-broken-links' into 'develop'
docs: Fix broken links

See merge request pleroma/pleroma!3920
2023-07-04 02:26:19 +00:00
Haelwenn (lanodan) Monnier 0c3709173f docs: Fix broken links 2023-07-04 04:23:48 +02:00
Haelwenn 53f4d6f238 Merge branch 'fix/pipeline-triggers' into 'develop'
CI: Fix pipeline tokens & exit status

See merge request pleroma/pleroma!3918
2023-07-04 02:04:24 +00:00
Haelwenn (lanodan) Monnier 3d79ceb23a Deprecate audio scrobbling 2023-07-04 03:40:11 +02:00
Haelwenn (lanodan) Monnier 8c3363a5e7 CI: Use CI_JOB_TOKEN for cross-repo pipeline triggers 2023-07-04 03:25:37 +02:00
Haelwenn (lanodan) Monnier 10249d1e42 CI: Let curl return non-0 on http failure code
Otherwise it silently fails
2023-07-04 03:24:13 +02:00
Haelwenn 6fbbf80800 Merge branch 'gentoo_otp' into 'develop'
Packaged installation guide for gentoo

See merge request pleroma/pleroma!3906
2023-07-03 21:04:23 +00:00
Haelwenn 2b9cd25cf4 Merge branch 'tusooa/media-altdomain' into 'develop'
Add instructions to serve media on another domain

See merge request pleroma/pleroma!3892
2023-07-02 21:30:16 +00:00
Haelwenn 0262916978 Merge branch 'testfix/system-config-use' into 'develop'
release_runtime_provider_test: Explicitely use non-existant config file

See merge request pleroma/pleroma!3910
2023-07-02 21:28:15 +00:00
Haelwenn a31a4c522f Merge branch 'tusooa/3131-handle-report-from-deactivated-user' into 'develop'
Fix handling report from a deactivated user

Closes #3131

See merge request pleroma/pleroma!3915
2023-07-02 21:27:15 +00:00
Haelwenn 379590d438 Merge branch 'tusooa/3142-featured-collection-shouldnt-break-user-fetch' into 'develop'
Fix user fetch completely broken if featured collection is not in a supported form

See merge request pleroma/pleroma!3914
2023-07-02 21:25:45 +00:00
Haelwenn 8cf231c0d1 Merge branch 'tusooa/3151-amd64-runner' into 'develop'
Force the use of amd64 runners for jobs using ci-base

Closes #3151

See merge request pleroma/pleroma!3913
2023-07-02 20:20:49 +00:00
tusooa 6e4de2383f
Fix handling report from a deactivated user 2023-07-02 11:15:34 -04:00
tusooa a1621839cc
Fix user fetch completely broken if featured collection is not in a supported form 2023-07-02 11:03:09 -04:00
tusooa 63b9f76782
Force the use of amd64 runners for jobs using ci-base 2023-07-01 23:25:04 -04:00
tusooa 48e490cd58 Merge branch 'bugfix/full-revert-media-host-validation' into 'develop'
Merge Revert "Merge branch 'validate-host' into 'develop'"

Closes #3136

See merge request pleroma/pleroma!3909
2023-07-01 21:54:18 +00:00
Haelwenn (lanodan) Monnier bf2b4b9400 README.md: Update packaging state (GURU, AUR) 2023-06-27 21:13:02 +02:00
Haelwenn 043a00991d Merge branch 'instance-nodeinfo-metadata' into 'develop'
instances: Store some metadata based on NodeInfo

See merge request pleroma/pleroma!3853
2023-06-27 18:58:04 +00:00
Haelwenn ae0ca49451 Merge branch 'tusooa/3119-bio-update' into 'develop'
Show more informative errors when profile exceeds char limits

Closes #3119

See merge request pleroma/pleroma!3886
2023-06-27 18:49:43 +00:00
Haelwenn 41f2ee69a8 Merge branch 'from/upstream-develop/tusooa/backup-status' into 'develop'
Detail backup states

Closes #3024

See merge request pleroma/pleroma!3809
2023-06-27 12:08:11 +00:00
Haelwenn (lanodan) Monnier d7e049d5e8 router: Fix usage of globs
warning: doing a prefix match with globs is deprecated, invalid segment "pleroma*path".
    You can either replace by a single segment match:
        /foo/bar-:var
    Or by mixing single segment match with globs:
        /foo/bar-:var/*rest
2023-06-27 10:42:10 +02:00
Haelwenn (lanodan) Monnier 3a67b8f287 endpoint: Use custom Multipart module for dynamic configuration 2023-06-27 10:41:25 +02:00
Haelwenn (lanodan) Monnier 9e69adf76f mix: Remove override on plug 2023-06-27 02:38:31 +02:00
Haelwenn (lanodan) Monnier aa4c4ab2a0 mix: 2023-06 deps update
this fixes compatibility with Erlang OTP 26

Related: https://git.pleroma.social/pleroma/pleroma/-/issues/2913
2023-06-27 02:38:31 +02:00
Haelwenn (lanodan) Monnier 8bc51288be release_runtime_provider_test: Explicitely use non-existant config file 2023-06-27 00:20:29 +02:00
Haelwenn 4e26fbda08 Merge branch 'weblate-extract' into 'develop'
Extract translatable strings

See merge request pleroma/pleroma!3871
2023-06-22 19:40:18 +00:00
Haelwenn (lanodan) Monnier dd9f8150fc Merge Revert "Merge branch 'validate-host' into 'develop'"
This reverts commit d998a114e2, reversing
changes made to da6b4003ac.
2023-06-22 21:28:25 +02:00
Haelwenn 4367579949 Merge branch 'fix/bypass-authorized-fetch-mode-json' into 'develop'
Prevent using a .json format to bypass authorized fetch mode

See merge request pleroma/pleroma!3908
2023-06-22 10:35:56 +00:00
weblate-extractor 8bf8906045 Extract translatable strings 2023-06-22 06:09:47 +00:00
Sean King 994bfc4c09
Add changelog entry 2023-06-21 23:13:16 -06:00
Sean King a5a354a36e
Prevent bypassing authorized fetch mode with a json file 2023-06-21 23:10:56 -06:00
tusooa 8fa435f370 Add "potentially outdated" notice in non-English versions 2023-06-14 21:48:10 +00:00
Haelwenn (lanodan) Monnier 937fa36ec4 changelog.d/gentoo_otp.skip: Doc-only MR 2023-06-13 16:05:37 +02:00
Haelwenn (lanodan) Monnier eddfd41c1f gentoo_en: Reference packaged installation 2023-06-13 16:05:37 +02:00
Haelwenn (lanodan) Monnier fb19f0d844 gentoo_otp_en: Add packaged installation documentation 2023-06-13 16:05:37 +02:00
Haelwenn (lanodan) Monnier 4392fff212 otp_vs_from_source*: Acknowledge distro packages 2023-06-13 16:05:37 +02:00
Haelwenn (lanodan) Monnier d5a7079f42 media_graphics_packages.md: Fix markdown syntax 2023-06-13 15:44:29 +02:00
lain 589301ce06 Merge branch 'no_new_privs' into 'develop'
Add no_new_privs to OpenRC service files

See merge request pleroma/pleroma!3905
2023-06-13 13:34:21 +00:00
Haelwenn (lanodan) Monnier a663b73634 Add no_new_privs to OpenRC service files 2023-06-13 12:47:02 +02:00
lain fdb5bec431 Merge branch 'unused_indexes' into 'develop'
Remove unused indexes

See merge request pleroma/pleroma!3874
2023-06-11 19:48:23 +00:00
lain d65a8bcd2d Merge branch 'fix-otp-documentation' into 'develop'
fix OTP install documentation

See merge request pleroma/pleroma!3869
2023-06-11 16:45:53 +00:00
lain 4e6ea7cc91 Merge branch 'tusooa/3054-banned-delete' into 'develop'
Fix deleting banned users' statuses

See merge request pleroma/pleroma!3889
2023-06-11 13:17:12 +00:00
lain d93b47cf2c Merge branch 'pleroma-double_mentions' into 'develop'
ForceMentionsInContent: fix double mentions for Mastodon/Misskey posts

See merge request pleroma/pleroma!3903
2023-06-11 13:04:59 +00:00
Lain Soykaf 6611c6ce4e B ForceMentionsInContent: Fix test, refactor. 2023-06-11 16:45:31 +04:00
Lain Soykaf 55dd8ef1c7 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into pleroma-double_mentions 2023-06-11 16:31:20 +04:00
Lain Soykaf 22878cf84a B Migrations: Don't remove activity_visibility_index for now. 2023-06-11 16:22:16 +04:00
Lain Soykaf 10dfa107d5 Update changelog 2023-06-11 16:22:03 +04:00
Lain Soykaf 175ee9e6fe Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into unused_indexes 2023-06-11 16:20:30 +04:00
lain 16313af7eb Merge branch 'fix/metadata-tags' into 'develop'
static frontend: fix meta tags

See merge request pleroma/pleroma!3885
2023-06-11 11:57:16 +00:00
lain 1f4618d64b Merge branch 'cleanup/ostatus-user-upgrade' into 'develop'
Cleanup OStatus-era user upgrades and ap_enabled indicator

See merge request pleroma/pleroma!3880
2023-06-11 11:13:57 +00:00
feld 75900f21f0 Merge branch 'revert-mediaproxy-host-validation' into 'develop'
Revert MediaProxy Host header validation

See merge request pleroma/pleroma!3902
2023-06-11 11:10:51 +00:00
lain 1db29f734f Merge branch 'fep-fffd-url' into 'develop'
CommonFields: Use BareUri for :url

Closes #3121

See merge request pleroma/pleroma!3884
2023-06-11 11:02:39 +00:00
lain b762a7503c Merge branch 'distro-docs-elixir-1.11' into 'develop'
installation/debian_based_*: Elixir 1.11 means Debian 12+ and Ubuntu 22.04+

See merge request pleroma/pleroma!3898
2023-06-11 10:42:22 +00:00
Mark Felder 1ca1b4b32f changelog.d 2023-06-07 09:25:57 -04:00
Mark Felder fadcd7f1a9 Revert MediaProxy Host header validation
Something is going wrong here even though the tests are correct.
2023-06-07 09:19:22 -04:00
lain 43458cb7a1 Merge branch 'preload-escaping' into 'develop'
B Preload: Make sure that the preloaded json is html safe

See merge request pleroma/pleroma!3901
2023-06-06 13:31:08 +00:00
Lain Soykaf 40d40d67a3 Add changelog. 2023-06-02 17:09:58 +04:00
Lain Soykaf cbc5b8cebd B Preload: Make sure that the preloaded json is html safe 2023-06-02 17:03:21 +04:00
Haelwenn e8d3525665 Merge branch 'bump-gettext' into 'develop'
mix: bump gettext to 0.22

See merge request pleroma/pleroma!3831
2023-06-02 01:38:41 +00:00
Haelwenn (lanodan) Monnier 313e68c180 mix: bump gettext to ~0.20
Includes https://github.com/elixir-gettext/gettext/pull/304 in 0.20.0+
Includes https://github.com/elixir-gettext/expo/issues/91 in 0.22+ via expo 0.2.0+
2023-06-02 03:06:32 +02:00
Haelwenn e2a63dadd1 Merge branch 'test_improvement' into 'develop'
Use Phoenix.ConnTest.redirected_to/2

See merge request pleroma/pleroma!3899
2023-06-01 09:40:25 +00:00
Sean King c9cb90ff4f
Media proxy base URL doesn't need /proxy 2023-05-31 17:49:06 -06:00
Sean King a2bbd7c9da
Fix base media and proxy URL in instructions to serve media on another domain 2023-05-31 12:22:13 -06:00
Mark Felder 46c799f528 Use Phoenix.ConnTest.redirected_to/2 2023-05-31 09:54:37 -04:00
Haelwenn (lanodan) Monnier 737e45c102 installation/debian_based_jp: Elixir 1.11 means Debian 12+ and Ubuntu 22.04+
I checked for what each part of the debian&ubuntu sentences meant with the
help of Jisho.org, should be safe but it did make me notice that this guide
hasn't been updated in years
2023-05-31 08:32:58 +02:00
Haelwenn (lanodan) Monnier 8336519f30 installation/debian_based_en: Elixir 1.11 means Debian 12+ and Ubuntu 22.04+ 2023-05-31 08:32:58 +02:00
Haelwenn d998a114e2 Merge branch 'validate-host' into 'develop'
Validate Host header for MediaProxy and Uploads

See merge request pleroma/pleroma!3896
2023-05-31 00:50:01 +00:00
Mark Felder b3c3bd99c3 Switch from serving a 400 to a 302 2023-05-30 16:56:09 -04:00
lain da6b4003ac Merge branch 'only_media_filter' into 'develop'
Add OnlyMedia Upload Filter

See merge request pleroma/pleroma!3897
2023-05-30 08:04:23 +00:00
Mark Felder 50a20f3bbd Esacpe the asterisks in Markdown 2023-05-29 15:53:16 -04:00
Mark Felder 9caa0b0be1 Add OnlyMedia Upload Filter to simplify restricting uploads to audio, image, and video types 2023-05-29 15:49:04 -04:00
Mark Felder da7394f33b Fix unused assignment 2023-05-29 15:09:31 -04:00
Mark Felder 43bb2f39db Remove unwanted parameter 2023-05-29 15:05:37 -04:00
Mark Felder 84974efe4c Host header validation is now required for MediaProxy and Uploads 2023-05-29 14:17:27 -04:00
Mark Felder a60dd0d92d Validate Host header matches expected value before allowing access to Uploads 2023-05-29 14:16:03 -04:00
Mark Felder 843fcca5b4 Validate Host header matches expected value before allowing access to MediaProxy 2023-05-29 13:59:51 -04:00
Mark Felder 506a1c98e7 ConnCase: Make sure the host we use in tests is the actual Endpoint host 2023-05-29 13:55:48 -04:00
faried nawaz 4c91c0d1ba
oops, forgot the test cases 2023-05-29 02:52:50 +05:00
faried nawaz 8b390d27dc
twitter card: handle case where image has no alt text 2023-05-29 02:52:49 +05:00
faried nawaz a1af122499
changelog entry 2023-05-29 02:52:49 +05:00
faried nawaz 52368e6702
fix meta tag for twitter cards and image attachments
The name of the tag should be twitter:image, not twitter:player.

Also, add twitter:image:alt meta tags.
2023-05-29 02:52:49 +05:00
faried nawaz b6b7de2010
add url to Metadata.build_tags call
If static_fe is enabled, going to https://pleroma/notice/some-id
results in

<meta content="https://pleroma/users/someuser" property="og:url">

With this fix, it is

<meta content="https://pleroma/notice/some-id" property="og:url">

Additionally, Pleroma.Web.Metadata.Providers.OpenGraph now
generates meta tags for attachments in the post.
2023-05-29 02:52:41 +05:00
tusooa e92eb5f482 Add instructions to other distro's guides 2023-05-27 00:57:22 +00:00
Haelwenn 31ec5cd35e Merge branch 'mergeback/2.5.2' into 'develop'
Mergeback: 2.5.2

Closes #3030, #3062, and #3045

See merge request pleroma/pleroma!3893
2023-05-26 22:16:18 +00:00
Haelwenn (lanodan) Monnier 869f0d24a6 Merge branch 'release/2.5.2' into mergeback/2.5.2 2023-05-26 23:47:50 +02:00
tusooa 408ea697aa
Add changelog 2023-05-26 17:28:41 -04:00
tusooa 85902ad1ae
Recommend users to serve media on another domain in guide 2023-05-26 17:27:35 -04:00
tusooa f970091c6a
Add instructions to serve media on another domain 2023-05-26 17:17:13 -04:00
Haelwenn 2d193861db Merge branch 'release/2.5.2' into 'stable'
Security release 2.5.2

See merge request pleroma/pleroma!3863
2023-05-26 19:35:31 +00:00
Haelwenn cd9d6a12ab Merge branch 'issue/3126' into 'develop'
Filter OEmbed HTML tags

See merge request pleroma/pleroma!3891
2023-05-26 18:26:40 +00:00
Haelwenn (lanodan) Monnier 7618e562b3 Version 2.5.2 2023-05-26 19:57:00 +02:00
Mark Felder 4505bc1e58 Filter OEmbed HTML tags 2023-05-26 19:56:36 +02:00
Mark Felder 0d68804aa7 Filter OEmbed HTML tags 2023-05-26 19:54:24 +02:00
tusooa d0c2e0830b Enforce unauth restrictions for public streaming endpoints 2023-05-26 19:24:08 +02:00
Haelwenn b36263e5ff Merge branch 'issue/3126' into 'develop'
MediaProxyController: Apply CSP sandbox

See merge request pleroma/pleroma!3890
2023-05-26 19:24:08 +02:00
Haelwenn 4339230f64 Merge branch 'tusooa/fix-object-test' into 'develop'
Fix ObjectTest

See merge request pleroma/pleroma!3887
2023-05-26 19:24:08 +02:00
Haelwenn 72833c84b5 Merge branch 'tusooa/rework-refetch' into 'develop'
Make sure object refetching follows update rules

See merge request pleroma/pleroma!3883
2023-05-26 19:24:08 +02:00
Haelwenn 47e66c9500 Merge branch 'issue/3126' into 'develop'
MediaProxyController: Apply CSP sandbox

See merge request pleroma/pleroma!3890
2023-05-26 17:12:18 +00:00
Mark Felder 38bcf6b19e MediaProxyController: Apply CSP sandbox 2023-05-26 12:34:01 -04:00
Zero 279fd47b48 ForceMentionsInContent: fix double mentions for Mastodon/Misskey posts
The code checked for duplicates using "ap_id", but in Mastodon and Misskey the look like that:
Mastodon: https://mastodon.example.com/users/roger
Misskey: https:///misskey.example.com/users/104ab42f11

The fix is to also check for "uri", which is what will be in the "explicitly_mentioned_uris" list:
Mastodon: https://mastodon.example.com/@roger
Misskey: https://misskey.example.com/@roger
2023-05-26 12:30:19 -04:00
tusooa 1fa196d8f7
Fix deleting banned users' statuses 2023-05-25 19:00:38 -04:00
tusooa 2c66f584b5
Show more informative errors when profile exceeds char limits 2023-05-25 08:22:33 -04:00
Haelwenn 5433742faf Merge branch 'tusooa/fix-object-test' into 'develop'
Fix ObjectTest

See merge request pleroma/pleroma!3887
2023-05-23 01:57:07 +00:00
tusooa 819a82da99
Fix unused variable 2023-05-22 08:19:58 -04:00
tusooa 6aafa7fe76
Add changelog 2023-05-22 08:16:14 -04:00
tusooa 505e58d4eb
Fix ObjectTest 2023-05-22 08:14:20 -04:00
Haelwenn 0524e66a05 Merge branch 'accept-tags-2.5' into 'develop'
TagValidator: Drop unrecognized Tag types

Closes #2952

See merge request pleroma/pleroma!3823
2023-05-17 19:04:51 +00:00
Haelwenn ce1c0f75cd Merge branch 'tusooa/3065-scopes' into 'develop'
OAuth scopes descriptions

Closes #3065

See merge request pleroma/pleroma!3848
2023-05-17 18:51:26 +00:00
Haelwenn 66327b56e9 Merge branch 'tusooa/rework-refetch' into 'develop'
Make sure object refetching follows update rules

See merge request pleroma/pleroma!3883
2023-05-17 18:50:35 +00:00
Haelwenn b8b15cec9e Merge branch 'tusooa/changelog-improve' into 'develop'
Use git diff to search for changelog entry

See merge request pleroma/pleroma!3875
2023-05-17 15:49:54 +00:00
Haelwenn 143676f58c Merge branch 'tusooa/allow-lang' into 'develop'
Allow lang attribute

See merge request pleroma/pleroma!3882
2023-05-17 15:28:32 +00:00
Haelwenn (lanodan) Monnier a5066bb078 CommonFields: Use BareUri for :url
Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3121
2023-05-17 17:25:46 +02:00
Haelwenn (lanodan) Monnier fb3335ffe2 EctoType: Add BareUri 2023-05-17 17:14:38 +02:00
tusooa e170fc40dd
Fix build warning 2023-05-09 21:38:28 -04:00
tusooa be5c5118cb
Make sure object refetching follows update rules 2023-05-09 21:04:27 -04:00
tusooa 163e82bab1
Allow lang attribute 2023-05-09 19:27:32 -04:00
Henry Jameson 2a07411b0c keep the websocket url for all modes 2023-05-07 15:34:17 +03:00
Henry Jameson f50fd9278f reduce redundant reduntancy reduction 2023-05-07 15:29:19 +03:00
Henry Jameson f8ef4924ec fix whitespace 2023-05-07 15:24:09 +03:00
Henry Jameson c0d11da2d8 conditionally set csp depnding on media-proxy state 2023-05-07 15:16:30 +03:00
Haelwenn (lanodan) Monnier c63bf6a040 Add changelog for !3880 2023-05-05 11:13:50 +02:00
Haelwenn (lanodan) Monnier fcd49e3985 User: Remove ap_enabled field 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 238edc30de User: Remove ap_enabled?/1 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 9dfa1c4be0 ActivityPub: Mark fetch_and_prepare_user_from_ap_id/1 as private 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 8181be89a2 Federator: Stop using ap_enabled?/1 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier e17265a7a2 TransmogrifierWorker: Remove obsolete worker 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 2ee483ba41 Transmogrifier: Remove upgrade_user_from_ap_id 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 3962253cf1 Publisher: Stop filtering via ap_enabled?/1 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 606f78f5e5 ActivityPub: Stop relying on ap_enabled and upgrade_user_from_ap_id 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 0903c41645 User: Stop relying on ap_enabled 2023-05-05 11:11:26 +02:00
Haelwenn (lanodan) Monnier 4fd96b24ae AddRemoveValidator: Use User.fetch_by_ap_id instead of upgrade_user_from_ap_id 2023-05-05 11:11:26 +02:00
tusooa 6a3fd8e014
Do not count for renames when diffing 2023-05-02 22:16:00 -04:00
tusooa 99f157e280
Fix MR pipelines not having build and test jobs 2023-05-02 22:12:15 -04:00
tusooa 9283c784a3
Add English translation for oauth scopes 2023-05-02 17:03:09 -04:00
tusooa b6dd194000
Add changelog 2023-05-02 16:33:53 -04:00
tusooa 6d0ebccdb0
Make webui use translated scope descriptions 2023-05-02 16:32:33 -04:00
tusooa 530284e1b9
Add extracted pot 2023-05-02 16:32:33 -04:00
tusooa 85bdbb102e
Add extraction process for oauth scopes 2023-05-02 16:32:10 -04:00
HJ cd20d15bb8 changelog 2023-04-28 11:19:14 +00:00
HJ 675639225a allow https: so that flash works across instances without need for media proxy 2023-04-28 11:13:42 +00:00
tusooa 248f914e6e Merge branch 'list-installed-frontends' into 'develop'
List installed frontend refs in admin API

See merge request pleroma/pleroma!3862
2023-04-27 02:56:19 +00:00
tusooa ddf57596be Merge branch 'bugfix/content-disposition' into 'develop'
UploadedMedia: Add missing disposition_type to Content-Disposition

Closes #3114

See merge request pleroma/pleroma!3873
2023-04-26 15:39:20 +00:00
Haelwenn 286b9bb66c Merge branch 'tusooa/no-more-needs' into 'develop'
Do not use needs: in pipeline yaml

See merge request pleroma/pleroma!3878
2023-04-26 14:23:47 +00:00
tusooa d5e8345946
Do not use needs: in pipeline yaml 2023-04-26 09:14:49 -04:00
lain d97425d49e Merge branch 'duponin/remove-ssh' into 'develop'
Remove SSH/BBS feature from core

Closes #932, #2389, and #2931

See merge request pleroma/pleroma!3872
2023-04-26 12:19:46 +00:00
Haelwenn 18913c4cd8 Merge branch 'tusooa/combine-login' into 'develop'
Work around docker login needing daemon

See merge request pleroma/pleroma!3877
2023-04-26 11:43:46 +00:00
tusooa 1a50db36d3
Skip changelog entry for 3877 2023-04-26 07:20:35 -04:00
tusooa a946917206
Work around docker login needing daemon 2023-04-26 07:19:30 -04:00
Haelwenn 3b2d7cc67f Merge branch 'tusooa/kaniko' into 'develop'
Add ELIXIR_IMG arg to latest

See merge request pleroma/pleroma!3876
2023-04-26 02:59:13 +00:00
tusooa 47e95fe9f5
Add changelog for 3876 2023-04-25 21:40:28 -04:00
tusooa 9c7b036401
Add ELIXIR_IMG arg to latest 2023-04-25 21:39:15 -04:00
Haelwenn 6bd0df1357 Merge branch 'tusooa/kaniko' into 'develop'
Use kaniko to build docker images

See merge request pleroma/pleroma!3870
2023-04-25 23:14:21 +00:00
tusooa c5ffdd0609
Use self-built elixir image for arm 2023-04-24 20:03:59 -04:00
tusooa 2736c3f294
Use --custom-platform to replace the deprecated one 2023-04-24 19:57:32 -04:00
tusooa 66d23713e9
Do not use nested levels for arch 2023-04-24 19:56:54 -04:00
duponin af38c6104e add changelog entry for BBS/SSH feature remove 2023-04-23 10:58:50 +02:00
duponin b2dc9ad9d8 fix test after removing esshd/SSH feature 2023-04-23 10:47:17 +02:00
duponin 0231a09310 Remove SSH/BBS feature from core
And link to sshocial, the replacement client for this removed feature
2023-04-23 10:47:07 +02:00
tusooa ae8f359f22
Skip changelog check for automated MRs 2023-04-22 21:07:18 -04:00
tusooa 30bc37c3ca
Explain changelog.d in merge request templates 2023-04-22 21:02:13 -04:00
tusooa c1aa83069d
Skip changelog 2023-04-22 20:45:27 -04:00
tusooa e13b331762
Fetch upstream in the repo 2023-04-22 20:42:59 -04:00
tusooa 50e237759a
Use git diff to search for changelog entry 2023-04-22 20:31:48 -04:00
Mark Felder d91a823836 Remove unused indexes
These indexes were always listed as unused and several grow quite large.
The most significant impact is the activities_visibility_index which takes many hours to rebuild when restoring the server from backup even on fast hardware.
2023-04-22 16:43:33 +00:00
Haelwenn (lanodan) Monnier 2148ef5e2f UploadedMedia: Increase readability via ~s sigil 2023-04-18 00:12:42 +02:00
Haelwenn (lanodan) Monnier 8f0f58e28b UploadedMedia: Add missing disposition_type to Content-Disposition
Set it to `inline` because the vast majority of what's sent is multimedia
content while `attachment` would have the side-effect of triggering a
download dialog.

Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3114
2023-04-18 00:09:19 +02:00
Duponin 7944271c1b Unify install guides using sudo to use `sudo -Hu` 2023-04-15 19:03:51 +00:00
Haelwenn 3867b52aef Merge branch 'tusooa/3027-dedupe-poll' into 'develop'
Dedupe poll options

Closes #3027

See merge request pleroma/pleroma!3860
2023-04-13 08:40:04 +00:00
Haelwenn cf1ba77b9e Merge branch '2023-04-mix-deps-update' into 'develop'
mix: Update all dependencies

See merge request pleroma/pleroma!3867
2023-04-13 08:36:35 +00:00
tusooa 23bca0c4b3
Skip changelog entry 2023-04-12 12:40:26 -04:00
tusooa b37a90caa3
Combine images of different platforms into one 2023-04-12 12:38:47 -04:00
tusooa 7997ba0abe
Build images with kaniko 2023-04-12 11:49:33 -04:00
Duponin e444832bb5 fix OTP install documentation
'su pleroma' will never work if 'pleroma' user has no password, which is
better for security purpose.

If admin has no 'sudo' binary, I'm expecting them to be skilled enough 
to make their way on their own.
2023-04-10 20:17:30 +00:00
Haelwenn b7a831ca55 Merge branch 'from/upstream-develop/tusooa/require-changelog' into 'develop'
require changelog

See merge request pleroma/pleroma!3739
2023-04-05 07:53:11 +00:00
tusooa 686c3e03bd
Fix counting 2023-04-04 12:24:45 -04:00
Haelwenn 89a40b867d Allow more than 1 changelog entry 2023-04-04 16:20:46 +00:00
Haelwenn (lanodan) Monnier ce16ff7ae8 mix: Update all dependencies 2023-04-04 11:19:38 +02:00
tusooa 78a6f56295 Merge branch 'doc/add-fedistar' into 'develop'
Add Fedistar as a desktop client in docs

See merge request pleroma/pleroma!3866
2023-04-01 17:46:30 +00:00
AkiraFukushima e5f36f9f8d
Update contact information for Whalebird and Fedistar 2023-04-02 01:07:07 +09:00
AkiraFukushima 17f1b8d133
Remove Roma from docs
Because this app is no longer maintained
2023-04-02 01:03:15 +09:00
AkiraFukushima 81e1d6d9d0
Add Fedistar as a desktop client in docs 2023-04-02 01:02:22 +09:00
Ekaterina Vaartis 6a63dced4a Fix tests for frontend installation 2023-03-30 19:25:35 +03:00
Haelwenn e4288df502 Merge branch 'background-timeout' into 'develop'
Set background worker timeout to 15 minutes

See merge request pleroma/pleroma!3857
2023-03-30 12:48:35 +02:00
tusooa ad38cc3b0c Merge branch 'docs-otp-support' into 'develop'
docs: Be more explicit about the level of compatibility of OTP releases

See merge request pleroma/pleroma!3849
2023-03-30 12:48:12 +02:00
tusooa 40f14fd31c Merge branch 'remove-crypt' into 'develop'
Remove crypt(3) support

Closes #3030 and #3062

See merge request pleroma/pleroma!3847
2023-03-30 12:47:36 +02:00
Haelwenn 937df7e465 Merge branch 'fix/tag-feed-crashes' into 'develop'
fix: atom/rss feed issues

Closes #3045

See merge request pleroma/pleroma!3851
2023-03-30 12:46:35 +02:00
Haelwenn d640df3927 Merge branch 'fix/static-fe-feed-500' into 'develop'
fix: remove static_fe pipeline for /users/:nickname/feed

See merge request pleroma/pleroma!3852
2023-03-30 12:45:39 +02:00
Haelwenn 22b72cd6b8 Merge branch 'tusooa/oban-common-pipeline' into 'develop'
Stop oban from retrying if validating errors occur when processing incoming data

See merge request pleroma/pleroma!3844
2023-03-30 12:43:58 +02:00
Ekaterina Vaartis 3037d2780c Also list frontends that are not in the config file 2023-03-30 11:16:40 +03:00
Ekaterina Vaartis d3b27d45a9 List installed frontend refs in admin API 2023-03-29 23:23:06 +03:00
Haelwenn 4f7c11b281 Merge branch 'tusooa/3073-react-legacy' into 'develop'
Fix emoji reactions for legacy 2-tuple formats

Closes #3073

See merge request pleroma/pleroma!3861
2023-03-27 10:05:47 +00:00
tusooa c5d946bc92
Fix emoji reactions for legacy 2-tuple formats 2023-03-26 15:12:40 -04:00
tusooa 67d1897c6e
Fix existing tests 2023-03-26 11:19:44 -04:00
tusooa 10930f7507
Dedupe poll options 2023-03-25 23:20:07 -04:00
Haelwenn 6d0cc8fa2a Merge branch 'features/image-object' into 'develop'
Add support for Image objects

Closes #1581

See merge request pleroma/pleroma!3145
2023-03-25 06:35:55 +00:00
Haelwenn 9c53d1fe19 Merge branch 'background-timeout' into 'develop'
Set background worker timeout to 15 minutes

See merge request pleroma/pleroma!3857
2023-03-25 05:40:35 +00:00
anemone f463b7570e Set background worker timeout to 15 minutes 2023-03-23 23:14:52 -07:00
tusooa bf9db78426 Merge branch 'docs-otp-support' into 'develop'
docs: Be more explicit about the level of compatibility of OTP releases

See merge request pleroma/pleroma!3849
2023-03-16 08:11:44 +00:00
Haelwenn (lanodan) Monnier 9a2523a09a instances: Store some metadata based on NodeInfo 2023-03-16 09:02:20 +01:00
Haelwenn 353538d16c Merge branch 'pleroma-akkoma-emoji-port' into 'develop'
Custom emoji reactions support

See merge request pleroma/pleroma!3845
2023-03-16 08:00:00 +00:00
Haelwenn c3600b6104 Merge branch 'feat/fields-rel-me-tag' into 'develop'
feat: build rel me tags with profile fields

See merge request pleroma/pleroma!3850
2023-03-16 07:53:27 +00:00
kPherox 83c7415803
fix: append field values to bio before parsing 2023-03-15 23:55:24 +09:00
tusooa 9145fd04f2 Merge branch 'remove-crypt' into 'develop'
Remove crypt(3) support

Closes #3030 and #3062

See merge request pleroma/pleroma!3847
2023-03-12 16:06:00 +00:00
tusooa d18441e9c4 Indicate in changelog that removal of crypt is breaking 2023-03-12 16:04:43 +00:00
Alexander Tumin 2c2ea16b50 Allow custom emoji reactions: Add pleroma_custom_emoji_reactions feature, review changes 2023-03-12 11:39:17 +03:00
Haelwenn (lanodan) Monnier ea07ec51ef Add support for Image objects 2023-03-09 14:21:12 +01:00
Haelwenn f5c6e44731 Merge branch 'tusooa/block-rel' into 'develop'
Allow with_relationships param for blocks

See merge request pleroma/pleroma!3843
2023-03-09 13:13:14 +00:00
Haelwenn 5cc23dc382 Merge branch 'fix/tag-feed-crashes' into 'develop'
fix: atom/rss feed issues

Closes #3045

See merge request pleroma/pleroma!3851
2023-03-06 22:55:24 +00:00
Haelwenn 0a042979b8 Merge branch 'fix/static-fe-feed-500' into 'develop'
fix: remove static_fe pipeline for /users/:nickname/feed

See merge request pleroma/pleroma!3852
2023-03-06 21:08:27 +00:00
faried nawaz 8241eff05b remove static_fe pipeline for /users/:nickname/feed 2023-03-06 23:34:00 +05:00
faried nawaz 7b42ec5633 oops, remove unused import 2023-03-06 02:44:36 +05:00
faried nawaz 141146d1f1 use scrub_html_and_truncate instead of scrub_html for feed item title
Sometimes this truncated properly encoded HTML entities in the
wrong place.  The new flow calls scrub_html, removes emojis,
decodes entities (a second time), truncates, and then re-encodes.

Fixes #3045.
2023-03-06 02:38:02 +05:00
faried nawaz 86ee4b72f3 modify Utils.scrub_html_and_truncate to take omission parameter 2023-03-06 02:30:52 +05:00
faried nawaz 117a53b88e format feed_view.ex 2023-03-06 01:16:24 +05:00
faried nawaz d3f22d24f6 feed eex templates: use published field from @data, not @activity.data 2023-03-06 00:23:31 +05:00
faried nawaz f33e89765a fix tag feeds: remote activities might not have a summary field 2023-03-06 00:20:57 +05:00
Haelwenn (lanodan) Monnier 8e072baed0 docs: Be more explicit about the level of compatibility of OTP releases 2023-03-05 08:55:18 +01:00
Haelwenn c00a19f371 Merge branch 'tusooa/oban-common-pipeline' into 'develop'
Stop oban from retrying if validating errors occur when processing incoming data

See merge request pleroma/pleroma!3844
2023-03-05 06:37:59 +00:00
Haelwenn (lanodan) Monnier 5716654d12 Remove crypt(3) support
This was used to support migration from GNU Social, which was used by at least
shitposter.club, should be entirely irrelevant now.

Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3030
Closes: https://git.pleroma.social/pleroma/pleroma/-/issues/3062
2023-03-05 01:37:57 +01:00
Alexander Tumin 8d3b29aaba Allow custom emoji reactions: add test for mixed emoji react, fix credo errors 2023-03-02 11:18:16 +03:00
Alexander Tumin 4b85d1c617 Allow custom emoji reactions: Fix tests, mixed custom and unicode reactions 2023-03-02 11:18:16 +03:00
floatingghost 787e30c5fd Allow reacting with remote emoji when they exist on the post (#200)
Co-authored-by: FloatingGhost <hannah@coffee-and-dreams.uk>
Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/200
2023-03-02 11:18:16 +03:00
tusooa 714bf0cb23 Merge branch 'mergeback/2.5.1' into 'develop'
mergeback: 2.5.1

See merge request pleroma/pleroma!3846
2023-03-02 02:25:11 +00:00
tusooa a0ec66ce7e
Make clear the test names 2023-03-01 21:14:52 -05:00
tusooa bec4e5ac31
Fix FederatorTest 2023-03-01 21:04:19 -05:00
tusooa 1babd0798f
Stop oban from retrying if validating errors occur when processing incoming data 2023-03-01 21:03:30 -05:00
tusooa f33401f54b
Merge remote-tracking branch 'upstream/stable' into mergeback/2.5.1 2023-03-01 20:09:50 -05:00
tusooa fd46f83d2d Merge branch 'release/2.5.1' into 'stable'
release: 2.5.1

See merge request pleroma/pleroma!3841
2023-03-02 00:50:02 +00:00
tusooa 938e238ea1
Add the security fix to the changelog 2023-03-01 18:44:29 -05:00
tusooa e4925f813a
Sanitize filenames when uploading 2023-03-01 18:40:02 -05:00
tusooa d83f16fe44
Allow with_relationships param for blocks 2023-02-28 22:16:01 -05:00
silverpill 98b9c1bcb1 Merge branch 'develop' into accept-tags-2.5 2023-02-27 23:10:36 +00:00
silverpill 5cfb0578a6 TagValidator: Drop unrecognized tags 2023-02-27 23:09:46 +00:00
tusooa 5d34fe1868
Bundle frontend 2023-02-20 12:37:44 -05:00
tusooa 75b76a0666
Bump version in mix project to 2.5.1 2023-02-20 12:32:45 -05:00
tusooa db06e445f1
Compose changelog for 2.5.1 2023-02-20 12:32:18 -05:00
tusooa 410d50afe5
Ignores in exiftool read descriptions 2023-02-20 12:30:36 -05:00
Sean King c69ae5f7c7
Bump crypt to v1.0.1 2023-02-20 12:29:38 -05:00
lain bb9ed51da7
Update mix.exs 2023-02-20 12:28:52 -05:00
tusooa 002159fc1c
Bump linkify 2023-02-20 12:28:52 -05:00
tusooa f2ed05191c
Test double dot link 2023-02-20 12:28:42 -05:00
tusooa 0e89a9ad15
Test that zwnj is treated as word char in hashtags 2023-02-20 12:28:41 -05:00
Alexander Tumin c3a0703564
Require related object for notifications to filter on content 2023-02-20 12:27:50 -05:00
tusooa 8e8a0f005c
Fix inproper content being cached in report content 2023-02-20 12:26:16 -05:00
tusooa 772d99c582
Use versioned image from hexpm 2023-02-20 12:25:31 -05:00
tusooa 1c225bfd6e
Allow customizing instance languages 2023-02-20 12:25:00 -05:00
Mark Felder 1b82fd95d4
Remove unwanted code specific to MIX_ENV=test 2023-02-20 12:24:38 -05:00
Mark Felder 88ce0e8b24
Fix rel="me"
Cachex for this was not started
2023-02-20 12:24:32 -05:00
tusooa 3ab3404817
Fix block_from_stranger setting 2023-02-20 12:21:27 -05:00
Lain Soykaf d5125e6ce7
B StripLocation: Add test, work for all svgs. 2023-02-20 12:21:04 -05:00
Dmytro Poltavchenko e8fca8882a
Added SVG to formats not compatible with exiftool 2023-02-20 12:21:04 -05:00
tusooa 259905a893
Bump earmark to 1.4.22 2023-02-20 12:20:29 -05:00
tusooa 8a0162cd96 Merge branch 'weblate-extract' into 'develop'
Extract translatable strings

See merge request pleroma/pleroma!3839
2023-02-19 00:21:24 +00:00
kPherox d5d7648789
feat: build rel me tags with profile fields 2023-02-18 17:57:41 +09:00
weblate-extractor 274b3a0d26 Extract translatable strings 2023-02-18 06:06:52 +00:00
lain 19933a06bf Merge branch 'tusooa/exiftool' into 'develop'
Ignores in exiftool read descriptions

See merge request pleroma/pleroma!3840
2023-02-13 17:10:58 +00:00
lain a5509de389 Merge branch 'upgrade/crypt' into 'develop'
Bump crypt to v1.0.1

See merge request pleroma/pleroma!3838
2023-02-13 17:10:17 +00:00
tusooa 024bb27fc7
Ignores in exiftool read descriptions 2023-02-11 00:30:52 -05:00
Sean King bf346cf07c
Bump crypt to v1.0.1 2023-02-09 23:06:04 -07:00
lain d0b781ab69 Merge branch 'from/upstream-develop/tusooa/2974-zwnj' into 'develop'
Bump linkify - Fix zwnj in tags and double-dot links

Closes #2974 and #3022

See merge request pleroma/pleroma!3830
2023-02-09 21:25:15 +00:00
lain 7abb248ceb Merge branch 'notification-content-filtering-noobj' into 'develop'
Require related object for content-filtering on notification

See merge request pleroma/pleroma!3837
2023-02-09 19:54:59 +00:00
lain 00b39dea5d Merge branch 'tusooa/3059-report-fake-create-render' into 'develop'
Fix inproper content being cached in report content

Closes #3059

See merge request pleroma/pleroma!3836
2023-02-09 19:52:01 +00:00
lain 755279e253 Merge branch 'tusooa/api-spec-property-map' into 'develop'
OpenApiSpex: overhaul

See merge request pleroma/pleroma!3832
2023-02-09 19:50:59 +00:00
lain a7079057a9 Merge branch 'tusooa/docker-hexpm' into 'develop'
Use versioned image from hexpm for docker images

See merge request pleroma/pleroma!3834
2023-02-09 19:47:00 +00:00
lain 7138910f30 Update mix.exs 2023-02-09 14:37:34 -05:00
lain 724bf7c647 Merge branch 'tusooa/3055-instance-languages' into 'develop'
Allow customizing instance languages

Closes #3055

See merge request pleroma/pleroma!3835
2023-02-09 19:23:29 +00:00
lain 50abb54d15 Merge branch 'fix-relme' into 'develop'
Fix rel="me"

See merge request pleroma/pleroma!3824
2023-02-09 19:09:54 +00:00
lain 4d3c2fb21b Merge branch 'tusooa/notif-setting' into 'develop'
Fix block_from_stranger setting

See merge request pleroma/pleroma!3833
2023-02-09 19:09:23 +00:00
lain 16276c8f87 Merge branch 'test-warnings' into 'develop'
Fix warnings in tests, treat warnings as errors in CI.

See merge request pleroma/pleroma!3827
2023-02-09 19:05:50 +00:00
Lain Soykaf 8583b3721d B TestHelper, CI: Work with older elixir version. 2023-02-09 12:36:02 -05:00
Lain Soykaf e412363ff8 Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into test-warnings 2023-02-09 12:28:02 -05:00
Alexander Tumin 55a8aa9787 Require related object for notifications to filter on content 2023-02-08 13:07:34 +03:00
tusooa 08132002d2
Fix inproper content being cached in report content 2023-02-03 16:00:39 -05:00
tusooa bc7ec43179
Allow customizing instance languages 2023-01-26 20:17:13 -05:00
tusooa 1cf20184ff
Use versioned image from hexpm 2023-01-18 19:01:10 -05:00
tusooa 7467b24730
Fix block_from_stranger setting 2023-01-18 18:36:52 -05:00
tusooa 97f947deaf
Fix tests 2023-01-15 21:39:05 -05:00
tusooa 5af9ce4a01
Fix type of admin_account.is_confirmed 2023-01-15 18:41:36 -05:00
tusooa 3b4b84b74c
Force spec for every operation to have a listed tag 2023-01-15 18:31:37 -05:00
tusooa bddcb3ed68
Add names to additionalProperties 2023-01-15 17:28:32 -05:00
tusooa a2766f310c
Bump linkify 2023-01-06 14:12:07 -05:00
tusooa 09ed8f4f8a
Test double dot link 2023-01-06 14:11:56 -05:00
tusooa 686fef59db
Test that zwnj is treated as word char in hashtags 2023-01-06 14:01:42 -05:00
lain 2a244b391d Merge branch '2768-strip-location' into 'develop'
Resolve "Exiftool may conflict with SVG files"

Closes #2768

See merge request pleroma/pleroma!3829
2023-01-05 16:50:02 +00:00
Lain Soykaf fe00fbfd54 B StripLocation: Add test, work for all svgs. 2023-01-05 11:29:06 -05:00
Dmytro Poltavchenko 5b4962165e Added SVG to formats not compatible with exiftool 2023-01-05 11:26:57 -05:00
lain 51b4513258 Merge branch 'tusooa/earmark' into 'develop'
Bump earmark to 1.4.~34~22

Closes #3033

See merge request pleroma/pleroma!3820
2023-01-03 22:10:28 +00:00
Lain Soykaf 2eec3f8207 B TestHelper: Remove warnings-as-errors
It's already set in mix.exs
2023-01-03 17:01:56 -05:00
Lain Soykaf b3a1cfaa7a Tests: Capture logs to clean up the test output. 2023-01-03 15:39:14 -05:00
Lain Soykaf 72b3ec35f8 Fix warnings in tests, treat warnings as errors in CI.
The warnings revealed two bad tests, the code still worked but the test
didn't actually test for it. Activating this for CI to prevent issues
like these in the future.
2023-01-03 14:59:14 -05:00
silverpill 45646ff52c TagValidator: Add test for Link tag 2022-12-30 20:55:02 +00:00
Mark Felder 39e4b788ad Remove unwanted code specific to MIX_ENV=test 2022-12-30 15:36:21 -05:00
Mark Felder bea43aba33 Fix rel="me"
Cachex for this was not started
2022-12-29 19:42:14 +00:00
silverpill c7dc5ce85c TagValidator: Allow unrecognized Tag types 2022-12-29 14:21:20 +00:00
tusooa 4b66f2b7f1
Bump earmark to 1.4.22 2022-12-28 11:57:29 -05:00
tusooa 179efd9467
Make backup parameters configurable 2022-12-24 00:20:25 -05:00
tusooa 7d3e4eaeb9
Log errors more extensively 2022-12-24 00:04:51 -05:00
tusooa 070fbb89e1
Lint 2022-12-24 00:04:51 -05:00
tusooa a1b95922c5
Fix compile error 2022-12-24 00:04:50 -05:00
tusooa 46ab97d721
Simplify backup update clause 2022-12-24 00:04:50 -05:00
tusooa bdd63d2a3a
Expose backup status via Pleroma API 2022-12-24 00:04:50 -05:00
tusooa e4ac2a7cd6
Detail backup states 2022-12-24 00:04:32 -05:00
Tusooa Zhu 6aa9b023f0
Use dedicated script 2022-08-28 11:13:36 -04:00
Tusooa Zhu f8566e91a6
Fix {} not working with alpine sh 2022-08-28 11:10:25 -04:00
Tusooa Zhu a26fb6ab48
Display error info 2022-08-28 10:24:01 -04:00
Tusooa Zhu d3871fa360
Allow to explicitly skip changelog 2022-08-28 09:57:32 -04:00
Tusooa Zhu 27a8f6a8d9
Prevent duplicate pipelines 2022-08-28 09:54:28 -04:00
Tusooa Zhu 50d3209ce8
Check for changelog in ci 2022-08-28 09:48:01 -04:00
350 changed files with 9491 additions and 2749 deletions

View File

@ -8,6 +8,13 @@ variables: &global_variables
DB_PORT: 5432
MIX_ENV: test
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH
cache: &global_cache_policy
key:
files:
@ -17,12 +24,14 @@ cache: &global_cache_policy
- _build
stages:
- check-changelog
- build
- test
- benchmark
- deploy
- release
- docker
- docker-combine
before_script:
- echo $MIX_ENV
@ -32,24 +41,51 @@ before_script:
after_script:
- rm -rf _build/*/lib/pleroma
check-changelog:
stage: check-changelog
image: alpine
rules:
- if: $CI_MERGE_REQUEST_SOURCE_PROJECT_PATH == 'pleroma/pleroma' && $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'weblate-extract'
when: never
- if: $CI_MERGE_REQUEST_SOURCE_PROJECT_PATH == 'pleroma/pleroma' && $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == 'weblate'
when: never
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop"
before_script: ''
after_script: ''
cache: {}
script:
- apk add git
- sh ./tools/check-changelog
.build_changes_policy:
rules:
- changes:
- ".gitlab-ci.yml"
- "**/*.ex"
- "**/*.exs"
- "mix.lock"
.using-ci-base:
tags:
- amd64
build:
extends:
- .build_changes_policy
- .using-ci-base
stage: build
only:
changes: &build_changes_policy
- ".gitlab-ci.yml"
- "**/*.ex"
- "**/*.exs"
- "mix.lock"
script:
- mix compile --force
spec-build:
extends:
- .using-ci-base
stage: test
only:
changes:
- ".gitlab-ci.yml"
- "lib/pleroma/web/api_spec/**/*.ex"
- "lib/pleroma/web/api_spec.ex"
rules:
- changes:
- ".gitlab-ci.yml"
- "lib/pleroma/web/api_spec/**/*.ex"
- "lib/pleroma/web/api_spec.ex"
artifacts:
paths:
- spec.json
@ -57,6 +93,8 @@ spec-build:
- mix pleroma.openapi_spec spec.json
benchmark:
extends:
- .using-ci-base
stage: benchmark
when: manual
variables:
@ -71,9 +109,10 @@ benchmark:
- mix pleroma.load_testing
unit-testing:
extends:
- .build_changes_policy
- .using-ci-base
stage: test
only:
changes: *build_changes_policy
cache: &testing_cache_policy
<<: *global_cache_policy
policy: pull
@ -94,11 +133,12 @@ unit-testing:
path: coverage.xml
unit-testing-erratic:
extends:
- .build_changes_policy
- .using-ci-base
stage: test
retry: 2
allow_failure: true
only:
changes: *build_changes_policy
cache: &testing_cache_policy
<<: *global_cache_policy
policy: pull
@ -129,9 +169,10 @@ unit-testing-erratic:
# - mix test --trace --only federated
unit-testing-rum:
extends:
- .build_changes_policy
- .using-ci-base
stage: test
only:
changes: *build_changes_policy
cache: *testing_cache_policy
services:
- name: minibikini/postgres-with-rum:12
@ -147,10 +188,9 @@ unit-testing-rum:
- mix test --preload-modules
lint:
extends: .build_changes_policy
image: &current_elixir elixir:1.12-alpine
stage: test
only:
changes: *build_changes_policy
cache: *testing_cache_policy
before_script: &current_bfr_script
- apk update
@ -162,18 +202,18 @@ lint:
- mix format --check-formatted
analysis:
extends:
- .build_changes_policy
- .using-ci-base
stage: test
only:
changes: *build_changes_policy
cache: *testing_cache_policy
script:
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
cycles:
extends: .build_changes_policy
image: *current_elixir
stage: test
only:
changes: *build_changes_policy
cache: {}
before_script: *current_bfr_script
script:
@ -190,7 +230,7 @@ docs-deploy:
before_script:
- apk add curl
script:
- curl -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
- curl --fail-with-body -X POST -F"token=$CI_JOB_TOKEN" -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
@ -231,7 +271,7 @@ spec-deploy:
before_script:
- apk add curl
script:
- curl -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
- curl --fail-with-body -X POST -F"token=$CI_JOB_TOKEN" -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
stop_review_app:
@ -354,104 +394,167 @@ arm64-musl:
before_script: *before-release-musl
script: *release
docker:
.kaniko:
stage: docker
image: docker:latest
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
cache: {}
dependencies: []
variables: &docker-variables
DOCKER_DRIVER: overlay2
DOCKER_HOST: unix:///var/run/docker.sock
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
IMAGE_TAG_SLUG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
IMAGE_TAG_LATEST: $CI_REGISTRY_IMAGE:latest
IMAGE_TAG_LATEST_STABLE: $CI_REGISTRY_IMAGE:latest-stable
DOCKER_BUILDX_URL: https://github.com/docker/buildx/releases/download/v0.6.3/buildx-v0.6.3.linux-amd64
DOCKER_BUILDX_HASH: 980e6b9655f971991fbbb5fd6cd19f1672386195
before_script: &before-docker
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker pull $IMAGE_TAG_SLUG || true
before_script: &before-kaniko
- export CI_JOB_TIMESTAMP=$(date --utc -Iseconds)
- export CI_VCS_REF=$CI_COMMIT_SHORT_SHA
allow_failure: true
script:
- mkdir -p /root/.docker/cli-plugins
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
- chmod +x ~/.docker/cli-plugins/docker-buildx
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- docker buildx create --name mbuilder --driver docker-container --use
- docker buildx inspect --bootstrap
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST .
tags:
- dind
- export IMAGE_TAG=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:$CI_COMMIT_SHORT_SHA
- export IMAGE_TAG_SLUG=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:$CI_COMMIT_REF_SLUG
- export IMAGE_TAG_LATEST=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:latest
- export IMAGE_TAG_LATEST_STABLE=$CI_REGISTRY_IMAGE/$BUILD_ARCH_IMG_SUFFIX:latest-stable
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
.kaniko-latest:
extends: .kaniko
only:
- develop@pleroma/pleroma
docker-stable:
stage: docker
image: docker:latest
cache: {}
dependencies: []
variables: *docker-variables
before_script: *before-docker
allow_failure: true
script:
- mkdir -p /root/.docker/cli-plugins
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
- chmod +x ~/.docker/cli-plugins/docker-buildx
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- docker buildx create --name mbuilder --driver docker-container --use
- docker buildx inspect --bootstrap
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG -t $IMAGE_TAG_LATEST_STABLE .
tags:
- dind
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG --destination $IMAGE_TAG_LATEST
.kaniko-stable:
extends: .kaniko
only:
- stable@pleroma/pleroma
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG --destination $IMAGE_TAG_LATEST_STABLE
docker-release:
stage: docker
image: docker:latest
cache: {}
dependencies: []
variables: *docker-variables
before_script: *before-docker
allow_failure: true
script:
script:
- mkdir -p /root/.docker/cli-plugins
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
- chmod +x ~/.docker/cli-plugins/docker-buildx
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- docker buildx create --name mbuilder --driver docker-container --use
- docker buildx inspect --bootstrap
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
tags:
- dind
.kaniko-release:
extends: .kaniko
only:
- /^release/.*$/@pleroma/pleroma
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG
docker-adhoc:
stage: docker
image: docker:latest
cache: {}
dependencies: []
variables: *docker-variables
before_script: *before-docker
allow_failure: true
script:
script:
- mkdir -p /root/.docker/cli-plugins
- wget "${DOCKER_BUILDX_URL}" -O ~/.docker/cli-plugins/docker-buildx
- echo "${DOCKER_BUILDX_HASH} /root/.docker/cli-plugins/docker-buildx" | sha1sum -c
- chmod +x ~/.docker/cli-plugins/docker-buildx
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- docker buildx create --name mbuilder --driver docker-container --use
- docker buildx inspect --bootstrap
- docker buildx build --platform linux/amd64,linux/arm/v7,linux/arm64/v8 --push --cache-from $IMAGE_TAG_SLUG --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP -t $IMAGE_TAG -t $IMAGE_TAG_SLUG .
tags:
- dind
.kaniko-adhoc:
extends: .kaniko
only:
- /^build-docker/.*$/@pleroma/pleroma
script:
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --custom-platform=$BUILD_ARCH --build-arg VCS_REF=$CI_VCS_REF --build-arg BUILD_DATE=$CI_JOB_TIMESTAMP --build-arg ELIXIR_IMG=$ELIXIR_IMG --destination $IMAGE_TAG --destination $IMAGE_TAG_SLUG
.kaniko:linux/amd64:
variables:
BUILD_ARCH: linux/amd64
BUILD_ARCH_IMG_SUFFIX: linux-amd64
ELIXIR_IMG: hexpm/elixir
tags:
- amd64
.kaniko:linux/arm64:
variables:
BUILD_ARCH: linux/arm64/v8
BUILD_ARCH_IMG_SUFFIX: linux-arm64-v8
ELIXIR_IMG: hexpm/elixir
tags:
- arm
.kaniko:linux/arm:
variables:
BUILD_ARCH: linux/arm/v7
BUILD_ARCH_IMG_SUFFIX: linux-arm-v7
ELIXIR_IMG: git.pleroma.social:5050/pleroma/ci-image/elixir-linux-arm-v7
tags:
- arm32-specified
kaniko-latest:linux/amd64:
extends:
- .kaniko-latest
- .kaniko:linux/amd64
kaniko-latest:linux/arm64:
extends:
- .kaniko-latest
- .kaniko:linux/arm64
kaniko-latest:linux/arm:
extends:
- .kaniko-latest
- .kaniko:linux/arm
kaniko-stable:linux/amd64:
extends:
- .kaniko-stable
- .kaniko:linux/amd64
kaniko-stable:linux/arm64:
extends:
- .kaniko-stable
- .kaniko:linux/arm64
kaniko-stable:linux/arm:
extends:
- .kaniko-stable
- .kaniko:linux/arm
kaniko-release:linux/amd64:
extends:
- .kaniko-release
- .kaniko:linux/amd64
kaniko-release:linux/arm64:
extends:
- .kaniko-release
- .kaniko:linux/arm64
kaniko-release:linux/arm:
extends:
- .kaniko-release
- .kaniko:linux/arm
.docker-combine:
stage: docker-combine
image: docker:cli
cache: {}
before_script:
- 'BUILD_ARCHES="linux-amd64 linux-arm64-v8 linux-arm-v7"'
- export IMAGE_TAG=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- export IMAGE_TAG_SLUG=$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
- export IMAGE_TAG_LATEST=$CI_REGISTRY_IMAGE:latest
- export IMAGE_TAG_LATEST_STABLE=$CI_REGISTRY_IMAGE:latest-stable
- 'IMAGES=; for arch in $BUILD_ARCHES; do IMAGES="$IMAGES $CI_REGISTRY_IMAGE/$arch:$CI_COMMIT_SHORT_SHA"; done'
- 'IMAGES_SLUG=; for arch in $BUILD_ARCHES; do IMAGES_SLUG="$IMAGES_SLUG $CI_REGISTRY_IMAGE/$arch:$CI_COMMIT_REF_SLUG"; done'
- 'IMAGES_LATEST=; for arch in $BUILD_ARCHES; do IMAGES_LATEST="$IMAGES_LATEST $CI_REGISTRY_IMAGE/$arch:latest"; done'
- 'IMAGES_LATEST_STABLE=; for arch in $BUILD_ARCHES; do IMAGES_LATEST_STABLE="$IMAGES_LATEST_STABLE $CI_REGISTRY_IMAGE/$arch:latest"; done'
- mkdir -p ~/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > ~/.docker/config.json
docker-combine:latest:
extends: .docker-combine
only:
- develop@pleroma/pleroma
script:
- 'docker manifest create $IMAGE_TAG $IMAGES'
- 'docker manifest push $IMAGE_TAG'
- 'docker manifest create $IMAGE_TAG_SLUG $IMAGES_SLUG'
- 'docker manifest push $IMAGE_TAG_SLUG'
- 'docker manifest create $IMAGE_TAG_LATEST $IMAGES_LATEST'
- 'docker manifest push $IMAGE_TAG_LATEST'
docker-combine:stable:
extends: .docker-combine
only:
- stable@pleroma/pleroma
script:
- 'docker manifest create $IMAGE_TAG $IMAGES'
- 'docker manifest push $IMAGE_TAG'
- 'docker manifest create $IMAGE_TAG_SLUG $IMAGES_SLUG'
- 'docker manifest push $IMAGE_TAG_SLUG'
- 'docker manifest create $IMAGE_TAG_LATEST_STABLE $IMAGES_LATEST_STABLE'
- 'docker manifest push $IMAGE_TAG_LATEST_STABLE'
docker-combine:release:
extends: .docker-combine
only:
- /^release/.*$/@pleroma/pleroma
script:
- 'docker manifest create $IMAGE_TAG $IMAGES'
- 'docker manifest push $IMAGE_TAG'
- 'docker manifest create $IMAGE_TAG_SLUG $IMAGES_SLUG'
- 'docker manifest push $IMAGE_TAG_SLUG'

View File

@ -0,0 +1,10 @@
### Checklist
- [ ] Adding a changelog: In the `changelog.d` directory, create a file named `<code>.<type>`.
`<code>` can be anything, but we recommend using a more or less unique identifier to avoid collisions, such as the branch name.
`<type>` can be `add`, `remove`, `fix`, `security` or `skip`. `skip` is only used if there is no user-visible change in the MR (for example, only editing comments in the code). Otherwise, choose a type that corresponds to your change.
In the file, write the changelog entry. For example, if an MR adds group functionality, we can create a file named `group.add` and write `Add group functionality` in it.
If one changelog entry is not enough, you may add more. But that might mean you can split it into two MRs. Only use more than one changelog entry if you really need to (for example, when one change in the code fix two different bugs, or when refactoring).

View File

@ -1,6 +1,6 @@
### Release checklist
* [ ] Bump version in `mix.exs`
* [ ] Compile a changelog
* [ ] Compile a changelog with the `tools/collect-changelog` script
* [ ] Create an MR with an announcement to pleroma.social
#### post-merge
* [ ] Tag the release on the merge commit

View File

@ -4,15 +4,130 @@ 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/).
## Unreleased
## 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
- OnlyMedia Upload Filter
- Implement MRF policy to reject or delist according to emojis
- (hardening) Add no_new_privs=yes to OpenRC service files
- Implement quotes
- 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?
- UploadedMedia: Add missing disposition_type to Content-Disposition
- fix not being able to fetch flash file from remote instance
- Fix abnormal behaviour when refetching a poll
- Allow non-HTTP(s) URIs in "url" fields for compatibility with "FEP-fffd: Proxy Objects"
- Fix opengraph and twitter card meta tags
- ForceMentionsInContent: fix double mentions for Mastodon/Misskey posts
- OEmbed HTML tags are now filtered
- Restrict attachments to only uploaded files only
- Fix error 404 when deleting status of a banned user
- Fix config ownership in dockerfile to pass restriction test
- Fix user fetch completely broken if featured collection is not in a supported form
- Correctly handle the situation when a poll has both "anyOf" and "oneOf" but one of them being empty
- Fix handling report from a deactivated user
- Prevent using the .json format to bypass authorized fetch mode
- Fix mentioning punycode domains when using Markdown
- 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.
- Cleanup OStatus-era user upgrades and ap_enabled indicator
- Deprecate Pleroma's audio scrobbling
## 2.5.4
## Security
- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary 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 arbitary 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
- Fix `block_from_stranger` setting
- Fix rel="me"
- Docker images will now run properly
- Fix inproper content being cached in report content
- Notification filter on object content will not operate on the ones that inherently have no content
- ZWNJ and double dots in links are parsed properly for Plain-text posts
- OTP releases will work on systems with a newer libcrypt
- Errors when running Exiftool.ReadDescription filter will not be filled into the image description
## 2.5.0 - 2022-12-23

View File

@ -1,4 +1,9 @@
FROM elixir:1.11.4-alpine as build
ARG ELIXIR_IMG=hexpm/elixir
ARG ELIXIR_VER=1.11.4
ARG ERLANG_VER=24.2.1
ARG ALPINE_VER=3.17.0
FROM ${ELIXIR_IMG}:${ELIXIR_VER}-erlang-${ERLANG_VER}-alpine-${ALPINE_VER} as build
COPY . .
@ -12,7 +17,7 @@ RUN apk add git gcc g++ musl-dev make cmake file-dev &&\
mkdir release &&\
mix release --path release
FROM alpine
FROM alpine:${ALPINE_VER}
ARG BUILD_DATE
ARG VCS_REF
@ -44,7 +49,7 @@ USER pleroma
COPY --from=build --chown=pleroma:0 /release ${HOME}
COPY ./config/docker.exs /etc/pleroma/config.exs
COPY --chown=pleroma --chmod=640 ./config/docker.exs /etc/pleroma/config.exs
COPY ./docker-entrypoint.sh ${HOME}
EXPOSE 4000

View File

@ -30,7 +30,8 @@ If your platform is not supported, or you just want to be able to edit the sourc
- [OpenBSD (fi)](https://docs-develop.pleroma.social/backend/installation/openbsd_fi/)
### OS/Distro packages
Currently Pleroma is packaged for [YunoHost](https://yunohost.org) and [NixOS](https://nixos.org). If you want to package Pleroma for any OS/Distros, we can guide you through the process on our [community channels](#community-channels). If you want to change default options in your Pleroma package, please **discuss it with us first**.
Currently Pleroma is packaged for [YunoHost](https://yunohost.org), [NixOS](https://nixos.org), [Gentoo through GURU](https://gentoo.org/) and [Archlinux through AUR](https://aur.archlinux.org/packages/pleroma). You may find more at <https://repology.org/project/pleroma/versions>.
If you want to package Pleroma for any OS/Distros, we can guide you through the process on our [community channels](#community-channels). If you want to change default options in your Pleroma package, please **discuss it with us first**.
### Docker
While we dont provide docker files, other people have written very good ones. Take a look at <https://github.com/angristan/docker-pleroma> or <https://glitch.sh/sn0w/pleroma-docker>.

View File

@ -408,6 +408,12 @@
federated_timeline_removal: [],
replace: []
config :pleroma, :mrf_emoji,
remove_url: [],
remove_shortcode: [],
federated_timeline_removal_url: [],
federated_timeline_removal_shortcode: []
config :pleroma, :mrf_hashtag,
sensitive: ["nsfw"],
reject: [],
@ -428,6 +434,8 @@
config :pleroma, :mrf_follow_bot, follower_nickname: nil
config :pleroma, :mrf_inline_quote, template: "<bdi>RT:</bdi> {url}"
config :pleroma, :rich_media,
enabled: true,
ignore_hosts: [],
@ -617,9 +625,6 @@
base: System.get_env("LDAP_BASE") || "dc=example,dc=com",
uid: System.get_env("LDAP_UID") || "cn"
config :esshd,
enabled: false
oauth_consumer_strategies =
System.get_env("OAUTH_CONSUMER_STRATEGIES")
|> to_string()
@ -855,7 +860,11 @@
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
config :pleroma, :mrf,
policies: [Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy, Pleroma.Web.ActivityPub.MRF.TagPolicy],
policies: [
Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy,
Pleroma.Web.ActivityPub.MRF.TagPolicy,
Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy
],
transparency: true,
transparency_exclusions: []
@ -874,7 +883,9 @@
config :pleroma, Pleroma.User.Backup,
purge_after_days: 30,
limit_days: 7,
dir: nil
dir: nil,
process_wait_time: 30_000,
process_chunk_size: 100
config :pleroma, ConcurrentLimiter, [
{Pleroma.Web.RichMedia.Helpers, [max_running: 5, max_waiting: 5]},

View File

@ -1052,6 +1052,15 @@
description:
"Minimum required age (in days) for users to create account. Only used if birthday is required.",
suggestions: [6570]
},
%{
key: :languages,
type: {:list, :string},
description:
"Languages to be exposed in /api/v1/instance. Should be in the format of BCP47 language codes.",
suggestions: [
"en"
]
}
]
},
@ -2619,45 +2628,6 @@
}
]
},
%{
group: :esshd,
label: "ESSHD",
type: :group,
description:
"Before enabling this you must add :esshd to mix.exs as one of the extra_applications " <>
"and generate host keys in your priv dir with ssh-keygen -m PEM -N \"\" -b 2048 -t rsa -f ssh_host_rsa_key",
children: [
%{
key: :enabled,
type: :boolean,
description: "Enables SSH"
},
%{
key: :priv_dir,
type: :string,
description: "Dir with SSH keys",
suggestions: ["/some/path/ssh_keys"]
},
%{
key: :handler,
type: :string,
description: "Handler module",
suggestions: ["Pleroma.BBS.Handler"]
},
%{
key: :port,
type: :integer,
description: "Port to connect",
suggestions: [10_022]
},
%{
key: :password_authenticator,
type: :string,
description: "Authenticator module",
suggestions: ["Pleroma.BBS.Authenticator"]
}
]
},
%{
group: :mime,
label: "Mime Types",
@ -3394,6 +3364,21 @@
type: :integer,
description: "Limit user to export not more often than once per N days",
suggestions: [7]
},
%{
key: :process_wait_time,
type: :integer,
label: "Process Wait Time",
description:
"The amount of time to wait for backup to report progress, in milliseconds. If no progress is received from the backup job for that much time, terminate it and deem it failed.",
suggestions: [30_000]
},
%{
key: :process_chunk_size,
type: :integer,
label: "Process Chunk Size",
description: "The number of activities to fetch in the backup job for each chunk.",
suggestions: [100]
}
]
},

View File

@ -0,0 +1,71 @@
# Managing installed frontends
Pleroma lets you install multiple frontends including multiple versions of same frontend. Right now it's only possible to switch which frontend is the default, but in the future it would be possible for user to select which frontend they prefer to use.
As of 2.6.0 there are two ways of managing frontends - through PleromaFE's Admin Dashboard (preferred, easier method) or through AdminFE (clunky but also works on versions older than 2.6.0).
!!! note
Managing frontends through UI requires [in-database configuration](../configuration/howto_database_config.md) to be enabled (default on newer instances but might be off on older ones).
## How it works
When installing frontends, it creates a folder in [static directory](../configuration/static_dir.md) that follows this pattern: `/frontends/${front-end name}/${front-end version}/`, puts contents of the built frontend in there. Then when accessing the server backend checks what front-end name and version are set to be default and serves index.html and assets from appropriate path.
!!! warning
If you've been putting your frontend build directly into static dir as an antiquated way of serving custom frontend, this system will not work and will still serve the custom index.html you put in there. You can still serve custom frontend builds if you put your build into `/frontends/$name/$version` instead and set the "default frontend" fields appropriately.
Currently, there is no backup system, i.e. when installing `master` version it _will_ overwrite installed `master` version, for now if you want to keep previous version you should back it up manually, i.e. running `cp -r ./frontends/pleroma-fe/master ./frontends/pleroma-fe/master_old` in your static dir.
## Managing front-ends through Admin Dashboard
Open up Admin Dashboard (gauge icon in top bar, same as where link to AdminFE was),__
![location of Admin Dashboard icon](../assets/admin_dash_location.png)
switch to "Front-ends" tab.
![screenshot of Front-ends tab](../assets/frontends_tab.png)
This page is designed to be self-explanatory and easy to use, while avoiding issues and pitfalls of AdminFE, but it's also early in development, everything is subject to change.
!!! warning
This goes without saying, but if you set default frontend to anything except >2.6.0 version of PleromaFE you'll lose the access to Admin Dashboard and will have to use AdminFE to get it back. See below on how to use AdminFE.
### Limitations
Currently the list of available for install frontends is essentially hard-coded in backend's configuration, each providing only one version, with exception for PleromaFE which overrides 'pleroma-fe' to also include `develop` version. There is no way to manually install build with a URL (coming soon) nor add more available frontends to the repository (it's broken).
There is also no way to tell if there is an update available or not, for now you should watch for [announcements](https://pleroma.social/announcements/) of new PleromaFE stable releases to see if there is new stable version. For `develop` version it's up to you whether you want to follow the development process or just reinstall it periodically hoping for new stuff.
## Using AdminFE to manage frontends
Access AdminFE either directly by going to `/pleroma/admin` of your instance or by opening Admin Dashboard and clicking the link at the bottom of the window
![link to open old AdminFE](../assets/old_adminfe_link.png)
Go to Settings -> Frontend.
### Installing front-ends
At the very top of the page there's a list of available frontends and button to install custom front-end
!!! tip
Remember to click "Submit" in bottom right corner to save your changes!
!!! bug
**Available Frontends** section lets you _install_ frontends but **NOT** update/reinstall them. It's only useful for installing a frontend once.
Due to aforementioned bug, preferred way of installing frontends in AdminFE is by clicking the "Install another frontend"
![screenshot of admin-fe with instructions on how to install a frontend](../assets/way_to_install_frontends.png)
and filling in the fields. Unfortunately AdminFE does not provide the raw data necessary for you to fill those fields, so your best bet is to see what backend returns in browser's devtools or refer to the [source code](https://git.pleroma.social/pleroma/pleroma/-/blob/develop/config/config.exs?ref_type=heads#L742-791). For the most part, only **Name**, **Ref** (i.e. version) and **Build URL** fields are required, although some frontends might also require **Build Directory** to work.
For pleroma-fe you can use either `master` or `develop` refs, or potentially any ref in GitLab that has artifacts for `build` job, but that's outside scope of this document.
### Selecting default frontend
Scroll page waaaaay down, search for "Frontends" section, subtitled "Installed frontends management", change the name and reference of the "Primary" frontend.
![screenshot of admin-fe with instructions on how to install a frontend](../assets/primary_frontend_section.png)
!!! danger
If you change "Admin" frontend name/reference you risk losing access to AdminFE as well.
!!! warning
Don't put anything into the "Available" section as it will break the list of available frontends completely, including the "add another frontend" button. If you accidentally put something in there, click the trashbin icon next to "Available" to reset it and restore the frontends list.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -3,12 +3,6 @@ Note: Additional clients may be working but theses are officially supporting Ple
Feel free to contact us to be added to this list!
## Desktop
### Roma for Desktop
- Homepage: <https://www.pleroma.com/#desktopApp>
- Source Code: <https://github.com/roma-apps/roma-desktop>
- Platforms: Windows, Mac, Linux
- Features: MastoAPI, Streaming Ready
### Social
- Source Code: <https://gitlab.gnome.org/World/Social>
- Contact: [@brainblasted@social.libre.fi](https://social.libre.fi/users/brainblasted)
@ -19,7 +13,14 @@ Feel free to contact us to be added to this list!
### Whalebird
- Homepage: <https://whalebird.social/>
- Source Code: <https://github.com/h3poteto/whalebird-desktop>
- Contact: [@h3poteto@pleroma.io](https://pleroma.io/users/h3poteto)
- Contact: [@whalebird@pleroma.io](https://pleroma.io/users/whalebird)
- Platforms: Windows, Mac, Linux
- Features: MastoAPI, Streaming Ready
### Fedistar
- Homepage: <https://fedistar.net>
- Source Code: <https://github.com/h3poteto/fedistar>
- Contact: [@fedistar@pleroma.io](https://pleroma.io/users/fedistar)
- Platforms: Windows, Mac, Linux
- Features: MastoAPI, Streaming Ready

View File

@ -160,6 +160,8 @@ To add configuration to your config file, you can copy it from the base config.
* `Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy`: Drops follow requests from followbots. Users can still allow bots to follow them by first following the bot.
* `Pleroma.Web.ActivityPub.MRF.KeywordPolicy`: Rejects or removes from the federated timeline or replaces keywords. (See [`:mrf_keyword`](#mrf_keyword)).
* `Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent`: Forces every mentioned user to be reflected in the post content.
* `Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy`: Forces quote post URLs to be reflected in the message content inline.
* `Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy`: Force a Link tag for posts quoting another post. (may break outgoing federation of quote posts with older Pleroma versions)
* `transparency`: Make the content of your Message Rewrite Facility settings public (via nodeinfo).
* `transparency_exclusions`: Exclude specific instance names from MRF transparency. The use of the exclusions feature will be disclosed in nodeinfo as a boolean value.
@ -261,6 +263,14 @@ Notes:
* `follower_nickname`: The name of the bot account to use for following newly discovered users. Using `followbot` or similar is strongly suggested.
#### :mrf_emoji
* `remove_url`: A list of patterns which result in emoji whose URL matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles. Each pattern can be a string or a [regular expression](https://hexdocs.pm/elixir/Regex.html).
* `remove_shortcode`: A list of patterns which result in emoji whose shortcode matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles. Each pattern can be a string or a [regular expression](https://hexdocs.pm/elixir/Regex.html).
* `federated_timeline_removal_url`: A list of patterns which result in message with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses. Each pattern can be a string or a [regular expression](https://hexdocs.pm/elixir/Regex.html).
* `federated_timeline_removal_shortcode`: A list of patterns which result in message with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses. Each pattern can be a string or a [regular expression](https://hexdocs.pm/elixir/Regex.html).
#### :mrf_inline_quote
* `template`: The template to append to the post. `{url}` will be replaced with the actual link to the quoted post. Default: `<bdi>RT:</bdi> {url}`
### :activitypub
* `unfollow_blocked`: Whether blocks result in people getting unfollowed
@ -671,6 +681,12 @@ This filter reads the ImageDescription and iptc:Caption-Abstract fields with Exi
No specific configuration.
#### Pleroma.Upload.Filter.OnlyMedia
This filter rejects uploads that are not identified with Content-Type matching audio/\*, image/\*, or video/\*
No specific configuration.
#### Pleroma.Upload.Filter.Mogrify
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
@ -873,21 +889,8 @@ This will probably take a long time.
### BBS / SSH access
To enable simple command line interface accessible over ssh, add a setting like this to your configuration file:
```exs
app_dir = File.cwd!
priv_dir = Path.join([app_dir, "priv/ssh_keys"])
config :esshd,
enabled: true,
priv_dir: priv_dir,
handler: "Pleroma.BBS.Handler",
port: 10_022,
password_authenticator: "Pleroma.BBS.Authenticator"
```
Feel free to adjust the priv_dir and port number. Then you will have to create the key for the keys (in the example `priv/ssh_keys`) and create the host keys with `ssh-keygen -m PEM -N "" -b 2048 -t rsa -f ssh_host_rsa_key`. After restarting, you should be able to connect to your Pleroma instance with `ssh username@server -p $PORT`
This feature has been removed from Pleroma core.
However, a client has been made and is available at https://git.pleroma.social/Duponin/sshocial.
### :gopher
* `enabled`: Enables the gopher interface

View File

@ -62,6 +62,20 @@ An additional “Expect-CT” header will be sent with the configured `ct_max_ag
If you click on a link, your browsers request to the other site will include from where it is coming from. The “Referrer policy” header tells the browser how and if it should send this information. (see [Referrer policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy))
### Uploaded media and media proxy
It is STRONGLY RECOMMENDED to serve both the locally-uploaded media and the media proxy from another domain than the domain that Pleroma runs on, if applicable.
```elixir
config :pleroma, :media_proxy,
base_url: "https://some.other.domain"
config :pleroma, Pleroma.Upload,
base_url: "https://some.other.domain/media"
```
See `installation/pleroma-mediaproxy.nginx` for examples on how to configure your media proxy.
## systemd
A systemd unit example is provided at `installation/pleroma.service`.

View File

@ -1585,6 +1585,7 @@ Returns the content of the document
"build_url": "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build",
"git": "https://git.pleroma.social/pleroma/fedi-fe",
"installed": true,
"installed_refs": ["master"],
"name": "fedi-fe",
"ref": "master"
},
@ -1592,6 +1593,7 @@ Returns the content of the document
"build_url": "https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build",
"git": "https://git.pleroma.social/lambadalambda/kenoma",
"installed": false,
"installed_refs": [],
"name": "kenoma",
"ref": "master"
}

View File

@ -357,6 +357,122 @@ The message payload consist of:
- `follower_count`: follower count
- `following_count`: following count
### Authenticating via `sec-websocket-protocol` header
Pleroma allows to authenticate via the `sec-websocket-protocol` header, for example, if your access token is `your-access-token`, you can authenticate using the following:
```
sec-websocket-protocol: your-access-token
```
### Authenticating after connection via `pleroma:authenticate` event
Pleroma allows to authenticate after connection is established, via the `pleroma:authenticate` event. For example, if your access token is `your-access-token`, you can send the following after the connection is established:
```
{"type": "pleroma:authenticate", "token": "your-access-token"}
```
### Response to client-sent events
Pleroma will respond to client-sent events that it recognizes. Supported event types are:
- `subscribe`
- `unsubscribe`
- `pleroma:authenticate`
The reply will be in the following format:
```
{
"event": "pleroma:respond",
"payload": "{\"type\": \"<type of the client-sent event>\", \"result\": \"<result of the action>\", \"error\": \"<error code>\"}"
}
```
Result of the action can be either `success`, `ignored` or `error`. If it is `error`, the `error` property will contain the error code. Otherwise, the `error` property will not be present. Below are some examples:
```
{
"event": "pleroma:respond",
"payload": "{\"type\": \"pleroma:authenticate\", \"result\": \"success\"}"
}
{
"event": "pleroma:respond",
"payload": "{\"type\": \"subscribe\", \"result\": \"ignored\"}"
}
{
"event": "pleroma:respond",
"payload": "{\"type\": \"unsubscribe\", \"result\": \"error\", \"error\": \"bad_topic\"}"
}
```
If the sent event is not of a type that Pleroma supports, it will not reply.
### The `stream` attribute of a server-sent event
Technically, this is in Mastodon, but its documentation does nothing to specify its format.
This attribute appears on every event type except `pleroma:respond` and `delete`. It helps clients determine where they should display the new statuses.
The value of the attribute is an array containing one or two elements. The first element is the type of the stream. The second is the identifier related to that specific stream, if applicable.
For the following stream types, there is a second element in the array:
- `list`: The second element is the id of the list, as a string.
- `hashtag`: The second element is the name of the hashtag.
- `public:remote:media` and `public:remote`: The second element is the domain of the corresponding instance.
For all other stream types, there is no second element.
Some examples of valid `stream` values:
- `["list", "1"]`: List of id 1.
- `["hashtag", "mew"]`: The hashtag #mew.
- `["user:notifications"]`: Notifications for the current user.
- `["user"]`: Home timeline.
- `["public:remote", "mew.moe"]`: Public posts from the instance mew.moe .
### The unified streaming endpoint
If you do not specify a stream to connect to when requesting `/api/v1/streaming`, you will enter a connection that subscribes to no streams. After the connection is established, you can authenticate and then subscribe to different streams.
### List of supported streams
Below is a list of supported streams by Pleroma. To make a single-stream WebSocket connection, append the string specified in "Query style" to the streaming endpoint url.
To subscribe to a stream after the connection is established, merge the JSON object specified in "Subscribe style" with `{"type": "subscribe"}`. To unsubscribe, merge it with `{"type": "unsubscribe"}`.
For example, to receive updates on the list 1, you can connect to `/api/v1/streaming/?stream=list&list=1`, or send
```
{"type": "subscribe", "stream": "list", "list": "1"}
```
upon establishing the websocket connection.
To unsubscribe to list 1, send
```
{"type": "unsubscribe", "stream": "list", "list": "1"}
```
Note that if you specify a stream that requires a logged-in user in the query string (for example, `user` or `list`), you have to specify the access token when you are trying to establish the connection, i.e. in the query string or via the `sec-websocket-protocol` header.
- `list`
- Query style: `?stream=list&list=<id>`
- Subscribe style: `{"stream": "list", "list": "<id>"}`
- `public`, `public:local`, `public:media`, `public:local:media`, `user`, `user:pleroma_chat`, `user:notifications`, `direct`
- Query style: `?stream=<stream name>`
- Subscribe style: `{"stream": "<stream name>"}`
- `hashtag`
- Query style: `?stream=hashtag&tag=<name>`
- Subscribe style: `{"stream": "hashtag", "tag": "<name>"}`
- `public:remote`, `public:remote:media`
- Query style: `?stream=<stream name>&instance=<instance domain>`
- Subscribe style: `{"stream": "<stream name>", "instance": "<instance domain>"}`
## User muting and thread muting
Both user muting and thread muting can be done for only a certain time by adding an `expires_in` parameter to the API calls and giving the expiration time in seconds.

View File

@ -577,6 +577,9 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
404 if the pack does not exist
## `GET /api/v1/pleroma/accounts/:id/scrobbles`
Audio scrobbling in Pleroma is **deprecated**.
### Requests a list of current and recent Listen activities for an account
* Method `GET`
* Authentication: not required
@ -598,6 +601,9 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
```
## `POST /api/v1/pleroma/scrobble`
Audio scrobbling in Pleroma is **deprecated**.
### Creates a new Listen activity for an account
* Method `POST`
* Authentication: required

View File

@ -183,6 +183,9 @@ server {
...
}
```
* (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
* Enable and start nginx:

View File

@ -173,6 +173,11 @@ sudo ln -s /etc/nginx/sites-available/pleroma.nginx /etc/nginx/sites-enabled/ple
```
* Before starting nginx edit the configuration and change it to your needs (e.g. change servername, change cert paths)
* (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
* Enable and start nginx:
```shell

View File

@ -4,7 +4,7 @@
## Installation
This guide will assume you are on Debian 11 (“bullseye”) or later. This guide should also work with Ubuntu 18.04 (“Bionic Beaver”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
This guide will assume you are on Debian 12 (“bookworm”) or later. This guide should also work with Ubuntu 22.04 (“jammy”) and later. It also assumes that you have administrative rights, either as root or a user with [sudo permissions](https://www.digitalocean.com/community/tutorials/how-to-add-delete-and-grant-sudo-privileges-to-users-on-a-debian-vps). If you want to run this guide with root, ignore the `sudo` at the beginning of the lines, unless it calls a user like `sudo -Hu pleroma`; in this case, use `su <username> -s $SHELL -c 'command'` instead.
{! backend/installation/generic_dependencies.include !}
@ -136,6 +136,11 @@ sudo ln -s /etc/nginx/sites-available/pleroma.nginx /etc/nginx/sites-enabled/ple
```
* Before starting nginx edit the configuration and change it to your needs (e.g. change servername, change cert paths)
* (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
* Enable and start nginx:
```shell

View File

@ -1,11 +1,14 @@
# Pleromaの入れ方
Note: This article is potentially outdated because at this time we may not have people who can speak this language well enough to update it. To see the up-to-date version, which may have significant differences or important caveats of the installation process, look up the English version.
## 日本語訳について
この記事は [Installing on Debian based distributions](Installing on Debian based distributions) の日本語訳です。何かがおかしいと思ったら、原文を見てください。
## インストール
このガイドはDebian Stretchを利用することを想定しています。Ubuntu 16.04や18.04でもおそらく動作します。また、ユーザはrootもしくはsudoにより管理者権限を持っていることを前提とします。もし、以下の操作をrootユーザで行う場合は、 `sudo` を無視してください。ただし、`sudo -Hu pleroma` のようにユーザを指定している場合には `su <username> -s $SHELL -c 'command'` を代わりに使ってください。
このガイドはDebian Bookwormを利用することを想定しています。Ubuntu 22.04でもおそらく動作します。また、ユーザはrootもしくはsudoにより管理者権限を持っていることを前提とします。もし、以下の操作をrootユーザで行う場合は、 `sudo` を無視してください。ただし、`sudo -Hu pleroma` のようにユーザを指定している場合には `su <username> -s $SHELL -c 'command'` を代わりに使ってください。
### 必要なソフトウェア

View File

@ -173,6 +173,10 @@ Edit the defaults of `/usr/local/etc/nginx/sites-available/pleroma.nginx`:
* Change `ssl_certificate_key` to `/var/db/acme/certs/example.tld/example.tld.key`.
* Change all references of `example.tld` to your instance's domain name.
#### (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
## Creating a startup script for Pleroma
Pleroma will need to compile when it initially starts, which typically takes a longer

View File

@ -1,11 +1,11 @@
## Required dependencies
* PostgreSQL 9.6+
* Elixir 1.10+
* Erlang OTP 22.2+
* PostgreSQL >=9.6
* Elixir >=1.11.0 <1.15
* Erlang OTP >=22.2.0 <26
* git
* file / libmagic
* gcc (clang might also work)
* gcc or clang
* GNU make
* CMake

View File

@ -1,6 +1,8 @@
# Installing on Gentoo GNU/Linux
# Manual install on Gentoo GNU/Linux
{! backend/installation/otp_vs_from_source_source.include !}
{! backend/installation/otp_vs_from_source.include !}
This guide covers a manual from-source installation. To use the gentoo package, please check the [packaged installation guide for gentoo](./gentoo_otp_en.md).
## Installation
@ -227,6 +229,10 @@ Replace all instances of `example.tld` with your instance's public URL. If for w
Pay special attention to the line that begins with `ssl_ecdh_curve`. It is stongly advised to comment that line out so that OpenSSL will use its full capabilities, and it is also possible you are running OpenSSL 1.0.2 necessitating that you do this.
* (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
* Enable and start nginx:
```shell

View File

@ -0,0 +1,207 @@
# Packaged install on Gentoo Linux
{! backend/installation/otp_vs_from_source.include !}
This guide covers installation via Gentoo provided packaging. A [manual installation guide for gentoo](./gentoo_en.md) is also available.
## Installation
This guide will assume that you have administrative rights, either as root or a user with [sudo permissions](https://wiki.gentoo.org/wiki/Sudo). Lines that begin with `#` indicate that they should be run as the superuser. Lines using `$` should be run as the indicated user, e.g. `pleroma$` should be run as the `pleroma` user.
{! backend/installation/generic_dependencies.include !}
### Installing a cron daemon
Gentoo quite pointedly does not come with a cron daemon installed, and as such it is recommended you install one to automate certbot renewals and to allow other system administration tasks to be run automatically. Gentoo has [a whole wide world of cron options](https://wiki.gentoo.org/wiki/Cron) but if you just want A Cron That Works, `emerge --ask virtual/cron` will install the default cron implementation (probably cronie) which will work just fine. For the purpouses of this guide, we will be doing just that.
### Required ebuilds
* `www-apps/pleroma`
#### Optional ebuilds used in this guide
* `www-servers/nginx` (preferred, example configs for other reverse proxies can be found in the repo)
* `app-crypt/certbot` (or any other ACME client for Lets Encrypt certificates)
* `app-crypt/certbot-nginx` (nginx certbot plugin that allows use of the all-powerful `--nginx` flag on certbot)
* `media-gfx/imagemagick`
* `media-video/ffmpeg`
* `media-libs/exiftool`
### Prepare the system
* If you haven't yet done so, add the [Gentoo User Repository (GURU)](https://wiki.gentoo.org/wiki/Project:GURU), where the `www-apps/pleroma` ebuild currently lives at:
```shell
# eselect repository enable guru
```
* Ensure that you have the latest copy of the Gentoo and GURU ebuilds if you have not synced them yet:
```shell
# emaint sync -a
```
* Emerge all required the required and suggested software in one go:
```shell
# emerge --ask www-apps/pleroma www-servers/nginx app-crypt/certbot app-crypt/certbot-nginx
```
If you would not like to install the optional packages, remove them from this line.
If you're running this from a low-powered virtual machine, it should work though it will take some time. There were no issues on a VPS with a single core and 1GB of RAM; if you are using an even more limited device and run into issues, you can try creating a swapfile or use a more powerful machine running Gentoo to [cross build](https://wiki.gentoo.org/wiki/Cross_build_environment). If you have a wait ahead of you, now would be a good time to take a break, strech a bit, refresh your beverage of choice and/or get a snack, and reply to Arch users' posts with "I use Gentoo btw" as we do.
### Setup PostgreSQL
[Gentoo Wiki article](https://wiki.gentoo.org/wiki/PostgreSQL) as well as [PostgreSQL QuickStart](https://wiki.gentoo.org/wiki/PostgreSQL/QuickStart) might be worth a quick glance, as the way Gentoo handles postgres is slightly unusual, with built in capability to have two different databases running for testing and live or whatever other purpouse. While it is still straightforward to install, it does mean that the version numbers used in this guide might change for future updates, so keep an eye out for the output you get from `emerge` to ensure you are using the correct ones.
* Initialize the database cluster
The output from emerging postgresql should give you a command for initializing the postgres database. The default slot should be indicated in this command, ensure that it matches the command below.
```shell
# emerge --config dev-db/postgresql:11
```
### Install media / graphics packages (optional)
See [Optional software packages needed for specific functionality](optional/media_graphics_packages.md) for details.
```shell
# emerge --ask media-video/ffmpeg media-gfx/imagemagick media-libs/exiftool
```
### Setup PleromaBE
* Generate the configuration:
```shell
# pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql"
```
* Create the PostgreSQL database
```shell
# sudo -u postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql"
```
* Now run the database migration:
```shell
# pleroma_ctl migrate
```
* Optional: If you have installed RUM indexes (`dev-db/rum`) you also need to run:
```
# sudo -Hu pleroma "pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
```
* Now you can start Pleroma already and add it in the default runlevel
```shell
# rc-service pleroma start
# rc-update add pleroma default
```
It probably won't work over the public internet quite yet, however, as we still need to set up a web server to proxy to the pleroma application, as well as configure SSL.
### Finalize installation
Assuming you want to open your newly installed federated social network to, well, the federation, you should run nginx or some other webserver/proxy in front of Pleroma. It is also a good idea to set up Pleroma to run as a system service.
#### Nginx
* Install nginx, if not already done:
```shell
# emerge --ask www-servers/nginx
```
* Create directories for available and enabled sites:
```shell
# mkdir -p /etc/nginx/sites-{available,enabled}
```
* Append the following line at the end of the `http` block in `/etc/nginx/nginx.conf`:
```Nginx
include sites-enabled/*;
```
* Setup your SSL cert, using your method of choice or certbot. If using certbot, install it if you haven't already:
```shell
# emerge --ask app-crypt/certbot app-crypt/certbot-nginx
```
and then set it up:
```shell
# mkdir -p /var/lib/letsencrypt/
# certbot certonly --email <your@emailaddress> -d <yourdomain> --standalone
```
If that doesn't work the first time, add `--dry-run` to further attempts to avoid being ratelimited as you identify the issue, and do not remove it until the dry run succeeds. If that doesnt work, make sure, that nginx is not already running. If it still doesnt work, try setting up nginx first (change ssl “on” to “off” and try again). Often the answer to issues with certbot is to use the `--nginx` flag once you have nginx up and running.
If you are using any additional subdomains, such as for a media proxy, you can re-run the same command with the subdomain in question. When it comes time to renew later, you will not need to run multiple times for each domain, one renew will handle it.
---
* Copy the example nginx configuration and activate it:
```shell
# cp /opt/pleroma/installation/pleroma.nginx /etc/nginx/sites-available/
# ln -s /etc/nginx/sites-available/pleroma.nginx /etc/nginx/sites-enabled/pleroma.nginx
```
* Take some time to ensure that your nginx config is correct
Replace all instances of `example.tld` with your instance's public URL. If for whatever reason you made changes to the port that your pleroma app runs on, be sure that is reflected in your configuration.
Pay special attention to the line that begins with `ssl_ecdh_curve`. It is stongly advised to comment that line out so that OpenSSL will use its full capabilities, and it is also possible you are running OpenSSL 1.0.2 necessitating that you do this.
* Enable and start nginx:
```shell
# rc-update add nginx default
# /etc/init.d/nginx start
```
If you are using certbot, it is HIGHLY recommend you set up a cron job that renews your certificate, and that you install the suggested `certbot-nginx` plugin. If you don't do these things, you only have yourself to blame when your instance breaks suddenly because you forgot about it.
First, ensure that the command you will be installing into your crontab works.
```shell
# /usr/bin/certbot renew --nginx
```
Assuming not much time has passed since you got certbot working a few steps ago, you should get a message for all domains you installed certificates for saying `Cert not yet due for renewal`.
Now, run crontab as a superuser with `crontab -e` or `sudo crontab -e` as appropriate, and add the following line to your cron:
```cron
0 0 1 * * /usr/bin/certbot renew --nginx
```
This will run certbot on the first of the month at midnight. If you'd rather run more frequently, it's not a bad idea, feel free to go for it.
#### Other webserver/proxies
If you would like to use other webservers or proxies, there are example configurations for some popular alternatives in `/opt/pleroma/installation/`. You can, of course, check out [the Gentoo wiki](https://wiki.gentoo.org) for more information on installing and configuring said alternatives.
#### Create your first user
If your instance is up and running, you can create your first user with administrative rights with the following task:
```shell
pleroma$ pleroma_ctl user new <username> <your@emailaddress> --admin
```
#### Further reading
{! backend/installation/further_reading.include !}
## Questions
Questions about the installation or didnt it work as it should be, ask in [#pleroma:libera.chat](https://matrix.to/#/#pleroma:libera.chat) via Matrix or **#pleroma** on **libera.chat** via IRC.

View File

@ -86,26 +86,26 @@ export FLAVOUR="amd64-musl"
# Clone the release build into a temporary directory and unpack it
# Replace `stable` with `unstable` if you want to run the unstable branch
su pleroma -s $SHELL -lc "
sudo -Hu pleroma "
curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=$FLAVOUR' -o /tmp/pleroma.zip
unzip /tmp/pleroma.zip -d /tmp/
"
# Move the release to the home directory and delete temporary files
su pleroma -s $SHELL -lc "
sudo -Hu pleroma "
mv /tmp/release/* ~pleroma/
rmdir /tmp/release
rm /tmp/pleroma.zip
"
# Start the instance to verify that everything is working as expected
su pleroma -s $SHELL -lc "./bin/pleroma daemon"
sudo -Hu pleroma "./bin/pleroma daemon"
# Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly
sleep 20 && curl http://localhost:4000/api/v1/instance
# Stop the instance
su pleroma -s $SHELL -lc "./bin/pleroma stop"
sudo -Hu pleroma "./bin/pleroma stop"
```
## Setting up a system service

View File

@ -123,6 +123,10 @@ Edit the defaults:
* Change `ssl_certificate_key` to `/etc/nginx/tls/key`.
* Change `example.tld` to your instance's domain name.
### (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
## Configuring acme.sh
We'll be using acme.sh in Stateless Mode for TLS certificate renewal.

View File

@ -195,6 +195,10 @@ rcctl enable relayd
rcctl start relayd
```
##### (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
#### pf
Enabling and configuring pf is highly recommended.
In /etc/pf.conf, insert the following configuration:

View File

@ -1,5 +1,7 @@
# Pleroman asennus OpenBSD:llä
Note: This article is potentially outdated because at this time we may not have people who can speak this language well enough to update it. To see the up-to-date version, which may have significant differences or important caveats of the installation process, look up the English version.
Tarvitset:
* Oman domainin
* OpenBSD 6.3 -serverin

View File

@ -1,9 +1,10 @@
# Optional software packages needed for specific functionality
For specific Pleroma functionality (which is disabled by default) some or all of the below packages are required:
* `ImageMagic`
* `ffmpeg`
* `exiftool`
* `ImageMagic`
* `ffmpeg`
* `exiftool`
Please refer to documentation in `docs/installation` on how to install them on specific OS.
@ -14,20 +15,23 @@ Note: the packages are not required with the current default settings of Pleroma
`ImageMagick` is a set of tools to create, edit, compose, or convert bitmap images.
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`)
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
## `ffmpeg`
`ffmpeg` is software to record, convert and stream audio and video.
It is required for the following Pleroma features:
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
## `exiftool`
`exiftool` is media files metadata reader/writer.
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: `Plaroma.Upload/filters` in `config/config.exs`)
* `Pleroma.Upload.Filters.Exiftool.ReadDescription` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)

View File

@ -2,15 +2,16 @@
{! backend/installation/otp_vs_from_source.include !}
This guide covers a installation using an OTP release. To install Pleroma from source, please check out the corresponding guide for your distro.
This guide covers a installation using OTP releases as built by the Pleroma project, it is meant as a fallback to distribution packages/recipes which are the preferred installation method.
To install Pleroma from source, please check out the corresponding guide for your distro.
## Pre-requisites
* A machine running Linux with GNU (e.g. Debian, Ubuntu) or musl (e.g. Alpine) libc and `x86_64`, `aarch64` or `armv7l` CPU, you have root access to. If you are not sure if it's compatible see [Detecting flavour section](#detecting-flavour) below
* A machine you have root access to running Debian GNU/Linux or compatible (eg. Ubuntu), or Alpine on `x86_64`, `aarch64` or `armv7l` CPU. If you are not sure what you are running see [Detecting flavour section](#detecting-flavour) below
* A (sub)domain pointed to the machine
You will be running commands as root. If you aren't root already, please elevate your privileges by executing `sudo su`/`su`.
You will be running commands as root. If you aren't root already, please elevate your privileges by executing `sudo -i`/`su`.
While in theory OTP releases are possbile to install on any compatible machine, for the sake of simplicity this guide focuses only on Debian/Ubuntu and Alpine.
Similarly to other binaries, OTP releases tend to be only compatible with the distro they are built on, as such this guide focuses only on Debian/Ubuntu and Alpine.
### Detecting flavour
@ -19,7 +20,7 @@ Paste the following into the shell:
arch="$(uname -m)";if [ "$arch" = "x86_64" ];then arch="amd64";elif [ "$arch" = "armv7l" ];then arch="arm";elif [ "$arch" = "aarch64" ];then arch="arm64";else echo "Unsupported arch: $arch">&2;fi;if getconf GNU_LIBC_VERSION>/dev/null;then libc_postfix="";elif [ "$(ldd 2>&1|head -c 9)" = "musl libc" ];then libc_postfix="-musl";elif [ "$(find /lib/libc.musl*|wc -l)" ];then libc_postfix="-musl";else echo "Unsupported libc">&2;fi;echo "$arch$libc_postfix"
```
If your platform is supported the output will contain the flavour string, you will need it later. If not, this just means that we don't build releases for your platform, you can still try installing from source.
This should give your flavour string. If not this just means that we don't build releases for your platform, you can still try installing from source.
### Installing the required packages
@ -114,13 +115,13 @@ adduser --system --shell /bin/false --home /opt/pleroma pleroma
export FLAVOUR="amd64-musl"
# Clone the release build into a temporary directory and unpack it
su pleroma -s $SHELL -lc "
sudo -Hu pleroma "
curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=$FLAVOUR' -o /tmp/pleroma.zip
unzip /tmp/pleroma.zip -d /tmp/
"
# Move the release to the home directory and delete temporary files
su pleroma -s $SHELL -lc "
sudo -Hu pleroma "
mv /tmp/release/* /opt/pleroma
rmdir /tmp/release
rm /tmp/pleroma.zip
@ -141,25 +142,25 @@ mkdir -p /etc/pleroma
chown -R pleroma /etc/pleroma
# Run the config generator
su pleroma -s $SHELL -lc "./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql"
sudo -Hu pleroma "./bin/pleroma_ctl instance gen --output /etc/pleroma/config.exs --output-psql /tmp/setup_db.psql"
# Create the postgres database
su postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql"
sudo -u postgres -s $SHELL -lc "psql -f /tmp/setup_db.psql"
# Create the database schema
su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate"
sudo -Hu pleroma "./bin/pleroma_ctl migrate"
# If you have installed RUM indexes uncommend and run
# su pleroma -s $SHELL -lc "./bin/pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
# sudo -Hu pleroma "./bin/pleroma_ctl migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
# Start the instance to verify that everything is working as expected
su pleroma -s $SHELL -lc "./bin/pleroma daemon"
sudo -Hu pleroma "./bin/pleroma daemon"
# Wait for about 20 seconds and query the instance endpoint, if it shows your uri, name and email correctly, you are configured correctly
sleep 20 && curl http://localhost:4000/api/v1/instance
# Stop the instance
su pleroma -s $SHELL -lc "./bin/pleroma stop"
sudo -Hu pleroma "./bin/pleroma stop"
```
### Setting up nginx and getting Let's Encrypt SSL certificaties
@ -197,6 +198,10 @@ $EDITOR path-to-nginx-config
# Verify that the config is valid
nginx -t
```
#### (Strongly recommended) serve media on another domain
Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors.
#### Start nginx
=== "Alpine"

View File

@ -1,3 +1,8 @@
## OTP releases vs from-source installations
## Packaged (OTP) installation vs Manual (from-source) installations
There are two ways to install Pleroma. You can use OTP releases or do a from-source installation. OTP releases are as close as you can get to binary releases with Erlang/Elixir. The release is self-contained, and provides everything needed to boot it, it is easily administered via the provided shell script to open up a remote console, start/stop/restart the release, start in the background, send remote commands, and more. With from source installations you install Pleroma from source, meaning you have to install certain dependencies like Erlang+Elixir and compile Pleroma yourself.
There is multiple ways to install Pleroma.
<dl>
<dt>Distro-provided packages</dt><dd>This is the recommended method, where you can get the strongest compatibility guarantees and the best dependency-management</dd>
<dt>Pleroma-provided OTP binaries</dt><dd>Intended as fallback for Alpine/Debian-compatible systems lacking a proper Pleroma package, they are heavier than proper distro packages as they also contain Erlang/Elixir and can break after system updates</dd>
<dt>Manual from-source installation</dt><dd>Needs build-dependencies to be installed and manual updates+rebuilds. Allows for easier source-customisations.</dd>
</dl>

View File

@ -1,3 +1,3 @@
{! backend/installation/otp_vs_from_source.include !}
This guide covers a from-source installation. To install using OTP releases, please check out [the OTP guide](./otp_en.md).
This guide covers a manual from-source installation. To install using OTP releases, please check for the presence of a distro package, failing that you can use [Pleroma-provided OTP binaries](./otp_en.md).

View File

@ -8,6 +8,7 @@ pidfile="/var/run/pleroma.pid"
directory=/opt/pleroma
healthcheck_delay=60
healthcheck_timer=30
no_new_privs="yes"
: ${pleroma_port:-4000}

View File

@ -0,0 +1,97 @@
# This file is for those who want to serve uploaded media and media proxy over
# another domain. This is STRONGLY RECOMMENDED.
# This is meant to be used ALONG WITH `pleroma.nginx`.
# If this is a new instance, replace the `location ~ ^/(media|proxy)` section in
# `pleroma.nginx` with the following to completely disable access to media from the main domain:
# location ~ ^/(media|proxy) {
# return 404;
# }
#
# If you are configuring an existing instance to use another domain
# for media, you will want to keep redirecting all existing local media to the new domain
# so already-uploaded media will not break.
# Replace the `location ~ ^/(media|proxy)` section in `pleroma.nginx` with the following:
#
# location /media {
# return 301 https://some.other.domain$request_uri;
# }
#
# location /proxy {
# return 404;
# }
server {
server_name some.other.domain;
listen 80;
listen [::]:80;
# Uncomment this if you need to use the 'webroot' method with certbot. Make sure
# that the directory exists and that it is accessible by the webserver. If you followed
# the guide, you already ran 'mkdir -p /var/lib/letsencrypt' to create the folder.
# You may need to load this file with the ssl server block commented out, run certbot
# to get the certificate, and then uncomment it.
#
# location ~ /\.well-known/acme-challenge {
# root /var/lib/letsencrypt/;
# }
location / {
return 301 https://$server_name$request_uri;
}
}
server {
server_name some.other.domain;
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
ssl_trusted_certificate /etc/letsencrypt/live/some.other.domain/chain.pem;
ssl_certificate /etc/letsencrypt/live/some.other.domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/some.other.domain/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;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
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
client_max_body_size 16m;
ignore_invalid_headers off;
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 / { return 404; }
location ~ ^/(media|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

@ -266,12 +266,20 @@ def run(["gen" | rest]) do
config_dir = Path.dirname(config_path)
psql_dir = Path.dirname(psql_path)
# Note: Distros requiring group read (0o750) on those directories should
# pre-create the directories.
[config_dir, psql_dir, static_dir, uploads_dir]
|> Enum.reject(&File.exists?/1)
|> Enum.map(&File.mkdir_p!/1)
|> Enum.each(fn dir ->
File.mkdir_p!(dir)
File.chmod!(dir, 0o700)
end)
shell_info("Writing config to #{config_path}.")
# Sadly no fchmod(2) equivalent in Elixir…
File.touch!(config_path)
File.chmod!(config_path, 0o640)
File.write(config_path, result_config)
shell_info("Writing the postgres script to #{psql_path}.")
File.write(psql_path, result_psql)
@ -290,8 +298,7 @@ def run(["gen" | rest]) do
else
shell_error(
"The task would have overwritten the following files:\n" <>
(Enum.map(will_overwrite, &"- #{&1}\n") |> Enum.join("")) <>
"Rerun with `--force` to overwrite them."
Enum.map_join(will_overwrite, &"- #{&1}\n") <> "Rerun with `--force` to overwrite them."
)
end
end

View File

@ -6,7 +6,70 @@ defmodule Mix.Tasks.Pleroma.OpenapiSpec do
def run([path]) do
# Load Pleroma application to get version info
Application.load(:pleroma)
spec = Pleroma.Web.ApiSpec.spec(server_specific: false) |> Jason.encode!()
File.write(path, spec)
spec_json = Pleroma.Web.ApiSpec.spec(server_specific: false) |> Jason.encode!()
# to get rid of the structs
spec_regened = spec_json |> Jason.decode!()
check_specs!(spec_regened)
File.write(path, spec_json)
end
defp check_specs!(spec) do
with :ok <- check_specs(spec) do
:ok
else
{_, errors} ->
IO.puts(IO.ANSI.format([:red, :bright, "Spec check failed, errors:"]))
Enum.map(errors, &IO.puts/1)
raise "Spec check failed"
end
end
def check_specs(spec) do
errors =
spec["paths"]
|> Enum.flat_map(fn {path, %{} = endpoints} ->
Enum.map(
endpoints,
fn {method, endpoint} ->
with :ok <- check_endpoint(spec, endpoint) do
:ok
else
error ->
"#{endpoint["operationId"]} (#{method} #{path}): #{error}"
end
end
)
|> Enum.reject(fn res -> res == :ok end)
end)
if errors == [] do
:ok
else
{:error, errors}
end
end
defp check_endpoint(spec, endpoint) do
valid_tags = available_tags(spec)
with {_, [_ | _] = tags} <- {:tags, endpoint["tags"]},
{_, []} <- {:unavailable, Enum.reject(tags, &(&1 in valid_tags))} do
:ok
else
{:tags, _} ->
"No tags specified"
{:unavailable, tags} ->
"Tags #{inspect(tags)} not available. Please add it in \"x-tagGroups\" in Pleroma.Web.ApiSpec"
end
end
defp available_tags(spec) do
spec["x-tagGroups"]
|> Enum.flat_map(fn %{"tags" => tags} -> tags end)
end
end

View File

@ -209,7 +209,8 @@ defp cachex_children do
build_cachex("chat_message_id_idempotency_key",
expiration: chat_message_id_idempotency_key_expiration(),
limit: 500_000
)
),
build_cachex("rel_me", limit: 2500)
]
end

View File

@ -1,20 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.BBS.Authenticator do
use Sshd.PasswordAuthenticator
alias Pleroma.User
alias Pleroma.Web.Plugs.AuthenticationPlug
def authenticate(username, password) do
username = to_string(username)
password = to_string(password)
with %User{} = user <- User.get_by_nickname(username) do
AuthenticationPlug.checkpw(password, user.password_hash)
else
_e -> false
end
end
end

View File

@ -1,246 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.BBS.Handler do
use Sshd.ShellHandler
alias Pleroma.Activity
alias Pleroma.HTML
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
def on_shell(username, _pubkey, _ip, _port) do
:ok = IO.puts("Welcome to #{Pleroma.Config.get([:instance, :name])}!")
user = Pleroma.User.get_cached_by_nickname(to_string(username))
Logger.debug("#{inspect(user)}")
loop(run_state(user: user))
end
def on_connect(username, ip, port, method) do
Logger.debug(fn ->
"""
Incoming SSH shell #{inspect(self())} requested for #{username} from #{inspect(ip)}:#{inspect(port)} using #{inspect(method)}
"""
end)
end
def on_disconnect(username, ip, port) do
Logger.debug(fn ->
"Disconnecting SSH shell for #{username} from #{inspect(ip)}:#{inspect(port)}"
end)
end
defp loop(state) do
self_pid = self()
counter = state.counter
prefix = state.prefix
user = state.user
input = spawn(fn -> io_get(self_pid, prefix, counter, user.nickname) end)
wait_input(state, input)
end
def puts_activity(activity) do
status = Pleroma.Web.MastodonAPI.StatusView.render("show.json", %{activity: activity})
IO.puts("-- #{status.id} by #{status.account.display_name} (#{status.account.acct})")
status.content
|> String.split("<br/>")
|> Enum.map(&HTML.strip_tags/1)
|> Enum.map(&HtmlEntities.decode/1)
|> Enum.map(&IO.puts/1)
end
def puts_notification(activity, user) do
notification =
Pleroma.Web.MastodonAPI.NotificationView.render("show.json", %{
notification: activity,
for: user
})
IO.puts(
"== (#{notification.type}) #{notification.status.id} by #{notification.account.display_name} (#{notification.account.acct})"
)
notification.status.content
|> String.split("<br/>")
|> Enum.map(&HTML.strip_tags/1)
|> Enum.map(&HtmlEntities.decode/1)
|> (fn x ->
case x do
[content] ->
"> " <> content
[head | _tail] ->
# "> " <> hd <> "..."
head
|> String.slice(1, 80)
|> (fn x -> "> " <> x <> "..." end).()
end
end).()
|> IO.puts()
IO.puts("")
end
def handle_command(state, "help") do
IO.puts("Available commands:")
IO.puts("help - This help")
IO.puts("home - Show the home timeline")
IO.puts("p <text> - Post the given text")
IO.puts("r <id> <text> - Reply to the post with the given id")
IO.puts("t <id> - Show a thread from the given id")
IO.puts("n - Show notifications")
IO.puts("n read - Mark all notifactions as read")
IO.puts("f <id> - Favourites the post with the given id")
IO.puts("R <id> - Repeat the post with the given id")
IO.puts("quit - Quit")
state
end
def handle_command(%{user: user} = state, "r " <> text) do
text = String.trim(text)
[activity_id, rest] = String.split(text, " ", parts: 2)
with %Activity{} <- Activity.get_by_id(activity_id),
{:ok, _activity} <-
CommonAPI.post(user, %{status: rest, in_reply_to_status_id: activity_id}) do
IO.puts("Replied!")
else
_e -> IO.puts("Could not reply...")
end
state
end
def handle_command(%{user: user} = state, "t " <> activity_id) do
with %Activity{} = activity <- Activity.get_by_id(activity_id) do
activities =
ActivityPub.fetch_activities_for_context(activity.data["context"], %{
blocking_user: user,
user: user,
exclude_id: activity.id
})
case activities do
[] ->
activity_id
|> Activity.get_by_id()
|> puts_activity()
_ ->
activities
|> Enum.reverse()
|> Enum.each(&puts_activity/1)
end
else
_e -> IO.puts("Could not show this thread...")
end
state
end
def handle_command(%{user: user} = state, "n read") do
Pleroma.Notification.clear(user)
IO.puts("All notifications were marked as read")
state
end
def handle_command(%{user: user} = state, "n") do
user
|> Pleroma.Web.MastodonAPI.MastodonAPI.get_notifications(%{})
|> Enum.each(&puts_notification(&1, user))
state
end
def handle_command(%{user: user} = state, "p " <> text) do
text = String.trim(text)
with {:ok, activity} <- CommonAPI.post(user, %{status: text}) do
IO.puts("Posted! ID: #{activity.id}")
else
_e -> IO.puts("Could not post...")
end
state
end
def handle_command(%{user: user} = state, "f " <> id) do
id = String.trim(id)
with %Activity{} = activity <- Activity.get_by_id(id),
{:ok, _activity} <- CommonAPI.favorite(user, activity) do
IO.puts("Favourited!")
else
_e -> IO.puts("Could not Favourite...")
end
state
end
def handle_command(state, "home") do
user = state.user
params =
%{}
|> Map.put(:type, ["Create"])
|> Map.put(:blocking_user, user)
|> Map.put(:muting_user, user)
|> Map.put(:user, user)
activities =
[user.ap_id | Pleroma.User.following(user)]
|> ActivityPub.fetch_activities(params)
Enum.each(activities, fn activity ->
puts_activity(activity)
end)
state
end
def handle_command(state, command) do
IO.puts("Unknown command '#{command}'")
state
end
defp wait_input(state, input) do
receive do
{:input, ^input, "quit\n"} ->
IO.puts("Exiting...")
{:input, ^input, code} when is_binary(code) ->
code = String.trim(code)
state = handle_command(state, code)
loop(%{state | counter: state.counter + 1})
{:input, ^input, {:error, :interrupted}} ->
IO.puts("Caught Ctrl+C...")
loop(%{state | counter: state.counter + 1})
{:input, ^input, msg} ->
:ok = Logger.warn("received unknown message: #{inspect(msg)}")
loop(%{state | counter: state.counter + 1})
end
end
defp run_state(opts) do
%{prefix: "pleroma", counter: 1, user: opts[:user]}
end
defp io_get(pid, prefix, counter, username) do
prompt = prompt(prefix, counter, username)
send(pid, {:input, self(), IO.gets(:stdio, prompt)})
end
defp prompt(prefix, counter, username) do
prompt = "#{username}@#{prefix}:#{counter}>"
prompt <> " "
end
end

View File

@ -20,6 +20,20 @@ def load(config, opts) do
with_runtime_config =
if File.exists?(config_path) do
# <https://git.pleroma.social/pleroma/pleroma/-/issues/3135>
%File.Stat{mode: mode} = File.lstat!(config_path)
if Bitwise.band(mode, 0o007) > 0 do
raise "Configuration at #{config_path} has world-permissions, execute the following: chmod o= #{config_path}"
end
if Bitwise.band(mode, 0o020) > 0 do
raise "Configuration at #{config_path} has group-wise write permissions, execute the following: chmod g-w #{config_path}"
end
# Note: Elixir doesn't provides a getuid(2)
# so cannot forbid group-read only when config is owned by us
runtime_config = Config.Reader.read!(config_path)
with_defaults

View File

@ -42,6 +42,18 @@ defmodule Pleroma.Constants do
]
)
const(status_object_types,
do: [
"Note",
"Question",
"Audio",
"Video",
"Event",
"Article",
"Page"
]
)
const(updatable_object_types,
do: [
"Note",
@ -69,4 +81,21 @@ defmodule Pleroma.Constants do
const(mime_regex,
do: ~r/^[^[:cntrl:] ()<>@,;:\\"\/\[\]?=]+\/[^[:cntrl:] ()<>@,;:\\"\/\[\]?=]+(; .*)?$/
)
const(upload_object_types, do: ["Document", "Image"])
const(activity_json_canonical_mime_type,
do: "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
)
const(activity_json_mime_types,
do: [
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
"application/activity+json"
]
)
const(public_streams,
do: ["public", "public:local", "public:media", "public:local:media"]
)
end

View File

@ -27,3 +27,11 @@
failed: 4,
manual: 5
)
defenum(Pleroma.User.Backup.State,
pending: 1,
running: 2,
complete: 3,
failed: 4,
invalid: 5
)

View File

@ -0,0 +1,23 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri do
use Ecto.Type
def type, do: :string
def cast(uri) when is_binary(uri) do
case URI.parse(uri) do
%URI{scheme: nil} -> :error
%URI{} -> {:ok, uri}
_ -> :error
end
end
def cast(_), do: :error
def dump(data), do: {:ok, data}
def load(data), do: {:ok, data}
end

View File

@ -51,6 +51,8 @@ def reload do
@doc "Returns the path of the emoji `name`."
@spec get(String.t()) :: String.t() | nil
def get(name) do
name = maybe_strip_name(name)
case :ets.lookup(@ets, name) do
[{_, path}] -> path
_ -> nil
@ -139,6 +141,57 @@ def is_unicode_emoji?(unquote(emoji)), do: true
def is_unicode_emoji?(_), do: false
@emoji_regex ~r/:[A-Za-z0-9_-]+(@.+)?:/
def is_custom_emoji?(s) when is_binary(s), do: Regex.match?(@emoji_regex, s)
def is_custom_emoji?(_), do: false
def maybe_strip_name(name) when is_binary(name), do: String.trim(name, ":")
def maybe_strip_name(name), do: name
def maybe_quote(name) when is_binary(name) do
if is_unicode_emoji?(name) do
name
else
if String.starts_with?(name, ":") do
name
else
":#{name}:"
end
end
end
def maybe_quote(name), do: name
def emoji_url(%{"type" => "EmojiReact", "content" => _, "tag" => []}), do: nil
def emoji_url(%{"type" => "EmojiReact", "content" => emoji, "tag" => tags}) do
emoji = maybe_strip_name(emoji)
tag =
tags
|> Enum.find(fn tag ->
tag["type"] == "Emoji" && !is_nil(tag["name"]) && tag["name"] == emoji
end)
if is_nil(tag) do
nil
else
tag
|> Map.get("icon")
|> Map.get("url")
end
end
def emoji_url(_), do: nil
def emoji_name_with_instance(name, url) do
url = url |> URI.parse() |> Map.get(:host)
"#{name}@#{url}"
end
emoji_qualification_map =
emojis
|> Enum.filter(&String.contains?(&1, "\uFE0F"))

View File

@ -285,6 +285,7 @@ def update_metadata(name, data) do
@spec load_pack(String.t()) :: {:ok, t()} | {:error, :file.posix()}
def load_pack(name) do
name = Path.basename(name)
pack_file = Path.join([emoji_path(), name, "pack.json"])
with {:ok, _} <- File.stat(pack_file),

View File

@ -124,7 +124,7 @@ def mentions_escape(text, options \\ []) do
end
def markdown_to_html(text) do
Earmark.as_html!(text, %Earmark.Options{compact_output: true})
Earmark.as_html!(text, %Earmark.Options{compact_output: true, smartypants: false})
end
def html_escape({text, mentions, hashtags}, type) do

View File

@ -7,6 +7,7 @@ defmodule Pleroma.Instances.Instance do
alias Pleroma.Instances
alias Pleroma.Instances.Instance
alias Pleroma.Maps
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Workers.BackgroundWorker
@ -24,6 +25,14 @@ defmodule Pleroma.Instances.Instance do
field(:favicon, :string)
field(:favicon_updated_at, :naive_datetime)
embeds_one :metadata, Pleroma.Instances.Metadata, primary_key: false do
field(:software_name, :string)
field(:software_version, :string)
field(:software_repository, :string)
end
field(:metadata_updated_at, :utc_datetime)
timestamps()
end
@ -31,11 +40,17 @@ defmodule Pleroma.Instances.Instance do
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:host, :unreachable_since, :favicon, :favicon_updated_at])
|> cast(params, __schema__(:fields) -- [:metadata])
|> cast_embed(:metadata, with: &metadata_changeset/2)
|> validate_required([:host])
|> unique_constraint(:host)
end
def metadata_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:software_name, :software_version, :software_repository])
end
def filter_reachable([]), do: %{}
def filter_reachable(urls_or_hosts) when is_list(urls_or_hosts) do
@ -198,6 +213,89 @@ defp scrape_favicon(%URI{} = instance_uri) do
end
end
def get_or_update_metadata(%URI{host: host} = instance_uri) do
existing_record = Repo.get_by(Instance, %{host: host})
now = NaiveDateTime.utc_now()
if existing_record && existing_record.metadata_updated_at &&
NaiveDateTime.diff(now, existing_record.metadata_updated_at) < 86_400 do
existing_record.metadata
else
metadata = scrape_metadata(instance_uri)
if existing_record do
existing_record
|> changeset(%{metadata: metadata, metadata_updated_at: now})
|> Repo.update()
else
%Instance{}
|> changeset(%{host: host, metadata: metadata, metadata_updated_at: now})
|> Repo.insert()
end
metadata
end
end
defp get_nodeinfo_uri(well_known) do
links = Map.get(well_known, "links", [])
nodeinfo21 =
Enum.find(links, &(&1["rel"] == "http://nodeinfo.diaspora.software/ns/schema/2.1"))["href"]
nodeinfo20 =
Enum.find(links, &(&1["rel"] == "http://nodeinfo.diaspora.software/ns/schema/2.0"))["href"]
cond do
is_binary(nodeinfo21) -> {:ok, nodeinfo21}
is_binary(nodeinfo20) -> {:ok, nodeinfo20}
true -> {:error, :no_links}
end
end
defp scrape_metadata(%URI{} = instance_uri) do
try do
with {_, true} <- {:reachable, reachable?(instance_uri.host)},
{:ok, %Tesla.Env{body: well_known_body}} <-
instance_uri
|> URI.merge("/.well-known/nodeinfo")
|> to_string()
|> Pleroma.HTTP.get([{"accept", "application/json"}]),
{:ok, well_known_json} <- Jason.decode(well_known_body),
{:ok, nodeinfo_uri} <- get_nodeinfo_uri(well_known_json),
{:ok, %Tesla.Env{body: nodeinfo_body}} <-
Pleroma.HTTP.get(nodeinfo_uri, [{"accept", "application/json"}]),
{:ok, nodeinfo} <- Jason.decode(nodeinfo_body) do
# Can extract more metadata from NodeInfo but need to be careful about it's size,
# can't just dump the entire thing
software = Map.get(nodeinfo, "software", %{})
%{
software_name: software["name"],
software_version: software["version"]
}
|> Maps.put_if_present(:software_repository, software["repository"])
else
{:reachable, false} ->
Logger.debug(
"Instance.scrape_metadata(\"#{to_string(instance_uri)}\") ignored unreachable host"
)
nil
_ ->
nil
end
rescue
e ->
Logger.warn(
"Instance.scrape_metadata(\"#{to_string(instance_uri)}\") error: #{inspect(e)}"
)
nil
end
end
@doc """
Deletes all users from an instance in a background task, thus also deleting
all of those users' activities and notifications.

View File

@ -178,6 +178,7 @@ defp exclude_filtered(query, user) do
from([_n, a, o] in query,
where:
fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
fragment("?->>'content' is null", o.data) or
fragment("?->>'actor' = ?", o.data, ^user.ap_id)
)
end
@ -679,7 +680,7 @@ def skip?(
cond do
opts[:type] == "poll" -> false
user.ap_id == actor -> false
!User.following?(follower, user) -> true
!User.following?(user, follower) -> true
true -> false
end
end

View File

@ -425,4 +425,30 @@ def object_data_hashtags(%{"tag" => tags}) when is_list(tags) do
end
def object_data_hashtags(_), do: []
def get_emoji_reactions(object) do
reactions = object.data["reactions"]
if is_list(reactions) or is_map(reactions) do
reactions
|> Enum.map(fn
[_emoji, users, _maybe_url] = item when is_list(users) ->
item
[emoji, users] when is_list(users) ->
[emoji, users, nil]
# This case is here to process the Map situation, which will happen
# only with the legacy two-value format.
{emoji, users} when is_list(users) ->
[emoji, users, nil]
_ ->
nil
end)
|> Enum.reject(&is_nil/1)
else
[]
end
end
end

View File

@ -8,77 +8,30 @@ defmodule Pleroma.Object.Fetcher do
alias Pleroma.Maps
alias Pleroma.Object
alias Pleroma.Object.Containment
alias Pleroma.Repo
alias Pleroma.Signature
alias Pleroma.Web.ActivityPub.InternalFetchActor
alias Pleroma.Web.ActivityPub.MRF
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.Federator
require Logger
require Pleroma.Constants
defp touch_changeset(changeset) do
updated_at =
NaiveDateTime.utc_now()
|> NaiveDateTime.truncate(:second)
Ecto.Changeset.put_change(changeset, :updated_at, updated_at)
end
defp maybe_reinject_internal_fields(%{data: %{} = old_data}, new_data) do
has_history? = fn
%{"formerRepresentations" => %{"orderedItems" => list}} when is_list(list) -> true
_ -> false
end
internal_fields = Map.take(old_data, Pleroma.Constants.object_internal_fields())
remote_history_exists? = has_history?.(new_data)
# If the remote history exists, we treat that as the only source of truth.
new_data =
if has_history?.(old_data) and not remote_history_exists? do
Map.put(new_data, "formerRepresentations", old_data["formerRepresentations"])
else
new_data
end
# If the remote does not have history information, we need to manage it ourselves
new_data =
if not remote_history_exists? do
changed? =
Pleroma.Constants.status_updatable_fields()
|> Enum.any?(fn field -> Map.get(old_data, field) != Map.get(new_data, field) end)
%{updated_object: updated_object} =
new_data
|> Object.Updater.maybe_update_history(old_data,
updated: changed?,
use_history_in_new_object?: false
)
updated_object
else
new_data
end
Map.merge(new_data, internal_fields)
end
defp maybe_reinject_internal_fields(_, new_data), do: new_data
@spec reinject_object(struct(), map()) :: {:ok, Object.t()} | {:error, any()}
defp reinject_object(%Object{data: %{"type" => "Question"}} = object, new_data) do
defp reinject_object(%Object{data: %{}} = object, new_data) do
Logger.debug("Reinjecting object #{new_data["id"]}")
with data <- maybe_reinject_internal_fields(object, new_data),
{:ok, data, _} <- ObjectValidator.validate(data, %{}),
changeset <- Object.change(object, %{data: data}),
changeset <- touch_changeset(changeset),
{:ok, object} <- Repo.insert_or_update(changeset),
{:ok, object} <- Object.set_cache(object) do
{:ok, object}
with {:ok, new_data, _} <- ObjectValidator.validate(new_data, %{}),
{:ok, new_data} <- MRF.filter(new_data),
{:ok, new_object, _} <-
Object.Updater.do_update_and_invalidate_cache(
object,
new_data,
_touch_changeset? = true
) do
{:ok, new_object}
else
e ->
Logger.error("Error while processing object: #{inspect(e)}")
@ -86,20 +39,11 @@ defp reinject_object(%Object{data: %{"type" => "Question"}} = object, new_data)
end
end
defp reinject_object(%Object{} = object, new_data) do
Logger.debug("Reinjecting object #{new_data["id"]}")
with new_data <- Transmogrifier.fix_object(new_data),
data <- maybe_reinject_internal_fields(object, new_data),
changeset <- Object.change(object, %{data: data}),
changeset <- touch_changeset(changeset),
{:ok, object} <- Repo.insert_or_update(changeset),
{:ok, object} <- Object.set_cache(object) do
defp reinject_object(_, new_data) do
with {:ok, object, _} <- Pipeline.common_pipeline(new_data, local: false) do
{:ok, object}
else
e ->
Logger.error("Error while processing object: #{inspect(e)}")
{:error, e}
e -> e
end
end

View File

@ -5,6 +5,9 @@
defmodule Pleroma.Object.Updater do
require Pleroma.Constants
alias Pleroma.Object
alias Pleroma.Repo
def update_content_fields(orig_object_data, updated_object) do
Pleroma.Constants.status_updatable_fields()
|> Enum.reduce(
@ -97,12 +100,14 @@ def maybe_update_history(
end
defp maybe_update_poll(to_be_updated, updated_object) do
choice_key = fn data ->
if Map.has_key?(data, "anyOf"), do: "anyOf", else: "oneOf"
choice_key = fn
%{"anyOf" => [_ | _]} -> "anyOf"
%{"oneOf" => [_ | _]} -> "oneOf"
_ -> nil
end
with true <- to_be_updated["type"] == "Question",
key <- choice_key.(updated_object),
key when not is_nil(key) <- choice_key.(updated_object),
true <- key == choice_key.(to_be_updated),
orig_choices <- to_be_updated[key] |> Enum.map(&Map.drop(&1, ["replies"])),
new_choices <- updated_object[key] |> Enum.map(&Map.drop(&1, ["replies"])),
@ -237,4 +242,49 @@ def do_with_history(object, fun) do
{:history_items, e} -> e
end
end
defp maybe_touch_changeset(changeset, true) do
updated_at =
NaiveDateTime.utc_now()
|> NaiveDateTime.truncate(:second)
Ecto.Changeset.put_change(changeset, :updated_at, updated_at)
end
defp maybe_touch_changeset(changeset, _), do: changeset
def do_update_and_invalidate_cache(orig_object, updated_object, touch_changeset? \\ false) do
orig_object_ap_id = updated_object["id"]
orig_object_data = orig_object.data
%{
updated_data: updated_object_data,
updated: updated,
used_history_in_new_object?: used_history_in_new_object?
} = make_new_object_data_from_update_object(orig_object_data, updated_object)
changeset =
orig_object
|> Repo.preload(:hashtags)
|> Object.change(%{data: updated_object_data})
|> maybe_touch_changeset(touch_changeset?)
with {:ok, new_object} <- Repo.update(changeset),
{:ok, _} <- Object.invalid_object_cache(new_object),
{:ok, _} <- Object.set_cache(new_object),
# The metadata/utils.ex uses the object id for the cache.
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(new_object.id) do
if used_history_in_new_object? do
with create_activity when not is_nil(create_activity) <-
Pleroma.Activity.get_create_by_object_ap_id(orig_object_ap_id),
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(create_activity.id) do
nil
else
_ -> nil
end
end
{:ok, new_object, updated}
end
end
end

View File

@ -40,7 +40,11 @@ defp with_media_attachments(
%{changes: %{params: %{"media_ids" => media_ids} = params}} = changeset
)
when is_list(media_ids) do
media_attachments = Utils.attachments_from_ids(%{media_ids: media_ids})
media_attachments =
Utils.attachments_from_ids(
%{media_ids: media_ids},
User.get_cached_by_id(changeset.data.user_id)
)
params =
params

View File

@ -38,9 +38,9 @@ def filter([filter | rest], upload) do
{:ok, :noop} ->
filter(rest, upload)
error ->
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(error)}")
error
{:error, e} ->
Logger.error("#{__MODULE__}: Filter #{filter} failed: #{inspect(e)}")
{:error, e}
end
end
end

View File

@ -33,7 +33,10 @@ defp read_when_empty(current_description, _, _) when is_binary(current_descripti
defp read_when_empty(_, file, tag) do
try do
{tag_content, 0} =
System.cmd("exiftool", ["-b", "-s3", tag, file], stderr_to_stdout: true, parallelism: true)
System.cmd("exiftool", ["-b", "-s3", tag, file],
stderr_to_stdout: false,
parallelism: true
)
tag_content = String.trim(tag_content)

View File

@ -14,6 +14,7 @@ defmodule Pleroma.Upload.Filter.Exiftool.StripLocation do
# Formats not compatible with exiftool at this time
def filter(%Pleroma.Upload{content_type: "image/heic"}), do: {:ok, :noop}
def filter(%Pleroma.Upload{content_type: "image/webp"}), do: {:ok, :noop}
def filter(%Pleroma.Upload{content_type: "image/svg" <> _}), do: {:ok, :noop}
def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do
try do

View File

@ -0,0 +1,20 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.OnlyMedia do
@behaviour Pleroma.Upload.Filter
alias Pleroma.Upload
def filter(%Upload{content_type: content_type}) do
[type, _subtype] = String.split(content_type, "/")
if type in ["image", "video", "audio"] do
{:ok, :noop}
else
{:error, "Disallowed content-type: #{content_type}"}
end
end
def filter(_), do: {:ok, :noop}
end

View File

@ -124,7 +124,6 @@ defmodule Pleroma.User do
field(:domain_blocks, {:array, :string}, default: [])
field(:is_active, :boolean, default: true)
field(:no_rich_text, :boolean, default: false)
field(:ap_enabled, :boolean, default: false)
field(:is_moderator, :boolean, default: false)
field(:is_admin, :boolean, default: false)
field(:show_role, :boolean, default: true)
@ -488,7 +487,6 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do
:nickname,
:public_key,
:avatar,
:ap_enabled,
:banner,
:is_locked,
:last_refreshed_at,
@ -1061,11 +1059,7 @@ def maybe_direct_follow(%User{} = follower, %User{local: true} = followed) do
end
def maybe_direct_follow(%User{} = follower, %User{} = followed) do
if not ap_enabled?(followed) do
follow(follower, followed)
else
{:ok, follower, followed}
end
{:ok, follower, followed}
end
@doc "A mass follow for local users. Respects blocks in both directions but does not create activities."
@ -1898,7 +1892,6 @@ def purge_user_changeset(user) do
confirmation_token: nil,
domain_blocks: [],
is_active: false,
ap_enabled: false,
is_moderator: false,
is_admin: false,
mascot: nil,
@ -2151,10 +2144,6 @@ def get_public_key_for_ap_id(ap_id) do
end
end
def ap_enabled?(%User{local: true}), do: true
def ap_enabled?(%User{ap_enabled: ap_enabled}), do: ap_enabled
def ap_enabled?(_), do: false
@doc "Gets or fetch a user by uri or nickname."
@spec get_or_fetch(String.t()) :: {:ok, User.t()} | {:error, String.t()}
def get_or_fetch("http://" <> _host = uri), do: get_or_fetch_by_ap_id(uri)

View File

@ -9,12 +9,14 @@ defmodule Pleroma.User.Backup do
import Ecto.Query
import Pleroma.Web.Gettext
require Logger
require Pleroma.Constants
alias Pleroma.Activity
alias Pleroma.Bookmark
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.User.Backup.State
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.UserView
@ -25,6 +27,8 @@ defmodule Pleroma.User.Backup do
field(:file_name, :string)
field(:file_size, :integer, default: 0)
field(:processed, :boolean, default: false)
field(:state, State, default: :invalid)
field(:processed_number, :integer, default: 0)
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
@ -46,7 +50,8 @@ def new(user) do
%__MODULE__{
user_id: user.id,
content_type: "application/zip",
file_name: name
file_name: name,
state: :pending
}
end
@ -109,27 +114,108 @@ def remove_outdated(%__MODULE__{id: latest_id, user_id: user_id}) do
def get(id), do: Repo.get(__MODULE__, id)
defp set_state(backup, state, processed_number \\ nil) do
struct =
%{state: state}
|> Pleroma.Maps.put_if_present(:processed_number, processed_number)
backup
|> cast(struct, [:state, :processed_number])
|> Repo.update()
end
def process(%__MODULE__{} = backup) do
with {:ok, zip_file} <- export(backup),
set_state(backup, :running, 0)
current_pid = self()
task =
Task.Supervisor.async_nolink(
Pleroma.TaskSupervisor,
__MODULE__,
:do_process,
[backup, current_pid]
)
wait_backup(backup, backup.processed_number, task)
end
def do_process(backup, current_pid) do
with {:ok, zip_file} <- export(backup, current_pid),
{:ok, %{size: size}} <- File.stat(zip_file),
{:ok, _upload} <- upload(backup, zip_file) do
backup
|> cast(%{file_size: size, processed: true}, [:file_size, :processed])
|> cast(
%{
file_size: size,
processed: true,
state: :complete
},
[:file_size, :processed, :state]
)
|> Repo.update()
end
end
defp wait_backup(backup, current_processed, task) do
wait_time = Pleroma.Config.get([__MODULE__, :process_wait_time])
receive do
{:progress, new_processed} ->
total_processed = current_processed + new_processed
set_state(backup, :running, total_processed)
wait_backup(backup, total_processed, task)
{:DOWN, _ref, _proc, _pid, reason} ->
backup = get(backup.id)
if reason != :normal do
Logger.error("Backup #{backup.id} process ended abnormally: #{inspect(reason)}")
{:ok, backup} = set_state(backup, :failed)
cleanup(backup)
{:error,
%{
backup: backup,
reason: :exit,
details: reason
}}
else
{:ok, backup}
end
after
wait_time ->
Logger.error(
"Backup #{backup.id} timed out after no response for #{wait_time}ms, terminating"
)
Task.Supervisor.terminate_child(Pleroma.TaskSupervisor, task.pid)
{:ok, backup} = set_state(backup, :failed)
cleanup(backup)
{:error,
%{
backup: backup,
reason: :timeout
}}
end
end
@files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json']
def export(%__MODULE__{} = backup) do
def export(%__MODULE__{} = backup, caller_pid) do
backup = Repo.preload(backup, :user)
name = String.trim_trailing(backup.file_name, ".zip")
dir = dir(name)
dir = backup_tempdir(backup)
with :ok <- File.mkdir(dir),
:ok <- actor(dir, backup.user),
:ok <- statuses(dir, backup.user),
:ok <- likes(dir, backup.user),
:ok <- bookmarks(dir, backup.user),
:ok <- actor(dir, backup.user, caller_pid),
:ok <- statuses(dir, backup.user, caller_pid),
:ok <- likes(dir, backup.user, caller_pid),
:ok <- bookmarks(dir, backup.user, caller_pid),
{:ok, zip_path} <- :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: dir),
{:ok, _} <- File.rm_rf(dir) do
{:ok, to_string(zip_path)}
@ -157,11 +243,12 @@ def upload(%__MODULE__{} = backup, zip_path) do
end
end
defp actor(dir, user) do
defp actor(dir, user, caller_pid) do
with {:ok, json} <-
UserView.render("user.json", %{user: user})
|> Map.merge(%{"likes" => "likes.json", "bookmarks" => "bookmarks.json"})
|> Jason.encode() do
send(caller_pid, {:progress, 1})
File.write(Path.join(dir, "actor.json"), json)
end
end
@ -180,47 +267,80 @@ defp write_header(file, name) do
)
end
defp write(query, dir, name, fun) do
defp should_report?(num, chunk_size), do: rem(num, chunk_size) == 0
defp backup_tempdir(backup) do
name = String.trim_trailing(backup.file_name, ".zip")
dir(name)
end
defp cleanup(backup) do
dir = backup_tempdir(backup)
File.rm_rf(dir)
end
defp write(query, dir, name, fun, caller_pid) do
path = Path.join(dir, "#{name}.json")
chunk_size = Pleroma.Config.get([__MODULE__, :process_chunk_size])
with {:ok, file} <- File.open(path, [:write, :utf8]),
:ok <- write_header(file, name) do
total =
query
|> Pleroma.Repo.chunk_stream(100)
|> Pleroma.Repo.chunk_stream(chunk_size, _returns_as = :one, timeout: :infinity)
|> Enum.reduce(0, fn i, acc ->
with {:ok, data} <- fun.(i),
with {:ok, data} <-
(try do
fun.(i)
rescue
e -> {:error, e}
end),
{:ok, str} <- Jason.encode(data),
:ok <- IO.write(file, str <> ",\n") do
if should_report?(acc + 1, chunk_size) do
send(caller_pid, {:progress, chunk_size})
end
acc + 1
else
_ -> acc
{:error, e} ->
Logger.warn(
"Error processing backup item: #{inspect(e)}\n The item is: #{inspect(i)}"
)
acc
_ ->
acc
end
end)
send(caller_pid, {:progress, rem(total, chunk_size)})
with :ok <- :file.pwrite(file, {:eof, -2}, "\n],\n \"totalItems\": #{total}}") do
File.close(file)
end
end
end
defp bookmarks(dir, %{id: user_id} = _user) do
defp bookmarks(dir, %{id: user_id} = _user, caller_pid) do
Bookmark
|> where(user_id: ^user_id)
|> join(:inner, [b], activity in assoc(b, :activity))
|> select([b, a], %{id: b.id, object: fragment("(?)->>'object'", a.data)})
|> write(dir, "bookmarks", fn a -> {:ok, a.object} end)
|> write(dir, "bookmarks", fn a -> {:ok, a.object} end, caller_pid)
end
defp likes(dir, user) do
defp likes(dir, user, caller_pid) do
user.ap_id
|> Activity.Queries.by_actor()
|> Activity.Queries.by_type("Like")
|> select([like], %{id: like.id, object: fragment("(?)->>'object'", like.data)})
|> write(dir, "likes", fn a -> {:ok, a.object} end)
|> write(dir, "likes", fn a -> {:ok, a.object} end, caller_pid)
end
defp statuses(dir, user) do
defp statuses(dir, user, caller_pid) do
opts =
%{}
|> Map.put(:type, ["Create", "Announce"])
@ -233,10 +353,15 @@ defp statuses(dir, user) do
]
|> Enum.concat()
|> ActivityPub.fetch_activities_query(opts)
|> write(dir, "outbox", fn a ->
with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do
{:ok, Map.delete(activity, "@context")}
end
end)
|> write(
dir,
"outbox",
fn a ->
with {:ok, activity} <- Transmogrifier.prepare_outgoing(a.data) do
{:ok, Map.delete(activity, "@context")}
end
end,
caller_pid
)
end
end

View File

@ -96,7 +96,7 @@ defp increase_replies_count_if_reply(%{
defp increase_replies_count_if_reply(_create_data), do: :noop
@object_types ~w[ChatMessage Question Answer Audio Video Event Article Note Page]
@object_types ~w[ChatMessage Question Answer Audio Video Image Event Article Note Page]
@impl true
def persist(%{"type" => type} = object, meta) when type in @object_types do
with {:ok, object} <- Object.create(object) do
@ -455,6 +455,7 @@ def fetch_activities_for_context_query(context, opts) do
|> maybe_preload_objects(opts)
|> maybe_preload_bookmarks(opts)
|> maybe_set_thread_muted_field(opts)
|> restrict_unauthenticated(opts[:user])
|> restrict_blocked(opts)
|> restrict_blockers_visibility(opts)
|> restrict_recipients(recipients, opts[:user])
@ -1215,6 +1216,27 @@ defp restrict_filtered(query, %{blocking_user: %User{} = user}) do
defp restrict_filtered(query, _), do: query
defp restrict_unauthenticated(query, nil) do
local = Config.restrict_unauthenticated_access?(:activities, :local)
remote = Config.restrict_unauthenticated_access?(:activities, :remote)
cond do
local and remote ->
from(activity in query, where: false)
local ->
from(activity in query, where: activity.local == false)
remote ->
from(activity in query, where: activity.local == true)
true ->
query
end
end
defp restrict_unauthenticated(query, _), do: query
defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query
defp exclude_poll_votes(query, _) do
@ -1453,13 +1475,22 @@ def fetch_activities_bounded(
@spec upload(Upload.source(), keyword()) :: {:ok, Object.t()} | {:error, any()}
def upload(file, opts \\ []) do
with {:ok, data} <- Upload.store(file, opts) do
with {:ok, data} <- Upload.store(sanitize_upload_file(file), opts) do
obj_data = Maps.put_if_present(data, "actor", opts[:actor])
Repo.insert(%Object{data: obj_data})
end
end
defp sanitize_upload_file(%Plug.Upload{filename: filename} = upload) when is_binary(filename) do
%Plug.Upload{
upload
| filename: Path.basename(filename)
}
end
defp sanitize_upload_file(upload), do: upload
@spec get_actor_url(any()) :: binary() | nil
defp get_actor_url(url) when is_binary(url), do: url
defp get_actor_url(%{"href" => href}) when is_binary(href), do: href
@ -1538,7 +1569,6 @@ defp object_to_user_data(data, additional) do
%{
ap_id: data["id"],
uri: get_actor_url(data["url"]),
ap_enabled: true,
banner: normalize_image(data["image"]),
fields: fields,
emoji: emojis,
@ -1659,7 +1689,7 @@ def user_data_from_user_object(data, additional \\ []) do
end
end
def fetch_and_prepare_user_from_ap_id(ap_id, additional \\ []) do
defp fetch_and_prepare_user_from_ap_id(ap_id, additional) do
with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id),
{:ok, data} <- user_data_from_user_object(data, additional) do
{:ok, maybe_update_follow_information(data)}
@ -1712,6 +1742,11 @@ def pin_data_from_featured_collection(%{
end)
end
def pin_data_from_featured_collection(obj) do
Logger.error("Could not parse featured collection #{inspect(obj)}")
%{}
end
def fetch_and_prepare_featured_from_ap_id(nil) do
{:ok, %{}}
end
@ -1742,24 +1777,20 @@ def pinned_fetch_task(%{pinned_objects: pins}) do
def make_user_from_ap_id(ap_id, additional \\ []) do
user = User.get_cached_by_ap_id(ap_id)
if user && !User.ap_enabled?(user) do
Transmogrifier.upgrade_user_from_ap_id(ap_id)
else
with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do
{:ok, _pid} = Task.start(fn -> pinned_fetch_task(data) end)
with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, additional) do
{:ok, _pid} = Task.start(fn -> pinned_fetch_task(data) end)
if user do
user
|> User.remote_user_changeset(data)
|> User.update_and_set_cache()
else
maybe_handle_clashing_nickname(data)
if user do
user
|> User.remote_user_changeset(data)
|> User.update_and_set_cache()
else
maybe_handle_clashing_nickname(data)
data
|> User.remote_user_changeset()
|> Repo.insert()
|> User.set_cache()
end
data
|> User.remote_user_changeset()
|> Repo.insert()
|> User.set_cache()
end
end
end

View File

@ -16,6 +16,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.CommonAPI.ActivityDraft
alias Pleroma.Web.Endpoint
require Pleroma.Constants
@ -54,13 +55,87 @@ def follow(follower, followed) do
{:ok, data, []}
end
defp unicode_emoji_react(_object, data, emoji) do
data
|> Map.put("content", emoji)
|> Map.put("type", "EmojiReact")
end
defp add_emoji_content(data, emoji, url) do
tag = [
%{
"id" => url,
"type" => "Emoji",
"name" => Emoji.maybe_quote(emoji),
"icon" => %{
"type" => "Image",
"url" => url
}
}
]
data
|> Map.put("content", Emoji.maybe_quote(emoji))
|> Map.put("type", "EmojiReact")
|> Map.put("tag", tag)
end
defp remote_custom_emoji_react(
%{data: %{"reactions" => existing_reactions}},
data,
emoji
) do
[emoji_code, instance] = String.split(Emoji.maybe_strip_name(emoji), "@")
matching_reaction =
Enum.find(
existing_reactions,
fn [name, _, url] ->
if url != nil do
url = URI.parse(url)
url.host == instance && name == emoji_code
end
end
)
if matching_reaction do
[name, _, url] = matching_reaction
add_emoji_content(data, name, url)
else
{:error, "Could not react"}
end
end
defp remote_custom_emoji_react(_object, _data, _emoji) do
{:error, "Could not react"}
end
defp local_custom_emoji_react(data, emoji) do
with %{file: path} = emojo <- Emoji.get(emoji) do
url = "#{Endpoint.url()}#{path}"
add_emoji_content(data, emojo.code, url)
else
_ -> {:error, "Emoji does not exist"}
end
end
defp custom_emoji_react(object, data, emoji) do
if String.contains?(emoji, "@") do
remote_custom_emoji_react(object, data, emoji)
else
local_custom_emoji_react(data, emoji)
end
end
@spec emoji_react(User.t(), Object.t(), String.t()) :: {:ok, map(), keyword()}
def emoji_react(actor, object, emoji) do
with {:ok, data, meta} <- object_action(actor, object) do
data =
data
|> Map.put("content", emoji)
|> Map.put("type", "EmojiReact")
if Emoji.is_unicode_emoji?(emoji) do
unicode_emoji_react(object, data, emoji)
else
custom_emoji_react(object, data, emoji)
end
{:ok, data, meta}
end
@ -142,6 +217,7 @@ def note(%ActivityDraft{} = draft) do
"tag" => Keyword.values(draft.tags) |> Enum.uniq()
}
|> add_in_reply_to(draft.in_reply_to)
|> add_quote(draft.quote_post)
|> Map.merge(draft.extra)
{:ok, data, []}
@ -157,6 +233,16 @@ defp add_in_reply_to(object, in_reply_to) do
end
end
defp add_quote(object, nil), do: object
defp add_quote(object, quote_post) do
with %Object{} = quote_object <- Object.normalize(quote_post, fetch: false) do
Map.put(object, "quoteUrl", quote_object.data["id"])
else
_ -> object
end
end
def chat_message(actor, recipient, content, opts \\ []) do
basic = %{
"id" => Utils.generate_object_id(),

View File

@ -0,0 +1,281 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.EmojiPolicy do
require Pleroma.Constants
alias Pleroma.Object.Updater
alias Pleroma.Web.ActivityPub.MRF.Utils
@moduledoc "Reject or force-unlisted emojis with certain URLs or names"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
defp config_remove_url do
Pleroma.Config.get([:mrf_emoji, :remove_url], [])
end
defp config_remove_shortcode do
Pleroma.Config.get([:mrf_emoji, :remove_shortcode], [])
end
defp config_unlist_url do
Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_url], [])
end
defp config_unlist_shortcode do
Pleroma.Config.get([:mrf_emoji, :federated_timeline_removal_shortcode], [])
end
@impl Pleroma.Web.ActivityPub.MRF.Policy
def history_awareness, do: :manual
@impl Pleroma.Web.ActivityPub.MRF.Policy
def filter(%{"type" => type, "object" => %{"type" => objtype} = object} = message)
when type in ["Create", "Update"] and objtype in Pleroma.Constants.status_object_types() do
with {:ok, object} <-
Updater.do_with_history(object, fn object ->
{:ok, process_remove(object, :url, config_remove_url())}
end),
{:ok, object} <-
Updater.do_with_history(object, fn object ->
{:ok, process_remove(object, :shortcode, config_remove_shortcode())}
end),
activity <- Map.put(message, "object", object),
activity <- maybe_delist(activity) do
{:ok, activity}
end
end
@impl Pleroma.Web.ActivityPub.MRF.Policy
def filter(%{"type" => type} = object) when type in Pleroma.Constants.actor_types() do
with object <- process_remove(object, :url, config_remove_url()),
object <- process_remove(object, :shortcode, config_remove_shortcode()) do
{:ok, object}
end
end
@impl Pleroma.Web.ActivityPub.MRF.Policy
def filter(%{"type" => "EmojiReact"} = object) do
with {:ok, _} <-
matched_emoji_checker(config_remove_url(), config_remove_shortcode()).(object) do
{:ok, object}
else
_ ->
{:reject, "[EmojiPolicy] Rejected for having disallowed emoji"}
end
end
@impl Pleroma.Web.ActivityPub.MRF.Policy
def filter(message) do
{:ok, message}
end
defp match_string?(string, pattern) when is_binary(pattern) do
string == pattern
end
defp match_string?(string, %Regex{} = pattern) do
String.match?(string, pattern)
end
defp match_any?(string, patterns) do
Enum.any?(patterns, &match_string?(string, &1))
end
defp url_from_tag(%{"icon" => %{"url" => url}}), do: url
defp url_from_tag(_), do: nil
defp url_from_emoji({_name, url}), do: url
defp shortcode_from_tag(%{"name" => name}) when is_binary(name), do: String.trim(name, ":")
defp shortcode_from_tag(_), do: nil
defp shortcode_from_emoji({name, _url}), do: name
defp process_remove(object, :url, patterns) do
process_remove_impl(object, &url_from_tag/1, &url_from_emoji/1, patterns)
end
defp process_remove(object, :shortcode, patterns) do
process_remove_impl(object, &shortcode_from_tag/1, &shortcode_from_emoji/1, patterns)
end
defp process_remove_impl(object, extract_from_tag, extract_from_emoji, patterns) do
object =
if object["tag"] do
Map.put(
object,
"tag",
Enum.filter(
object["tag"],
fn
%{"type" => "Emoji"} = tag ->
str = extract_from_tag.(tag)
if is_binary(str) do
not match_any?(str, patterns)
else
true
end
_ ->
true
end
)
)
else
object
end
object =
if object["emoji"] do
Map.put(
object,
"emoji",
object["emoji"]
|> Enum.reduce(%{}, fn {name, url} = emoji, acc ->
if not match_any?(extract_from_emoji.(emoji), patterns) do
Map.put(acc, name, url)
else
acc
end
end)
)
else
object
end
object
end
defp matched_emoji_checker(urls, shortcodes) do
fn object ->
if any_emoji_match?(object, &url_from_tag/1, &url_from_emoji/1, urls) or
any_emoji_match?(
object,
&shortcode_from_tag/1,
&shortcode_from_emoji/1,
shortcodes
) do
{:matched, nil}
else
{:ok, %{}}
end
end
end
defp maybe_delist(%{"object" => object, "to" => to, "type" => "Create"} = activity) do
check = matched_emoji_checker(config_unlist_url(), config_unlist_shortcode())
should_delist? = fn object ->
with {:ok, _} <- Pleroma.Object.Updater.do_with_history(object, check) do
false
else
_ -> true
end
end
if Pleroma.Constants.as_public() in to and should_delist?.(object) do
to = List.delete(to, Pleroma.Constants.as_public())
cc = [Pleroma.Constants.as_public() | activity["cc"] || []]
activity
|> Map.put("to", to)
|> Map.put("cc", cc)
else
activity
end
end
defp maybe_delist(activity), do: activity
defp any_emoji_match?(object, extract_from_tag, extract_from_emoji, patterns) do
Kernel.||(
Enum.any?(
object["tag"] || [],
fn
%{"type" => "Emoji"} = tag ->
str = extract_from_tag.(tag)
if is_binary(str) do
match_any?(str, patterns)
else
false
end
_ ->
false
end
),
(object["emoji"] || [])
|> Enum.any?(fn emoji -> match_any?(extract_from_emoji.(emoji), patterns) end)
)
end
@impl Pleroma.Web.ActivityPub.MRF.Policy
def describe do
mrf_emoji =
Pleroma.Config.get(:mrf_emoji, [])
|> Enum.map(fn {key, value} ->
{key, Enum.map(value, &Utils.describe_regex_or_string/1)}
end)
|> Enum.into(%{})
{:ok, %{mrf_emoji: mrf_emoji}}
end
@impl Pleroma.Web.ActivityPub.MRF.Policy
def config_description do
%{
key: :mrf_emoji,
related_policy: "Pleroma.Web.ActivityPub.MRF.EmojiPolicy",
label: "MRF Emoji",
description:
"Reject or force-unlisted emojis whose URLs or names match a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html).",
children: [
%{
key: :remove_url,
type: {:list, :string},
description: """
A list of patterns which result in emoji whose URL matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
suggestions: ["https://example.org/foo.png", ~r/example.org\/foo/iu]
},
%{
key: :remove_shortcode,
type: {:list, :string},
description: """
A list of patterns which result in emoji whose shortcode matches being removed from the message. This will apply to statuses, emoji reactions, and user profiles.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
suggestions: ["foo", ~r/foo/iu]
},
%{
key: :federated_timeline_removal_url,
type: {:list, :string},
description: """
A list of patterns which result in message with emojis whose URLs match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
suggestions: ["https://example.org/foo.png", ~r/example.org\/foo/iu]
},
%{
key: :federated_timeline_removal_shortcode,
type: {:list, :string},
description: """
A list of patterns which result in message with emojis whose shortcodes match being removed from federated timelines (a.k.a unlisted). This will apply only to statuses.
Each pattern can be a string or [Regex](https://hexdocs.pm/elixir/Regex.html) in the format of `~r/PATTERN/`.
""",
suggestions: ["foo", ~r/foo/iu]
}
]
}
end
end

View File

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.ForceMentionsInContent do
@ -95,11 +95,13 @@ def filter(
|> Enum.reject(&is_nil/1)
|> sort_replied_user(replied_to_user)
explicitly_mentioned_uris = extract_mention_uris_from_content(content)
explicitly_mentioned_uris =
extract_mention_uris_from_content(content)
|> MapSet.new()
added_mentions =
Enum.reduce(mention_users, "", fn %User{ap_id: uri} = user, acc ->
unless uri in explicitly_mentioned_uris do
Enum.reduce(mention_users, "", fn %User{ap_id: ap_id, uri: uri} = user, acc ->
if MapSet.disjoint?(MapSet.new([ap_id, uri]), explicitly_mentioned_uris) do
acc <> Formatter.mention_from_user(user, %{mentions_format: :compact}) <> " "
else
acc

View File

@ -0,0 +1,78 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
@moduledoc "Force a quote line into the message content."
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
defp build_inline_quote(template, url) do
quote_line = String.replace(template, "{url}", "<a href=\"#{url}\">#{url}</a>")
"<span class=\"quote-inline\"><br/><br/>#{quote_line}</span>"
end
defp has_inline_quote?(content, quote_url) do
cond do
# Does the quote URL exist in the content?
content =~ quote_url -> true
# Does the content already have a .quote-inline span?
content =~ "<span class=\"quote-inline\">" -> true
# No inline quote found
true -> false
end
end
defp filter_object(%{"quoteUrl" => quote_url} = object) do
content = object["content"] || ""
if has_inline_quote?(content, quote_url) do
object
else
template = Pleroma.Config.get([:mrf_inline_quote, :template])
content =
if String.ends_with?(content, "</p>"),
do:
String.trim_trailing(content, "</p>") <>
build_inline_quote(template, quote_url) <> "</p>",
else: content <> build_inline_quote(template, quote_url)
Map.put(object, "content", content)
end
end
@impl true
def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
{:ok, Map.put(activity, "object", filter_object(object))}
end
@impl true
def filter(object), do: {:ok, object}
@impl true
def describe, do: {:ok, %{}}
@impl Pleroma.Web.ActivityPub.MRF.Policy
def history_awareness, do: :auto
@impl true
def config_description do
%{
key: :mrf_inline_quote,
related_policy: "Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy",
label: "MRF Inline Quote Policy",
type: :group,
description: "Force quote url to appear in post content.",
children: [
%{
key: :template,
type: :string,
description:
"The template to append to the post. `{url}` will be replaced with the actual link to the quoted post.",
suggestions: ["<bdi>RT:</bdi> {url}"]
}
]
}
end
end

View File

@ -5,6 +5,8 @@
defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
require Pleroma.Constants
alias Pleroma.Web.ActivityPub.MRF.Utils
@moduledoc "Reject or Word-Replace messages with a keyword or regex"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
@ -128,7 +130,6 @@ def filter(message), do: {:ok, message}
@impl true
def describe do
# This horror is needed to convert regex sigils to strings
mrf_keyword =
Pleroma.Config.get(:mrf_keyword, [])
|> Enum.map(fn {key, value} ->
@ -136,21 +137,12 @@ def describe do
Enum.map(value, fn
{pattern, replacement} ->
%{
"pattern" =>
if not is_binary(pattern) do
inspect(pattern)
else
pattern
end,
"pattern" => Utils.describe_regex_or_string(pattern),
"replacement" => replacement
}
pattern ->
if not is_binary(pattern) do
inspect(pattern)
else
pattern
end
Utils.describe_regex_or_string(pattern)
end)}
end)
|> Enum.into(%{})

View File

@ -0,0 +1,49 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.QuoteToLinkTagPolicy do
@moduledoc "Force a Link tag for posts quoting another post. (may break outgoing federation of quote posts with older Pleroma versions)"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
require Pleroma.Constants
@impl Pleroma.Web.ActivityPub.MRF.Policy
def filter(%{"object" => %{"quoteUrl" => _} = object} = activity) do
{:ok, Map.put(activity, "object", filter_object(object))}
end
@impl Pleroma.Web.ActivityPub.MRF.Policy
def filter(object), do: {:ok, object}
@impl Pleroma.Web.ActivityPub.MRF.Policy
def describe, do: {:ok, %{}}
@impl Pleroma.Web.ActivityPub.MRF.Policy
def history_awareness, do: :auto
defp filter_object(%{"quoteUrl" => quote_url} = object) do
tags = object["tag"] || []
if Enum.any?(tags, fn tag ->
CommonFixes.is_object_link_tag(tag) and tag["href"] == quote_url
end) do
object
else
object
|> Map.put(
"tag",
tags ++
[
%{
"type" => "Link",
"mediaType" => Pleroma.Constants.activity_json_canonical_mime_type(),
"href" => quote_url
}
]
)
end
end
end

View File

@ -34,6 +34,7 @@ defp steal_emoji({shortcode, url}, emoji_dir_path) do
|> Path.basename()
|> Path.extname()
shortcode = Path.basename(shortcode)
file_path = Path.join(emoji_dir_path, shortcode <> (extension || ".png"))
case File.write(file_path, response.body) do
@ -76,6 +77,7 @@ def filter(%{"object" => %{"emoji" => foreign_emojis, "actor" => actor}} = messa
new_emojis =
foreign_emojis
|> Enum.reject(fn {shortcode, _url} -> shortcode in installed_emoji end)
|> Enum.reject(fn {shortcode, _url} -> String.contains?(shortcode, ["/", "\\"]) end)
|> Enum.filter(fn {shortcode, _url} ->
reject_emoji? =
[:mrf_steal_emoji, :rejected_shortcodes]

View File

@ -0,0 +1,15 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.Utils do
@spec describe_regex_or_string(String.t() | Regex.t()) :: String.t()
def describe_regex_or_string(pattern) do
# This horror is needed to convert regex sigils to strings
if not is_binary(pattern) do
inspect(pattern)
else
pattern
end
end
end

View File

@ -21,7 +21,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.AnnounceValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AnswerValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.BlockValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator
@ -102,7 +102,7 @@ def validate(
%{"type" => "Create", "object" => %{"type" => objtype} = object} = create_activity,
meta
)
when objtype in ~w[Question Answer Audio Video Event Article Note Page] do
when objtype in ~w[Question Answer Audio Video Image Event Article Note Page] do
with {:ok, object_data} <- cast_and_apply_and_stringify_with_history(object),
meta = Keyword.put(meta, :object_data, object_data),
{:ok, create_activity} <-
@ -115,13 +115,14 @@ def validate(
end
def validate(%{"type" => type} = object, meta)
when type in ~w[Event Question Audio Video Article Note Page] do
when type in ~w[Event Question Audio Video Image Article Note Page] do
validator =
case type do
"Event" -> EventValidator
"Question" -> QuestionValidator
"Audio" -> AudioVideoValidator
"Video" -> AudioVideoValidator
"Audio" -> AudioImageVideoValidator
"Video" -> AudioImageVideoValidator
"Image" -> AudioImageVideoValidator
"Article" -> ArticleNotePageValidator
"Note" -> ArticleNotePageValidator
"Page" -> ArticleNotePageValidator
@ -233,8 +234,8 @@ def cast_and_apply(%{"type" => "Answer"} = object) do
AnswerValidator.cast_and_apply(object)
end
def cast_and_apply(%{"type" => type} = object) when type in ~w[Audio Video] do
AudioVideoValidator.cast_and_apply(object)
def cast_and_apply(%{"type" => type} = object) when type in ~w[Audio Image Video] do
AudioImageVideoValidator.cast_and_apply(object)
end
def cast_and_apply(%{"type" => "Event"} = object) do

View File

@ -73,6 +73,7 @@ defp maybe_refetch_user(%User{featured_address: address} = user) when is_binary(
end
defp maybe_refetch_user(%User{ap_id: ap_id}) do
Pleroma.Web.ActivityPub.Transmogrifier.upgrade_user_from_ap_id(ap_id)
# Maybe it could use User.get_or_fetch_by_ap_id to avoid refreshing too often
User.fetch_by_ap_id(ap_id)
end
end

View File

@ -84,6 +84,7 @@ defp fix(data) do
|> fix_tag()
|> fix_replies()
|> fix_attachments()
|> CommonFixes.fix_quote_url()
|> Transmogrifier.fix_emoji()
|> Transmogrifier.fix_content_map()
end

View File

@ -2,7 +2,7 @@
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioVideoValidator do
defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioImageVideoValidator do
use Ecto.Schema
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
@ -55,9 +55,14 @@ defp find_attachment(url) do
url
|> Enum.concat(mpeg_url["tag"] || [])
|> Enum.find(fn
%{"mediaType" => mime_type} -> String.starts_with?(mime_type, ["video/", "audio/"])
%{"mimeType" => mime_type} -> String.starts_with?(mime_type, ["video/", "audio/"])
_ -> false
%{"mediaType" => mime_type} ->
String.starts_with?(mime_type, ["video/", "audio/", "image/"])
%{"mimeType" => mime_type} ->
String.starts_with?(mime_type, ["video/", "audio/", "image/"])
_ ->
false
end)
end
@ -94,6 +99,7 @@ defp fix(data) do
data
|> CommonFixes.fix_actor()
|> CommonFixes.fix_object_defaults()
|> CommonFixes.fix_quote_url()
|> Transmogrifier.fix_emoji()
|> fix_url()
|> fix_content()
@ -110,7 +116,7 @@ def changeset(struct, data) do
defp validate_data(data_cng) do
data_cng
|> validate_inclusion(:type, ["Audio", "Video"])
|> validate_inclusion(:type, ~w[Audio Image Video])
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|> CommonValidations.validate_any_presence([:cc, :to])
|> CommonValidations.validate_fields_match([:actor, :attributedTo])

View File

@ -27,7 +27,7 @@ defmacro activity_fields do
end
end
# All objects except Answer and CHatMessage
# All objects except Answer and ChatMessage
defmacro object_fields do
quote bind_quoted: binding() do
field(:content, :string)
@ -58,7 +58,8 @@ defmacro status_object_fields do
field(:like_count, :integer, default: 0)
field(:announcement_count, :integer, default: 0)
field(:inReplyTo, ObjectValidators.ObjectID)
field(:url, ObjectValidators.Uri)
field(:quoteUrl, ObjectValidators.ObjectID)
field(:url, ObjectValidators.BareUri)
field(:likes, {:array, ObjectValidators.ObjectID}, default: [])
field(:announcements, {:array, ObjectValidators.ObjectID}, default: [])

View File

@ -10,6 +10,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
require Pleroma.Constants
def cast_and_filter_recipients(message, field, follower_collection, field_fallback \\ []) do
{:ok, data} = ObjectValidators.Recipients.cast(message[field] || field_fallback)
@ -76,4 +78,48 @@ def fix_object_action_recipients(data, %Object{data: %{"actor" => actor}}) do
Map.put(data, "to", to)
end
def fix_quote_url(%{"quoteUrl" => _quote_url} = data), do: data
# Fedibird
# https://github.com/fedibird/mastodon/commit/dbd7ae6cf58a92ec67c512296b4daaea0d01e6ac
def fix_quote_url(%{"quoteUri" => quote_url} = data) do
Map.put(data, "quoteUrl", quote_url)
end
# Old Fedibird (bug)
# https://github.com/fedibird/mastodon/issues/9
def fix_quote_url(%{"quoteURL" => quote_url} = data) do
Map.put(data, "quoteUrl", quote_url)
end
# Misskey fallback
def fix_quote_url(%{"_misskey_quote" => quote_url} = data) do
Map.put(data, "quoteUrl", quote_url)
end
def fix_quote_url(%{"tag" => [_ | _] = tags} = data) do
tag = Enum.find(tags, &is_object_link_tag/1)
if not is_nil(tag) do
data
|> Map.put("quoteUrl", tag["href"])
else
data
end
end
def fix_quote_url(data), do: data
# https://codeberg.org/fediverse/fep/src/branch/main/fep/e232/fep-e232.md
def is_object_link_tag(%{
"type" => "Link",
"mediaType" => media_type,
"href" => href
})
when media_type in Pleroma.Constants.activity_json_mime_types() and is_binary(href) do
true
end
def is_object_link_tag(_), do: false
end

View File

@ -5,8 +5,10 @@
defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
use Ecto.Schema
alias Pleroma.Emoji
alias Pleroma.Object
alias Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes
alias Pleroma.Web.ActivityPub.ObjectValidators.TagValidator
import Ecto.Changeset
import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
@ -19,6 +21,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
import Elixir.Pleroma.Web.ActivityPub.ObjectValidators.CommonFields
message_fields()
activity_fields()
embeds_many(:tag, TagValidator)
end
end
@ -43,7 +46,8 @@ def cast_data(data) do
def changeset(struct, data) do
struct
|> cast(data, __schema__(:fields))
|> cast(data, __schema__(:fields) -- [:tag])
|> cast_embed(:tag)
end
defp fix(data) do
@ -53,12 +57,16 @@ defp fix(data) do
|> CommonFixes.fix_actor()
|> CommonFixes.fix_activity_addressing()
with %Object{} = object <- Object.normalize(data["object"]) do
data
|> CommonFixes.fix_activity_context(object)
|> CommonFixes.fix_object_action_recipients(object)
else
_ -> data
data = Map.put_new(data, "tag", [])
case Object.normalize(data["object"]) do
%Object{} = object ->
data
|> CommonFixes.fix_activity_context(object)
|> CommonFixes.fix_object_action_recipients(object)
_ ->
data
end
end
@ -82,11 +90,31 @@ defp fix_emoji_qualification(data), do: data
defp validate_emoji(cng) do
content = get_field(cng, :content)
if Pleroma.Emoji.is_unicode_emoji?(content) do
if Emoji.is_unicode_emoji?(content) || Emoji.is_custom_emoji?(content) do
cng
else
cng
|> add_error(:content, "must be a single character emoji")
|> add_error(:content, "is not a valid emoji")
end
end
defp maybe_validate_tag_presence(cng) do
content = get_field(cng, :content)
if Emoji.is_unicode_emoji?(content) do
cng
else
tag = get_field(cng, :tag)
emoji_name = Emoji.maybe_strip_name(content)
case tag do
[%{name: ^emoji_name, type: "Emoji", icon: %{url: _}}] ->
cng
_ ->
cng
|> add_error(:tag, "does not contain an Emoji tag")
end
end
end
@ -97,5 +125,6 @@ defp validate_data(data_cng) do
|> validate_actor_presence()
|> validate_object_presence()
|> validate_emoji()
|> maybe_validate_tag_presence()
end
end

View File

@ -62,6 +62,7 @@ defp fix(data) do
data
|> CommonFixes.fix_actor()
|> CommonFixes.fix_object_defaults()
|> CommonFixes.fix_quote_url()
|> Transmogrifier.fix_emoji()
|> fix_closed()
end

View File

@ -9,15 +9,20 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do
import Ecto.Changeset
require Pleroma.Constants
@primary_key false
embedded_schema do
# Common
field(:type, :string)
field(:name, :string)
# Mention, Hashtag
# Mention, Hashtag, Link
field(:href, ObjectValidators.Uri)
# Link
field(:mediaType, :string)
# Emoji
embeds_one :icon, IconObjectValidator, primary_key: false do
field(:type, :string)
@ -68,6 +73,19 @@ def changeset(struct, %{"type" => "Emoji"} = data) do
|> validate_required([:type, :name, :icon])
end
def changeset(struct, %{"type" => "Link"} = data) do
struct
|> cast(data, [:type, :name, :mediaType, :href])
|> validate_inclusion(:mediaType, Pleroma.Constants.activity_json_mime_types())
|> validate_required([:type, :href, :mediaType])
end
def changeset(struct, %{"type" => _} = data) do
struct
|> cast(data, [])
|> Map.put(:action, :ignore)
end
def icon_changeset(struct, data) do
struct
|> cast(data, [:type, :url])

View File

@ -199,7 +199,6 @@ def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
inboxes =
recipients
|> Enum.filter(&User.ap_enabled?/1)
|> Enum.map(fn actor -> actor.inbox end)
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
|> Instances.filter_reachable()
@ -241,7 +240,6 @@ def publish(%User{} = actor, %Activity{} = activity) do
json = Jason.encode!(data)
recipients(actor, activity)
|> Enum.filter(fn user -> User.ap_enabled?(user) end)
|> Enum.map(fn %User{} = user ->
determine_inbox(activity, user)
end)

View File

@ -428,37 +428,13 @@ defp handle_update_object(
end
if orig_object_data["type"] in Pleroma.Constants.updatable_object_types() do
%{
updated_data: updated_object_data,
updated: updated,
used_history_in_new_object?: used_history_in_new_object?
} = Object.Updater.make_new_object_data_from_update_object(orig_object_data, updated_object)
{:ok, _, updated} =
Object.Updater.do_update_and_invalidate_cache(orig_object, updated_object)
changeset =
orig_object
|> Repo.preload(:hashtags)
|> Object.change(%{data: updated_object_data})
with {:ok, new_object} <- Repo.update(changeset),
{:ok, _} <- Object.invalid_object_cache(new_object),
{:ok, _} <- Object.set_cache(new_object),
# The metadata/utils.ex uses the object id for the cache.
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(new_object.id) do
if used_history_in_new_object? do
with create_activity when not is_nil(create_activity) <-
Pleroma.Activity.get_create_by_object_ap_id(orig_object_ap_id),
{:ok, _} <- Pleroma.Activity.HTML.invalidate_cache_for(create_activity.id) do
nil
else
_ -> nil
end
end
if updated do
object
|> Activity.normalize()
|> ActivityPub.notify_and_stream()
end
if updated do
object
|> Activity.normalize()
|> ActivityPub.notify_and_stream()
end
end
@ -520,7 +496,7 @@ def handle_object_creation(%{"type" => "Answer"} = object_map, _activity, meta)
end
def handle_object_creation(%{"type" => objtype} = object, _activity, meta)
when objtype in ~w[Audio Video Event Article Note Page] do
when objtype in ~w[Audio Video Image Event Article Note Page] do
with {:ok, object, meta} <- Pipeline.common_pipeline(object, meta) do
{:ok, object, meta}
end

View File

@ -20,7 +20,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.Web.Federator
alias Pleroma.Workers.TransmogrifierWorker
import Ecto.Query
@ -167,6 +166,27 @@ def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object, options)
def fix_in_reply_to(object, _options), do: object
def fix_quote_url_and_maybe_fetch(object, options \\ []) do
quote_url =
case Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes.fix_quote_url(object) do
%{"quoteUrl" => quote_url} -> quote_url
_ -> nil
end
with {:quoting?, true} <- {:quoting?, not is_nil(quote_url)},
{:ok, quoted_object} <- get_obj_helper(quote_url, options),
%Activity{} <- Activity.get_create_by_object_ap_id(quoted_object.data["id"]) do
Map.put(object, "quoteUrl", quoted_object.data["id"])
else
{:quoting?, _} ->
object
e ->
Logger.warn("Couldn't fetch #{inspect(quote_url)}, error: #{inspect(e)}")
object
end
end
defp prepare_in_reply_to(in_reply_to) do
cond do
is_bitstring(in_reply_to) ->
@ -447,7 +467,7 @@ def handle_incoming(
%{"type" => "Create", "object" => %{"type" => objtype, "id" => obj_id}} = data,
options
)
when objtype in ~w{Question Answer ChatMessage Audio Video Event Article Note Page} do
when objtype in ~w{Question Answer ChatMessage Audio Video Event Article Note Page Image} do
fetch_options = Keyword.put(options, :depth, (options[:depth] || 0) + 1)
object =
@ -455,6 +475,7 @@ def handle_incoming(
|> strip_internal_fields()
|> fix_type(fetch_options)
|> fix_in_reply_to(fetch_options)
|> fix_quote_url_and_maybe_fetch(fetch_options)
data = Map.put(data, "object", object)
options = Keyword.put(options, :local, false)
@ -629,6 +650,16 @@ def set_reply_to_uri(%{"inReplyTo" => in_reply_to} = object) when is_binary(in_r
def set_reply_to_uri(obj), do: obj
@doc """
Fedibird compatibility
https://github.com/fedibird/mastodon/commit/dbd7ae6cf58a92ec67c512296b4daaea0d01e6ac
"""
def set_quote_url(%{"quoteUrl" => quote_url} = object) when is_binary(quote_url) do
Map.put(object, "quoteUri", quote_url)
end
def set_quote_url(obj), do: obj
@doc """
Serialized Mastodon-compatible `replies` collection containing _self-replies_.
Based on Mastodon's ActivityPub::NoteSerializer#replies.
@ -683,6 +714,7 @@ def prepare_object(object) do
|> prepare_attachments
|> set_conversation
|> set_reply_to_uri
|> set_quote_url
|> set_replies
|> strip_internal_fields
|> strip_internal_tags
@ -946,47 +978,6 @@ defp strip_internal_tags(%{"tag" => tags} = object) do
defp strip_internal_tags(object), do: object
def perform(:user_upgrade, user) do
# we pass a fake user so that the followers collection is stripped away
old_follower_address = User.ap_followers(%User{nickname: user.nickname})
from(
a in Activity,
where: ^old_follower_address in a.recipients,
update: [
set: [
recipients:
fragment(
"array_replace(?,?,?)",
a.recipients,
^old_follower_address,
^user.follower_address
)
]
]
)
|> Repo.update_all([])
end
def upgrade_user_from_ap_id(ap_id) do
with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id),
{:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id),
{:ok, user} <- update_user(user, data) do
{:ok, _pid} = Task.start(fn -> ActivityPub.pinned_fetch_task(user) end)
TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id})
{:ok, user}
else
%User{} = user -> {:ok, user}
e -> e
end
end
defp update_user(user, data) do
user
|> User.remote_user_changeset(data)
|> User.update_and_set_cache()
end
def maybe_fix_user_url(%{"url" => url} = data) when is_map(url) do
Map.put(data, "url", url["href"])
end

View File

@ -31,7 +31,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do
"Page",
"Question",
"Answer",
"Audio"
"Audio",
"Image"
]
@strip_status_report_states ~w(closed resolved)
@supported_report_states ~w(open closed resolved)
@ -325,21 +326,29 @@ def update_element_in_object(property, element, object, count \\ nil) do
{:ok, Object.t()} | {:error, Ecto.Changeset.t()}
def add_emoji_reaction_to_object(
%Activity{data: %{"content" => emoji, "actor" => actor}},
%Activity{data: %{"content" => emoji, "actor" => actor}} = activity,
object
) do
reactions = get_cached_emoji_reactions(object)
emoji = Pleroma.Emoji.maybe_strip_name(emoji)
url = maybe_emoji_url(emoji, activity)
new_reactions =
case Enum.find_index(reactions, fn [candidate, _] -> emoji == candidate end) do
case Enum.find_index(reactions, fn [candidate, _, candidate_url] ->
if is_nil(candidate_url) do
emoji == candidate
else
url == candidate_url
end
end) do
nil ->
reactions ++ [[emoji, [actor]]]
reactions ++ [[emoji, [actor], url]]
index ->
List.update_at(
reactions,
index,
fn [emoji, users] -> [emoji, Enum.uniq([actor | users])] end
fn [emoji, users, url] -> [emoji, Enum.uniq([actor | users]), url] end
)
end
@ -348,18 +357,40 @@ def add_emoji_reaction_to_object(
update_element_in_object("reaction", new_reactions, object, count)
end
defp maybe_emoji_url(
name,
%Activity{
data: %{
"tag" => [
%{"type" => "Emoji", "name" => name, "icon" => %{"url" => url}}
]
}
}
),
do: url
defp maybe_emoji_url(_, _), do: nil
def emoji_count(reactions_list) do
Enum.reduce(reactions_list, 0, fn [_, users], acc -> acc + length(users) end)
Enum.reduce(reactions_list, 0, fn [_, users, _], acc -> acc + length(users) end)
end
def remove_emoji_reaction_from_object(
%Activity{data: %{"content" => emoji, "actor" => actor}},
%Activity{data: %{"content" => emoji, "actor" => actor}} = activity,
object
) do
emoji = Pleroma.Emoji.maybe_strip_name(emoji)
reactions = get_cached_emoji_reactions(object)
url = maybe_emoji_url(emoji, activity)
new_reactions =
case Enum.find_index(reactions, fn [candidate, _] -> emoji == candidate end) do
case Enum.find_index(reactions, fn [candidate, _, candidate_url] ->
if is_nil(candidate_url) do
emoji == candidate
else
url == candidate_url
end
end) do
nil ->
reactions
@ -367,9 +398,9 @@ def remove_emoji_reaction_from_object(
List.update_at(
reactions,
index,
fn [emoji, users] -> [emoji, List.delete(users, actor)] end
fn [emoji, users, url] -> [emoji, List.delete(users, actor), url] end
)
|> Enum.reject(fn [_, users] -> Enum.empty?(users) end)
|> Enum.reject(fn [_, users, _] -> Enum.empty?(users) end)
end
count = emoji_count(new_reactions)
@ -377,11 +408,7 @@ def remove_emoji_reaction_from_object(
end
def get_cached_emoji_reactions(object) do
if is_list(object.data["reactions"]) do
object.data["reactions"]
else
[]
end
Object.get_emoji_reactions(object)
end
@spec add_like_to_object(Activity.t(), Object.t()) ::
@ -489,17 +516,37 @@ def fetch_latest_undo(%User{ap_id: ap_id}) do
def get_latest_reaction(internal_activity_id, %{ap_id: ap_id}, emoji) do
%{data: %{"object" => object_ap_id}} = Activity.get_by_id(internal_activity_id)
emoji = Pleroma.Emoji.maybe_quote(emoji)
"EmojiReact"
|> Activity.Queries.by_type()
|> where(actor: ^ap_id)
|> where([activity], fragment("?->>'content' = ?", activity.data, ^emoji))
|> custom_emoji_discriminator(emoji)
|> Activity.Queries.by_object_id(object_ap_id)
|> order_by([activity], fragment("? desc nulls last", activity.id))
|> limit(1)
|> Repo.one()
end
defp custom_emoji_discriminator(query, emoji) do
if String.contains?(emoji, "@") do
stripped = Pleroma.Emoji.maybe_strip_name(emoji)
[name, domain] = String.split(stripped, "@")
domain_pattern = "%/" <> domain <> "/%"
emoji_pattern = Pleroma.Emoji.maybe_quote(name)
query
|> where([activity], fragment("?->>'content' = ?
AND EXISTS (
SELECT FROM jsonb_array_elements(?->'tag') elem
WHERE elem->>'id' ILIKE ?
)", activity.data, ^emoji_pattern, activity.data, ^domain_pattern))
else
query
|> where([activity], fragment("?->>'content' = ?", activity.data, ^emoji))
end
end
#### Announce-related helpers
@doc """

View File

@ -18,13 +18,24 @@ defmodule Pleroma.Web.AdminAPI.FrontendController do
def index(conn, _params) do
installed = installed()
# FIrst get frontends from config,
# then add frontends that are installed but not in the config
frontends =
[:frontends, :available]
|> Config.get([])
Config.get([:frontends, :available], [])
|> Enum.map(fn {name, desc} ->
Map.put(desc, "installed", name in installed)
desc
|> Map.put("installed", name in installed)
|> Map.put("installed_refs", installed_refs(name))
end)
frontends =
frontends ++
(installed
|> Enum.filter(fn n -> not Enum.any?(frontends, fn f -> f["name"] == n end) end)
|> Enum.map(fn name ->
%{"name" => name, "installed" => true, "installed_refs" => installed_refs(name)}
end))
render(conn, "index.json", frontends: frontends)
end
@ -43,4 +54,12 @@ defp installed do
[]
end
end
def installed_refs(name) do
if name in installed() do
File.ls!(Path.join(Pleroma.Frontend.dir(), name))
else
[]
end
end
end

View File

@ -31,7 +31,7 @@ def extract_report_info(
defp make_fake_activity(act, user) do
%Activity{
id: "pleroma:fake",
id: "pleroma:fake:#{act["id"]}",
data: %{
"actor" => user.ap_id,
"type" => "Create",

View File

@ -15,7 +15,8 @@ def render("show.json", %{frontend: frontend}) do
git: frontend["git"],
build_url: frontend["build_url"],
ref: frontend["ref"],
installed: frontend["installed"]
installed: frontend["installed"],
installed_refs: frontend["installed_refs"]
}
end
end

View File

@ -10,6 +10,14 @@ defmodule Pleroma.Web.ApiSpec do
@behaviour OpenApi
defp streaming_paths do
%{
"/api/v1/streaming" => %OpenApiSpex.PathItem{
get: Pleroma.Web.ApiSpec.StreamingOperation.streaming_operation()
}
}
end
@impl OpenApi
def spec(opts \\ []) do
%OpenApi{
@ -45,7 +53,7 @@ def spec(opts \\ []) do
}
},
# populate the paths from a phoenix router
paths: OpenApiSpex.Paths.from_router(Router),
paths: Map.merge(streaming_paths(), OpenApiSpex.Paths.from_router(Router)),
components: %OpenApiSpex.Components{
parameters: %{
"accountIdOrNickname" =>
@ -95,7 +103,8 @@ def spec(opts \\ []) do
"Relays",
"Report managment",
"Status administration",
"User administration"
"User administration",
"Announcement management"
]
},
%{"name" => "Applications", "tags" => ["Applications", "Push subscriptions"]},
@ -110,10 +119,12 @@ def spec(opts \\ []) do
"Follow requests",
"Mascot",
"Markers",
"Notifications"
"Notifications",
"Filters",
"Settings"
]
},
%{"name" => "Instance", "tags" => ["Custom emojis"]},
%{"name" => "Instance", "tags" => ["Custom emojis", "Instance misc"]},
%{"name" => "Messaging", "tags" => ["Chats", "Conversations"]},
%{
"name" => "Statuses",
@ -125,10 +136,21 @@ def spec(opts \\ []) do
"Retrieve status information",
"Scheduled statuses",
"Search",
"Status actions"
"Status actions",
"Media attachments"
]
},
%{"name" => "Miscellaneous", "tags" => ["Emoji packs", "Reports", "Suggestions"]}
%{
"name" => "Miscellaneous",
"tags" => [
"Emoji packs",
"Reports",
"Suggestions",
"Announcements",
"Remote interaction",
"Others"
]
}
]
}
}

View File

@ -452,7 +452,7 @@ def blocks_operation do
operationId: "AccountController.blocks",
description: "View your blocks. See also accounts/:id/{block,unblock}",
security: [%{"oAuth" => ["read:blocks"]}],
parameters: pagination_params(),
parameters: [with_relationships_param() | pagination_params()],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
}
@ -461,7 +461,7 @@ def blocks_operation do
def lookup_operation do
%Operation{
tags: ["Account lookup"],
tags: ["Retrieve account information"],
summary: "Find a user by nickname",
operationId: "AccountController.lookup",
parameters: [

View File

@ -17,7 +17,7 @@ def open_api_operation(action) do
def index_operation do
%Operation{
tags: ["Announcement managment"],
tags: ["Announcement management"],
summary: "Retrieve a list of announcements",
operationId: "AdminAPI.AnnouncementController.index",
security: [%{"oAuth" => ["admin:read"]}],
@ -46,7 +46,7 @@ def index_operation do
def show_operation do
%Operation{
tags: ["Announcement managment"],
tags: ["Announcement management"],
summary: "Display one announcement",
operationId: "AdminAPI.AnnouncementController.show",
security: [%{"oAuth" => ["admin:read"]}],
@ -69,7 +69,7 @@ def show_operation do
def delete_operation do
%Operation{
tags: ["Announcement managment"],
tags: ["Announcement management"],
summary: "Delete one announcement",
operationId: "AdminAPI.AnnouncementController.delete",
security: [%{"oAuth" => ["admin:write"]}],
@ -92,7 +92,7 @@ def delete_operation do
def create_operation do
%Operation{
tags: ["Announcement managment"],
tags: ["Announcement management"],
summary: "Create one announcement",
operationId: "AdminAPI.AnnouncementController.create",
security: [%{"oAuth" => ["admin:write"]}],
@ -107,7 +107,7 @@ def create_operation do
def change_operation do
%Operation{
tags: ["Announcement managment"],
tags: ["Announcement management"],
summary: "Change one announcement",
operationId: "AdminAPI.AnnouncementController.change",
security: [%{"oAuth" => ["admin:write"]}],

View File

@ -51,8 +51,9 @@ defp list_of_frontends do
name: %Schema{type: :string},
git: %Schema{type: :string, format: :uri, nullable: true},
build_url: %Schema{type: :string, format: :uri, nullable: true},
ref: %Schema{type: :string},
installed: %Schema{type: :boolean}
ref: %Schema{type: :string, nullable: true},
installed: %Schema{type: :boolean},
installed_refs: %Schema{type: :array, items: %Schema{type: :string}}
}
}
}

View File

@ -70,7 +70,7 @@ def index_operation do
def show_operation do
%Operation{
tags: ["Status adminitration)"],
tags: ["Status administration"],
summary: "Get status",
operationId: "AdminAPI.StatusController.show",
parameters: [id_param() | admin_api_params()],
@ -84,7 +84,7 @@ def show_operation do
def update_operation do
%Operation{
tags: ["Status adminitration)"],
tags: ["Status administration"],
summary: "Change the scope of a status",
operationId: "AdminAPI.StatusController.update",
parameters: [id_param() | admin_api_params()],
@ -99,7 +99,7 @@ def update_operation do
def delete_operation do
%Operation{
tags: ["Status adminitration)"],
tags: ["Status administration"],
summary: "Delete status",
operationId: "AdminAPI.StatusController.delete",
parameters: [id_param() | admin_api_params()],
@ -143,7 +143,7 @@ def admin_account do
}
},
tags: %Schema{type: :string},
is_confirmed: %Schema{type: :string}
is_confirmed: %Schema{type: :boolean}
}
}
end

View File

@ -15,7 +15,7 @@ def open_api_operation(action) do
def index_operation do
%Operation{
tags: ["Announcement"],
tags: ["Announcements"],
summary: "Retrieve a list of announcements",
operationId: "MastodonAPI.AnnouncementController.index",
security: [%{"oAuth" => []}],
@ -28,7 +28,7 @@ def index_operation do
def mark_read_operation do
%Operation{
tags: ["Announcement"],
tags: ["Announcements"],
summary: "Mark one announcement as read",
operationId: "MastodonAPI.AnnouncementController.mark_read",
security: [%{"oAuth" => ["write:accounts"]}],

View File

@ -17,7 +17,7 @@ def open_api_operation(action) do
def index_operation do
%Operation{
tags: ["Directory"],
tags: ["Others"],
summary: "Profile directory",
operationId: "DirectoryController.index",
parameters:

View File

@ -13,7 +13,7 @@ def open_api_operation(action) do
def show_operation do
%Operation{
tags: ["Instance"],
tags: ["Instance misc"],
summary: "Retrieve instance information",
description: "Information about the server",
operationId: "InstanceController.show",
@ -25,7 +25,7 @@ def show_operation do
def peers_operation do
%Operation{
tags: ["Instance"],
tags: ["Instance misc"],
summary: "Retrieve list of known instances",
operationId: "InstanceController.peers",
responses: %{

View File

@ -64,7 +64,13 @@ defp backup do
content_type: %Schema{type: :string},
file_name: %Schema{type: :string},
file_size: %Schema{type: :integer},
processed: %Schema{type: :boolean}
processed: %Schema{type: :boolean, description: "whether this backup has succeeded"},
state: %Schema{
type: :string,
description: "the state of the backup",
enum: ["pending", "running", "complete", "failed"]
},
processed_number: %Schema{type: :integer, description: "the number of records processed"}
},
example: %{
"content_type" => "application/zip",
@ -72,7 +78,9 @@ defp backup do
"https://cofe.fe:4000/media/backups/archive-foobar-20200908T164207-Yr7vuT5Wycv-sN3kSN2iJ0k-9pMo60j9qmvRCdDqIew.zip",
"file_size" => 4105,
"inserted_at" => "2020-09-08T16:42:07.000Z",
"processed" => true
"processed" => true,
"state" => "complete",
"processed_number" => 20
}
}
end

View File

@ -133,7 +133,11 @@ defp name_param do
defp files_object do
%Schema{
type: :object,
additionalProperties: %Schema{type: :string},
additionalProperties: %Schema{
type: :string,
description: "Filename of the emoji",
extensions: %{"x-additionalPropertiesName": "Emoji name"}
},
description: "Object with emoji names as keys and filenames as values"
}
end

View File

@ -227,13 +227,29 @@ defp ok_response do
defp emoji_packs_response do
Operation.response(
"Object with pack names as keys and pack contents as values",
"Emoji packs and the count",
"application/json",
%Schema{
type: :object,
additionalProperties: emoji_pack(),
properties: %{
packs: %Schema{
type: :object,
description: "Object with pack names as keys and pack contents as values",
additionalProperties: %Schema{
emoji_pack()
| extensions: %{"x-additionalPropertiesName": "Pack name"}
}
},
count: %Schema{
type: :integer,
description: "Number of emoji packs"
}
},
example: %{
"emojos" => emoji_pack().example
"packs" => %{
"emojos" => emoji_pack().example
},
"count" => 1
}
}
)
@ -274,7 +290,11 @@ defp emoji_pack do
defp files_object do
%Schema{
type: :object,
additionalProperties: %Schema{type: :string},
additionalProperties: %Schema{
type: :string,
description: "Filename",
extensions: %{"x-additionalPropertiesName": "Emoji name"}
},
description: "Object with emoji names as keys and filenames as values"
}
end

View File

@ -13,7 +13,7 @@ def open_api_operation(action) do
def show_operation do
%Operation{
tags: ["Instance"],
tags: ["Instance misc"],
summary: "Retrieve federation status",
description: "Information about instances deemed unreachable by the server",
operationId: "PleromaInstances.show",

View File

@ -22,6 +22,7 @@ def create_operation do
summary: "Creates a new Listen activity for an account",
security: [%{"oAuth" => ["write"]}],
operationId: "PleromaAPI.ScrobbleController.create",
deprecated: true,
requestBody: request_body("Parameters", create_request(), requried: true),
responses: %{
200 => Operation.response("Scrobble", "application/json", scrobble())
@ -34,6 +35,7 @@ def index_operation do
tags: ["Scrobbles"],
summary: "Requests a list of current and recent Listen activities for an account",
operationId: "PleromaAPI.ScrobbleController.index",
deprecated: true,
parameters: [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"} | pagination_params()
],

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