logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/
commit: 250a4873a6f50f71cb5c387de46d711dc1bd1a39
parent 51aef6b78dcf709872de32a02533e943f08858d4
Author: marcin mikołajczak <me@mkljczk.pl>
Date:   Fri, 19 Jan 2024 16:36:37 +0000

Merge branch 'develop' into 'post-languages'

# Conflicts:
#   lib/pleroma/web/activity_pub/transmogrifier.ex
#   test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs

Diffstat:

MCHANGELOG.md12++++++------
Achangelog.d/account-rendering-auth-check.fix1+
Achangelog.d/api-docs.skip0
Achangelog.d/chat-attachment-empty-array.fix1+
Achangelog.d/emoji-download-paginate.fix2++
Achangelog.d/emoji-use-v1.fix2++
Achangelog.d/federator-modules.remove1+
Achangelog.d/federator.skip0
Achangelog.d/finch_redirects.fix1+
Achangelog.d/fix-duplicate-inbox-deliveries.fix0
Achangelog.d/group-actor.add1+
Achangelog.d/instance-defdelegates.skip0
Achangelog.d/local-webfinger.fix2++
Achangelog.d/mrf-regex-error.fix1+
Achangelog.d/mrf-steal-emoji-extname.fix1+
Achangelog.d/nil-content-map.fix1+
Achangelog.d/otp26.add1+
Achangelog.d/publisher_discard.change1+
Achangelog.d/publisher_log.change1+
Achangelog.d/qtfaststart.fix1+
Achangelog.d/typo.skip0
Mconfig/config.exs3---
Mconfig/description.exs6+++---
Mdocs/administration/CLI_tasks/config.md4++--
Mdocs/administration/backup.md2+-
Mdocs/configuration/cheatsheet.md8++++----
Mdocs/configuration/custom_emoji.md2+-
Mdocs/configuration/i2p.md2+-
Mdocs/configuration/onion_federation.md2+-
Mdocs/configuration/optimizing_beam.md2+-
Mdocs/configuration/postgresql.md2+-
Mdocs/configuration/search.md4++--
Mdocs/development/API/admin_api.md10+++++-----
Mdocs/development/API/differences_in_mastoapi_responses.md13+++++++++++--
Mdocs/development/API/pleroma_api.md30++++++++++++++++++++++++++++--
Mdocs/development/ap_extensions.md6+++---
Mdocs/development/setting_up_pleroma_dev.md2+-
Mdocs/installation/generic_dependencies.include2+-
Mdocs/installation/gentoo_en.md4++--
Mdocs/installation/gentoo_otp_en.md2+-
Mdocs/installation/openbsd_en.md4++--
Mdocs/installation/otp_en.md2+-
Minstallation/pleroma-mongooseim.cfg6+++---
Mlib/mix/tasks/pleroma/database.ex2+-
Mlib/mix/tasks/pleroma/digest.ex2+-
Mlib/mix/tasks/pleroma/ecto/rollback.ex2+-
Mlib/mix/tasks/pleroma/instance.ex2+-
Mlib/pleroma/captcha/kocaptcha.ex2+-
Mlib/pleroma/config/deprecation_warnings.ex8++++----
Mlib/pleroma/constants.ex8++++++++
Mlib/pleroma/docs/generator.ex2+-
Mlib/pleroma/emoji/pack.ex12+++++++++---
Mlib/pleroma/helpers/qt_fast_start.ex25+++++++++++++++----------
Mlib/pleroma/http.ex4++++
Mlib/pleroma/instances.ex11+++++------
Mlib/pleroma/search/search_backend.ex2+-
Mlib/pleroma/user.ex5+++--
Mlib/pleroma/user/query.ex2+-
Mlib/pleroma/web/activity_pub/activity_pub.ex1+
Mlib/pleroma/web/activity_pub/mrf.ex13+++++++++++--
Mlib/pleroma/web/activity_pub/mrf/hashtag_policy.ex2+-
Mlib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex4+++-
Mlib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex5+++++
Mlib/pleroma/web/activity_pub/publisher.ex76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mlib/pleroma/web/activity_pub/side_effects.ex2++
Mlib/pleroma/web/activity_pub/utils.ex23+++++++++++++++++++++++
Mlib/pleroma/web/api_spec.ex8++++----
Mlib/pleroma/web/api_spec/operations/account_operation.ex2+-
Mlib/pleroma/web/api_spec/operations/admin/frontend_operation.ex4++--
Mlib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex8++++----
Mlib/pleroma/web/api_spec/operations/admin/report_operation.ex10+++++-----
Mlib/pleroma/web/api_spec/operations/instance_operation.ex4++--
Mlib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex2+-
Mlib/pleroma/web/api_spec/operations/status_operation.ex4++--
Mlib/pleroma/web/api_spec/operations/twitter_util_operation.ex6+++---
Mlib/pleroma/web/api_spec/schemas/attachment.ex2+-
Mlib/pleroma/web/federator.ex8+++-----
Dlib/pleroma/web/federator/publisher.ex110-------------------------------------------------------------------------------
Mlib/pleroma/web/mastodon_api/controllers/account_controller.ex2+-
Mlib/pleroma/web/mastodon_api/views/account_view.ex16+++++++++++++---
Mlib/pleroma/web/mastodon_api/views/instance_view.ex5++++-
Mlib/pleroma/web/nodeinfo/nodeinfo.ex2+-
Mlib/pleroma/web/o_auth/o_auth_controller.ex2+-
Mlib/pleroma/web/plugs/cache.ex2+-
Mlib/pleroma/web/plugs/uploaded_media.ex2+-
Mlib/pleroma/web/router.ex4++--
Mlib/pleroma/web/streamer.ex2+-
Mlib/pleroma/web/twitter_api/controllers/password_controller.ex2+-
Mlib/pleroma/web/twitter_api/controllers/util_controller.ex4++--
Mlib/pleroma/web/web_finger.ex2+-
Mlib/pleroma/web/web_finger/web_finger_controller.ex2+-
Mlib/pleroma/workers/publisher_worker.ex4++--
Mmix.exs4++--
Mmix.lock4++--
Mtest/mix/pleroma_test.exs2+-
Mtest/mix/tasks/pleroma/config_test.exs5++---
Mtest/mix/tasks/pleroma/ecto/rollback_test.exs2+-
Mtest/mix/tasks/pleroma/robots_txt_test.exs2+-
Mtest/pleroma/activity_test.exs1+
Mtest/pleroma/config/deprecation_warnings_test.exs11+++++------
Mtest/pleroma/config_db_test.exs4++--
Mtest/pleroma/conversation/participation_test.exs2+-
Mtest/pleroma/emoji/loader_test.exs2+-
Mtest/pleroma/formatter_test.exs4++--
Mtest/pleroma/healthcheck_test.exs8+++++---
Mtest/pleroma/http/adapter_helper/gun_test.exs4++--
Mtest/pleroma/mfa/totp_test.exs6+++++-
Mtest/pleroma/otp_version_test.exs2+-
Mtest/pleroma/repo/migrations/autolinker_to_linkify_test.exs6+++---
Mtest/pleroma/repo/migrations/fix_malformed_formatter_config_test.exs4++--
Mtest/pleroma/reverse_proxy_test.exs2+-
Mtest/pleroma/user_test.exs36+++++++++++++++++++++++-------------
Mtest/pleroma/web/activity_pub/activity_pub_test.exs2+-
Mtest/pleroma/web/activity_pub/mrf/ensure_re_prepended_test.exs2+-
Mtest/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs27+++++++++++++++++++++++++++
Mtest/pleroma/web/activity_pub/mrf_test.exs13++++++++++++-
Mtest/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs2+-
Mtest/pleroma/web/activity_pub/object_validators/chat_validation_test.exs15+++++++++++++++
Mtest/pleroma/web/activity_pub/publisher_test.exs29+++++++++++++----------------
Mtest/pleroma/web/activity_pub/side_effects_test.exs89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs15++++++++++++++-
Mtest/pleroma/web/activity_pub/transmogrifier/undo_handling_test.exs2+-
Mtest/pleroma/web/activity_pub/utils_test.exs6+++---
Mtest/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs2+-
Mtest/pleroma/web/common_api_test.exs57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/pleroma/web/federator_test.exs38++++++++++++++++++++++++++++++++++++++
Mtest/pleroma/web/mastodon_api/controllers/account_controller_test.exs6+++---
Mtest/pleroma/web/mastodon_api/controllers/search_controller_test.exs1+
Mtest/pleroma/web/mastodon_api/controllers/status_controller_test.exs6+++++-
Mtest/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs15+++++++++------
Mtest/pleroma/web/mastodon_api/update_credentials_test.exs16++++++++++++++++
Mtest/pleroma/web/o_auth/mfa_controller_test.exs2+-
Mtest/pleroma/web/o_auth/token/utils_test.exs4++--
Mtest/pleroma/web/pleroma_api/controllers/chat_controller_test.exs50+++++++++++++++++++++++++++++++++++++++-----------
Mtest/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs16+++++++++-------
Mtest/pleroma/web/pleroma_api/controllers/instances_controller_test.exs2+-
Mtest/pleroma/web/web_finger/web_finger_controller_test.exs25++++++++++---------------
Mtest/support/helpers.ex33+++++++++++++++++++++++++++++++++
Mtest/support/http_request_mock.ex4++--
Mtest/test_helper.exs6++++++
140 files changed, 800 insertions(+), 378 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -62,7 +62,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 2.5.4 ## Security -- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem +- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem ## 2.5.3 @@ -78,7 +78,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 2.5.4 ## Security -- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitary files from the server's filesystem +- Fix XML External Entity (XXE) loading vulnerability allowing to fetch arbitrary files from the server's filesystem ## 2.5.3 @@ -118,7 +118,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix `block_from_stranger` setting - Fix rel="me" - Docker images will now run properly -- Fix inproper content being cached in report content +- Fix improper 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 @@ -784,7 +784,7 @@ switched to a new configuration mechanism, however it was not officially removed - Rate limiter crashes when there is no explicitly specified ip in the config - 500 errors when no `Accept` header is present if Static-FE is enabled - Instance panel not being updated immediately due to wrong `Cache-Control` headers -- Statuses posted with BBCode/Markdown having unncessary newlines in Pleroma-FE +- Statuses posted with BBCode/Markdown having unnecessary newlines in Pleroma-FE - OTP: Fix some settings not being migrated to in-database config properly - No `Cache-Control` headers on attachment/media proxy requests - Character limit enforcement being off by 1 @@ -1104,10 +1104,10 @@ curl -Lo ./bin/pleroma_ctl 'https://git.pleroma.social/pleroma/pleroma/raw/devel - Reverse Proxy limiting `max_body_length` was incorrectly defined and only checked `Content-Length` headers which may not be sufficient in some circumstances ### Added -- Expiring/ephemeral activites. All activities can have expires_at value set, which controls when they should be deleted automatically. +- Expiring/ephemeral activities. All activities can have expires_at value set, which controls when they should be deleted automatically. - Mastodon API: in post_status, the expires_in parameter lets you set the number of seconds until an activity expires. It must be at least one hour. - Mastodon API: all status JSON responses contain a `pleroma.expires_at` item which states when an activity will expire. The value is only shown to the user who created the activity. To everyone else it's empty. -- Configuration: `ActivityExpiration.enabled` controls whether expired activites will get deleted at the appropriate time. Enabled by default. +- Configuration: `ActivityExpiration.enabled` controls whether expired activities will get deleted at the appropriate time. Enabled by default. - Conversations: Add Pleroma-specific conversation endpoints and status posting extensions. Run the `bump_all_conversations` task again to create the necessary data. - MRF: Support for priming the mediaproxy cache (`Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy`) - MRF: Support for excluding specific domains from Transparency. diff --git a/changelog.d/account-rendering-auth-check.fix b/changelog.d/account-rendering-auth-check.fix @@ -0,0 +1 @@ +Fix authentication check on account rendering when bio is defined diff --git a/changelog.d/api-docs.skip b/changelog.d/api-docs.skip diff --git a/changelog.d/chat-attachment-empty-array.fix b/changelog.d/chat-attachment-empty-array.fix @@ -0,0 +1 @@ +ChatMessage: Tolerate attachment field set to an empty array diff --git a/changelog.d/emoji-download-paginate.fix b/changelog.d/emoji-download-paginate.fix @@ -0,0 +1 @@ +When downloading remote emojis packs, account for pagination +\ No newline at end of file diff --git a/changelog.d/emoji-use-v1.fix b/changelog.d/emoji-use-v1.fix @@ -0,0 +1 @@ +Make remote emoji packs API use specifically the V1 URL. Akkoma does not understand it without V1, and it works either way with normal pleroma, so no reason to not do this +\ No newline at end of file diff --git a/changelog.d/federator-modules.remove b/changelog.d/federator-modules.remove @@ -0,0 +1 @@ +Removed support for multiple federator modules as we only support ActivityPub diff --git a/changelog.d/federator.skip b/changelog.d/federator.skip diff --git a/changelog.d/finch_redirects.fix b/changelog.d/finch_redirects.fix @@ -0,0 +1 @@ +Following HTTP Redirects when the HTTP Adapter is Finch diff --git a/changelog.d/fix-duplicate-inbox-deliveries.fix b/changelog.d/fix-duplicate-inbox-deliveries.fix diff --git a/changelog.d/group-actor.add b/changelog.d/group-actor.add @@ -0,0 +1 @@ +Implement group actors diff --git a/changelog.d/instance-defdelegates.skip b/changelog.d/instance-defdelegates.skip diff --git a/changelog.d/local-webfinger.fix b/changelog.d/local-webfinger.fix @@ -0,0 +1 @@ +Use correct domain for fqn and InstanceView +\ No newline at end of file diff --git a/changelog.d/mrf-regex-error.fix b/changelog.d/mrf-regex-error.fix @@ -0,0 +1 @@ +MRF: Log sensible error for subdomains_regex diff --git a/changelog.d/mrf-steal-emoji-extname.fix b/changelog.d/mrf-steal-emoji-extname.fix @@ -0,0 +1 @@ +MRF.StealEmojiPolicy: Properly add fallback extension to filenames missing one diff --git a/changelog.d/nil-content-map.fix b/changelog.d/nil-content-map.fix @@ -0,0 +1 @@ +Support objects with a null contentMap (firefish) diff --git a/changelog.d/otp26.add b/changelog.d/otp26.add @@ -0,0 +1 @@ +Support for Erlang OTP 26 diff --git a/changelog.d/publisher_discard.change b/changelog.d/publisher_discard.change @@ -0,0 +1 @@ +Activity publishing failures will prevent the job from retrying if the publishing request returns a 403 or 410 diff --git a/changelog.d/publisher_log.change b/changelog.d/publisher_log.change @@ -0,0 +1 @@ +Publisher errors will now emit logs indicating the inbox that was not available for delivery. diff --git a/changelog.d/qtfaststart.fix b/changelog.d/qtfaststart.fix @@ -0,0 +1 @@ +MediaProxy Preview failures prevented when encountering certain video files diff --git a/changelog.d/typo.skip b/changelog.d/typo.skip diff --git a/config/config.exs b/config/config.exs @@ -192,9 +192,6 @@ config :pleroma, :instance, federating: true, federation_incoming_replies_max_depth: 100, federation_reachability_timeout_days: 7, - federation_publisher_modules: [ - Pleroma.Web.ActivityPub.Publisher - ], allow_relay: true, public: true, quarantined_instances: [], diff --git a/config/description.exs b/config/description.exs @@ -1444,7 +1444,7 @@ config :pleroma, :config_description, [ label: "Subject line behavior", type: :string, description: "Allows changing the default behaviour of subject lines in replies. - `email`: copy and preprend re:, as in email, + `email`: copy and prepend re:, as in email, `masto`: copy verbatim, as in Mastodon, `noop`: don't copy the subject.", suggestions: ["email", "masto", "noop"] @@ -3096,7 +3096,7 @@ config :pleroma, :config_description, [ key: :max_waiting, type: :integer, description: - "Maximum number of requests waiting for other requests to finish. After this number is reached, the pool will start returning errrors when a new request is made", + "Maximum number of requests waiting for other requests to finish. After this number is reached, the pool will start returning errors when a new request is made", suggestions: [10] }, %{ @@ -3362,7 +3362,7 @@ config :pleroma, :config_description, [ %{ key: :purge_after_days, type: :integer, - description: "Remove backup achives after N days", + description: "Remove backup archives after N days", suggestions: [30] }, %{ diff --git a/docs/administration/CLI_tasks/config.md b/docs/administration/CLI_tasks/config.md @@ -1,4 +1,4 @@ -# Transfering the config to/from the database +# Transferring the config to/from the database {! backend/administration/CLI_tasks/general_cli_task_info.include !} @@ -34,7 +34,7 @@ Options: -- `<path>` - where to save migrated config. E.g. `--path=/tmp`. If file saved into non standart folder, you must manually copy file into directory where Pleroma can read it. For OTP install path will be `PLEROMA_CONFIG_PATH` or `/etc/pleroma`. For installation from source - `config` directory in the pleroma folder. +- `<path>` - where to save migrated config. E.g. `--path=/tmp`. If file saved into non-standard folder, you must manually copy file into directory where Pleroma can read it. For OTP install path will be `PLEROMA_CONFIG_PATH` or `/etc/pleroma`. For installation from source - `config` directory in the pleroma folder. - `<env>` - environment, for which is migrated config. By default is `prod`. - To delete transferred settings from database optional flag `-d` can be used diff --git a/docs/administration/backup.md b/docs/administration/backup.md @@ -31,7 +31,7 @@ 1. Optionally you can remove the users of your instance. This will trigger delete requests for their accounts and posts. Note that this is 'best effort' and doesn't mean that all traces of your instance will be gone from the fediverse. * You can do this from the admin-FE where you can select all local users and delete the accounts using the *Moderate multiple users* dropdown. - * You can also list local users and delete them individualy using the CLI tasks for [Managing users](./CLI_tasks/user.md). + * You can also list local users and delete them individually using the CLI tasks for [Managing users](./CLI_tasks/user.md). 2. Stop the Pleroma service `systemctl stop pleroma` 3. Disable pleroma from systemd `systemctl disable pleroma` 4. Remove the files and folders you created during installation (see installation guide). This includes the pleroma, nginx and systemd files and folders. diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md @@ -154,7 +154,7 @@ To add configuration to your config file, you can copy it from the base config. * `Pleroma.Web.ActivityPub.MRF.MentionPolicy`: Drops posts mentioning configurable users. (See [`:mrf_mention`](#mrf_mention)). * `Pleroma.Web.ActivityPub.MRF.VocabularyPolicy`: Restricts activities to a configured set of vocabulary. (See [`:mrf_vocabulary`](#mrf_vocabulary)). * `Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy`: Rejects or delists posts based on their age when received. (See [`:mrf_object_age`](#mrf_object_age)). - * `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled delections. + * `Pleroma.Web.ActivityPub.MRF.ActivityExpirationPolicy`: Sets a default expiration on all posts made by users of the local instance. Requires `Pleroma.Workers.PurgeExpiredActivity` to be enabled for processing the scheduled deletions. * `Pleroma.Web.ActivityPub.MRF.ForceBotUnlistedPolicy`: Makes all bot posts to disappear from public timelines. * `Pleroma.Web.ActivityPub.MRF.FollowBotPolicy`: Automatically follows newly discovered users from the specified bot account. Local accounts, locked accounts, and users with "#nobot" in their bio are respected and excluded from being followed. * `Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy`: Drops follow requests from followbots. Users can still allow bots to follow them by first following the bot. @@ -506,7 +506,7 @@ config :pleroma, :rate_limit, Means that: 1. In 60 seconds, 15 authentication attempts can be performed from the same IP address. -2. In 1 second, 10 search requests can be performed from the same IP adress by unauthenticated users, while authenticated users can perform 30 search requests per second. +2. In 1 second, 10 search requests can be performed from the same IP address by unauthenticated users, while authenticated users can perform 30 search requests per second. Supported rate limiters: @@ -1081,7 +1081,7 @@ config :pleroma, Pleroma.Formatter, ## :configurable_from_database -Boolean, enables/disables in-database configuration. Read [Transfering the config to/from the database](../administration/CLI_tasks/config.md) for more information. +Boolean, enables/disables in-database configuration. Read [Transferring the config to/from the database](../administration/CLI_tasks/config.md) for more information. ## :database_config_whitelist @@ -1142,7 +1142,7 @@ Control favicons for instances. !!! note Requires enabled email -* `:purge_after_days` an integer, remove backup achives after N days. +* `:purge_after_days` an integer, remove backup achieves after N days. * `:limit_days` an integer, limit user to export not more often than once per N days. * `:dir` a string with a path to backup temporary directory or `nil` to let Pleroma choose temporary directory in the following order: 1. the directory named by the TMPDIR environment variable diff --git a/docs/configuration/custom_emoji.md b/docs/configuration/custom_emoji.md @@ -29,7 +29,7 @@ foo, /emoji/custom/foo.png The files should be PNG (APNG is okay with `.png` for `image/png` Content-type) and under 50kb for compatibility with mastodon. -Default file extentions and locations for emojis are set in `config.exs`. To use different locations or file-extentions, add the `shortcode_globs` to your secrets file (`prod.secret.exs` or `dev.secret.exs`) and edit it. Note that not all fediverse-software will show emojis with other file extentions: +Default file extensions and locations for emojis are set in `config.exs`. To use different locations or file-extensions, add the `shortcode_globs` to your secrets file (`prod.secret.exs` or `dev.secret.exs`) and edit it. Note that not all fediverse-software will show emojis with other file extensions: ```elixir config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png", "/emoji/custom/**/*.gif"] ``` diff --git a/docs/configuration/i2p.md b/docs/configuration/i2p.md @@ -1,4 +1,4 @@ -# I2P Federation and Accessability +# I2P Federation and Accessibility This guide is going to focus on the Pleroma federation aspect. The actual installation is neatly explained in the official documentation, and more likely to remain up-to-date. It might be added to this guide if there will be a need for that. diff --git a/docs/configuration/onion_federation.md b/docs/configuration/onion_federation.md @@ -29,7 +29,7 @@ HiddenServiceDir /var/lib/tor/pleroma_hidden_service/ HiddenServicePort 80 127.0.0.1:8099 HiddenServiceVersion 3 # Remove if Tor version is below 0.3 ( tor --version ) ``` -Restart Tor to generate an adress: +Restart Tor to generate an address: ``` systemctl restart tor@default.service ``` diff --git a/docs/configuration/optimizing_beam.md b/docs/configuration/optimizing_beam.md @@ -1,6 +1,6 @@ # Optimizing the BEAM -Pleroma is built upon the Erlang/OTP VM known as BEAM. The BEAM VM is highly optimized for latency, but this has drawbacks in environments without dedicated hardware. One of the tricks used by the BEAM VM is [busy waiting](https://en.wikipedia.org/wiki/Busy_waiting). This allows the application to pretend to be busy working so the OS kernel does not pause the application process and switch to another process waiting for the CPU to execute its workload. It does this by spinning for a period of time which inflates the apparent CPU usage of the application so it is immediately ready to execute another task. This can be observed with utilities like **top(1)** which will show consistently high CPU usage for the process. Switching between procesess is a rather expensive operation and also clears CPU caches further affecting latency and performance. The goal of busy waiting is to avoid this penalty. +Pleroma is built upon the Erlang/OTP VM known as BEAM. The BEAM VM is highly optimized for latency, but this has drawbacks in environments without dedicated hardware. One of the tricks used by the BEAM VM is [busy waiting](https://en.wikipedia.org/wiki/Busy_waiting). This allows the application to pretend to be busy working so the OS kernel does not pause the application process and switch to another process waiting for the CPU to execute its workload. It does this by spinning for a period of time which inflates the apparent CPU usage of the application so it is immediately ready to execute another task. This can be observed with utilities like **top(1)** which will show consistently high CPU usage for the process. Switching between processes is a rather expensive operation and also clears CPU caches further affecting latency and performance. The goal of busy waiting is to avoid this penalty. This strategy is very successful in making a performant and responsive application, but is not desirable on Virtual Machines or hardware with few CPU cores. Pleroma instances are often deployed on the same server as the required PostgreSQL database which can lead to situations where the Pleroma application is holding the CPU in a busy-wait loop and as a result the database cannot process requests in a timely manner. The fewer CPUs available, the more this problem is exacerbated. The latency is further amplified by the OS being installed on a Virtual Machine as the Hypervisor uses CPU time-slicing to pause the entire OS and switch between other tasks. diff --git a/docs/configuration/postgresql.md b/docs/configuration/postgresql.md @@ -22,7 +22,7 @@ config :pleroma, Pleroma.Repo, ] ``` -A more detailed explaination of the issue can be found at <https://blog.soykaf.com/post/postgresql-elixir-troubles/>. +A more detailed explanation of the issue can be found at <https://blog.soykaf.com/post/postgresql-elixir-troubles/>. ## Example configurations diff --git a/docs/configuration/search.md b/docs/configuration/search.md @@ -38,7 +38,7 @@ indexes faster when it can process many posts in a single batch. Information about setting up meilisearch can be found in the [official documentation](https://docs.meilisearch.com/learn/getting_started/installation.html). You probably want to start it with `MEILI_NO_ANALYTICS=true` environment variable to disable analytics. -At least version 0.25.0 is required, but you are strongly adviced to use at least 0.26.0, as it introduces +At least version 0.25.0 is required, but you are strongly advised to use at least 0.26.0, as it introduces the `--enable-auto-batching` option which drastically improves performance. Without this option, the search is hardly usable on a somewhat big instance. @@ -61,7 +61,7 @@ You will see a "Default Admin API Key", this is the key you actually put into yo ### Initial indexing -After setting up the configuration, you'll want to index all of your already existsing posts. Only public posts are indexed. You'll only +After setting up the configuration, you'll want to index all of your already existing posts. Only public posts are indexed. You'll only have to do it one time, but it might take a while, depending on the amount of posts your instance has seen. This is also a fairly RAM consuming process for `meilisearch`, and it will take a lot of RAM when running if you have a lot of posts (seems to be around 5G for ~1.2 million posts while idle and up to 7G while indexing initially, but your experience may be different). diff --git a/docs/development/API/admin_api.md b/docs/development/API/admin_api.md @@ -303,7 +303,7 @@ Removes the user(s) from follower recommendations. ## `GET /api/v1/pleroma/admin/users/:nickname_or_id` -### Retrive the details of a user +### Retrieve the details of a user - Params: - `nickname` or `id` @@ -313,7 +313,7 @@ Removes the user(s) from follower recommendations. ## `GET /api/v1/pleroma/admin/users/:nickname_or_id/statuses` -### Retrive user's latest statuses +### Retrieve user's latest statuses - Params: - `nickname` or `id` @@ -337,7 +337,7 @@ Removes the user(s) from follower recommendations. ## `GET /api/v1/pleroma/admin/instances/:instance/statuses` -### Retrive instance's latest statuses +### Retrieve instance's latest statuses - Params: - `instance`: instance name @@ -377,7 +377,7 @@ It may take some time. ## `GET /api/v1/pleroma/admin/statuses` -### Retrives all latest statuses +### Retrieves all latest statuses - Params: - *optional* `page_size`: number of statuses to return (default is `20`) @@ -541,7 +541,7 @@ Response: ## `PATCH /api/v1/pleroma/admin/users/force_password_reset` -### Force passord reset for a user with a given nickname +### Force password reset for a user with a given nickname - Params: - `nicknames` diff --git a/docs/development/API/differences_in_mastoapi_responses.md b/docs/development/API/differences_in_mastoapi_responses.md @@ -1,6 +1,6 @@ # Differences in Mastodon API responses from vanilla Mastodon -A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance` +A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance` and `/api/v2/instance` ## Flake IDs @@ -39,6 +39,7 @@ Has these additional fields under the `pleroma` object: - `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint. - `parent_visible`: If the parent of this post is visible to the user or not. - `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise. +- `quotes_count`: the count of status quotes. The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes: @@ -304,19 +305,27 @@ Has these additional parameters (which are the same as in Pleroma-API): `GET /api/v1/instance` has additional fields - `max_toot_chars`: The maximum characters per post +- `max_media_attachments`: Maximum number of post media attachments - `chat_limit`: The maximum characters per chat message - `description_limit`: The maximum characters per image description - `poll_limits`: The limits of polls +- `shout_limit`: The maximum characters per Shoutbox message - `upload_limit`: The maximum upload file size - `avatar_upload_limit`: The same for avatars - `background_upload_limit`: The same for backgrounds - `banner_upload_limit`: The same for banners - `background_image`: A background image that frontends can use +- `pleroma.metadata.account_activation_required`: Whether users are required to confirm their emails before signing in +- `pleroma.metadata.birthday_required`: Whether users are required to provide their birth day when signing in +- `pleroma.metadata.birthday_min_age`: The minimum user age (in days) - `pleroma.metadata.features`: A list of supported features - `pleroma.metadata.federation`: The federation restrictions of this instance - `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields. - `pleroma.metadata.post_formats`: A list of the allowed post format types -- `vapid_public_key`: The public key needed for push messages +- `pleroma.stats.mau`: Monthly active user count +- `pleroma.vapid_public_key`: The public key needed for push messages + +In, `GET /api/v2/instance` Pleroma-specific fields are all moved into `pleroma` object. `max_toot_chars`, `poll_limits` and `upload_limit` are replaced with their MastoAPI counterparts. ## Push Subscription diff --git a/docs/development/API/pleroma_api.md b/docs/development/API/pleroma_api.md @@ -129,7 +129,7 @@ The `/api/v1/pleroma/*` path is backwards compatible with `/api/pleroma/*` (`/ap * method: `GET` * Authentication: required * OAuth scope: `write:security` -* Response: JSON. Returns `{"codes": codes}`when successful, otherwise HTTP 422 `{"error": "[error message]"}` +* Response: JSON. Returns `{"codes": codes}` when successful, otherwise HTTP 422 `{"error": "[error message]"}` ## `/api/v1/pleroma/admin/` See [Admin-API](admin_api.md) @@ -251,6 +251,15 @@ See [Admin-API](admin_api.md) ] ``` + +## `/api/v1/pleroma/accounts/:id/endorsements` +### Returns users endorsed by a user +* Method `GET` +* Authentication: not required +* Params: + * `id`: the id of the account for whom to return results +* Response: JSON, returns a list of Mastodon Account entities + ## `/api/v1/pleroma/accounts/update_*` ### Set and clear account avatar, banner, and background @@ -266,6 +275,14 @@ See [Admin-API](admin_api.md) * Authentication: not required * Response: 204 No Content +## `/api/v1/pleroma/statuses/:id/quotes` +### Gets quotes for a given status +* Method `GET` +* Authentication: not required +* Params: + * `id`: the id of the status +* Response: JSON, returns a list of Mastodon Status entities + ## `/api/v1/pleroma/mascot` ### Gets user mascot image * Method `GET` @@ -372,6 +389,15 @@ See [Admin-API](admin_api.md) * `alias`: the nickname of the alias to delete, e.g. `foo@example.org`. * Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise +## `/api/v1/pleroma/remote_interaction` +## Interact with profile or status from remote account +* Metod `POST` +* Authentication: not required +* Params: + * `ap_id`: Profile or status ActivityPub ID + * `profile`: Remote profile webfinger +* Response: JSON. Returns `{"url": "[redirect url]"}` on success, `{"error": "[error message]"}` otherwise + # Pleroma Conversations Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints: @@ -382,7 +408,7 @@ Pleroma Conversations have the same general structure that Mastodon Conversation Conversations have the additional field `recipients` under the `pleroma` key. This holds a list of all the accounts that will receive a message in this conversation. -The status posting endpoint takes an additional parameter, `in_reply_to_conversation_id`, which, when set, will set the visiblity to direct and address only the people who are the recipients of that Conversation. +The status posting endpoint takes an additional parameter, `in_reply_to_conversation_id`, which, when set, will set the visibility to direct and address only the people who are the recipients of that Conversation. ⚠ Conversation IDs can be found in direct messages with the `pleroma.direct_conversation_id` key, do not confuse it with `pleroma.conversation_id`. diff --git a/docs/development/ap_extensions.md b/docs/development/ap_extensions.md @@ -20,16 +20,16 @@ Content-Type: multipart/form-data Parameters: - (required) `file`: The file being uploaded -- (optionnal) `description`: A plain-text description of the media, for accessibility purposes. +- (optional) `description`: A plain-text description of the media, for accessibility purposes. Response: HTTP 201 Created with the object into the body, no `Location` header provided as it doesn't have an `id` -The object given in the reponse should then be inserted into an Object's `attachment` field. +The object given in the response should then be inserted into an Object's `attachment` field. ## ChatMessages `ChatMessage`s are the messages sent in 1-on-1 chats. They are similar to -`Note`s, but the addresing is done by having a single AP actor in the `to` +`Note`s, but the addressing is done by having a single AP actor in the `to` field. Addressing multiple actors is not allowed. These messages are always private, there is no public version of them. They are created with a `Create` activity. diff --git a/docs/development/setting_up_pleroma_dev.md b/docs/development/setting_up_pleroma_dev.md @@ -15,7 +15,7 @@ Pleroma requires some adjustments from the defaults for running the instance loc 2. Change the dev.secret.exs * Change the scheme in `config :pleroma, Pleroma.Web.Endpoint` to http (see examples below) * If you want to change other settings, you can do that too -3. You can now start the server `mix phx.server`. Once it's build and started, you can access the instance on `http://<host>:<port>` (e.g.http://localhost:4000 ) and should be able to do everything locally you normaly can. +3. You can now start the server `mix phx.server`. Once it's build and started, you can access the instance on `http://<host>:<port>` (e.g.http://localhost:4000 ) and should be able to do everything locally you normally can. Example config to change the scheme to http. Change the port if you want to run on another port. ```elixir diff --git a/docs/installation/generic_dependencies.include b/docs/installation/generic_dependencies.include @@ -2,7 +2,7 @@ * PostgreSQL >=9.6 * Elixir >=1.11.0 <1.15 -* Erlang OTP >=22.2.0 <26 +* Erlang OTP >=22.2.0 (supported: <27) * git * file / libmagic * gcc or clang diff --git a/docs/installation/gentoo_en.md b/docs/installation/gentoo_en.md @@ -59,7 +59,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i 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. +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, stretch 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. ### Install PostgreSQL @@ -104,7 +104,7 @@ Not only does this make it much easier to deploy changes you make, as you can co * Add a new system user for the Pleroma service and set up default directories: -Remove `,wheel` if you do not want this user to be able to use `sudo`, however note that being able to `sudo` as the `pleroma` user will make finishing the insallation and common maintenence tasks somewhat easier: +Remove `,wheel` if you do not want this user to be able to use `sudo`, however note that being able to `sudo` as the `pleroma` user will make finishing the installation and common maintenance tasks somewhat easier: ```shell # useradd -m -G users,wheel -s /bin/bash pleroma diff --git a/docs/installation/gentoo_otp_en.md b/docs/installation/gentoo_otp_en.md @@ -49,7 +49,7 @@ Gentoo quite pointedly does not come with a cron daemon installed, and as such i 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. +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, stretch 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 diff --git a/docs/installation/openbsd_en.md b/docs/installation/openbsd_en.md @@ -62,7 +62,7 @@ rcctl start postgresql To check that it started properly and didn't fail right after starting, you can run `ps aux | grep postgres`, there should be multiple lines of output. #### httpd -httpd will have three fuctions: +httpd will have three functions: * redirect requests trying to reach the instance over http to the https URL * serve a robots.txt file @@ -225,7 +225,7 @@ pass in quick on $if inet6 proto icmp6 to ($if) icmp6-type { echoreq unreach par pass in quick on $if proto tcp to ($if) port { http https } # relayd/httpd pass in quick on $if proto tcp from $authorized_ssh_clients to ($if) port ssh ``` -Replace *<network interface\>* by your server's network interface name (which you can get with ifconfig). Consider replacing the content of the authorized\_ssh\_clients macro by, for exemple, your home IP address, to avoid SSH connection attempts from bots. +Replace *<network interface\>* by your server's network interface name (which you can get with ifconfig). Consider replacing the content of the authorized\_ssh\_clients macro by, for example, your home IP address, to avoid SSH connection attempts from bots. Check pf's configuration by running `pfctl -nf /etc/pf.conf`, load it with `pfctl -f /etc/pf.conf` and enable pf at boot with `rcctl enable pf`. diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md @@ -238,7 +238,7 @@ At this point if you open your (sub)domain in a browser you should see a 502 err systemctl enable pleroma ``` -If everything worked, you should see Pleroma-FE when visiting your domain. If that didn't happen, try reviewing the installation steps, starting Pleroma in the foreground and seeing if there are any errrors. +If everything worked, you should see Pleroma-FE when visiting your domain. If that didn't happen, try reviewing the installation steps, starting Pleroma in the foreground and seeing if there are any errors. Questions about the installation or didn’t 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, you can also [file an issue on our Gitlab](https://git.pleroma.social/pleroma/pleroma-support/issues/new). diff --git a/installation/pleroma-mongooseim.cfg b/installation/pleroma-mongooseim.cfg @@ -204,7 +204,7 @@ ]} ]}, - %% Following HTTP API is deprected, the new one abouve should be used instead + %% Following HTTP API is deprecated, the new one above should be used instead { {5288, "127.0.0.1"} , ejabberd_cowboy, [ {num_acceptors, 10}, @@ -824,7 +824,7 @@ %% Enable archivization for private messages (default) % {pm, [ - %% Top-level options can be overriden here if needed, for example: + %% Top-level options can be overridden here if needed, for example: % {async_writer, false} % ]}, @@ -834,7 +834,7 @@ %% % {muc, [ % {host, "muc.@HOST@"} - %% As with pm, top-level options can be overriden for MUC archive + %% As with pm, top-level options can be overridden for MUC archive % ]}, % %% Do not use a <stanza-id/> element (by default stanzaid is used) diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex @@ -193,7 +193,7 @@ defmodule Mix.Tasks.Pleroma.Database do "ALTER DATABASE #{db} SET default_text_search_config = '#{tsconfig}';" ) - # non-exist config will not raise excpetion but only give >0 messages + # non-exist config will not raise exception but only give >0 messages if length(msg) > 0 do shell_info("Error: #{inspect(msg, pretty: true)}") else diff --git a/lib/mix/tasks/pleroma/digest.ex b/lib/mix/tasks/pleroma/digest.ex @@ -30,7 +30,7 @@ defmodule Mix.Tasks.Pleroma.Digest do shell_info("Digest email have been sent to #{nickname} (#{user.email})") else _ -> - shell_info("Cound't find any mentions for #{nickname} since #{last_digest_emailed_at}") + shell_info("Couldn't find any mentions for #{nickname} since #{last_digest_emailed_at}") end end end diff --git a/lib/mix/tasks/pleroma/ecto/rollback.ex b/lib/mix/tasks/pleroma/ecto/rollback.ex @@ -61,7 +61,7 @@ defmodule Mix.Tasks.Pleroma.Ecto.Rollback do Logger.configure(level: :info) if opts[:env] == "test" do - Logger.info("Rollback succesfully") + Logger.info("Rollback successfully") else {:ok, _, _} = Ecto.Migrator.with_repo(Pleroma.Repo, &Ecto.Migrator.run(&1, path, :down, opts)) diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex @@ -292,7 +292,7 @@ defmodule Mix.Tasks.Pleroma.Instance do if db_configurable? do shell_info( - " Please transfer your config to the database after running database migrations. Refer to \"Transfering the config to/from the database\" section of the docs for more information." + " Please transfer your config to the database after running database migrations. Refer to \"Transferring the config to/from the database\" section of the docs for more information." ) end else diff --git a/lib/pleroma/captcha/kocaptcha.ex b/lib/pleroma/captcha/kocaptcha.ex @@ -29,7 +29,7 @@ defmodule Pleroma.Captcha.Kocaptcha do @impl Service def validate(_token, captcha, answer_data) do - # Here the token is unsed, because the unencrypted captcha answer is just passed to method + # Here the token is unused, because the unencrypted captcha answer is just passed to method if not is_nil(captcha) and :crypto.hash(:md5, captcha) |> Base.encode16() == String.upcase(answer_data), do: :ok, diff --git a/lib/pleroma/config/deprecation_warnings.ex b/lib/pleroma/config/deprecation_warnings.ex @@ -172,7 +172,7 @@ defmodule Pleroma.Config.DeprecationWarnings do ``` config :pleroma, :mrf, - transparency_exclusions: [{"instance.tld", "Reason to exlude transparency"}] + transparency_exclusions: [{"instance.tld", "Reason to exclude transparency"}] ``` """) @@ -213,7 +213,7 @@ defmodule Pleroma.Config.DeprecationWarnings do check_gun_pool_options(), check_activity_expiration_config(), check_remote_ip_plug_name(), - check_uploders_s3_public_endpoint(), + check_uploaders_s3_public_endpoint(), check_old_chat_shoutbox(), check_quarantined_instances_tuples(), check_transparency_exclusions_tuples(), @@ -372,8 +372,8 @@ defmodule Pleroma.Config.DeprecationWarnings do ) end - @spec check_uploders_s3_public_endpoint() :: :ok | nil - def check_uploders_s3_public_endpoint do + @spec check_uploaders_s3_public_endpoint() :: :ok | nil + def check_uploaders_s3_public_endpoint do s3_config = Pleroma.Config.get([Pleroma.Uploaders.S3]) use_old_config = Keyword.has_key?(s3_config, :public_endpoint) diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex @@ -78,6 +78,14 @@ defmodule Pleroma.Constants do ] ) + const(allowed_user_actor_types, + do: [ + "Person", + "Service", + "Group" + ] + ) + # basic regex, just there to weed out potential mistakes # https://datatracker.ietf.org/doc/html/rfc2045#section-5.1 const(mime_regex, diff --git a/lib/pleroma/docs/generator.ex b/lib/pleroma/docs/generator.ex @@ -15,7 +15,7 @@ defmodule Pleroma.Docs.Generator do :code.all_loaded() |> Enum.filter(fn {module, _} -> # This shouldn't be needed as all modules are expected to have module_info/1, - # but in test enviroments some transient modules `:elixir_compiler_XX` + # but in test environments some transient modules `:elixir_compiler_XX` # are loaded for some reason (where XX is a random integer). Code.ensure_loaded(module) diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex @@ -209,7 +209,9 @@ defmodule Pleroma.Emoji.Pack do with :ok <- validate_shareable_packs_available(uri) do uri - |> URI.merge("/api/pleroma/emoji/packs?page=#{opts[:page]}&page_size=#{opts[:page_size]}") + |> URI.merge( + "/api/v1/pleroma/emoji/packs?page=#{opts[:page]}&page_size=#{opts[:page_size]}" + ) |> http_get() end end @@ -249,8 +251,12 @@ defmodule Pleroma.Emoji.Pack do uri = url |> String.trim() |> URI.parse() with :ok <- validate_shareable_packs_available(uri), + {:ok, %{"files_count" => files_count}} <- + uri |> URI.merge("/api/v1/pleroma/emoji/pack?name=#{name}&page_size=0") |> http_get(), {:ok, remote_pack} <- - uri |> URI.merge("/api/pleroma/emoji/pack?name=#{name}") |> http_get(), + uri + |> URI.merge("/api/v1/pleroma/emoji/pack?name=#{name}&page_size=#{files_count}") + |> http_get(), {:ok, %{sha: sha, url: url} = pack_info} <- fetch_pack_info(remote_pack, uri, name), {:ok, archive} <- download_archive(url, sha), pack <- copy_as(remote_pack, as || name), @@ -592,7 +598,7 @@ defmodule Pleroma.Emoji.Pack do {:ok, %{ sha: sha, - url: URI.merge(uri, "/api/pleroma/emoji/packs/archive?name=#{name}") |> to_string() + url: URI.merge(uri, "/api/v1/pleroma/emoji/packs/archive?name=#{name}") |> to_string() }} %{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) -> diff --git a/lib/pleroma/helpers/qt_fast_start.ex b/lib/pleroma/helpers/qt_fast_start.ex @@ -40,16 +40,21 @@ defmodule Pleroma.Helpers.QtFastStart do got_mdat, acc ) do - full_size = (size - 8) * 8 - <<data::bits-size(full_size), rest::bits>> = rest - - acc = [ - {fourcc, pos, pos + size, size, - <<size::integer-big-size(32), fourcc::bits-size(32), data::bits>>} - | acc - ] - - fix(rest, pos + size, got_moov || fourcc == "moov", got_mdat || fourcc == "mdat", acc) + try do + full_size = (size - 8) * 8 + <<data::bits-size(full_size), rest::bits>> = rest + + acc = [ + {fourcc, pos, pos + size, size, + <<size::integer-big-size(32), fourcc::bits-size(32), data::bits>>} + | acc + ] + + fix(rest, pos + size, got_moov || fourcc == "moov", got_mdat || fourcc == "mdat", acc) + rescue + _ -> + :abort + end end defp fix(<<>>, _pos, _, _, acc) do diff --git a/lib/pleroma/http.ex b/lib/pleroma/http.ex @@ -106,6 +106,10 @@ defmodule Pleroma.HTTP do [Tesla.Middleware.FollowRedirects, Pleroma.Tesla.Middleware.ConnectionPool] end + defp adapter_middlewares({Tesla.Adapter.Finch, _}) do + [Tesla.Middleware.FollowRedirects] + end + defp adapter_middlewares(_) do if Pleroma.Config.get(:env) == :test do # Emulate redirects in test env, which are handled by adapters in other environments diff --git a/lib/pleroma/instances.ex b/lib/pleroma/instances.ex @@ -7,16 +7,15 @@ defmodule Pleroma.Instances do alias Pleroma.Instances.Instance - def filter_reachable(urls_or_hosts), do: Instance.filter_reachable(urls_or_hosts) + defdelegate filter_reachable(urls_or_hosts), to: Instance - def reachable?(url_or_host), do: Instance.reachable?(url_or_host) + defdelegate reachable?(url_or_host), to: Instance - def set_reachable(url_or_host), do: Instance.set_reachable(url_or_host) + defdelegate set_reachable(url_or_host), to: Instance - def set_unreachable(url_or_host, unreachable_since \\ nil), - do: Instance.set_unreachable(url_or_host, unreachable_since) + defdelegate set_unreachable(url_or_host, unreachable_since \\ nil), to: Instance - def get_consistently_unreachable, do: Instance.get_consistently_unreachable() + defdelegate get_consistently_unreachable, to: Instance def set_consistently_unreachable(url_or_host), do: set_unreachable(url_or_host, reachability_datetime_threshold()) diff --git a/lib/pleroma/search/search_backend.ex b/lib/pleroma/search/search_backend.ex @@ -17,7 +17,7 @@ defmodule Pleroma.Search.SearchBackend do Remove the object from the index. Just the object, as opposed to the whole activity, is passed, since the object - is what contains the actual content and there is no need for fitlering when removing + is what contains the actual content and there is no need for filtering when removing from index. """ @callback remove_from_index(object :: Pleroma.Object.t()) :: {:ok, any()} | {:error, any()} diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex @@ -39,6 +39,7 @@ defmodule Pleroma.User do alias Pleroma.Workers.BackgroundWorker require Logger + require Pleroma.Constants @type t :: %__MODULE__{} @type account_status :: @@ -579,7 +580,7 @@ defmodule Pleroma.User do |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, min: 1, max: name_limit) - |> validate_inclusion(:actor_type, ["Person", "Service"]) + |> validate_inclusion(:actor_type, Pleroma.Constants.allowed_user_actor_types()) |> put_fields() |> put_emoji() |> put_change_if_present(:bio, &{:ok, parse_bio(&1, struct)}) @@ -2252,7 +2253,7 @@ defmodule Pleroma.User do if String.contains?(user.nickname, "@") do user.nickname else - %{host: host} = URI.parse(user.ap_id) + host = Pleroma.Web.WebFinger.host() user.nickname <> "@" <> host end end diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex @@ -22,7 +22,7 @@ defmodule Pleroma.User.Query do - pass non empty string - e.g. Pleroma.User.Query.build(%{email: "email@example.com"}) - *contains criteria* - - add field to @containns_criteria list + - add field to @contains_criteria list - pass values list - e.g. Pleroma.User.Query.build(%{ap_id: ["http://ap_id1", "http://ap_id2"]}) """ diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -319,6 +319,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {:ok, _actor} <- update_last_status_at_if_public(actor, activity), _ <- notify_and_stream(activity), :ok <- maybe_schedule_poll_notifications(activity), + :ok <- maybe_handle_group_posts(activity), :ok <- maybe_federate(activity) do {:ok, activity} else diff --git a/lib/pleroma/web/activity_pub/mrf.ex b/lib/pleroma/web/activity_pub/mrf.ex @@ -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 do @@ -139,7 +139,16 @@ defmodule Pleroma.Web.ActivityPub.MRF do @spec subdomains_regex([String.t()]) :: [Regex.t()] def subdomains_regex(domains) when is_list(domains) do - for domain <- domains, do: ~r(^#{String.replace(domain, "*.", "(.*\\.)*")}$)i + for domain <- domains do + try do + target = String.replace(domain, "*.", "(.*\\.)*") + ~r<^#{target}$>i + rescue + e -> + Logger.error("MRF: Invalid subdomain Regex: #{domain}") + reraise e, __STACKTRACE__ + end + end end @spec subdomain_match?([Regex.t()], String.t()) :: boolean() diff --git a/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex b/lib/pleroma/web/activity_pub/mrf/hashtag_policy.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do alias Pleroma.Object @moduledoc """ - Reject, TWKN-remove or Set-Sensitive messsages with specific hashtags (without the leading #) + Reject, TWKN-remove or Set-Sensitive messages with specific hashtags (without the leading #) Note: This MRF Policy is always enabled, if you want to disable it you have to set empty lists. """ diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex @@ -34,7 +34,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do |> Path.basename() |> Path.extname() - file_path = Path.join(emoji_dir_path, shortcode <> (extension || ".png")) + extension = if extension == "", do: ".png", else: extension + + file_path = Path.join(emoji_dir_path, shortcode <> extension) case File.write(file_path, response.body) do :ok -> diff --git a/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex b/lib/pleroma/web/activity_pub/object_validators/chat_message_validator.ex @@ -57,6 +57,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatMessageValidator do |> Map.put("attachment", attachment) end + def fix_attachment(%{"attachment" => attachment} = data) when attachment == [] do + data + |> Map.drop(["attachment"]) + end + def fix_attachment(data), do: data def changeset(struct, data) do diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex @@ -13,13 +13,12 @@ defmodule Pleroma.Web.ActivityPub.Publisher do alias Pleroma.User alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.ActivityPub.Transmogrifier + alias Pleroma.Workers.PublisherWorker require Pleroma.Constants import Pleroma.Web.ActivityPub.Visibility - @behaviour Pleroma.Web.Federator.Publisher - require Logger @moduledoc """ @@ -27,6 +26,44 @@ defmodule Pleroma.Web.ActivityPub.Publisher do """ @doc """ + Enqueue publishing a single activity. + """ + @spec enqueue_one(Map.t(), Keyword.t()) :: {:ok, %Oban.Job{}} + def enqueue_one(%{} = params, worker_args \\ []) do + PublisherWorker.enqueue( + "publish_one", + %{"params" => params}, + worker_args + ) + end + + @doc """ + Gathers a set of remote users given an IR envelope. + """ + def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do + cc = Map.get(data, "cc", []) + + bcc = + data + |> Map.get("bcc", []) + |> Enum.reduce([], fn ap_id, bcc -> + case Pleroma.List.get_by_ap_id(ap_id) do + %Pleroma.List{user_id: ^user_id} = list -> + {:ok, following} = Pleroma.List.get_following(list) + bcc ++ Enum.map(following, & &1.ap_id) + + _ -> + bcc + end + end) + + [to, cc, bcc] + |> Enum.concat() + |> Enum.map(&User.get_cached_by_ap_id/1) + |> Enum.filter(fn user -> user && !user.local end) + end + + @doc """ Determine if an activity can be represented by running it through Transmogrifier. """ def is_representable?(%Activity{} = activity) do @@ -80,9 +117,23 @@ defmodule Pleroma.Web.ActivityPub.Publisher do result else - {_post_result, response} -> + {_post_result, %{status: code} = response} = e -> + unless params[:unreachable_since], do: Instances.set_unreachable(inbox) + Logger.metadata(activity: id, inbox: inbox, status: code) + Logger.error("Publisher failed to inbox #{inbox} with status #{code}") + + case response do + %{status: 403} -> {:discard, :forbidden} + %{status: 404} -> {:discard, :not_found} + %{status: 410} -> {:discard, :not_found} + _ -> {:error, e} + end + + e -> unless params[:unreachable_since], do: Instances.set_unreachable(inbox) - {:error, response} + Logger.metadata(activity: id, inbox: inbox) + Logger.error("Publisher failed to inbox #{inbox} #{inspect(e)}") + {:error, e} end end @@ -138,7 +189,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do [] end - mentioned = Pleroma.Web.Federator.Publisher.remote_users(actor, activity) + mentioned = remote_users(actor, activity) non_mentioned = (followers ++ fetchers) -- mentioned [mentioned, non_mentioned] @@ -204,7 +255,10 @@ defmodule Pleroma.Web.ActivityPub.Publisher do [priority_recipients, recipients] |> Enum.map(fn recipients -> recipients - |> Enum.map(fn actor -> actor.inbox end) + |> Enum.map(fn %User{} = user -> + determine_inbox(activity, user) + end) + |> Enum.uniq() |> Enum.filter(fn inbox -> should_federate?(inbox, public) end) |> Instances.filter_reachable() end) @@ -223,7 +277,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do |> Map.put("cc", cc) |> Jason.encode!() - Pleroma.Web.Federator.Publisher.enqueue_one(__MODULE__, %{ + __MODULE__.enqueue_one(%{ inbox: inbox, json: json, actor_id: actor.id, @@ -251,7 +305,10 @@ defmodule Pleroma.Web.ActivityPub.Publisher do recipients(actor, activity) |> Enum.map(fn recipients -> recipients - |> Enum.map(fn actor -> actor.inbox end) + |> Enum.map(fn %User{} = user -> + determine_inbox(activity, user) + end) + |> Enum.uniq() |> Enum.filter(fn inbox -> should_federate?(inbox, public) end) end) @@ -262,8 +319,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do inboxes |> Instances.filter_reachable() |> Enum.each(fn {inbox, unreachable_since} -> - Pleroma.Web.Federator.Publisher.enqueue_one( - __MODULE__, + __MODULE__.enqueue_one( %{ inbox: inbox, json: json, diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex @@ -233,6 +233,8 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do Pleroma.Search.add_to_index(Map.put(activity, :object, object)) + Utils.maybe_handle_group_posts(activity) + meta = meta |> add_notifications(notifications) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex @@ -942,4 +942,27 @@ defmodule Pleroma.Web.ActivityPub.Utils do |> where([a, object: o], fragment("(?)->>'type' = 'Answer'", o.data)) |> Repo.all() end + + def maybe_handle_group_posts(activity) do + poster = User.get_cached_by_ap_id(activity.actor) + + mentions = + activity.data["to"] + |> Enum.filter(&(&1 != activity.actor)) + + mentioned_local_groups = + User.get_all_by_ap_id(mentions) + |> Enum.filter(fn user -> + user.actor_type == "Group" and + user.local and + not User.blocks?(user, poster) + end) + + mentioned_local_groups + |> Enum.each(fn group -> + Pleroma.Web.CommonAPI.repeat(activity.id, group) + end) + + :ok + end end diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex @@ -43,7 +43,7 @@ defmodule Pleroma.Web.ApiSpec do - [Mastodon API documentation](https://docs.joinmastodon.org/client/intro/) - [Differences in Mastodon API responses from vanilla Mastodon](https://docs-develop.pleroma.social/backend/development/API/differences_in_mastoapi_responses/) - Please report such occurences on our [issue tracker](https://git.pleroma.social/pleroma/pleroma/-/issues). Feel free to submit API questions or proposals there too! + Please report such occurrences on our [issue tracker](https://git.pleroma.social/pleroma/pleroma/-/issues). Feel free to submit API questions or proposals there too! """, # Strip environment from the version version: Application.spec(:pleroma, :vsn) |> to_string() |> String.replace(~r/\+.*$/, ""), @@ -94,14 +94,14 @@ defmodule Pleroma.Web.ApiSpec do "tags" => [ "Chat administration", "Emoji pack administration", - "Frontend managment", + "Frontend management", "Instance configuration", "Instance documents", "Invites", "MediaProxy cache", - "OAuth application managment", + "OAuth application management", "Relays", - "Report managment", + "Report management", "Status administration", "User administration", "Announcement management" diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -347,7 +347,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do summary: "Endorse", operationId: "AccountController.endorse", security: [%{"oAuth" => ["follow", "write:accounts"]}], - description: "Addds the given account to endorsed accounts list.", + description: "Adds the given account to endorsed accounts list.", parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}], responses: %{ 200 => Operation.response("Relationship", "application/json", AccountRelationship), diff --git a/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex b/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex @@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do def index_operation do %Operation{ - tags: ["Frontend managment"], + tags: ["Frontend management"], summary: "Retrieve a list of available frontends", operationId: "AdminAPI.FrontendController.index", security: [%{"oAuth" => ["admin:read"]}], @@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do def install_operation do %Operation{ - tags: ["Frontend managment"], + tags: ["Frontend management"], summary: "Install a frontend", operationId: "AdminAPI.FrontendController.install", security: [%{"oAuth" => ["admin:read"]}], diff --git a/lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex b/lib/pleroma/web/api_spec/operations/admin/o_auth_app_operation.ex @@ -17,7 +17,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do def index_operation do %Operation{ summary: "Retrieve a list of OAuth applications", - tags: ["OAuth application managment"], + tags: ["OAuth application management"], operationId: "AdminAPI.OAuthAppController.index", security: [%{"oAuth" => ["admin:write"]}], parameters: [ @@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do def create_operation do %Operation{ - tags: ["OAuth application managment"], + tags: ["OAuth application management"], summary: "Create an OAuth application", operationId: "AdminAPI.OAuthAppController.create", requestBody: request_body("Parameters", create_request()), @@ -84,7 +84,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do def update_operation do %Operation{ - tags: ["OAuth application managment"], + tags: ["OAuth application management"], summary: "Update OAuth application", operationId: "AdminAPI.OAuthAppController.update", parameters: [id_param() | admin_api_params()], @@ -102,7 +102,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do def delete_operation do %Operation{ - tags: ["OAuth application managment"], + tags: ["OAuth application management"], summary: "Delete OAuth application", operationId: "AdminAPI.OAuthAppController.delete", parameters: [id_param() | admin_api_params()], diff --git a/lib/pleroma/web/api_spec/operations/admin/report_operation.ex b/lib/pleroma/web/api_spec/operations/admin/report_operation.ex @@ -19,7 +19,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do def index_operation do %Operation{ - tags: ["Report managment"], + tags: ["Report management"], summary: "Retrieve a list of reports", operationId: "AdminAPI.ReportController.index", security: [%{"oAuth" => ["admin:read:reports"]}], @@ -69,7 +69,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do def show_operation do %Operation{ - tags: ["Report managment"], + tags: ["Report management"], summary: "Retrieve a report", operationId: "AdminAPI.ReportController.show", parameters: [id_param() | admin_api_params()], @@ -83,7 +83,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do def update_operation do %Operation{ - tags: ["Report managment"], + tags: ["Report management"], summary: "Change state of specified reports", operationId: "AdminAPI.ReportController.update", security: [%{"oAuth" => ["admin:write:reports"]}], @@ -99,7 +99,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do def notes_create_operation do %Operation{ - tags: ["Report managment"], + tags: ["Report management"], summary: "Add a note to the report", operationId: "AdminAPI.ReportController.notes_create", parameters: [id_param() | admin_api_params()], @@ -120,7 +120,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do def notes_delete_operation do %Operation{ - tags: ["Report managment"], + tags: ["Report management"], summary: "Delete note attached to the report", operationId: "AdminAPI.ReportController.notes_delete", parameters: [ diff --git a/lib/pleroma/web/api_spec/operations/instance_operation.ex b/lib/pleroma/web/api_spec/operations/instance_operation.ex @@ -101,7 +101,7 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do languages: %Schema{ type: :array, items: %Schema{type: :string}, - description: "Primary langauges of the website and its staff" + description: "Primary languages of the website and its staff" }, registrations: %Schema{type: :boolean, description: "Whether registrations are enabled"}, # Extra (not present in Mastodon): @@ -252,7 +252,7 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do languages: %Schema{ type: :array, items: %Schema{type: :string}, - description: "Primary langauges of the website and its staff" + description: "Primary languages of the website and its staff" }, registrations: %Schema{ type: :object, diff --git a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex @@ -23,7 +23,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do security: [%{"oAuth" => ["write"]}], operationId: "PleromaAPI.ScrobbleController.create", deprecated: true, - requestBody: request_body("Parameters", create_request(), requried: true), + requestBody: request_body("Parameters", create_request(), required: true), responses: %{ 200 => Operation.response("Scrobble", "application/json", scrobble()) } diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex @@ -534,7 +534,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do format: :"date-time", nullable: true, description: - "ISO 8601 Datetime at which to schedule a status. Providing this paramter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future." + "ISO 8601 Datetime at which to schedule a status. Providing this parameter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future." }, language: %Schema{ type: :string, @@ -546,7 +546,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do allOf: [BooleanLike], nullable: true, description: - "If set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example" + "If set to `true` the post won't be actually posted, but the status entity would still be rendered back. This could be useful for previewing rich text/custom emoji, for example" }, content_type: %Schema{ type: :string, diff --git a/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex b/lib/pleroma/web/api_spec/operations/twitter_util_operation.ex @@ -87,7 +87,7 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do defp change_password_request do %Schema{ title: "ChangePasswordRequest", - description: "POST body for changing the account's passowrd", + description: "POST body for changing the account's password", type: :object, required: [:password, :new_password, :new_password_confirmation], properties: %{ @@ -136,12 +136,12 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do } end - def update_notificaton_settings_operation do + def update_notification_settings_operation do %Operation{ tags: ["Settings"], summary: "Update Notification Settings", security: [%{"oAuth" => ["write:accounts"]}], - operationId: "UtilController.update_notificaton_settings", + operationId: "UtilController.update_notification_settings", parameters: [ Operation.parameter( :block_from_strangers, diff --git a/lib/pleroma/web/api_spec/schemas/attachment.ex b/lib/pleroma/web/api_spec/schemas/attachment.ex @@ -11,7 +11,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Attachment do title: "Attachment", description: "Represents a file or media attachment that can be added to a status.", type: :object, - requried: [:id, :url, :preview_url], + required: [:id, :url, :preview_url], properties: %{ id: %Schema{type: :string, description: "The ID of the attachment in the database."}, url: %Schema{ diff --git a/lib/pleroma/web/federator.ex b/lib/pleroma/web/federator.ex @@ -6,9 +6,9 @@ defmodule Pleroma.Web.Federator do alias Pleroma.Activity alias Pleroma.Object.Containment alias Pleroma.User + alias Pleroma.Web.ActivityPub.Publisher alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.ActivityPub.Utils - alias Pleroma.Web.Federator.Publisher alias Pleroma.Workers.PublisherWorker alias Pleroma.Workers.ReceiverWorker @@ -68,10 +68,8 @@ defmodule Pleroma.Web.Federator do # Job Worker Callbacks - @spec perform(atom(), module(), any()) :: {:ok, any()} | {:error, any()} - def perform(:publish_one, module, params) do - apply(module, :publish_one, [params]) - end + @spec perform(atom(), any()) :: {:ok, any()} | {:error, any()} + def perform(:publish_one, params), do: Publisher.publish_one(params) def perform(:publish, activity) do Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end) diff --git a/lib/pleroma/web/federator/publisher.ex b/lib/pleroma/web/federator/publisher.ex @@ -1,110 +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.Web.Federator.Publisher do - alias Pleroma.Activity - alias Pleroma.Config - alias Pleroma.User - alias Pleroma.Workers.PublisherWorker - - require Logger - - @moduledoc """ - Defines the contract used by federation implementations to publish messages to - their peers. - """ - - @doc """ - Determine whether an activity can be relayed using the federation module. - """ - @callback is_representable?(Pleroma.Activity.t()) :: boolean() - - @doc """ - Relays an activity to a specified peer, determined by the parameters. The - parameters used are controlled by the federation module. - """ - @callback publish_one(Map.t()) :: {:ok, Map.t()} | {:error, any()} - - @doc """ - Enqueue publishing a single activity. - """ - @spec enqueue_one(module(), Map.t(), Keyword.t()) :: {:ok, %Oban.Job{}} - def enqueue_one(module, %{} = params, worker_args \\ []) do - PublisherWorker.enqueue( - "publish_one", - %{"module" => to_string(module), "params" => params}, - worker_args - ) - end - - @doc """ - Relays an activity to all specified peers. - """ - @callback publish(User.t(), Activity.t()) :: :ok | {:error, any()} - - @spec publish(User.t(), Activity.t()) :: :ok - def publish(%User{} = user, %Activity{} = activity) do - Config.get([:instance, :federation_publisher_modules]) - |> Enum.each(fn module -> - if module.is_representable?(activity) do - Logger.debug("Publishing #{activity.data["id"]} using #{inspect(module)}") - module.publish(user, activity) - end - end) - - :ok - end - - @doc """ - Gathers links used by an outgoing federation module for WebFinger output. - """ - @callback gather_webfinger_links(User.t()) :: list() - - @spec gather_webfinger_links(User.t()) :: list() - def gather_webfinger_links(%User{} = user) do - Config.get([:instance, :federation_publisher_modules]) - |> Enum.reduce([], fn module, links -> - links ++ module.gather_webfinger_links(user) - end) - end - - @doc """ - Gathers nodeinfo protocol names supported by the federation module. - """ - @callback gather_nodeinfo_protocol_names() :: list() - - @spec gather_nodeinfo_protocol_names() :: list() - def gather_nodeinfo_protocol_names do - Config.get([:instance, :federation_publisher_modules]) - |> Enum.reduce([], fn module, links -> - links ++ module.gather_nodeinfo_protocol_names() - end) - end - - @doc """ - Gathers a set of remote users given an IR envelope. - """ - def remote_users(%User{id: user_id}, %{data: %{"to" => to} = data}) do - cc = Map.get(data, "cc", []) - - bcc = - data - |> Map.get("bcc", []) - |> Enum.reduce([], fn ap_id, bcc -> - case Pleroma.List.get_by_ap_id(ap_id) do - %Pleroma.List{user_id: ^user_id} = list -> - {:ok, following} = Pleroma.List.get_following(list) - bcc ++ Enum.map(following, & &1.ap_id) - - _ -> - bcc - end - end) - - [to, cc, bcc] - |> Enum.concat() - |> Enum.map(&User.get_cached_by_ap_id/1) - |> Enum.filter(fn user -> user && !user.local end) - end -end diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -235,7 +235,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do # So we first build the normal local changeset, then apply it to the # user data, but don't persist it. With this, we generate the object # data for our update activity. We feed this and the changeset as meta - # inforation into the pipeline, where they will be properly updated and + # information into the pipeline, where they will be properly updated and # federated. with changeset <- User.update_changeset(user, user_params), {:ok, unpersisted_user} <- Ecto.Changeset.apply_action(changeset, :update), diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -194,6 +194,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do end defp do_render("show.json", %{user: user} = opts) do + self = opts[:for] == user + user = User.sanitize_html(user, User.html_filter_policy(opts[:for])) display_name = user.name || user.nickname @@ -203,16 +205,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do header_static = User.banner_url(user) |> MediaProxy.preview_url(static: true) following_count = - if !user.hide_follows_count or !user.hide_follows or opts[:for] == user, + if !user.hide_follows_count or !user.hide_follows or self, do: user.following_count, else: 0 followers_count = - if !user.hide_followers_count or !user.hide_followers or opts[:for] == user, + if !user.hide_followers_count or !user.hide_followers or self, do: user.follower_count, else: 0 - bot = user.actor_type == "Service" + bot = is_bot?(user) emojis = Enum.map(user.emoji, fn {shortcode, raw_url} -> @@ -468,4 +470,12 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp image_url(%{"url" => [%{"href" => href} | _]}), do: href defp image_url(_), do: nil + + defp is_bot?(user) do + # Because older and/or Mastodon clients may not recognize a Group actor properly, + # and currently the group actor can only boost things, we should let these clients + # think groups are bots. + # See https://git.pleroma.social/pleroma/pleroma-meta/-/issues/14 + user.actor_type == "Service" || user.actor_type == "Group" + end end diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -40,6 +40,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image), shout_limit: Config.get([:shout, :limit]), description_limit: Keyword.get(instance, :description_limit), + chat_limit: Keyword.get(instance, :chat_limit), pleroma: pleroma_configuration(instance) }) end @@ -125,7 +126,8 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do if Config.get([:instance, :profile_directory]) do "profile_directory" end, - "pleroma:get:main/ostatus" + "pleroma:get:main/ostatus", + "pleroma:group_actors" ] |> Enum.filter(& &1) end @@ -221,6 +223,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do banner_upload_limit: Keyword.get(instance, :banner_upload_limit), background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image), + chat_limit: Keyword.get(instance, :chat_limit), description_limit: Keyword.get(instance, :description_limit), shout_limit: Config.get([:shout, :limit]) }) diff --git a/lib/pleroma/web/nodeinfo/nodeinfo.ex b/lib/pleroma/web/nodeinfo/nodeinfo.ex @@ -6,7 +6,7 @@ defmodule Pleroma.Web.Nodeinfo.Nodeinfo do alias Pleroma.Config alias Pleroma.Stats alias Pleroma.User - alias Pleroma.Web.Federator.Publisher + alias Pleroma.Web.ActivityPub.Publisher alias Pleroma.Web.MastodonAPI.InstanceView # returns a nodeinfo 2.0 map, since 2.1 just adds a repository field diff --git a/lib/pleroma/web/o_auth/o_auth_controller.ex b/lib/pleroma/web/o_auth/o_auth_controller.ex @@ -310,7 +310,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do after_token_exchange(conn, %{token: token}) else _error -> - handle_token_exchange_error(conn, :invalid_credentails) + handle_token_exchange_error(conn, :invalid_credentials) end end diff --git a/lib/pleroma/web/plugs/cache.ex b/lib/pleroma/web/plugs/cache.ex @@ -20,7 +20,7 @@ defmodule Pleroma.Web.Plugs.Cache do - `ttl`: An expiration time (time-to-live). This value should be in milliseconds or `nil` to disable expiration. Defaults to `nil`. - `query_params`: Take URL query string into account (`true`), ignore it (`false`) or limit to specific params only (list). Defaults to `true`. - - `tracking_fun`: A function that is called on successfull responses, no matter if the request is cached or not. It should accept a conn as the first argument and the value assigned to `tracking_fun_data` as the second. + - `tracking_fun`: A function that is called on successful responses, no matter if the request is cached or not. It should accept a conn as the first argument and the value assigned to `tracking_fun_data` as the second. Additionally, you can overwrite the TTL inside a controller action by assigning `cache_ttl` to the connection struct: diff --git a/lib/pleroma/web/plugs/uploaded_media.ex b/lib/pleroma/web/plugs/uploaded_media.ex @@ -105,7 +105,7 @@ defmodule Pleroma.Web.Plugs.UploadedMedia do end defp get_media(conn, unknown, _, _) do - Logger.error("#{__MODULE__}: Unknown get startegy: #{inspect(unknown)}") + Logger.error("#{__MODULE__}: Unknown get strategy: #{inspect(unknown)}") conn |> send_resp(:internal_server_error, dgettext("errors", "Internal Error")) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex @@ -182,7 +182,7 @@ defmodule Pleroma.Web.Router do end pipeline :well_known do - plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"]) + plug(:accepts, ["json", "jrd", "jrd+json", "xml", "xrd+xml"]) end pipeline :config do @@ -481,7 +481,7 @@ defmodule Pleroma.Web.Router do post("/change_email", UtilController, :change_email) post("/change_password", UtilController, :change_password) post("/delete_account", UtilController, :delete_account) - put("/notification_settings", UtilController, :update_notificaton_settings) + put("/notification_settings", UtilController, :update_notification_settings) post("/disable_account", UtilController, :disable_account) post("/move_account", UtilController, :move_account) diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex @@ -396,7 +396,7 @@ defmodule Pleroma.Web.Streamer do end end - # In test environement, only return true if the registry is started. + # In test environment, only return true if the registry is started. # In benchmark environment, returns false. # In any other environment, always returns true. cond do diff --git a/lib/pleroma/web/twitter_api/controllers/password_controller.ex b/lib/pleroma/web/twitter_api/controllers/password_controller.ex @@ -4,7 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordController do @moduledoc """ - The module containts functions for reset password. + The module contains functions for password reset. """ use Pleroma.Web, :controller diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -35,7 +35,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do :change_email, :change_password, :delete_account, - :update_notificaton_settings, + :update_notification_settings, :disable_account, :move_account, :add_alias, @@ -181,7 +181,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do json(conn, emoji) end - def update_notificaton_settings(%{assigns: %{user: user}} = conn, params) do + def update_notification_settings(%{assigns: %{user: user}} = conn, params) do with {:ok, _} <- User.update_notification_settings(user, params) do json(conn, %{status: "success"}) end diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex @@ -5,8 +5,8 @@ defmodule Pleroma.Web.WebFinger do alias Pleroma.HTTP alias Pleroma.User + alias Pleroma.Web.ActivityPub.Publisher alias Pleroma.Web.Endpoint - alias Pleroma.Web.Federator.Publisher alias Pleroma.Web.XML alias Pleroma.XmlBuilder require Jason diff --git a/lib/pleroma/web/web_finger/web_finger_controller.ex b/lib/pleroma/web/web_finger/web_finger_controller.ex @@ -30,7 +30,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerController do end def webfinger(%{assigns: %{format: format}} = conn, %{"resource" => resource}) - when format in ["json", "jrd+json"] do + when format in ["jrd", "json", "jrd+json"] do with {:ok, response} <- WebFinger.webfinger(resource, "JSON") do json(conn, response) else diff --git a/lib/pleroma/workers/publisher_worker.ex b/lib/pleroma/workers/publisher_worker.ex @@ -18,9 +18,9 @@ defmodule Pleroma.Workers.PublisherWorker do Federator.perform(:publish, activity) end - def perform(%Job{args: %{"op" => "publish_one", "module" => module_name, "params" => params}}) do + def perform(%Job{args: %{"op" => "publish_one", "params" => params}}) do params = Map.new(params, fn {k, v} -> {String.to_atom(k), v} end) - Federator.perform(:publish_one, String.to_atom(module_name), params) + Federator.perform(:publish_one, params) end @impl Oban.Worker diff --git a/mix.exs b/mix.exs @@ -156,11 +156,11 @@ defmodule Pleroma.Mixfile do {:phoenix_swoosh, "~> 1.1"}, {:gen_smtp, "~> 0.13"}, {:ex_syslogger, "~> 1.4"}, - {:floki, "~> 0.27"}, + {:floki, "~> 0.35"}, {:timex, "~> 3.6"}, {:ueberauth, "~> 0.4"}, {:linkify, "~> 0.5.3"}, - {:http_signatures, "~> 0.1.1"}, + {:http_signatures, "~> 0.1.2"}, {:telemetry, "~> 1.0.0", override: true}, {:poolboy, "~> 1.5"}, {:prom_ex, "~> 1.9"}, diff --git a/mix.lock b/mix.lock @@ -50,14 +50,14 @@ "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"}, "flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"}, - "floki": {:hex, :floki, "0.34.3", "5e2dcaec5d7c228ce5b1d3501502e308b2d79eb655e4191751a1fe491c37feac", [:mix], [], "hexpm", "9577440eea5b97924b4bf3c7ea55f7b8b6dce589f9b28b096cc294a8dc342341"}, + "floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"}, "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"}, "gettext": {:hex, :gettext, "0.22.2", "6bfca374de34ecc913a28ba391ca184d88d77810a3e427afa8454a71a51341ac", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "8a2d389673aea82d7eae387e6a2ccc12660610080ae7beb19452cfdc1ec30f60"}, "gun": {:hex, :gun, "2.0.1", "160a9a5394800fcba41bc7e6d421295cf9a7894c2252c0678244948e3336ad73", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "a10bc8d6096b9502205022334f719cc9a08d9adcfbfc0dbee9ef31b56274a20b"}, "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, - "http_signatures": {:hex, :http_signatures, "0.1.1", "ca7ebc1b61542b163644c8c3b1f0e0f41037d35f2395940d3c6c7deceab41fd8", [:mix], [], "hexpm", "cc3b8a007322cc7b624c0c15eec49ee58ac977254ff529a3c482f681465942a3"}, + "http_signatures": {:hex, :http_signatures, "0.1.2", "ed1cc7043abcf5bb4f30d68fb7bad9d618ec1a45c4ff6c023664e78b67d9c406", [:mix], [], "hexpm", "f08aa9ac121829dae109d608d83c84b940ef2f183ae50f2dd1e9a8bc619d8be7"}, "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"}, diff --git a/test/mix/pleroma_test.exs b/test/mix/pleroma_test.exs @@ -39,7 +39,7 @@ defmodule Mix.PleromaTest do describe "get_option/3" do test "get from options" do - assert get_option([domain: "some-domain.com"], :domain, "Promt") == "some-domain.com" + assert get_option([domain: "some-domain.com"], :domain, "Prompt") == "some-domain.com" end test "get from prompt" do diff --git a/test/mix/tasks/pleroma/config_test.exs b/test/mix/tasks/pleroma/config_test.exs @@ -140,7 +140,6 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do federating: true, federation_incoming_replies_max_depth: 100, federation_reachability_timeout_days: 7, - federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher], allow_relay: true, public: true, quarantined_instances: [], @@ -183,8 +182,8 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do assert File.exists?(temp_file) {:ok, file} = File.read(temp_file) - assert file == - "import Config\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n federation_publisher_modules: [Pleroma.Web.ActivityPub.Publisher],\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" + assert file =~ "import Config\n" + assert file =~ "A Pleroma instance, an alternative fediverse server" end end diff --git a/test/mix/tasks/pleroma/ecto/rollback_test.exs b/test/mix/tasks/pleroma/ecto/rollback_test.exs @@ -13,7 +13,7 @@ defmodule Mix.Tasks.Pleroma.Ecto.RollbackTest do assert capture_log(fn -> Mix.Tasks.Pleroma.Ecto.Rollback.run(["--env", "test"]) - end) =~ "[info] Rollback succesfully" + end) =~ "[info] Rollback successfully" Logger.configure(level: level) end diff --git a/test/mix/tasks/pleroma/robots_txt_test.exs b/test/mix/tasks/pleroma/robots_txt_test.exs @@ -26,7 +26,7 @@ defmodule Mix.Tasks.Pleroma.RobotsTxtTest do assert file == "User-Agent: *\nDisallow: /\n" end - test "to existance folder" do + test "to existing folder" do path = "test/fixtures/" file_path = path <> "robots.txt" clear_config([:instance, :static_dir], path) diff --git a/test/pleroma/activity_test.exs b/test/pleroma/activity_test.exs @@ -145,6 +145,7 @@ defmodule Pleroma.ActivityTest do setup do: clear_config([:instance, :limit_to_local_content]) + @tag :skip_darwin test "finds utf8 text in statuses", %{ japanese_activity: japanese_activity, user: user diff --git a/test/pleroma/config/deprecation_warnings_test.exs b/test/pleroma/config/deprecation_warnings_test.exs @@ -125,13 +125,12 @@ defmodule Pleroma.Config.DeprecationWarningsTest do media_removal: ["some.removal", {"some.other.instance", "Some reason"}] ) - expected_config = [ + expected_config = {:media_removal, [{"some.removal", ""}, {"some.other.instance", "Some reason"}]} - ] capture_log(fn -> DeprecationWarnings.warn() end) - assert Config.get([:mrf_simple]) == expected_config + assert expected_config in Config.get([:mrf_simple]) end test "doesn't give a warning with correct config" do @@ -215,7 +214,7 @@ defmodule Pleroma.Config.DeprecationWarningsTest do ``` config :pleroma, :mrf, - transparency_exclusions: [{"instance.tld", "Reason to exlude transparency"}] + transparency_exclusions: [{"instance.tld", "Reason to exclude transparency"}] ``` """ end @@ -327,11 +326,11 @@ defmodule Pleroma.Config.DeprecationWarningsTest do end) =~ "Your config is using old namespace for activity expiration configuration." end - test "check_uploders_s3_public_endpoint/0" do + test "check_uploaders_s3_public_endpoint/0" do clear_config([Pleroma.Uploaders.S3], public_endpoint: "https://fake.amazonaws.com/bucket/") assert capture_log(fn -> - DeprecationWarnings.check_uploders_s3_public_endpoint() + DeprecationWarnings.check_uploaders_s3_public_endpoint() end) =~ "Your config is using the old setting for controlling the URL of media uploaded to your S3 bucket." end diff --git a/test/pleroma/config_db_test.exs b/test/pleroma/config_db_test.exs @@ -321,7 +321,7 @@ defmodule Pleroma.ConfigDBTest do }) == {:proxy_url, {:socks5, {127, 0, 0, 1}, 1234}} end - test "tuple with n childs" do + test "tuple with n children" do assert ConfigDB.to_elixir_types(%{ "tuple" => [ "v1", @@ -399,7 +399,7 @@ defmodule Pleroma.ConfigDBTest do assert ConfigDB.to_elixir_types(a: 1, b: 2, c: "string") == [a: 1, b: 2, c: "string"] end - test "complex keyword with nested mixed childs" do + test "complex keyword with nested mixed children" do assert ConfigDB.to_elixir_types([ %{"tuple" => [":uploader", "Pleroma.Uploaders.Local"]}, %{"tuple" => [":filters", ["Pleroma.Upload.Filter.Dedupe"]]}, diff --git a/test/pleroma/conversation/participation_test.exs b/test/pleroma/conversation/participation_test.exs @@ -57,7 +57,7 @@ defmodule Pleroma.Conversation.ParticipationTest do assert Participation.unread_count(other_user) == 0 end - test "for a new conversation, it sets the recipents of the participation" do + test "for a new conversation, it sets the recipients of the participation" do user = insert(:user) other_user = insert(:user) third_user = insert(:user) diff --git a/test/pleroma/emoji/loader_test.exs b/test/pleroma/emoji/loader_test.exs @@ -72,7 +72,7 @@ defmodule Pleroma.Emoji.LoaderTest do assert group == "special file" end - test "no mathing returns nil", %{groups: groups} do + test "no matching returns nil", %{groups: groups} do group = groups |> Loader.match_extra("/emoji/some_undefined.png") diff --git a/test/pleroma/formatter_test.exs b/test/pleroma/formatter_test.exs @@ -324,7 +324,7 @@ defmodule Pleroma.FormatterTest do assert {_text, [], ^expected_tags} = Formatter.linkify(text) end - test "parses mulitple tags in html" do + test "parses multiple tags in html" do text = "<p>#tag1 #tag2 #tag3 #tag4</p>" expected_tags = [ @@ -347,7 +347,7 @@ defmodule Pleroma.FormatterTest do assert {_text, [], ^expected_tags} = Formatter.linkify(text) end - test "parses mulitple tags on mulitple lines in html" do + test "parses multiple tags on multiple lines in html" do text = "<p>testing...</p><p>#tag1 #tag2 #tag3 #tag4</p><p>paragraph</p><p>#tag5 #tag6 #tag7 #tag8</p>" diff --git a/test/pleroma/healthcheck_test.exs b/test/pleroma/healthcheck_test.exs @@ -9,14 +9,16 @@ defmodule Pleroma.HealthcheckTest do test "system_info/0" do result = Healthcheck.system_info() |> Map.from_struct() - assert Map.keys(result) == [ + keys = Map.keys(result) + + assert Keyword.equal?(keys, [ :active, :healthy, :idle, :job_queue_stats, :memory_used, :pool_size - ] + ]) end describe "check_health/1" do @@ -25,7 +27,7 @@ defmodule Pleroma.HealthcheckTest do refute result.healthy end - test "chech_health/1" do + test "check_health/1" do result = Healthcheck.check_health(%Healthcheck{pool_size: 10, active: 9}) assert result.healthy end diff --git a/test/pleroma/http/adapter_helper/gun_test.exs b/test/pleroma/http/adapter_helper/gun_test.exs @@ -36,7 +36,7 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do assert opts[:certificates_verification] end - test "https url with non standart port" do + test "https url with non-standard port" do uri = URI.parse("https://example.com:115") opts = Gun.options([receive_conn: false], uri) @@ -44,7 +44,7 @@ defmodule Pleroma.HTTP.AdapterHelper.GunTest do assert opts[:certificates_verification] end - test "merges with defaul http adapter config" do + test "merges with default http adapter config" do defaults = Gun.options([receive_conn: false], URI.parse("https://example.com")) assert Keyword.has_key?(defaults, :a) assert Keyword.has_key?(defaults, :b) diff --git a/test/pleroma/mfa/totp_test.exs b/test/pleroma/mfa/totp_test.exs @@ -7,6 +7,8 @@ defmodule Pleroma.MFA.TOTPTest do alias Pleroma.MFA.TOTP + import Pleroma.Tests.Helpers, only: [uri_equal?: 2] + test "create provisioning_uri to generate qrcode" do uri = TOTP.provisioning_uri("test-secrcet", "test@example.com", @@ -15,7 +17,9 @@ defmodule Pleroma.MFA.TOTPTest do period: 60 ) - assert uri == + assert uri_equal?( + uri, "otpauth://totp/test@example.com?digits=8&issuer=Plerome-42&period=60&secret=test-secrcet" + ) end end diff --git a/test/pleroma/otp_version_test.exs b/test/pleroma/otp_version_test.exs @@ -28,7 +28,7 @@ defmodule Pleroma.OTPVersionTest do "23.0" end - test "with non existance file" do + test "with nonexistent file" do assert OTPVersion.get_version_from_files([ "test/fixtures/warnings/otp_version/non-exising", "test/fixtures/warnings/otp_version/22.4" diff --git a/test/pleroma/repo/migrations/autolinker_to_linkify_test.exs b/test/pleroma/repo/migrations/autolinker_to_linkify_test.exs @@ -29,13 +29,13 @@ defmodule Pleroma.Repo.Migrations.AutolinkerToLinkifyTest do %{value: new_opts} = ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Formatter}) - assert new_opts == [ + assert Keyword.equal?(new_opts, class: false, extra: true, new_window: false, rel: "testing", strip_prefix: false - ] + ) clear_config(Pleroma.Formatter, new_opts) assert new_opts == Pleroma.Config.get(Pleroma.Formatter) @@ -67,6 +67,6 @@ defmodule Pleroma.Repo.Migrations.AutolinkerToLinkifyTest do strip_prefix: false ] - assert migration.transform_opts(old_opts) == expected_opts + assert Keyword.equal?(migration.transform_opts(old_opts), expected_opts) end end diff --git a/test/pleroma/repo/migrations/fix_malformed_formatter_config_test.exs b/test/pleroma/repo/migrations/fix_malformed_formatter_config_test.exs @@ -26,13 +26,13 @@ defmodule Pleroma.Repo.Migrations.FixMalformedFormatterConfigTest do %{value: new_opts} = ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Formatter}) - assert new_opts == [ + assert Keyword.equal?(new_opts, class: false, extra: true, new_window: false, rel: "F", strip_prefix: false - ] + ) clear_config(Pleroma.Formatter, new_opts) assert new_opts == Pleroma.Config.get(Pleroma.Formatter) diff --git a/test/pleroma/reverse_proxy_test.exs b/test/pleroma/reverse_proxy_test.exs @@ -306,7 +306,7 @@ defmodule Pleroma.ReverseProxyTest do end describe "response content disposition header" do - test "not atachment", %{conn: conn} do + test "not attachment", %{conn: conn} do disposition_headers_mock([ {"content-type", "image/gif"}, {"content-length", "0"} diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs @@ -226,7 +226,7 @@ defmodule Pleroma.UserTest do assert [] = User.get_follow_requests(followed) end - test "follow_all follows mutliple users" do + test "follow_all follows multiple users" do user = insert(:user) followed_zero = insert(:user) followed_one = insert(:user) @@ -250,7 +250,7 @@ defmodule Pleroma.UserTest do refute User.following?(user, reverse_blocked) end - test "follow_all follows mutliple users without duplicating" do + test "follow_all follows multiple users without duplicating" do user = insert(:user) followed_zero = insert(:user) followed_one = insert(:user) @@ -873,7 +873,7 @@ defmodule Pleroma.UserTest do end end - describe "get_or_fetch/1 remote users with tld, while BE is runned on subdomain" do + describe "get_or_fetch/1 remote users with tld, while BE is running on a subdomain" do setup do: clear_config([Pleroma.Web.WebFinger, :update_nickname_on_user_fetch], true) test "for mastodon" do @@ -1018,13 +1018,13 @@ defmodule Pleroma.UserTest do @tag capture_log: true test "returns nil if no user could be fetched" do - {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la") - assert fetched_user == "not found nonexistant@social.heldscal.la" + {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistent@social.heldscal.la") + assert fetched_user == "not found nonexistent@social.heldscal.la" end - test "returns nil for nonexistant local user" do - {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant") - assert fetched_user == "not found nonexistant" + test "returns nil for nonexistent local user" do + {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistent") + assert fetched_user == "not found nonexistent" end test "updates an existing user, if stale" do @@ -1132,7 +1132,7 @@ defmodule Pleroma.UserTest do assert cs.valid? end - test "it sets the follower_adress" do + test "it sets the follower_address" do cs = User.remote_user_changeset(@valid_remote) # remote users get a fake local follower address assert cs.changes.follower_address == @@ -2683,13 +2683,23 @@ defmodule Pleroma.UserTest do end describe "full_nickname/1" do - test "returns fully qualified nickname for local and remote users" do - local_user = - insert(:user, nickname: "local_user", ap_id: "https://somehost.com/users/local_user") + test "returns fully qualified nickname for local users" do + local_user = insert(:user, nickname: "local_user") + assert User.full_nickname(local_user) == "local_user@localhost" + end + + test "returns fully qualified nickname for local users when using different domain for webfinger" do + clear_config([Pleroma.Web.WebFinger, :domain], "plemora.dev") + + local_user = insert(:user, nickname: "local_user") + + assert User.full_nickname(local_user) == "local_user@plemora.dev" + end + + test "returns fully qualified nickname for remote users" do remote_user = insert(:user, nickname: "remote@host.com", local: false) - assert User.full_nickname(local_user) == "local_user@somehost.com" assert User.full_nickname(remote_user) == "remote@host.com" end diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -1028,7 +1028,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do refute repeat_activity in activities end - test "see your own posts even when they adress actors from blocked domains" do + test "see your own posts even when they address actors from blocked domains" do user = insert(:user) domain = "dogwhistle.zone" diff --git a/test/pleroma/web/activity_pub/mrf/ensure_re_prepended_test.exs b/test/pleroma/web/activity_pub/mrf/ensure_re_prepended_test.exs @@ -24,7 +24,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.EnsureRePrependedTest do assert res["object"]["summary"] == "re: object-summary" end - test "it adds `re:` to summary object when child summary containts re-subject of parent summary " do + test "it adds `re:` to summary object when child summary contains re-subject of parent summary " do message = %{ "type" => "Create", "object" => %{ diff --git a/test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs b/test/pleroma/web/activity_pub/mrf/steal_emoji_policy_test.exs @@ -60,6 +60,33 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do |> File.exists?() end + test "works with unknown extension", %{path: path} do + message = %{ + "type" => "Create", + "object" => %{ + "emoji" => [{"firedfox", "https://example.org/emoji/firedfox"}], + "actor" => "https://example.org/users/admin" + } + } + + fullpath = Path.join(path, "firedfox.png") + + Tesla.Mock.mock(fn %{method: :get, url: "https://example.org/emoji/firedfox"} -> + %Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")} + end) + + clear_config(:mrf_steal_emoji, hosts: ["example.org"], size_limit: 284_468) + + refute "firedfox" in installed() + refute File.exists?(path) + + assert {:ok, _message} = StealEmojiPolicy.filter(message) + + assert "firedfox" in installed() + assert File.exists?(path) + assert File.exists?(fullpath) + end + test "reject regex shortcode", %{message: message} do refute "firedfox" in installed() diff --git a/test/pleroma/web/activity_pub/mrf_test.exs b/test/pleroma/web/activity_pub/mrf_test.exs @@ -1,10 +1,13 @@ # 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.MRFTest do use ExUnit.Case use Pleroma.Tests.Helpers + + import ExUnit.CaptureLog + alias Pleroma.Web.ActivityPub.MRF test "subdomains_regex/1" do @@ -61,6 +64,14 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do refute MRF.subdomain_match?(regexes, "EXAMPLE.COM") refute MRF.subdomain_match?(regexes, "example.com") end + + @tag capture_log: true + test "logs sensible error on accidental wildcard" do + assert_raise Regex.CompileError, fn -> + assert capture_log(MRF.subdomains_regex(["*unsafe.tld"])) =~ + "MRF: Invalid subdomain Regex: *unsafe.tld" + end + end end describe "instance_list_from_tuples/1" do diff --git a/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/attachment_validator_test.exs @@ -164,7 +164,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do assert attachment.mediaType == "image/jpeg" end - test "it transforms image dimentions to our internal format" do + test "it transforms image dimensions to our internal format" do attachment = %{ "type" => "Document", "name" => "Hello world", diff --git a/test/pleroma/web/activity_pub/object_validators/chat_validation_test.exs b/test/pleroma/web/activity_pub/object_validators/chat_validation_test.exs @@ -147,6 +147,21 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ChatValidationTest do assert object["attachment"] end + test "validates for a basic object with content but attachment set to empty array", %{ + user: user, + recipient: recipient + } do + {:ok, valid_chat_message, _} = Builder.chat_message(user, recipient.ap_id, "Hello!") + + valid_chat_message = + valid_chat_message + |> Map.put("attachment", []) + + assert {:ok, object, _meta} = ObjectValidator.validate(valid_chat_message, []) + + assert object == Map.drop(valid_chat_message, ["attachment"]) + end + test "does not validate if the message has no content", %{ valid_chat_message: valid_chat_message } do diff --git a/test/pleroma/web/activity_pub/publisher_test.exs b/test/pleroma/web/activity_pub/publisher_test.exs @@ -212,7 +212,8 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do actor = insert(:user) inbox = "http://404.site/users/nick1/inbox" - assert {:error, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1}) + assert {:discard, _} = + Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1}) assert called(Instances.set_unreachable(inbox)) end @@ -268,7 +269,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do describe "publish/2" do test_with_mock "doesn't publish a non-public activity to quarantined instances.", - Pleroma.Web.Federator.Publisher, + Pleroma.Web.ActivityPub.Publisher, [:passthrough], [] do Config.put([:instance, :quarantined_instances], [{"domain.com", "some reason"}]) @@ -295,7 +296,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do assert res == :ok assert not called( - Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{ + Publisher.enqueue_one(%{ inbox: "https://domain.com/users/nick1/inbox", actor_id: actor.id, id: note_activity.data["id"] @@ -304,7 +305,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do end test_with_mock "Publishes a non-public activity to non-quarantined instances.", - Pleroma.Web.Federator.Publisher, + Pleroma.Web.ActivityPub.Publisher, [:passthrough], [] do Config.put([:instance, :quarantined_instances], [{"somedomain.com", "some reason"}]) @@ -331,8 +332,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do assert res == :ok assert called( - Pleroma.Web.Federator.Publisher.enqueue_one( - Publisher, + Publisher.enqueue_one( %{ inbox: "https://domain.com/users/nick1/inbox", actor_id: actor.id, @@ -344,7 +344,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do end test_with_mock "Publishes to directly addressed actors with higher priority.", - Pleroma.Web.Federator.Publisher, + Pleroma.Web.ActivityPub.Publisher, [:passthrough], [] do note_activity = insert(:direct_note_activity) @@ -356,8 +356,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do assert res == :ok assert called( - Pleroma.Web.Federator.Publisher.enqueue_one( - Publisher, + Publisher.enqueue_one( %{ inbox: :_, actor_id: actor.id, @@ -369,7 +368,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do end test_with_mock "publishes an activity with BCC to all relevant peers.", - Pleroma.Web.Federator.Publisher, + Pleroma.Web.ActivityPub.Publisher, [:passthrough], [] do follower = @@ -393,7 +392,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do assert res == :ok assert called( - Pleroma.Web.Federator.Publisher.enqueue_one(Publisher, %{ + Publisher.enqueue_one(%{ inbox: "https://domain.com/users/nick1/inbox", actor_id: actor.id, id: note_activity.data["id"] @@ -402,7 +401,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do end test_with_mock "publishes a delete activity to peers who signed fetch requests to the create acitvity/object.", - Pleroma.Web.Federator.Publisher, + Pleroma.Web.ActivityPub.Publisher, [:passthrough], [] do fetcher = @@ -443,8 +442,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do assert res == :ok assert called( - Pleroma.Web.Federator.Publisher.enqueue_one( - Publisher, + Publisher.enqueue_one( %{ inbox: "https://domain.com/users/nick1/inbox", actor_id: actor.id, @@ -455,8 +453,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do ) assert called( - Pleroma.Web.Federator.Publisher.enqueue_one( - Publisher, + Publisher.enqueue_one( %{ inbox: "https://domain2.com/users/nick1/inbox", actor_id: actor.id, diff --git a/test/pleroma/web/activity_pub/side_effects_test.exs b/test/pleroma/web/activity_pub/side_effects_test.exs @@ -17,11 +17,19 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.SideEffects + alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.CommonAPI + alias Pleroma.Web.CommonAPI.ActivityDraft import Mock import Pleroma.Factory + defp get_announces_of_object(%{data: %{"id" => id}} = _object) do + Pleroma.Activity.Queries.by_type("Announce") + |> Pleroma.Activity.Queries.by_object_id(id) + |> Pleroma.Repo.all() + end + describe "handle_after_transaction" do test "it streams out notifications and streams" do author = insert(:user, local: true) @@ -915,4 +923,85 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do assert User.get_follow_state(user, followed, nil) == nil end end + + describe "Group actors" do + setup do + poster = + insert(:user, + local: false, + nickname: "poster@example.com", + ap_id: "https://example.com/users/poster" + ) + + group = insert(:user, actor_type: "Group") + + make_create = fn mentioned_users -> + mentions = mentioned_users |> Enum.map(fn u -> "@#{u.nickname}" end) |> Enum.join(" ") + {:ok, draft} = ActivityDraft.create(poster, %{status: "#{mentions} hey"}) + + create_activity_data = + Utils.make_create_data(draft.changes |> Map.put(:published, nil), %{}) + |> put_in(["object", "id"], "https://example.com/object") + |> put_in(["id"], "https://example.com/activity") + + assert Enum.all?(mentioned_users, fn u -> u.ap_id in create_activity_data["to"] end) + + create_activity_data + end + + %{poster: poster, group: group, make_create: make_create} + end + + test "group should boost it", %{make_create: make_create, group: group} do + create_activity_data = make_create.([group]) + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, _meta} = + SideEffects.handle(create_activity, + local: false, + object_data: create_activity_data["object"] + ) + + object = Object.normalize(create_activity, fetch: false) + assert [announce] = get_announces_of_object(object) + assert announce.actor == group.ap_id + end + + test "remote group should not boost it", %{make_create: make_create, group: group} do + remote_group = + insert(:user, actor_type: "Group", local: false, nickname: "remotegroup@example.com") + + create_activity_data = make_create.([group, remote_group]) + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, _meta} = + SideEffects.handle(create_activity, + local: false, + object_data: create_activity_data["object"] + ) + + object = Object.normalize(create_activity, fetch: false) + assert [announce] = get_announces_of_object(object) + assert announce.actor == group.ap_id + end + + test "group should not boost it if group is blocking poster", %{ + make_create: make_create, + group: group, + poster: poster + } do + {:ok, _} = CommonAPI.block(group, poster) + create_activity_data = make_create.([group]) + {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false) + + {:ok, _create_activity, _meta} = + SideEffects.handle(create_activity, + local: false, + object_data: create_activity_data["object"] + ) + + object = Object.normalize(create_activity, fetch: false) + assert [] = get_announces_of_object(object) + end + end end diff --git a/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/note_handling_test.exs @@ -251,6 +251,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do assert object.data["content"] == "Hi" end + test "it works for incoming notices with a nil contentMap (firefish)" do + data = + File.read!("test/fixtures/mastodon-post-activity-contentmap.json") + |> Jason.decode!() + |> Map.put("contentMap", nil) + + {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) + object = Object.normalize(data["object"], fetch: false) + + assert object.data["content"] == + "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>" + end + test "it works for incoming notices with to/cc not being an array (kroeg)" do data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!() @@ -538,7 +551,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do [data: data] end - test "returns not modified object when hasn't containts inReplyTo field", %{data: data} do + test "returns not modified object when has no inReplyTo field", %{data: data} do assert Transmogrifier.fix_in_reply_to(data) == data end diff --git a/test/pleroma/web/activity_pub/transmogrifier/undo_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/undo_handling_test.exs @@ -32,7 +32,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.UndoHandlingTest do assert activity.data["type"] == "Undo" end - test "it returns an error for incoming unlikes wihout a like activity" do + test "it returns an error for incoming unlikes without a like activity" do user = insert(:user) {:ok, activity} = CommonAPI.post(user, %{status: "leave a like pls"}) diff --git a/test/pleroma/web/activity_pub/utils_test.exs b/test/pleroma/web/activity_pub/utils_test.exs @@ -17,7 +17,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do require Pleroma.Constants describe "strip_report_status_data/1" do - test "does not break on issues with the reported activites" do + test "does not break on issues with the reported activities" do reporter = insert(:user) target_account = insert(:user) {:ok, activity} = CommonAPI.post(target_account, %{status: "foobar"}) @@ -153,7 +153,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do assert Enum.sort(cc) == expected_cc end - test "does not adress actor's follower address if the activity is not public", %{ + test "does not address actor's follower address if the activity is not public", %{ user: user, other_user: other_user, third_user: third_user @@ -636,7 +636,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do end describe "get_cached_emoji_reactions/1" do - test "returns the normalized data or an emtpy list" do + test "returns the normalized data or an empty list" do object = insert(:note) assert Utils.get_cached_emoji_reactions(object) == [] diff --git a/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs b/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs @@ -163,7 +163,7 @@ defmodule Pleroma.Web.AdminAPI.OAuthAppControllerTest do assert response == "" end - test "with non existance id", %{conn: conn} do + test "with nonexistent id", %{conn: conn} do response = conn |> delete("/api/pleroma/admin/oauth_app/0") diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs @@ -26,8 +26,15 @@ defmodule Pleroma.Web.CommonAPITest do import Mox import Pleroma.Factory + require Pleroma.Activity.Queries require Pleroma.Constants + defp get_announces_of_object(%{data: %{"id" => id}} = _object) do + Pleroma.Activity.Queries.by_type("Announce") + |> Pleroma.Activity.Queries.by_object_id(id) + |> Pleroma.Repo.all() + end + setup_all do Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) :ok @@ -1835,4 +1842,54 @@ defmodule Pleroma.Web.CommonAPITest do assert Map.has_key?(updated_object.data, "updated") end end + + describe "Group actors" do + setup do + poster = insert(:user) + group = insert(:user, actor_type: "Group") + other_group = insert(:user, actor_type: "Group") + %{poster: poster, group: group, other_group: other_group} + end + + test "it boosts public posts", %{poster: poster, group: group} do + {:ok, post} = CommonAPI.post(poster, %{status: "hey @#{group.nickname}"}) + + announces = get_announces_of_object(post.object) + assert [_] = announces + end + + test "it does not boost private posts", %{poster: poster, group: group} do + {:ok, private_post} = + CommonAPI.post(poster, %{status: "hey @#{group.nickname}", visibility: "private"}) + + assert [] = get_announces_of_object(private_post.object) + end + + test "remote groups do not boost any posts", %{poster: poster} do + remote_group = + insert(:user, actor_type: "Group", local: false, nickname: "remote@example.com") + + {:ok, post} = CommonAPI.post(poster, %{status: "hey @#{User.full_nickname(remote_group)}"}) + assert remote_group.ap_id in post.data["to"] + + announces = get_announces_of_object(post.object) + assert [] = announces + end + + test "multiple groups mentioned", %{poster: poster, group: group, other_group: other_group} do + {:ok, post} = + CommonAPI.post(poster, %{status: "hey @#{group.nickname} @#{other_group.nickname}"}) + + announces = get_announces_of_object(post.object) + assert [_, _] = announces + end + + test "it does not boost if group is blocking poster", %{poster: poster, group: group} do + {:ok, _} = CommonAPI.block(group, poster) + {:ok, post} = CommonAPI.post(poster, %{status: "hey @#{group.nickname}"}) + + announces = get_announces_of_object(post.object) + assert [] = announces + end + end end diff --git a/test/pleroma/web/federator_test.exs b/test/pleroma/web/federator_test.exs @@ -40,6 +40,44 @@ defmodule Pleroma.Web.FederatorTest do %{activity: activity, relay_mock: relay_mock} end + test "to shared inbox when multiple actors from same instance are recipients" do + user = insert(:user) + + shared_inbox = "https://domain.com/inbox" + + follower_one = + insert(:user, %{ + local: false, + nickname: "nick1@domain.com", + ap_id: "https://domain.com/users/nick1", + inbox: "https://domain.com/users/nick1/inbox", + shared_inbox: shared_inbox + }) + + follower_two = + insert(:user, %{ + local: false, + nickname: "nick2@domain.com", + ap_id: "https://domain.com/users/nick2", + inbox: "https://domain.com/users/nick2/inbox", + shared_inbox: shared_inbox + }) + + {:ok, _, _} = Pleroma.User.follow(follower_one, user) + {:ok, _, _} = Pleroma.User.follow(follower_two, user) + + {:ok, _activity} = CommonAPI.post(user, %{status: "Happy Friday everyone!"}) + + ObanHelpers.perform(all_enqueued(worker: PublisherWorker)) + + inboxes = + all_enqueued(worker: PublisherWorker) + |> Enum.filter(&(get_in(&1, [Access.key(:args), Access.key("op")]) == "publish_one")) + |> Enum.map(&get_in(&1, [Access.key(:args), Access.key("params"), Access.key("inbox")])) + + assert [shared_inbox] == inboxes + end + test "with relays active, it publishes to the relay", %{ activity: activity, relay_mock: relay_mock diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -1360,7 +1360,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do assert user.registration_reason == "I'm a cool dude, bro" end - test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do + test "returns error when user already registered", %{conn: conn, valid_params: valid_params} do _user = insert(:user, email: "lain@example.org") app_token = insert(:oauth_token, user: nil) @@ -1495,7 +1495,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do |> Plug.Conn.put_req_header("authorization", "Bearer " <> token) |> put_req_header("content-type", "multipart/form-data") |> post("/api/v1/accounts", %{ - nickname: "nickanme", + nickname: "nickname", agreement: true, email: "email@example.com", fullname: "Lain", @@ -1781,7 +1781,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do assert %{language: "ru_RU"} = Pleroma.User.get_by_nickname("foo") end - test "createing an account without language parameter should fallback to cookie/header language", + test "creating an account without language parameter should fallback to cookie/header language", %{conn: conn} do params = %{ username: "foo2", diff --git a/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/search_controller_test.exs @@ -42,6 +42,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do end end + @tag :skip_darwin test "search", %{conn: conn} do user = insert(:user) user_two = insert(:user, %{nickname: "shp@shitposter.club"}) diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -12,6 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do alias Pleroma.Object alias Pleroma.Repo alias Pleroma.ScheduledActivity + alias Pleroma.Tests.Helpers alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub @@ -2191,7 +2192,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do # Using the header for pagination works correctly [next, _] = get_resp_header(result, "link") |> hd() |> String.split(", ") - [_, max_id] = Regex.run(~r/max_id=([^&]+)/, next) + [next_url, _next_rel] = String.split(next, ";") + next_url = String.trim_trailing(next_url, ">") |> String.trim_leading("<") + + max_id = Helpers.get_query_parameter(next_url, "max_id") assert max_id == third_favorite.id diff --git a/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs @@ -3,7 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do - use Pleroma.Web.ConnCase, async: true + use Pleroma.Web.ConnCase, async: false import Pleroma.Factory @@ -35,17 +35,20 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do defmacro assert_error_when_disable_push(do: yield) do quote do - vapid_details = Application.get_env(:web_push_encryption, :vapid_details, []) - Application.put_env(:web_push_encryption, :vapid_details, []) - assert %{"error" => "Web push subscription is disabled on this Pleroma instance"} == unquote(yield) - - Application.put_env(:web_push_encryption, :vapid_details, vapid_details) end end describe "when disabled" do + setup do + vapid_config = Application.get_env(:web_push_encryption, :vapid_details) + + Application.put_env(:web_push_encryption, :vapid_details, []) + + on_exit(fn -> Application.put_env(:web_push_encryption, :vapid_details, vapid_config) end) + end + test "POST returns error", %{conn: conn} do assert_error_when_disable_push do conn diff --git a/test/pleroma/web/mastodon_api/update_credentials_test.exs b/test/pleroma/web/mastodon_api/update_credentials_test.exs @@ -732,4 +732,20 @@ defmodule Pleroma.Web.MastodonAPI.UpdateCredentialsTest do assert account["source"]["pleroma"]["actor_type"] == "Person" end end + + describe "Mark account as group" do + setup do: oauth_access(["write:accounts"]) + setup :request_content_type + + test "changing actor_type to Group makes account a Group and enables bot indicator for backward compatibility", + %{conn: conn} do + account = + conn + |> patch("/api/v1/accounts/update_credentials", %{actor_type: "Group"}) + |> json_response_and_validate_schema(200) + + assert account["bot"] + assert account["source"]["pleroma"]["actor_type"] == "Group" + end + end end diff --git a/test/pleroma/web/o_auth/mfa_controller_test.exs b/test/pleroma/web/o_auth/mfa_controller_test.exs @@ -214,7 +214,7 @@ defmodule Pleroma.Web.OAuth.MFAControllerTest do assert response == %{"error" => "Invalid code"} end - test "returns error when client credentails is wrong ", %{conn: conn, user: user} do + test "returns error when client credentials is wrong ", %{conn: conn, user: user} do otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret) mfa_token = insert(:mfa_token, user: user) diff --git a/test/pleroma/web/o_auth/token/utils_test.exs b/test/pleroma/web/o_auth/token/utils_test.exs @@ -13,7 +13,7 @@ defmodule Pleroma.Web.OAuth.Token.UtilsTest do Utils.fetch_app(%Plug.Conn{params: %{"client_id" => 1, "client_secret" => "x"}}) end - test "returns App by params credentails" do + test "returns App by params credentials" do app = insert(:oauth_app) assert {:ok, load_app} = @@ -24,7 +24,7 @@ defmodule Pleroma.Web.OAuth.Token.UtilsTest do assert load_app == app end - test "returns App by header credentails" do + test "returns App by header credentials" do app = insert(:oauth_app) header = "Basic " <> Base.encode64("#{app.client_id}:#{app.client_secret}") diff --git a/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs @@ -7,6 +7,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do alias Pleroma.Chat alias Pleroma.Chat.MessageReference alias Pleroma.Object + alias Pleroma.Tests.Helpers alias Pleroma.UnstubbedConfigMock, as: ConfigMock alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub @@ -212,36 +213,63 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do result = json_response_and_validate_schema(response, 200) [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ") - api_endpoint = "/api/v1/pleroma/chats/" + api_endpoint = Pleroma.Web.Endpoint.url() <> "/api/v1/pleroma/chats/" + + [next_url, next_rel] = String.split(next, ";") + next_url = String.trim_trailing(next_url, ">") |> String.trim_leading("<") + + next_url_sorted = Helpers.uri_query_sort(next_url) assert String.match?( - next, - ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*; rel=\"next\"$) + next_url_sorted, + ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&offset=\d+$) ) + assert next_rel =~ "next" + + [prev_url, prev_rel] = String.split(prev, ";") + prev_url = String.trim_trailing(prev_url, ">") |> String.trim_leading("<") + + prev_url_sorted = Helpers.uri_query_sort(prev_url) + assert String.match?( - prev, - ~r(#{api_endpoint}.*/messages\?limit=\d+&min_id=.*; rel=\"prev\"$) + prev_url_sorted, + ~r(#{api_endpoint}.*/messages\?limit=\d+&min_id=.*&offset=\d+$) ) + assert prev_rel =~ "prev" + assert length(result) == 20 - response = - get(conn, "/api/v1/pleroma/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}") + response = get(conn, "#{api_endpoint}#{chat.id}/messages?max_id=#{List.last(result)["id"]}") result = json_response_and_validate_schema(response, 200) [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ") + [next_url, next_rel] = String.split(next, ";") + next_url = String.trim_trailing(next_url, ">") |> String.trim_leading("<") + + next_url_sorted = Helpers.uri_query_sort(next_url) + assert String.match?( - next, - ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*; rel=\"next\"$) + next_url_sorted, + ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&offset=\d+$) ) + assert next_rel =~ "next" + + [prev_url, prev_rel] = String.split(prev, ";") + prev_url = String.trim_trailing(prev_url, ">") |> String.trim_leading("<") + + prev_url_sorted = Helpers.uri_query_sort(prev_url) + assert String.match?( - prev, - ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&min_id=.*; rel=\"prev\"$) + prev_url_sorted, + ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&min_id=.*&offset=\d+$) ) + assert prev_rel =~ "prev" + assert length(result) == 10 end diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs @@ -116,7 +116,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> json(%{metadata: %{features: ["shareable_emoji_packs"]}}) - %{method: :get, url: "https://example.com/api/pleroma/emoji/packs?page=2&page_size=1"} -> + %{method: :get, url: "https://example.com/api/v1/pleroma/emoji/packs?page=2&page_size=1"} -> json(resp) end) @@ -199,7 +199,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=test_pack" + url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack&page_size=" <> _n } -> conn |> get("/api/pleroma/emoji/pack?name=test_pack") @@ -208,7 +208,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/archive?name=test_pack" + url: "https://example.com/api/v1/pleroma/emoji/packs/archive?name=test_pack" } -> conn |> get("/api/pleroma/emoji/packs/archive?name=test_pack") @@ -217,7 +217,9 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=test_pack_nonshared" + url: + "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack_nonshared&page_size=" <> + _n } -> conn |> get("/api/pleroma/emoji/pack?name=test_pack_nonshared") @@ -305,14 +307,14 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=pack_bad_sha" + url: "https://example.com/api/v1/pleroma/emoji/pack?name=pack_bad_sha&page_size=" <> _n } -> {:ok, pack} = Pleroma.Emoji.Pack.load_pack("pack_bad_sha") %Tesla.Env{status: 200, body: Jason.encode!(pack)} %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/archive?name=pack_bad_sha" + url: "https://example.com/api/v1/pleroma/emoji/packs/archive?name=pack_bad_sha" } -> %Tesla.Env{ status: 200, @@ -342,7 +344,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=test_pack" + url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack&page_size=" <> _n } -> {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack") %Tesla.Env{status: 200, body: Jason.encode!(pack)} diff --git a/test/pleroma/web/pleroma_api/controllers/instances_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/instances_controller_test.exs @@ -16,7 +16,7 @@ defmodule Pleroma.Web.PleromaApi.InstancesControllerTest do {:ok, %Pleroma.Instances.Instance{unreachable_since: constant_unreachable}} = Instances.set_consistently_unreachable(constant) - _eventual_unrechable = Instances.set_unreachable(eventual) + _eventual_unreachable = Instances.set_unreachable(eventual) %{constant_unreachable: constant_unreachable, constant: constant} end diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs @@ -23,8 +23,15 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do assert response.status == 200 - assert response.resp_body == - ~s(<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="#{Pleroma.Web.Endpoint.url()}/.well-known/webfinger?resource={uri}" type="application/xrd+xml" /></XRD>) + response_xml = + response.resp_body + |> Floki.parse_document!(html_parser: Floki.HTMLParser.Mochiweb, attributes_as_maps: true) + + expected_xml = + ~s(<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="#{Pleroma.Web.Endpoint.url()}/.well-known/webfinger?resource={uri}" type="application/xrd+xml" /></XRD>) + |> Floki.parse_document!(html_parser: Floki.HTMLParser.Mochiweb, attributes_as_maps: true) + + assert match?(^response_xml, expected_xml) end test "Webfinger JRD" do @@ -48,12 +55,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do ] end - test "reach user on tld, while pleroma is runned on subdomain" do - Pleroma.Web.Endpoint.config_change( - [{Pleroma.Web.Endpoint, url: [host: "sub.example.com"]}], - [] - ) - + test "reach user on tld, while pleroma is running on subdomain" do clear_config([Pleroma.Web.Endpoint, :url, :host], "sub.example.com") clear_config([Pleroma.Web.WebFinger, :domain], "example.com") @@ -68,13 +70,6 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do assert response["subject"] == "acct:#{user.nickname}@example.com" assert response["aliases"] == ["https://sub.example.com/users/#{user.nickname}"] - - on_exit(fn -> - Pleroma.Web.Endpoint.config_change( - [{Pleroma.Web.Endpoint, url: [host: "localhost"]}], - [] - ) - end) end test "it returns 404 when user isn't found (JSON)" do diff --git a/test/support/helpers.ex b/test/support/helpers.ex @@ -10,6 +10,39 @@ defmodule Pleroma.Tests.Helpers do require Logger + @doc "Accepts two URLs/URIs and sorts the query parameters before comparing" + def uri_equal?(a, b) do + a_sorted = uri_query_sort(a) + b_sorted = uri_query_sort(b) + + match?(^a_sorted, b_sorted) + end + + @doc "Accepts a URL/URI and sorts the query parameters" + def uri_query_sort(uri) do + parsed = URI.parse(uri) + + sorted_query = + String.split(parsed.query, "&") + |> Enum.sort() + |> Enum.join("&") + + parsed + |> Map.put(:query, sorted_query) + |> URI.to_string() + end + + @doc "Returns the value of the specified query parameter for the provided URL" + def get_query_parameter(url, param) do + url + |> URI.parse() + |> Map.get(:query) + |> URI.query_decoder() + |> Enum.to_list() + |> Enum.into(%{}, fn {x, y} -> {x, y} end) + |> Map.get(param) + end + defmacro clear_config(config_path) do quote do clear_config(unquote(config_path)) do diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex @@ -178,7 +178,7 @@ defmodule HttpRequestMock do end def get( - "https://social.heldscal.la/.well-known/webfinger?resource=nonexistant@social.heldscal.la", + "https://social.heldscal.la/.well-known/webfinger?resource=nonexistent@social.heldscal.la", _, _, [{"accept", "application/xrd+xml,application/jrd+json"}] @@ -186,7 +186,7 @@ defmodule HttpRequestMock do {:ok, %Tesla.Env{ status: 200, - body: File.read!("test/fixtures/tesla_mock/nonexistant@social.heldscal.la.xml") + body: File.read!("test/fixtures/tesla_mock/nonexistent@social.heldscal.la.xml") }} end diff --git a/test/test_helper.exs b/test/test_helper.exs @@ -6,6 +6,12 @@ Code.put_compiler_option(:warnings_as_errors, true) ExUnit.start(exclude: [:federated, :erratic]) +if match?({:unix, :darwin}, :os.type()) do + excluded = ExUnit.configuration() |> Keyword.get(:exclude, []) + excluded = excluded ++ [:skip_darwin] + ExUnit.configure(exclude: excluded) +end + Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual) Mox.defmock(Pleroma.ReverseProxy.ClientMock, for: Pleroma.ReverseProxy.Client)