diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bfd9bf414..675d0e067 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -79,12 +79,12 @@ build-1.14.5-otp-25: script: - mix compile --force -build-1.18.3-otp-27: +build-1.17.1-otp-26: extends: - .build_changes_policy - .using-ci-base stage: build - image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.18.3-otp-27 + image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.17.1-otp-26 script: - mix compile --force @@ -142,12 +142,12 @@ unit-testing-1.14.5-otp-25: coverage_format: cobertura path: coverage.xml -unit-testing-1.18.3-otp-27: +unit-testing-1.17.1-otp-26: extends: - .build_changes_policy - .using-ci-base stage: test - image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.18.3-otp-27 + image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.17.1-otp-26 cache: *testing_cache_policy services: *testing_services script: *testing_script @@ -208,7 +208,7 @@ docs-deploy: before_script: - apk add curl script: - - curl --fail-with-body -X POST -F"token=$DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" https://git.pleroma.social/api/v4/projects/673/trigger/pipeline + - curl --fail-with-body -X POST -F"token=$CI_JOB_TOKEN" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" https://git.pleroma.social/api/v4/projects/673/trigger/pipeline review_app: image: alpine:3.9 stage: deploy @@ -249,7 +249,7 @@ spec-deploy: before_script: - apk add curl script: - - curl --fail-with-body -X POST -F"token=$API_DOCS_PIPELINE_TRIGGER" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline + - curl --fail-with-body -X POST -F"token=$CI_JOB_TOKEN" -F'ref=master' -F"variables[BRANCH]=$CI_COMMIT_REF_NAME" -F"variables[JOB_REF]=$CI_JOB_ID" https://git.pleroma.social/api/v4/projects/1130/trigger/pipeline stop_review_app: diff --git a/changelog.d/activity_type_index.change b/changelog.d/activity_type_index.change deleted file mode 100644 index ea2d7adbe..000000000 --- a/changelog.d/activity_type_index.change +++ /dev/null @@ -1 +0,0 @@ -Add new activity actor/type index. Greatly speeds up retrieval of rare types (like "Listen") diff --git a/changelog.d/admin-api-docs-fix.skip b/changelog.d/admin-api-docs-fix.skip deleted file mode 100644 index 5c1c68ea0..000000000 --- a/changelog.d/admin-api-docs-fix.skip +++ /dev/null @@ -1 +0,0 @@ -Fix 'Create a user' description in admin api docs diff --git a/changelog.d/admin-api-log-fix.skip b/changelog.d/admin-api-log-fix.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/assign-app-user-oom.fix b/changelog.d/assign-app-user-oom.fix deleted file mode 100644 index ac1de7159..000000000 --- a/changelog.d/assign-app-user-oom.fix +++ /dev/null @@ -1 +0,0 @@ -Fix AssignAppUser migration OOM diff --git a/changelog.d/deepl-json.fix b/changelog.d/deepl-json.fix deleted file mode 100644 index ee6f8664e..000000000 --- a/changelog.d/deepl-json.fix +++ /dev/null @@ -1 +0,0 @@ -Use JSON for DeepL API requests diff --git a/changelog.d/dislike-activity.add b/changelog.d/dislike-activity.add deleted file mode 100644 index 1fcbda78b..000000000 --- a/changelog.d/dislike-activity.add +++ /dev/null @@ -1 +0,0 @@ -Support Dislike activity, as sent by Mitra and Friendica, by changing it into a thumbs-down EmojiReact \ No newline at end of file diff --git a/changelog.d/doc-typo.skip b/changelog.d/doc-typo.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/elixir-1-18.fix b/changelog.d/elixir-1-18.fix deleted file mode 100644 index d4d5a3493..000000000 --- a/changelog.d/elixir-1-18.fix +++ /dev/null @@ -1 +0,0 @@ -Elixir 1.18: Fixed warnings and new deprecations diff --git a/changelog.d/emoji_likes.add b/changelog.d/emoji_likes.add deleted file mode 100644 index 13c91a950..000000000 --- a/changelog.d/emoji_likes.add +++ /dev/null @@ -1 +0,0 @@ -Support Mitra-style emoji likes. diff --git a/changelog.d/expiring-blocks.add b/changelog.d/expiring-blocks.add deleted file mode 100644 index 29989af15..000000000 --- a/changelog.d/expiring-blocks.add +++ /dev/null @@ -1 +0,0 @@ -Add `duration` to the block endpoint, which makes block expire \ No newline at end of file diff --git a/changelog.d/expose-markup-configuration.add b/changelog.d/expose-markup-configuration.add deleted file mode 100644 index 8c7f35697..000000000 --- a/changelog.d/expose-markup-configuration.add +++ /dev/null @@ -1 +0,0 @@ -Expose markup configuration in InstanceView diff --git a/changelog.d/fixtests.skip b/changelog.d/fixtests.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/freebsd-rc.fix b/changelog.d/freebsd-rc.fix deleted file mode 100644 index 1f59d4596..000000000 --- a/changelog.d/freebsd-rc.fix +++ /dev/null @@ -1 +0,0 @@ -Set PATH in the FreeBSD rc script to avoid failures starting the service diff --git a/changelog.d/gin-search.fix b/changelog.d/gin-search.fix deleted file mode 100644 index ba9977b6e..000000000 --- a/changelog.d/gin-search.fix +++ /dev/null @@ -1 +0,0 @@ -Improved performance of status search queries using the default GIN index diff --git a/changelog.d/language-detection.add b/changelog.d/language-detection.add deleted file mode 100644 index 6d1a7f705..000000000 --- a/changelog.d/language-detection.add +++ /dev/null @@ -1 +0,0 @@ -Implement language detection with fastText \ No newline at end of file diff --git a/changelog.d/openbsd-docs-update.skip b/changelog.d/openbsd-docs-update.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/openbsd-update-httpd-relayd.change b/changelog.d/openbsd-update-httpd-relayd.change deleted file mode 100644 index 2ee85c2b0..000000000 --- a/changelog.d/openbsd-update-httpd-relayd.change +++ /dev/null @@ -1 +0,0 @@ -Updated relayd/httpd config files to be on par with nginx diff --git a/changelog.d/openbsd-update-rc.fix b/changelog.d/openbsd-update-rc.fix deleted file mode 100644 index 2d4263827..000000000 --- a/changelog.d/openbsd-update-rc.fix +++ /dev/null @@ -1 +0,0 @@ -replaced depracated flags and functions, renamed service to fit other service files diff --git a/changelog.d/preserve-public-cc.fix b/changelog.d/preserve-public-cc.fix deleted file mode 100644 index 1b20ce9ad..000000000 --- a/changelog.d/preserve-public-cc.fix +++ /dev/null @@ -1 +0,0 @@ -Fix federation issue where Public visibility information in cc field was lost when sent to remote servers, causing posts to appear with inconsistent visibility across instances diff --git a/changelog.d/private-functions.skip b/changelog.d/private-functions.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/relax-also-known-as.change b/changelog.d/relax-also-known-as.change deleted file mode 100644 index 800c3e72a..000000000 --- a/changelog.d/relax-also-known-as.change +++ /dev/null @@ -1 +0,0 @@ -Relax alsoKnownAs requirements to just URI, not necessarily HTTP(S) \ No newline at end of file diff --git a/changelog.d/releases.fix b/changelog.d/releases.fix deleted file mode 100644 index 5436accc7..000000000 --- a/changelog.d/releases.fix +++ /dev/null @@ -1 +0,0 @@ -Fix release builds diff --git a/changelog.d/remove-forgotten-OTPVersion-usage.skip b/changelog.d/remove-forgotten-OTPVersion-usage.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/scrobbles.change b/changelog.d/scrobbles.change deleted file mode 100644 index ed1777b2d..000000000 --- a/changelog.d/scrobbles.change +++ /dev/null @@ -1 +0,0 @@ -Change scrobble external link param name to use snake case \ No newline at end of file diff --git a/changelog.d/siteinfo-baseurls.add b/changelog.d/siteinfo-baseurls.add deleted file mode 100644 index 6f0f19847..000000000 --- a/changelog.d/siteinfo-baseurls.add +++ /dev/null @@ -1 +0,0 @@ -Add `base_urls` to the /api/v1/instance pleroma metadata which provides information about the base URLs for media_proxy and uploads when configured \ No newline at end of file diff --git a/changelog.d/toctou-mkdir.fix b/changelog.d/toctou-mkdir.fix deleted file mode 100644 index b070db1a0..000000000 --- a/changelog.d/toctou-mkdir.fix +++ /dev/null @@ -1 +0,0 @@ -Backport [Elixir PR 14242](https://github.com/elixir-lang/elixir/pull/14242) fixing racy mkdir and lack of error handling of parent directory creation \ No newline at end of file diff --git a/changelog.d/tos-setting.add b/changelog.d/tos-setting.add deleted file mode 100644 index db9b0d5f2..000000000 --- a/changelog.d/tos-setting.add +++ /dev/null @@ -1 +0,0 @@ -Allow Terms of Service panel behaviour to be configurable diff --git a/changelog.d/translate-posts.add b/changelog.d/translate-posts.add deleted file mode 100644 index e7a9317a1..000000000 --- a/changelog.d/translate-posts.add +++ /dev/null @@ -1 +0,0 @@ -Support translation providers (DeepL, LibreTranslate) \ No newline at end of file diff --git a/changelog.d/truncate-rich-media.change b/changelog.d/truncate-rich-media.change deleted file mode 100644 index 1df064be1..000000000 --- a/changelog.d/truncate-rich-media.change +++ /dev/null @@ -1 +0,0 @@ -Truncate the length of Rich Media title and description fields diff --git a/changelog.d/typos.skip b/changelog.d/typos.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/webfinger.change b/changelog.d/webfinger.change deleted file mode 100644 index 353e65a89..000000000 --- a/changelog.d/webfinger.change +++ /dev/null @@ -1 +0,0 @@ -Don't require an Accept header for WebFinger queries and default to JSON. \ No newline at end of file diff --git a/ci/elixir-1.18.3-otp-27/Dockerfile b/ci/elixir-1.18.3-otp-27/Dockerfile deleted file mode 100644 index 2b42aa90d..000000000 --- a/ci/elixir-1.18.3-otp-27/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -FROM elixir:1.18.3-otp-27 - -# Single RUN statement, otherwise intermediate images are created -# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run -RUN apt-get update &&\ - apt-get install -y libmagic-dev cmake libimage-exiftool-perl ffmpeg &&\ - mix local.hex --force &&\ - mix local.rebar --force diff --git a/ci/elixir-1.18.3-otp-27/build_and_push.sh b/ci/elixir-1.18.3-otp-27/build_and_push.sh deleted file mode 100755 index 8a564fbf2..000000000 --- a/ci/elixir-1.18.3-otp-27/build_and_push.sh +++ /dev/null @@ -1 +0,0 @@ -docker buildx build --platform linux/amd64,linux/arm64 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.18.3-otp-27 --push . diff --git a/config/config.exs b/config/config.exs index b211d0776..d90d56d9b 100644 --- a/config/config.exs +++ b/config/config.exs @@ -48,7 +48,7 @@ config :pleroma, ecto_repos: [Pleroma.Repo] config :pleroma, Pleroma.Repo, telemetry_event: [Pleroma.Repo.Instrumenter], - migration_lock: :pg_advisory_lock + migration_lock: nil config :pleroma, Pleroma.Captcha, enabled: true, @@ -305,7 +305,6 @@ config :pleroma, :frontend_configurations, collapseMessageWithSubject: false, disableChat: false, greentext: false, - embeddedToS: true, hideFilteredStatuses: false, hideMutedPosts: false, hidePostStats: false, diff --git a/config/description.exs b/config/description.exs index e20fa4b28..996978298 100644 --- a/config/description.exs +++ b/config/description.exs @@ -1261,7 +1261,6 @@ config :pleroma, :config_description, [ background: "/static/aurora_borealis.jpg", collapseMessageWithSubject: false, greentext: false, - embeddedToS: true, hideFilteredStatuses: false, hideMutedPosts: false, hidePostStats: false, @@ -1313,12 +1312,6 @@ config :pleroma, :config_description, [ type: :boolean, description: "Enables green text on lines prefixed with the > character" }, - %{ - key: :embeddedToS, - label: "Embedded ToS panel", - type: :boolean, - description: "Hide Terms of Service panel decorations on About and Registration pages" - }, %{ key: :hideFilteredStatuses, label: "Hide Filtered Statuses", @@ -3507,71 +3500,5 @@ config :pleroma, :config_description, [ suggestion: [100_000] } ] - }, - %{ - group: :pleroma, - key: Pleroma.Language.LanguageDetector, - type: :group, - description: "Language detection providers", - children: [ - %{ - key: :provider, - type: :module, - suggestions: [ - Pleroma.Language.LanguageDetector.Fasttext - ] - }, - %{ - group: {:subgroup, Pleroma.Language.LanguageDetector.Fasttext}, - key: :model, - label: "fastText language detection model", - type: :string, - suggestions: ["/usr/share/fasttext/lid.176.bin"] - } - ] - }, - %{ - group: :pleroma, - key: Pleroma.Language.Translation, - type: :group, - description: "Translation providers", - children: [ - %{ - key: :provider, - type: :module, - suggestions: [ - Pleroma.Language.Translation.Deepl, - Pleroma.Language.Translation.Libretranslate - ] - }, - %{ - group: {:subgroup, Pleroma.Language.Translation.Deepl}, - key: :base_url, - label: "DeepL base URL", - type: :string, - suggestions: ["https://api-free.deepl.com", "https://api.deepl.com"] - }, - %{ - group: {:subgroup, Pleroma.Language.Translation.Deepl}, - key: :api_key, - label: "DeepL API Key", - type: :string, - suggestions: ["YOUR_API_KEY"] - }, - %{ - group: {:subgroup, Pleroma.Language.Translation.Libretranslate}, - key: :base_url, - label: "LibreTranslate instance URL", - type: :string, - suggestions: ["https://libretranslate.com"] - }, - %{ - group: {:subgroup, Pleroma.Language.Translation.Libretranslate}, - key: :api_key, - label: "LibreTranslate API Key", - type: :string, - suggestions: ["YOUR_API_KEY"] - } - ] } ] diff --git a/config/test.exs b/config/test.exs index fefdc2bbc..0f8b12ffe 100644 --- a/config/test.exs +++ b/config/test.exs @@ -156,7 +156,6 @@ config :pleroma, Pleroma.User.Backup, config_impl: Pleroma.UnstubbedConfigMock config :pleroma, Pleroma.Uploaders.S3, ex_aws_impl: Pleroma.Uploaders.S3.ExAwsMock config :pleroma, Pleroma.Uploaders.S3, config_impl: Pleroma.UnstubbedConfigMock config :pleroma, Pleroma.Upload, config_impl: Pleroma.UnstubbedConfigMock -config :pleroma, Pleroma.Language.LanguageDetector, config_impl: Pleroma.StaticStubbedConfigMock config :pleroma, Pleroma.ScheduledActivity, config_impl: Pleroma.UnstubbedConfigMock config :pleroma, Pleroma.Web.RichMedia.Helpers, config_impl: Pleroma.StaticStubbedConfigMock config :pleroma, Pleroma.Uploaders.IPFS, config_impl: Pleroma.UnstubbedConfigMock diff --git a/docs/development/API/admin_api.md b/docs/development/API/admin_api.md index 64c06ca2b..409e78a1e 100644 --- a/docs/development/API/admin_api.md +++ b/docs/development/API/admin_api.md @@ -70,8 +70,6 @@ The `/api/v1/pleroma/admin/*` path is backwards compatible with `/api/pleroma/ad - `nicknames` - Response: Array of user nicknames -## `POST /api/v1/pleroma/admin/users` - ### Create a user - Method: `POST` @@ -83,7 +81,7 @@ The `/api/v1/pleroma/admin/*` path is backwards compatible with `/api/pleroma/ad `password` } ] -- Response: Array of user objects +- Response: User’s nickname ## `POST /api/v1/pleroma/admin/users/follow` diff --git a/docs/development/API/pleroma_api.md b/docs/development/API/pleroma_api.md index b17f61cbb..000d7d27d 100644 --- a/docs/development/API/pleroma_api.md +++ b/docs/development/API/pleroma_api.md @@ -671,7 +671,6 @@ Audio scrobbling in Pleroma is **deprecated**. "artist": "Some Artist", "album": "Some Album", "length": 180000, - "external_link": "https://www.last.fm/music/Some+Artist/_/Some+Title", "created_at": "2019-09-28T12:40:45.000Z" } ] diff --git a/docs/development/index.md b/docs/development/index.md index 6b35321c5..01a617596 100644 --- a/docs/development/index.md +++ b/docs/development/index.md @@ -1,7 +1 @@ This section contains notes and guidelines for developers. - -- [Setting up a Pleroma development environment](setting_up_pleroma_dev.md) -- [Setting up a Gitlab Runner](setting_up_a_gitlab_runner.md) -- [Authentication & Authorization](authentication_authorization.md) -- [ActivityPub Extensions](ap_extensions.md) -- [Mox Testing Guide](mox_testing.md) diff --git a/docs/development/mox_testing.md b/docs/development/mox_testing.md deleted file mode 100644 index 673064022..000000000 --- a/docs/development/mox_testing.md +++ /dev/null @@ -1,485 +0,0 @@ -# Using Mox for Testing in Pleroma - -## Introduction - -This guide explains how to use [Mox](https://hexdocs.pm/mox/Mox.html) for testing in Pleroma and how to migrate existing tests from Mock/meck to Mox. Mox is a library for defining concurrent mocks in Elixir that offers several key advantages: - -- **Async-safe testing**: Mox supports concurrent testing with `async: true` -- **Explicit contract through behaviors**: Enforces implementation of behavior callbacks -- **No module redefinition**: Avoids runtime issues caused by redefining modules -- **Expectations scoped to the current process**: Prevents test state from leaking between tests - -## Why Migrate from Mock/meck to Mox? - -### Problems with Mock/meck - -1. **Not async-safe**: Tests using Mock/meck cannot safely run with `async: true`, which slows down the test suite -2. **Global state**: Mocked functions are global, leading to potential cross-test contamination -3. **No explicit contract**: No guarantee that mocked functions match the actual implementation -4. **Module redefinition**: Can lead to hard-to-debug runtime issues - -### Benefits of Mox - -1. **Async-safe testing**: Tests can run concurrently with `async: true`, significantly speeding up the test suite -2. **Process isolation**: Expectations are set per process, preventing leakage between tests -3. **Explicit contracts via behaviors**: Ensures mocks implement all required functions -4. **Compile-time checks**: Prevents mocking non-existent functions -5. **No module redefinition**: Mocks are defined at compile time, not runtime - -## Existing Mox Setup in Pleroma - -Pleroma already has a basic Mox setup in the `Pleroma.DataCase` module, which handles some common mocking scenarios automatically. Here's what's included: - -### Default Mox Configuration - -The `setup` function in `DataCase` does the following: - -1. Sets up Mox for either async or non-async tests -2. Verifies all mock expectations on test exit -3. Stubs common dependencies with their real implementations - -```elixir -# From test/support/data_case.ex -setup tags do - setup_multi_process_mode(tags) - setup_streamer(tags) - stub_pipeline() - - Mox.verify_on_exit!() - - :ok -end -``` - -### Async vs. Non-Async Test Setup - -Pleroma configures Mox differently depending on whether your test is async or not: - -```elixir -def setup_multi_process_mode(tags) do - :ok = Ecto.Adapters.SQL.Sandbox.checkout(Pleroma.Repo) - - if tags[:async] do - # For async tests, use process-specific mocks and stub CachexMock with NullCache - Mox.stub_with(Pleroma.CachexMock, Pleroma.NullCache) - Mox.set_mox_private() - else - # For non-async tests, use global mocks and stub CachexMock with CachexProxy - Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, {:shared, self()}) - - Mox.set_mox_global() - Mox.stub_with(Pleroma.CachexMock, Pleroma.CachexProxy) - clear_cachex() - end - - :ok -end -``` - -### Default Pipeline Stubs - -Pleroma automatically stubs several core components with their real implementations: - -```elixir -def stub_pipeline do - Mox.stub_with(Pleroma.Web.ActivityPub.SideEffectsMock, Pleroma.Web.ActivityPub.SideEffects) - Mox.stub_with(Pleroma.Web.ActivityPub.ObjectValidatorMock, Pleroma.Web.ActivityPub.ObjectValidator) - Mox.stub_with(Pleroma.Web.ActivityPub.MRFMock, Pleroma.Web.ActivityPub.MRF) - Mox.stub_with(Pleroma.Web.ActivityPub.ActivityPubMock, Pleroma.Web.ActivityPub.ActivityPub) - Mox.stub_with(Pleroma.Web.FederatorMock, Pleroma.Web.Federator) - Mox.stub_with(Pleroma.ConfigMock, Pleroma.Config) - Mox.stub_with(Pleroma.StaticStubbedConfigMock, Pleroma.Test.StaticConfig) - Mox.stub_with(Pleroma.StubbedHTTPSignaturesMock, Pleroma.Test.HTTPSignaturesProxy) -end -``` - -This means that by default, these mocks will behave like their real implementations unless you explicitly override them with expectations in your tests. - -### Understanding Config Mock Types - -Pleroma has three different Config mock implementations, each with a specific purpose and different characteristics regarding async test safety: - -#### 1. ConfigMock - -- Defined in `test/support/mocks.ex` as `Mox.defmock(Pleroma.ConfigMock, for: Pleroma.Config.Getting)` -- It's stubbed with the real `Pleroma.Config` by default in `DataCase`: `Mox.stub_with(Pleroma.ConfigMock, Pleroma.Config)` -- This means it falls back to the normal configuration behavior unless explicitly overridden -- Used for general mocking of configuration in tests where you want most config to behave normally -- ⚠️ **NOT ASYNC-SAFE**: Since it's stubbed with the real `Pleroma.Config`, it modifies global application state -- Can not be used in tests with `async: true` - -#### 2. StaticStubbedConfigMock - -- Defined in `test/support/mocks.ex` as `Mox.defmock(Pleroma.StaticStubbedConfigMock, for: Pleroma.Config.Getting)` -- It's stubbed with `Pleroma.Test.StaticConfig` (defined in `test/test_helper.exs`) -- `Pleroma.Test.StaticConfig` creates a completely static configuration snapshot at the start of the test run: - ```elixir - defmodule Pleroma.Test.StaticConfig do - @moduledoc """ - This module provides a Config that is completely static, built at startup time from the environment. - It's safe to use in testing as it will not modify any state. - """ - - @behaviour Pleroma.Config.Getting - @config Application.get_all_env(:pleroma) - - def get(path, default \\ nil) do - get_in(@config, path) || default - end - end - ``` -- Configuration is frozen at startup time and doesn't change during the test run -- ✅ **ASYNC-SAFE**: Never modifies global state since it uses a frozen snapshot of the configuration - -#### 3. UnstubbedConfigMock - -- Defined in `test/support/mocks.ex` as `Mox.defmock(Pleroma.UnstubbedConfigMock, for: Pleroma.Config.Getting)` -- Unlike the other two mocks, it's not automatically stubbed with any implementation in `DataCase` -- Starts completely "unstubbed" and requires tests to explicitly set expectations or stub it -- The most commonly used configuration mock in the test suite -- Often aliased as `ConfigMock` in individual test files: `alias Pleroma.UnstubbedConfigMock, as: ConfigMock` -- Set as the default config implementation in `config/test.exs`: `config :pleroma, :config_impl, Pleroma.UnstubbedConfigMock` -- Offers maximum flexibility for tests that need precise control over configuration values -- ✅ **ASYNC-SAFE**: Safe if used with `expect()` to set up test-specific expectations (since expectations are process-scoped) - -#### Configuring Components to Use Specific Mocks - -In `config/test.exs`, different components can be configured to use different configuration mocks: - -```elixir -# Components using UnstubbedConfigMock -config :pleroma, Pleroma.Upload, config_impl: Pleroma.UnstubbedConfigMock -config :pleroma, Pleroma.User.Backup, config_impl: Pleroma.UnstubbedConfigMock -config :pleroma, Pleroma.Uploaders.S3, config_impl: Pleroma.UnstubbedConfigMock - -# Components using StaticStubbedConfigMock (async-safe) -config :pleroma, Pleroma.Language.LanguageDetector, config_impl: Pleroma.StaticStubbedConfigMock -config :pleroma, Pleroma.Web.RichMedia.Helpers, config_impl: Pleroma.StaticStubbedConfigMock -config :pleroma, Pleroma.Web.Plugs.HTTPSecurityPlug, config_impl: Pleroma.StaticStubbedConfigMock -``` - -This allows different parts of the application to use the most appropriate configuration mocking strategy based on their specific needs. - -#### When to Use Each Config Mock Type - -- **ConfigMock**: ⚠️ For non-async tests only, when you want most configuration to behave normally with occasional overrides -- **StaticStubbedConfigMock**: ✅ For async tests where modifying global state would be problematic and a static configuration is sufficient -- **UnstubbedConfigMock**: ⚠️ Use carefully in async tests; set specific expectations rather than stubbing with implementations that modify global state - -#### Summary of Async Safety - -| Mock Type | Async-Safe? | Best Use Case | -|-----------|-------------|--------------| -| ConfigMock | ❌ No | Non-async tests that need minimal configuration overrides | -| StaticStubbedConfigMock | ✅ Yes | Async tests that need configuration values without modification | -| UnstubbedConfigMock | ⚠️ Depends | Any test with careful usage; set expectations rather than stubbing | - -## Configuration in Async Tests - -### Understanding `clear_config` Limitations - -The `clear_config` helper is commonly used in Pleroma tests to modify configuration for specific tests. However, it's important to understand that **`clear_config` is not async-safe** and should not be used in tests with `async: true`. - -Here's why: - -```elixir -# Implementation of clear_config in test/support/helpers.ex -defmacro clear_config(config_path, temp_setting) do - quote do - clear_config(unquote(config_path)) do - Config.put(unquote(config_path), unquote(temp_setting)) - end - end -end - -defmacro clear_config(config_path, do: yield) do - quote do - initial_setting = Config.fetch(unquote(config_path)) - - unquote(yield) - - on_exit(fn -> - case initial_setting do - :error -> - Config.delete(unquote(config_path)) - - {:ok, value} -> - Config.put(unquote(config_path), value) - end - end) - - :ok - end -end -``` - -The issue is that `clear_config`: -1. Modifies the global application environment -2. Uses `on_exit` to restore the original value after the test -3. Can lead to race conditions when multiple async tests modify the same configuration - -### Async-Safe Configuration Approaches - -When writing async tests with Mox, use these approaches instead of `clear_config`: - -1. **Dependency Injection with Module Attributes**: - ```elixir - # In your module - @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config) - - def some_function do - value = @config_impl.get([:some, :config]) - # ... - end - ``` - -2. **Mock the Config Module**: - ```elixir - # In your test - Pleroma.ConfigMock - |> expect(:get, fn [:some, :config] -> "test_value" end) - ``` - -3. **Use Test-Specific Implementations**: - ```elixir - # Define a test-specific implementation - defmodule TestConfig do - def get([:some, :config]), do: "test_value" - def get(_), do: nil - end - - # In your test - Mox.stub_with(Pleroma.ConfigMock, TestConfig) - ``` - -4. **Pass Configuration as Arguments**: - ```elixir - # Refactor functions to accept configuration as arguments - def some_function(config \\ nil) do - config = config || Pleroma.Config.get([:some, :config]) - # ... - end - - # In your test - some_function("test_value") - ``` - -By using these approaches, you can safely run tests with `async: true` without worrying about configuration conflicts. - -## Setting Up Mox in Pleroma - -### Step 1: Define a Behavior - -Start by defining a behavior for the module you want to mock. This specifies the contract that both the real implementation and mocks must follow. - -```elixir -# In your implementation module (e.g., lib/pleroma/uploaders/s3.ex) -defmodule Pleroma.Uploaders.S3.ExAwsAPI do - @callback request(op :: ExAws.Operation.t()) :: {:ok, ExAws.Operation.t()} | {:error, term()} -end -``` - -### Step 2: Make Your Implementation Configurable - -Modify your module to use a configurable implementation. This allows for dependency injection and easier testing. - -```elixir -# In your implementation module -@ex_aws_impl Application.compile_env(:pleroma, [__MODULE__, :ex_aws_impl], ExAws) -@config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config) - -def put_file(%Pleroma.Upload{} = upload) do - # Use @ex_aws_impl instead of ExAws directly - case @ex_aws_impl.request(op) do - {:ok, _} -> - {:ok, {:file, s3_name}} - - error -> - Logger.error("#{__MODULE__}: #{inspect(error)}") - error - end -end -``` - -### Step 3: Define the Mock in test/support/mocks.ex - -Add your mock definition in the central mocks file: - -```elixir -# In test/support/mocks.ex -Mox.defmock(Pleroma.Uploaders.S3.ExAwsMock, for: Pleroma.Uploaders.S3.ExAwsAPI) -``` - -### Step 4: Configure the Mock in Test Environment - -In your test configuration (e.g., `config/test.exs`), specify which mock implementation to use: - -```elixir -config :pleroma, Pleroma.Uploaders.S3, ex_aws_impl: Pleroma.Uploaders.S3.ExAwsMock -config :pleroma, Pleroma.Uploaders.S3, config_impl: Pleroma.UnstubbedConfigMock -``` - -## Writing Tests with Mox - -### Setting Up Your Test - -```elixir -defmodule Pleroma.Uploaders.S3Test do - use Pleroma.DataCase, async: true # Note: async: true is now possible! - - alias Pleroma.Uploaders.S3 - alias Pleroma.Uploaders.S3.ExAwsMock - alias Pleroma.UnstubbedConfigMock, as: ConfigMock - - import Mox # Import Mox functions - - # Note: verify_on_exit! is already called in DataCase setup - # so you don't need to add it explicitly in your test module -end -``` - -### Setting Expectations with Mox - -Mox uses an explicit expectation system. Here's how to use it: - -```elixir -# Basic expectation for a function call -ExAwsMock -|> expect(:request, fn _req -> {:ok, %{status_code: 200}} end) - -# Expectation for multiple calls with same response -ExAwsMock -|> expect(:request, 3, fn _req -> {:ok, %{status_code: 200}} end) - -# Expectation with specific arguments -ExAwsMock -|> expect(:request, fn %{bucket: "test_bucket"} -> {:ok, %{status_code: 200}} end) - -# Complex configuration mocking -ConfigMock -|> expect(:get, fn key -> - [ - {Pleroma.Upload, [uploader: Pleroma.Uploaders.S3, base_url: "https://s3.amazonaws.com"]}, - {Pleroma.Uploaders.S3, [bucket: "test_bucket"]} - ] - |> get_in(key) -end) -``` - -### Understanding Mox Modes in Pleroma - -Pleroma's DataCase automatically configures Mox differently based on whether your test is async or not: - -1. **Async tests** (`async: true`): - - Uses `Mox.set_mox_private()` - expectations are scoped to the current process - - Stubs `Pleroma.CachexMock` with `Pleroma.NullCache` - - Each test process has its own isolated mock expectations - -2. **Non-async tests** (`async: false`): - - Uses `Mox.set_mox_global()` - expectations are shared across processes - - Stubs `Pleroma.CachexMock` with `Pleroma.CachexProxy` - - Mock expectations can be set in one process and called from another - -Choose the appropriate mode based on your test requirements. For most tests, async mode is preferred for better performance. - -## Migrating from Mock/meck to Mox - -Here's a step-by-step guide for migrating existing tests from Mock/meck to Mox: - -### 1. Identify the Module to Mock - -Look for `with_mock` or `test_with_mock` calls in your tests: - -```elixir -# Old approach with Mock -with_mock ExAws, request: fn _ -> {:ok, :ok} end do - assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}} -end -``` - -### 2. Define a Behavior for the Module - -Create a behavior that defines the functions you want to mock: - -```elixir -defmodule Pleroma.Uploaders.S3.ExAwsAPI do - @callback request(op :: ExAws.Operation.t()) :: {:ok, ExAws.Operation.t()} | {:error, term()} -end -``` - -### 3. Update Your Implementation to Use a Configurable Dependency - -```elixir -# Old -def put_file(%Pleroma.Upload{} = upload) do - case ExAws.request(op) do - # ... - end -end - -# New -@ex_aws_impl Application.compile_env(:pleroma, [__MODULE__, :ex_aws_impl], ExAws) - -def put_file(%Pleroma.Upload{} = upload) do - case @ex_aws_impl.request(op) do - # ... - end -end -``` - -### 4. Define the Mock in mocks.ex - -```elixir -Mox.defmock(Pleroma.Uploaders.S3.ExAwsMock, for: Pleroma.Uploaders.S3.ExAwsAPI) -``` - -### 5. Configure the Test Environment - -```elixir -config :pleroma, Pleroma.Uploaders.S3, ex_aws_impl: Pleroma.Uploaders.S3.ExAwsMock -``` - -### 6. Update Your Tests to Use Mox - -```elixir -# Old (with Mock) -test_with_mock "save file", ExAws, request: fn _ -> {:ok, :ok} end do - assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}} - assert_called(ExAws.request(:_)) -end - -# New (with Mox) -test "save file" do - ExAwsMock - |> expect(:request, fn _req -> {:ok, %{status_code: 200}} end) - - assert S3.put_file(file_upload) == {:ok, {:file, "test_folder/image-tet.jpg"}} -end -``` - -### 7. Enable Async Testing - -Now you can safely enable `async: true` in your test module: - -```elixir -use Pleroma.DataCase, async: true -``` - -## Best Practices - -1. **Always define behaviors**: They serve as contracts and documentation -2. **Keep mocks in a central location**: Use test/support/mocks.ex for all mock definitions -3. **Use verify_on_exit!**: This is already set up in DataCase, ensuring all expected calls were made -4. **Use specific expectations**: Be as specific as possible with your expectations -5. **Enable async: true**: Take advantage of Mox's concurrent testing capability -6. **Don't over-mock**: Only mock external dependencies that are difficult to test directly -7. **Leverage existing stubs**: Use the default stubs provided by DataCase when possible -8. **Avoid clear_config in async tests**: Use dependency injection and mocking instead - -## Example: Complete Migration - -For a complete example of migrating a test from Mock/meck to Mox, you can refer to commit `90a47ca050c5839e8b4dc3bac315dc436d49152d` in the Pleroma repository, which shows how the S3 uploader tests were migrated. - -## Conclusion - -Migrating tests from Mock/meck to Mox provides significant benefits for the Pleroma test suite, including faster test execution through async testing, better isolation between tests, and more robust mocking through explicit contracts. By following this guide, you can successfully migrate existing tests and write new tests using Mox. \ No newline at end of file diff --git a/docs/installation/generic_dependencies.include b/docs/installation/generic_dependencies.include index 769347a3c..9f07f62c6 100644 --- a/docs/installation/generic_dependencies.include +++ b/docs/installation/generic_dependencies.include @@ -1,8 +1,8 @@ ## Required dependencies * PostgreSQL >=11.0 -* Elixir >=1.14.0 <1.19 -* Erlang OTP >=23.0.0 (supported: <28) +* Elixir >=1.14.0 <1.17 +* Erlang OTP >=23.0.0 (supported: <27) * git * file / libmagic * gcc or clang diff --git a/docs/installation/openbsd_en.md b/docs/installation/openbsd_en.md index 1de016cdd..78bbf399f 100644 --- a/docs/installation/openbsd_en.md +++ b/docs/installation/openbsd_en.md @@ -1,29 +1,25 @@ # Installing on OpenBSD -{! backend/installation/otp_vs_from_source_source.include !} - -This guide describes the installation and configuration of Pleroma (and the required software to run it) on a single OpenBSD 7.7 server. +This guide describes the installation and configuration of pleroma (and the required software to run it) on a single OpenBSD 6.6 server. For any additional information regarding commands and configuration files mentioned here, check the man pages [online](https://man.openbsd.org/) or directly on your server with the man command. {! backend/installation/generic_dependencies.include !} -## Installation - ### Preparing the system #### Required software -To install required packages, run the following command: +To install them, run the following command (with doas or as root): ``` -# pkg_add elixir gmake git postgresql-server postgresql-contrib cmake libmagic libvips +pkg_add elixir gmake git postgresql-server postgresql-contrib cmake ffmpeg ImageMagick libvips ``` -Pleroma requires a reverse proxy, OpenBSD has relayd in base (and is used in this guide) and packages/ports are available for nginx (www/nginx) and apache (www/apache-httpd). -Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acme-client) can be used to get a certificate from Let's Encrypt. +Pleroma requires a reverse proxy, OpenBSD has relayd in base (and is used in this guide) and packages/ports are available for nginx (www/nginx) and apache (www/apache-httpd). Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acme-client) can be used to get a certificate from Let's Encrypt. #### Optional software +Per [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md): * ImageMagick * ffmpeg * exiftool @@ -31,351 +27,234 @@ Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acm To install the above: ``` -# pkg_add ImageMagick ffmpeg p5-Image-ExifTool +pkg_add ImageMagick ffmpeg p5-Image-ExifTool ``` -For more information read [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md): - -### PostgreSQL - -Switch to the \_postgresql user and initialize PostgreSQL: - -``` -# su _postgresql -$ initdb -D /var/postgresql/data -U postgres --encoding=utf-8 --lc-collate=C -``` - -Running PostgreSQL in a different directory than `/var/postgresql/data` requires changing the `daemon_flags` variable in the `/etc/rc.d/postgresql` script. - -For security reasons it is recommended to change the authentication method for `local` and `host` connections with the localhost address to `scram-sha-256`.
-Do not forget to set a password for the `postgres` user before doing so, otherwise you won't be able to log back in unless you change the authentication method back to `trust`.
-Changing the password hashing algorithm is not needed.
-For more information [read](https://www.postgresql.org/docs/16/auth-pg-hba-conf.html) the PostgreSQL documentation. - -Enable and start the postgresql service: - -``` -# rcctl enable postgresql -# rcctl start postgresql -``` - -To check that PostgreSQL started properly and didn't fail right after starting, run `# rcctl check postgresql` which should return `postgresql(ok)`. - -### Configuring Pleroma - -Pleroma will be run by a dedicated \_pleroma user. Before creating it, insert the following lines in `/etc/login.conf`: - +#### Creating the pleroma user +Pleroma will be run by a dedicated user, \_pleroma. Before creating it, insert the following lines in login.conf: ``` pleroma:\ - :datasize=1536M:\ - :openfiles-max=4096:\ - :openfiles-cur=1024:\ - :setenv=LC_ALL=en_US.UTF-8,VIX_COMPILATION_MODE=PLATFORM_PROVIDED_LIBVIPS,MIX_ENV=prod:\ - :tc=daemon: + :datasize-max=1536M:\ + :datasize-cur=1536M:\ + :openfiles-max=4096 ``` +This creates a "pleroma" login class and sets higher values than default for datasize and openfiles (see [login.conf(5)](https://man.openbsd.org/login.conf)), this is required to avoid having pleroma crash some time after starting. -This creates a "pleroma" login class and sets higher values than default for datasize and openfiles (see [login.conf(5)](https://man.openbsd.org/login.conf)), this is required to avoid having Pleroma crash some time after starting. +Create the \_pleroma user, assign it the pleroma login class and create its home directory (/home/\_pleroma/): `useradd -m -L pleroma _pleroma` -Create the \_pleroma user, assign it the pleroma login class and create its home directory (/home/\_pleroma/): +#### Clone pleroma's directory +Enter a shell as the \_pleroma user. As root, run `su _pleroma -;cd`. Then clone the repository with `git clone -b stable https://git.pleroma.social/pleroma/pleroma.git`. Pleroma is now installed in /home/\_pleroma/pleroma/, it will be configured and started at the end of this guide. + +#### PostgreSQL +Start a shell as the \_postgresql user (as root run `su _postgresql -` then run the `initdb` command to initialize postgresql: +You will need to specify pgdata directory to the default (/var/postgresql/data) with the `-D ` and set the user to postgres with the `-U ` flag. This can be done as follows: ``` -# useradd -m -L pleroma _pleroma +initdb -D /var/postgresql/data -U postgres ``` +If you are not using the default directory, you will have to update the `datadir` variable in the /etc/rc.d/postgresql script. -Switch to the _pleroma user: - +When this is done, enable postgresql so that it starts on boot and start it. As root, run: ``` -# su -l _pleroma -``` - -Clone the Pleroma repository: - -``` -$ git clone -b stable https://git.pleroma.social/pleroma/pleroma.git -$ cd pleroma -``` - -Pleroma is now installed in /home/\_pleroma/pleroma/. To configure it run: - -``` -$ mix deps.get -$ MIX_ENV=prod mix pleroma.instance gen # You will be asked a few questions here. -$ cp config/generated_config.exs config/prod.secret.exs -``` - -Note: Answer yes when asked to install Hex and rebar3. This step might take some time as Pleroma gets compiled first. - -Create the Pleroma database: - -``` -$ psql -U postgres -f config/setup_db.psql -``` - -Apply database migrations: - -``` -$ MIX_ENV=prod mix ecto.migrate -``` - -Note: You will need to run this step again when updating your instance to a newer version with `git pull` or `git checkout tags/NEW_VERSION`. - -As \_pleroma in /home/\_pleroma/pleroma, you can now run `MIX_ENV=prod mix phx.server` to start your instance. -In another SSH session or a tmux window, check that it is working properly by running `ftp -MVo - http://127.0.0.1:4000/api/v1/instance`, you should get json output. -Double-check that the *uri* value near the bottom is your instance's domain name and the instance *title* are correct. - -### Configuring acme-client - -acme-client is used to get SSL/TLS certificates from Let's Encrypt. -Insert the following configuration in `/etc/acme-client.conf` and replace `example.tld` with your domain: - -``` -# -# $OpenBSD: acme-client.conf,v 1.5 2023/05/10 07:34:57 tb Exp $ -# - -authority letsencrypt { - api url "https://acme-v02.api.letsencrypt.org/directory" - account key "/etc/acme/letsencrypt-privkey.pem" -} - -domain example.tld { - # Adds alternative names to the certificate. Useful when serving media on another domain. Comma or space separated list. - # alternative names { } - - domain key "/etc/ssl/private/example.tld.key" - domain certificate "/etc/ssl/example.tld_cert-only.crt" - domain full chain certificate "/etc/ssl/example.tld.crt" - sign with letsencrypt -} -``` - -Check the configuration: - -``` -# acme-client -n -``` - -### Configuring the Web server - -Pleroma supports two Web servers: - - * nginx (recommended for most users) - * OpenBSD's httpd and relayd (ONLY for advanced users, media proxy cache is NOT supported and will NOT work properly) - -#### nginx - -Since nginx is not installed by default, install it by running: - -``` -# pkg_add nginx -``` - -Add the following to `/etc/nginx/nginx.conf`, within the `server {}` block listening on port 80 and change `server_name`, as follows: - -``` -http { - ... - - server { - ... - server_name localhost; # Replace with your domain - - location /.well-known/acme-challenge { - rewrite ^/\.well-known/acme-challenge/(.*) /$1 break; - root /var/www/acme; - } - } -} -``` - -Start the nginx service and acquire certificates: - -``` -# rcctl start nginx -# acme-client example.tld -``` - -Add certificate auto-renewal by adding acme-client to `/etc/weekly.local`, replace `example.tld` with your domain: - -``` -# echo "acme-client example.tld && rcctl reload nginx" >> /etc/weekly.local -``` - -OpenBSD's default nginx configuration does not contain an include directive, which is typically used for multiple sites. -Therefore, you will need to first create the required directory as follows: - -``` -# mkdir /etc/nginx/sites-available -# mkdir /etc/nginx/sites-enabled -``` - -Next add the `include` directive to `/etc/nginx/nginx.conf`, within the `http {}` block, as follows: - -``` -http { - ... - - server { - ... - } - - include /etc/nginx/sites-enabled/*; -} -``` - -As root, copy `/home/_pleroma/pleroma/installation/pleroma.nginx` to `/etc/nginx/sites-available/pleroma.nginx`. - -Edit default `/etc/nginx/sites-available/pleroma.nginx` settings and replace `example.tld` with your domain: - - * Uncomment the location block for `~ /\.well-known/acme-challenge` in the server block listening on port 80 - - add `rewrite ^/\.well-known/acme-challenge/(.*) /$1 break;` above the `root` location - - change the `root` location to `/var/www/acme;` - * Change `ssl_trusted_certificate` to `/etc/ssl/example.tld_cert-only.crt` - * Change `ssl_certificate` to `/etc/ssl/example.tld.crt` - * Change `ssl_certificate_key` to `/etc/ssl/private/example.tld.key` - -Remove the following `location {}` block from `/etc/nginx/nginx.conf`, that was previously added for acquiring certificates and change `server_name` back to `localhost`: - -``` -http { - ... - - server { - ... - server_name example.tld; # Change back to localhost - - # Delete this block - location /.well-known/acme-challenge { - rewrite ^/\.well-known/acme-challenge/(.*) /$1 break; - root /var/www/acme; - } - } -} -``` - -Symlink the Pleroma configuration to the enabled sites: - -``` -# ln -s /etc/nginx/sites-available/pleroma.nginx /etc/nginx/sites-enabled -``` - -Check nginx configuration syntax by running: - -``` -# nginx -t -``` - -Note: If the above command complains about a `conflicting server name`, check again that the `location {}` block for acquiring certificates has been removed from `/etc/nginx/nginx.conf` and that the `server_name` has been reverted back to `localhost`. -After doing so run `# nginx -t` again. - -If the configuration is correct, you can now enable and reload the nginx service: - -``` -# rcctl enable nginx -# rcctl reload nginx +rcctl enable postgresql +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 - -***Skip this section when using nginx*** - -httpd will have two functions: +httpd will have three functions: * redirect requests trying to reach the instance over http to the https URL + * serve a robots.txt file * get Let's Encrypt certificates, with acme-client -As root, copy `/home/_pleroma/pleroma/installation/openbsd/httpd.conf` to `/etc/httpd.conf`, or modify the existing one. - -Edit `/etc/httpd.conf` settings and change: - - * `` with your instance's IPv4 address - * All occurrences of `example.tld` with your instance's domain name - * When using IPv6 also change: - - Uncomment the `ext_inet6=""` line near the beginning of the file and change `* to your server's address(es). If httpd should only listen on one protocol family, comment one of the two first *listen* options. + +Create the /var/www/htdocs/local/ folder and write the content of your robots.txt in /var/www/htdocs/local/robots.txt. +Check the configuration with `httpd -n`, if it is OK enable and start httpd (as root): +``` +rcctl enable httpd +rcctl start httpd ``` -If the configuration is correct, enable and start the `httpd` service: +#### acme-client +acme-client is used to get SSL/TLS certificates from Let's Encrypt. +Insert the following configuration in /etc/acme-client.conf: +``` +# +# $OpenBSD: acme-client.conf,v 1.4 2017/03/22 11:14:14 benno Exp $ +# -``` -# rcctl enable httpd -# rcctl start httpd -``` +authority letsencrypt- { + #agreement url "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf" + api url "https://acme-v02.api.letsencrypt.org/directory" + account key "/etc/acme/letsencrypt-privkey-.pem" +} -Acquire certificate: +domain { + domain key "/etc/ssl/private/.key" + domain certificate "/etc/ssl/.crt" + domain full chain certificate "/etc/ssl/.fullchain.pem" + sign with letsencrypt- + challengedir "/var/www/acme/" +} +``` +Replace ** by the domain name you'll use for your instance. As root, run `acme-client -n` to check the config, then `acme-client -ADv ` to create account and domain keys, and request a certificate for the first time. +Make acme-client run everyday by adding it in /etc/daily.local. As root, run the following command: `echo "acme-client " >> /etc/daily.local`. +Relayd will look for certificates and keys based on the address it listens on (see next part), the easiest way to make them available to relayd is to create a link, as root run: ``` -# acme-client example.tld +ln -s /etc/ssl/.fullchain.pem /etc/ssl/.crt +ln -s /etc/ssl/private/.key /etc/ssl/private/.key ``` +This will have to be done for each IPv4 and IPv6 address relayd listens on. #### relayd - -***Skip this section when using nginx*** - relayd will be used as the reverse proxy sitting in front of pleroma. - -As root, copy `/home/_pleroma/pleroma/installation/openbsd/relayd.conf` to `/etc/relayd.conf`, or modify the existing one. - -Edit `/etc/relayd.conf` settings and change: - - * `` with your instance's IPv4 address - * All occurrences of `example.tld` with your instance's domain name - * When using IPv6 also change: - - Uncomment the `ext_inet6=""` line near the beginning of the file and change `` to your instance's IPv6 address - - Uncomment the line starting with `listen on $ext_inet6` in the `relay wwwtls` block - -Check the configuration by running: +Insert the following configuration in /etc/relayd.conf: ``` -# relayd -n +# $OpenBSD: relayd.conf,v 1.4 2018/03/23 09:55:06 claudio Exp $ + +ext_inet="" +ext_inet6="" + +table { 127.0.0.1 } +table { 127.0.0.1 } + +http protocol plerup { # Protocol for upstream pleroma server + #tcp { nodelay, sack, socket buffer 65536, backlog 128 } # Uncomment and adjust as you see fit + tls ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305" + tls ecdhe secp384r1 + + # Forward some paths to the local server (as pleroma won't respond to them as you might want) + pass request quick path "/robots.txt" forward to + + # Append a bunch of headers + match request header append "X-Forwarded-For" value "$REMOTE_ADDR" # This two header and the next one are not strictly required by pleroma but adding them won't hurt + match request header append "X-Forwarded-By" value "$SERVER_ADDR:$SERVER_PORT" + + match response header append "X-XSS-Protection" value "1; mode=block" + match response header append "X-Permitted-Cross-Domain-Policies" value "none" + match response header append "X-Frame-Options" value "DENY" + match response header append "X-Content-Type-Options" value "nosniff" + match response header append "Referrer-Policy" value "same-origin" + match response header append "X-Download-Options" value "noopen" + match response header append "Content-Security-Policy" value "default-src 'none'; base-uri 'self'; form-action 'self'; img-src 'self' data: https:; media-src 'self' https:; style-src 'self' 'unsafe-inline'; font-src 'self'; script-src 'self'; connect-src 'self' wss://CHANGEME.tld; upgrade-insecure-requests;" # Modify "CHANGEME.tld" and set your instance's domain here + match request header append "Connection" value "upgrade" + #match response header append "Strict-Transport-Security" value "max-age=31536000; includeSubDomains" # Uncomment this only after you get HTTPS working. + + # If you do not want remote frontends to be able to access your Pleroma backend server, comment these lines + match response header append "Access-Control-Allow-Origin" value "*" + match response header append "Access-Control-Allow-Methods" value "POST, PUT, DELETE, GET, PATCH, OPTIONS" + match response header append "Access-Control-Allow-Headers" value "Authorization, Content-Type, Idempotency-Key" + match response header append "Access-Control-Expose-Headers" value "Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id" + # Stop commenting lines here +} + +relay wwwtls { + listen on $ext_inet port https tls # Comment to disable listening on IPv4 + listen on $ext_inet6 port https tls # Comment to disable listening on IPv6 + + protocol plerup + + forward to port 4000 check http "/" code 200 + forward to port 80 check http "/robots.txt" code 200 +} +``` +Again, change ** to your server's address(es) and comment one of the two *listen* options if needed. Also change *wss://CHANGEME.tld* to *wss://*. +Check the configuration with `relayd -n`, if it is OK enable and start relayd (as root): +``` +rcctl enable relayd +rcctl start relayd ``` -If the configuration is correct, enable and start the `relayd` service: - -``` -# rcctl enable relayd -# rcctl start relayd -``` - -Add certificate auto-renewal by adding acme-client to `/etc/weekly.local`, replace `example.tld` with your domain: - -``` -# echo "acme-client example.tld && rcctl reload relayd" >> /etc/weekly.local -``` - -#### (Strongly recommended) serve media on another domain +##### (Strongly recommended) serve media on another domain Refer to the [Hardening your instance](../configuration/hardening.md) document on how to serve media on another domain. We STRONGLY RECOMMEND you to do this to minimize attack vectors. -### Starting pleroma at boot - -Copy the startup script and make sure it's executable: - +#### pf +Enabling and configuring pf is highly recommended. +In /etc/pf.conf, insert the following configuration: ``` -# cp /home/_pleroma/pleroma/installation/openbsd/rc.d/pleroma /etc/rc.d/pleroma -# chmod 555 /etc/rc.d/pleroma +# Macros +if="" +authorized_ssh_clients="any" + +# Skip traffic on loopback interface +set skip on lo + +# Default behavior +set block-policy drop +block in log all +pass out quick + +# Security features +match in all scrub (no-df random-id) +block in log from urpf-failed + +# Rules +pass in quick on $if inet proto icmp to ($if) icmp-type { echoreq unreach paramprob trace } # ICMP +pass in quick on $if inet6 proto icmp6 to ($if) icmp6-type { echoreq unreach paramprob timex toobig } # ICMPv6 +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 ** 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`. + +#### Configure and start pleroma +Enter a shell as \_pleroma (as root `su _pleroma -`) and enter pleroma's installation directory (`cd ~/pleroma/`). + +Then follow the main installation guide: + + * run `mix deps.get` + * run `MIX_ENV=prod mix pleroma.instance gen` and enter your instance's information when asked + * copy config/generated\_config.exs to config/prod.secret.exs. The default values should be sufficient but you should edit it and check that everything seems OK. + * exit your current shell back to a root one and run `psql -U postgres -f /home/_pleroma/pleroma/config/setup_db.psql` to setup the database. + * return to a \_pleroma shell into pleroma's installation directory (`su _pleroma -;cd ~/pleroma`) and run `MIX_ENV=prod mix ecto.migrate` + +As \_pleroma in /home/\_pleroma/pleroma, you can now run `LC_ALL=en_US.UTF-8 MIX_ENV=prod mix phx.server` to start your instance. +In another SSH session/tmux window, check that it is working properly by running `ftp -MVo - http://127.0.0.1:4000/api/v1/instance`, you should get json output. Double-check that *uri*'s value is your instance's domain name. + +##### Starting pleroma at boot +An rc script to automatically start pleroma at boot hasn't been written yet, it can be run in a tmux session (tmux is in base). + + +#### Create administrative user + +If your instance is up and running, you can create your first user with administrative rights with the following command as the \_pleroma user. +``` +LC_ALL=en_US.UTF-8 MIX_ENV=prod mix pleroma.user new --admin ``` -Enable and start the pleroma service: - -``` -# rcctl enable pleroma -# rcctl start pleroma -``` - -### Create administrative user - -If your instance is up and running, you can create your first user with administrative rights with the following commands as the \_pleroma user: - -``` -$ cd pleroma -$ MIX_ENV=prod mix pleroma.user new --admin -``` - -### Further reading +#### Further reading {! backend/installation/further_reading.include !} diff --git a/docs/installation/openbsd_fi.md b/docs/installation/openbsd_fi.md index 858e64020..d7c94d8a0 100644 --- a/docs/installation/openbsd_fi.md +++ b/docs/installation/openbsd_fi.md @@ -4,7 +4,7 @@ Note: This article is potentially outdated because at this time we may not have Tarvitset: * Oman domainin -* OpenBSD 7.5 -serverin +* OpenBSD 6.3 -serverin * Auttavan ymmärryksen unix-järjestelmistä Komennot, joiden edessä on '#', tulee ajaa käyttäjänä `root`. Tämä on @@ -18,7 +18,7 @@ Matrix-kanava #pleroma:libera.chat ovat hyviä paikkoja löytää apua Asenna tarvittava ohjelmisto: -`# pkg_add git elixir gmake postgresql-server postgresql-contrib cmake libmagic libvips` +`# pkg_add git elixir gmake postgresql-server-10.3 postgresql-contrib-10.3 cmake ffmpeg ImageMagick libvips` #### Optional software diff --git a/installation/freebsd/rc.d/pleroma b/installation/freebsd/rc.d/pleroma index 149b40838..f62aef18d 100755 --- a/installation/freebsd/rc.d/pleroma +++ b/installation/freebsd/rc.d/pleroma @@ -24,6 +24,4 @@ command=/usr/local/bin/elixir command_args="--erl \"-detached\" -S /usr/local/bin/mix phx.server" procname="*beam.smp" -PATH="${PATH}:/usr/local/sbin:/usr/local/bin" - run_rc_command "$1" diff --git a/installation/openbsd/httpd.conf b/installation/openbsd/httpd.conf index f37325d91..82f4803fd 100644 --- a/installation/openbsd/httpd.conf +++ b/installation/openbsd/httpd.conf @@ -2,21 +2,20 @@ # Default httpd.conf file for Pleroma on OpenBSD # Simple installation instructions # 1. Place file in /etc -# 2. Replace with your public IP address -# 3. If using IPv6, uncomment IPv6 lines and replace with your public IPv6 address -# 4. Replace all occurences of example.tld with your instance's domain name. -# 5. Check file using 'doas httpd -n' -# 6. Enable and start httpd: +# 2. Replace with your public IP address +# 3. If using IPv6, uncomment IPv6 lines and replace with your public IPv6 address +# 4. Check file using 'doas httpd -n' +# 5. Enable and start httpd: # # doas rcctl enable httpd # # doas rcctl start httpd # -ext_inet="" -#ext_inet6="" +ext_inet="" +#ext_inet6="" -server "example.tld" { +server "default" { listen on $ext_inet port 80 # Comment to disable listening on IPv4 - #listen on $ext_inet6 port 80 # Comment to disable listening on IPv6 +# listen on $ext_inet6 port 80 # Comment to disable listening on IPv6 listen on 127.0.0.1 port 80 # Do NOT comment this line log syslog @@ -27,18 +26,10 @@ server "example.tld" { request strip 2 } - location "/*" { block return 301 "https://$HTTP_HOST$REQUEST_URI" } + location "/robots.txt" { root "/htdocs/local/" } + location "/*" { block return 302 "https://$HTTP_HOST$REQUEST_URI" } } -# Example of serving a basic static website besides Pleroma using the example configuration in relayd -#server "site.example.tld" { -# listen on 127.0.0.1 port 8080 -# -# location "/*" { -# root "/website" -# } -#} - types { include "/usr/share/misc/mime.types" } diff --git a/installation/openbsd/rc.d/pleroma b/installation/openbsd/rc.d/pleromad similarity index 63% rename from installation/openbsd/rc.d/pleroma rename to installation/openbsd/rc.d/pleromad index 6959c20b0..19ac4bb51 100755 --- a/installation/openbsd/rc.d/pleroma +++ b/installation/openbsd/rc.d/pleromad @@ -4,16 +4,15 @@ # # Simple installation instructions: # 1. Install Pleroma per wiki instructions -# 2. Place this pleroma file in /etc/rc.d +# 2. Place this pleromad file in /etc/rc.d # 3. Enable and start Pleroma -# # doas rcctl enable pleroma -# # doas rcctl start pleroma +# # doas rcctl enable pleromad +# # doas rcctl start pleromad # daemon="/usr/local/bin/elixir" -daemon_flags="--erl \"-detached\" -S /usr/local/bin/mix phx.server" +daemon_flags="--detached -S /usr/local/bin/mix phx.server" daemon_user="_pleroma" -daemon_execdir="/home/_pleroma/pleroma" . /etc/rc.d/rc.subr @@ -24,6 +23,10 @@ rc_check() { pgrep -q -U _pleroma -f "phx.server" } +rc_start() { + ${rcexec} "cd pleroma; ${daemon} ${daemon_flags}" +} + rc_stop() { pkill -q -U _pleroma -f "phx.server" } diff --git a/installation/openbsd/relayd.conf b/installation/openbsd/relayd.conf index 8b7be4ca6..31c2c1129 100644 --- a/installation/openbsd/relayd.conf +++ b/installation/openbsd/relayd.conf @@ -3,10 +3,9 @@ # Simple installation instructions: # 1. Place in /etc # 2. Replace with your public IPv4 address -# 3. If using IPv6, uncomment IPv6 lines and replace with your public IPv6 address -# 4. Replace all occurrences of example.tld with your instance's domain -# 5. Check file using 'doas relayd -n' -# 6. Reload/start relayd +# 3. If using IPv6i, uncomment IPv6 lines and replace with your public IPv6 address +# 4. Check file using 'doas relayd -n' +# 5. Reload/start relayd # # doas rcctl enable relayd # # doas rcctl start relayd # @@ -15,54 +14,31 @@ ext_inet="" #ext_inet6="" table { 127.0.0.1 } +table { 127.0.0.1 } -# Uncomment when you want to serve other services than Pleroma. -# In this example tables are used only as way to differentiate between Pleroma and other services. -# Feel free to rename "httpd_server" everywhere to fit your setup. -#table { 127.0.0.1 } - -http protocol pleroma { # Protocol for upstream Pleroma server +http protocol plerup { # Protocol for upstream pleroma server #tcp { nodelay, sack, socket buffer 65536, backlog 128 } # Uncomment and adjust as you see fit - tls ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4" - tls ecdhe "X25519,P-256,P-384,secp521r1" # relayd default+secp521r1 + tls ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA0-POLY1305" + tls ecdhe secp384r1 - return error + # Forward some paths to the local server (as pleroma won't respond to them as you might want) + pass request quick path "/robots.txt" forward to - # When serving multiple services with different certificates, specify multiple "tls keypair" keywords - # and add forwards to those services before the block keyword near the bottom of the protocol and relay configurations. - # The string in quotes must match the fullchain certificate file created by acme-client without the extension. - # For example: - # tls keypair "pleroma.example.tld" - # tls keypair "example.tld" - tls keypair "example.tld" + # Append a bunch of headers + match request header append "X-Forwarded-For" value "$REMOTE_ADDR" # This two header and the next one are not strictl required by pleroma but adding them won't hurt + match request header append "X-Forwarded-By" value "$SERVER_ADDR:$SERVER_PORT" - match request header append "X-Forwarded-For" value "$REMOTE_ADDR" match request header append "Connection" value "upgrade" - # When hosting Pleroma on a subdomain, replace example.tld accordingly (not the base domain). - # From the above example, "example.tld" should be replaced with "pleroma.example.tld" instead. - pass request quick header "Host" value "example.tld" forward to - - # Uncomment when serving media uploads on a different (sub)domain. - # Keep media proxy disabled, as it will NOT work under relayd/httpd. If you want to also setup media proxy, use nginx instead. - #pass request quick header "Host" value "media.example.tld" forward to - - # When serving multiple services, add the forwards here. - # Example: - #pass request quick header "Host" value "example.tld" forward to - - block } relay wwwtls { listen on $ext_inet port https tls # Comment to disable listening on IPv4 - #listen on $ext_inet6 port https tls # Comment to disable listening on IPv6 +# listen on $ext_inet6 port https tls # Comment to disable listening on IPv6 - protocol pleroma + protocol plerup - forward to port 4000 check tcp timeout 500 # Adjust timeout accordingly when relayd returns 502 while Pleroma is running without problems. - - # When serving multiple services, add the forwards here. - # Example: - #forward to port 8080 + forward to port 4000 check http "/" code 200 + forward to port 80 check http "/robots.txt" code 200 } + diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index 143af5cdd..0dc30549c 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -271,7 +271,7 @@ defmodule Mix.Tasks.Pleroma.Instance do [config_dir, psql_dir, static_dir, uploads_dir] |> Enum.reject(&File.exists?/1) |> Enum.each(fn dir -> - Pleroma.Backports.mkdir_p!(dir) + File.mkdir_p!(dir) File.chmod!(dir, 0o700) end) diff --git a/lib/mix/tasks/pleroma/robots_txt.ex b/lib/mix/tasks/pleroma/robots_txt.ex index e741f3cf0..5124c7c40 100644 --- a/lib/mix/tasks/pleroma/robots_txt.ex +++ b/lib/mix/tasks/pleroma/robots_txt.ex @@ -22,7 +22,7 @@ defmodule Mix.Tasks.Pleroma.RobotsTxt do static_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static/") if !File.exists?(static_dir) do - Pleroma.Backports.mkdir_p!(static_dir) + File.mkdir_p!(static_dir) end robots_txt_path = Path.join(static_dir, "robots.txt") diff --git a/lib/mix/tasks/pleroma/test_runner.ex b/lib/mix/tasks/pleroma/test_runner.ex index 67820247e..69fefb001 100644 --- a/lib/mix/tasks/pleroma/test_runner.ex +++ b/lib/mix/tasks/pleroma/test_runner.ex @@ -4,9 +4,7 @@ defmodule Mix.Tasks.Pleroma.TestRunner do use Mix.Task def run(args \\ []) do - case System.cmd("mix", ["test", "--warnings-as-errors"] ++ args, - into: IO.stream(:stdio, :line) - ) do + case System.cmd("mix", ["test"] ++ args, into: IO.stream(:stdio, :line)) do {_, 0} -> :ok diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 8e1c5de0d..3f199c002 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -43,6 +43,9 @@ defmodule Pleroma.Application do # every time the application is restarted, so we disable module # conflicts at runtime Code.compiler_options(ignore_module_conflict: true) + # Disable warnings_as_errors at runtime, it breaks Phoenix live reload + # due to protocol consolidation warnings + Code.compiler_options(warnings_as_errors: false) Pleroma.Telemetry.Logger.attach() Config.Holder.save_default() Pleroma.HTML.compile_scrubbers() @@ -53,10 +56,7 @@ defmodule Pleroma.Application do Pleroma.Web.Plugs.HTTPSecurityPlug.warn_if_disabled() end - if Config.get(:env) != :test do - Pleroma.ApplicationRequirements.verify!() - end - + Pleroma.ApplicationRequirements.verify!() load_custom_modules() Pleroma.Docs.JSON.compile() limiters_setup() @@ -68,11 +68,26 @@ defmodule Pleroma.Application do Finch.start_link(name: MyFinch) end - # Disable warnings_as_errors at runtime, it breaks Phoenix live reload - # due to protocol consolidation warnings - # :warnings_as_errors is deprecated via Code.compiler_options/2 since 1.18 - if Version.compare(System.version(), "1.18.0") == :lt do - Code.compiler_options(warnings_as_errors: false) + if adapter == Tesla.Adapter.Gun do + if version = Pleroma.OTPVersion.version() do + [major, minor] = + version + |> String.split(".") + |> Enum.map(&String.to_integer/1) + |> Enum.take(2) + + if (major == 22 and minor < 2) or major < 22 do + raise " + !!!OTP VERSION WARNING!!! + You are using gun adapter with OTP version #{version}, which doesn't support correct handling of unordered certificates chains. Please update your Erlang/OTP to at least 22.2. + " + end + else + raise " + !!!OTP VERSION WARNING!!! + To support correct handling of unordered certificates chains - OTP version must be > 22.2. + " + end end # Define workers and child supervisors to be supervised @@ -154,8 +169,7 @@ defmodule Pleroma.Application do limit: 500_000 ), build_cachex("rel_me", limit: 2500), - build_cachex("host_meta", default_ttl: :timer.minutes(120), limit: 5_000), - build_cachex("translations", default_ttl: :timer.hours(24), limit: 5_000) + build_cachex("host_meta", default_ttl: :timer.minutes(120), limit: 5000) ] end diff --git a/lib/pleroma/application_requirements.ex b/lib/pleroma/application_requirements.ex index 87ecb7e2d..a334d12ee 100644 --- a/lib/pleroma/application_requirements.ex +++ b/lib/pleroma/application_requirements.ex @@ -189,40 +189,7 @@ defmodule Pleroma.ApplicationRequirements do false end - language_detector_commands_status = - if Pleroma.Language.LanguageDetector.missing_dependencies() == [] do - true - else - Logger.error( - "The following dependencies required by the currently enabled " <> - "language detection provider are not installed: " <> - inspect(Pleroma.Language.LanguageDetector.missing_dependencies()) - ) - - false - end - - translation_commands_status = - if Pleroma.Language.Translation.missing_dependencies() == [] do - true - else - Logger.error( - "The following dependencies required by the currently enabled " <> - "translation provider are not installed: " <> - inspect(Pleroma.Language.Translation.missing_dependencies()) - ) - - false - end - - if Enum.all?( - [ - preview_proxy_commands_status, - language_detector_commands_status, - translation_commands_status | filter_commands_statuses - ], - & &1 - ) do + if Enum.all?([preview_proxy_commands_status | filter_commands_statuses], & &1) do :ok else {:error, diff --git a/lib/pleroma/backports.ex b/lib/pleroma/backports.ex deleted file mode 100644 index 68cb7b990..000000000 --- a/lib/pleroma/backports.ex +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2012 Plataformatec -# Copyright 2021 The Elixir Team -# SPDX-License-Identifier: Apache-2.0 - -defmodule Pleroma.Backports do - import File, only: [dir?: 1] - - # - # To be removed when we require Elixir 1.19 - @doc """ - Tries to create the directory `path`. - - Missing parent directories are created. Returns `:ok` if successful, or - `{:error, reason}` if an error occurs. - - Typical error reasons are: - - * `:eacces` - missing search or write permissions for the parent - directories of `path` - * `:enospc` - there is no space left on the device - * `:enotdir` - a component of `path` is not a directory - - """ - @spec mkdir_p(Path.t()) :: :ok | {:error, File.posix() | :badarg} - def mkdir_p(path) do - do_mkdir_p(IO.chardata_to_string(path)) - end - - defp do_mkdir_p("/") do - :ok - end - - defp do_mkdir_p(path) do - parent = Path.dirname(path) - - if parent == path do - :ok - else - case do_mkdir_p(parent) do - :ok -> - case :file.make_dir(path) do - {:error, :eexist} -> - if dir?(path), do: :ok, else: {:error, :enotdir} - - other -> - other - end - - e -> - e - end - end - end - - @doc """ - Same as `mkdir_p/1`, but raises a `File.Error` exception in case of failure. - Otherwise `:ok`. - """ - @spec mkdir_p!(Path.t()) :: :ok - def mkdir_p!(path) do - case mkdir_p(path) do - :ok -> - :ok - - {:error, reason} -> - raise File.Error, - reason: reason, - action: "make directory (with -p)", - path: IO.chardata_to_string(path) - end - end -end diff --git a/lib/pleroma/config_db.ex b/lib/pleroma/config_db.ex index e9990fa35..89d3050d6 100644 --- a/lib/pleroma/config_db.ex +++ b/lib/pleroma/config_db.ex @@ -302,7 +302,7 @@ defmodule Pleroma.ConfigDB do end def to_elixir_types(%{"tuple" => entity}) do - Enum.reduce(entity, {}, &Tuple.insert_at(&2, tuple_size(&2), to_elixir_types(&1))) + Enum.reduce(entity, {}, &Tuple.append(&2, to_elixir_types(&1))) end def to_elixir_types(entity) when is_map(entity) do diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex index 5ec1101b2..2cb8112ec 100644 --- a/lib/pleroma/constants.ex +++ b/lib/pleroma/constants.ex @@ -100,7 +100,6 @@ defmodule Pleroma.Constants do "Add", "Remove", "Like", - "Dislike", "Announce", "Undo", "Flag", @@ -116,7 +115,6 @@ defmodule Pleroma.Constants do "Flag", "Follow", "Like", - "Dislike", "EmojiReact", "Announce" ] diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index 99fa1994f..c58748d3c 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -488,7 +488,7 @@ defmodule Pleroma.Emoji.Pack do with true <- String.contains?(file_path, "/"), path <- Path.dirname(file_path), false <- File.exists?(path) do - Pleroma.Backports.mkdir_p!(path) + File.mkdir_p!(path) end end @@ -536,7 +536,7 @@ defmodule Pleroma.Emoji.Pack do emoji_path = emoji_path() # Create the directory first if it does not exist. This is probably the first request made # with the API so it should be sufficient - with {:create_dir, :ok} <- {:create_dir, Pleroma.Backports.mkdir_p(emoji_path)}, + with {:create_dir, :ok} <- {:create_dir, File.mkdir_p(emoji_path)}, {:ls, {:ok, results}} <- {:ls, File.ls(emoji_path)} do {:ok, Enum.sort(results)} else @@ -561,7 +561,7 @@ defmodule Pleroma.Emoji.Pack do end defp unzip(archive, pack_info, remote_pack, local_pack) do - with :ok <- Pleroma.Backports.mkdir_p!(local_pack.path) do + with :ok <- File.mkdir_p!(local_pack.path) do files = Enum.map(remote_pack["files"], fn {_, path} -> path end) # Fallback cannot contain a pack.json file files = if pack_info[:fallback], do: files, else: ["pack.json" | files] diff --git a/lib/pleroma/frontend.ex b/lib/pleroma/frontend.ex index e651d7d9d..fe7f525ea 100644 --- a/lib/pleroma/frontend.ex +++ b/lib/pleroma/frontend.ex @@ -66,7 +66,7 @@ defmodule Pleroma.Frontend do def unzip(zip, dest) do File.rm_rf!(dest) - Pleroma.Backports.mkdir_p!(dest) + File.mkdir_p!(dest) case Pleroma.SafeZip.unzip_data(zip, dest) do {:ok, _} -> :ok @@ -90,7 +90,7 @@ defmodule Pleroma.Frontend do defp install_frontend(frontend_info, source, dest) do from = frontend_info["build_dir"] || "dist" File.rm_rf!(dest) - Pleroma.Backports.mkdir_p!(dest) + File.mkdir_p!(dest) File.cp_r!(Path.join([source, from]), dest) :ok end diff --git a/lib/pleroma/language/language_detector.ex b/lib/pleroma/language/language_detector.ex deleted file mode 100644 index 68d243562..000000000 --- a/lib/pleroma/language/language_detector.ex +++ /dev/null @@ -1,59 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.LanguageDetector do - import Pleroma.EctoType.ActivityPub.ObjectValidators.LanguageCode, - only: [good_locale_code?: 1] - - @words_threshold 4 - @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config) - - def configured? do - provider = get_provider() - - !!provider and provider.configured?() - end - - def missing_dependencies do - provider = get_provider() - - if provider do - provider.missing_dependencies() - else - [] - end - end - - # Strip tags from text, etc. - defp prepare_text(text) do - text - |> Floki.parse_fragment!() - |> Floki.filter_out( - ".h-card, .mention, .hashtag, .u-url, .quote-inline, .recipients-inline, code, pre" - ) - |> Floki.text() - end - - def detect(text) do - provider = get_provider() - - text = prepare_text(text) - word_count = text |> String.split(~r/\s+/) |> Enum.count() - - if word_count < @words_threshold or !provider or !provider.configured?() do - nil - else - with language <- provider.detect(text), - true <- good_locale_code?(language) do - language - else - _ -> nil - end - end - end - - defp get_provider do - @config_impl.get([__MODULE__, :provider]) - end -end diff --git a/lib/pleroma/language/language_detector/fasttext.ex b/lib/pleroma/language/language_detector/fasttext.ex deleted file mode 100644 index 0f621a000..000000000 --- a/lib/pleroma/language/language_detector/fasttext.ex +++ /dev/null @@ -1,47 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.LanguageDetector.Fasttext do - import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1] - - alias Pleroma.Language.LanguageDetector.Provider - - @behaviour Provider - - @impl Provider - def missing_dependencies do - if Pleroma.Utils.command_available?("fasttext") do - [] - else - ["fasttext"] - end - end - - @impl Provider - def configured?, do: not_empty_string(get_model()) - - @impl Provider - def detect(text) do - text_path = Path.join(System.tmp_dir!(), "fasttext-#{Ecto.UUID.generate()}") - - File.write(text_path, text |> String.replace(~r/\s+/, " ")) - - detected_language = - case System.cmd("fasttext", ["predict", get_model(), text_path]) do - {"__label__" <> language, _} -> - language |> String.trim() - - _ -> - nil - end - - File.rm(text_path) - - detected_language - end - - defp get_model do - Pleroma.Config.get([__MODULE__, :model]) - end -end diff --git a/lib/pleroma/language/language_detector/provider.ex b/lib/pleroma/language/language_detector/provider.ex deleted file mode 100644 index 08e7c8eef..000000000 --- a/lib/pleroma/language/language_detector/provider.ex +++ /dev/null @@ -1,11 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.LanguageDetector.Provider do - @callback missing_dependencies() :: [String.t()] - - @callback configured?() :: boolean() - - @callback detect(text :: String.t()) :: String.t() | nil -end diff --git a/lib/pleroma/language/translation.ex b/lib/pleroma/language/translation.ex deleted file mode 100644 index 64f115ed8..000000000 --- a/lib/pleroma/language/translation.ex +++ /dev/null @@ -1,127 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.Translation do - @cachex Pleroma.Config.get([:cachex, :provider], Cachex) - - def configured? do - provider = get_provider() - - !!provider and provider.configured?() - end - - def missing_dependencies do - provider = get_provider() - - if provider do - provider.missing_dependencies() - else - [] - end - end - - def translate(text, source_language, target_language) do - cache_key = get_cache_key(text, source_language, target_language) - - case @cachex.get(:translations_cache, cache_key) do - {:ok, nil} -> - provider = get_provider() - - result = - if !configured?() do - {:error, :not_found} - else - provider.translate(text, source_language, target_language) - |> scrub_html() - end - - store_result(result, cache_key) - - result - - {:ok, result} -> - {:ok, result} - - {:error, error} -> - {:error, error} - end - end - - def supported_languages(type) when type in [:source, :target] do - provider = get_provider() - - cache_key = "#{type}_languages/#{provider.name()}" - - case @cachex.get(:translations_cache, cache_key) do - {:ok, nil} -> - result = - if !configured?() do - {:error, :not_found} - else - provider.supported_languages(type) - end - - store_result(result, cache_key) - - result - - {:ok, result} -> - {:ok, result} - - {:error, error} -> - {:error, error} - end - end - - def languages_matrix do - provider = get_provider() - - cache_key = "languages_matrix/#{provider.name()}" - - case @cachex.get(:translations_cache, cache_key) do - {:ok, nil} -> - result = - if !configured?() do - {:error, :not_found} - else - provider.languages_matrix() - end - - store_result(result, cache_key) - - result - - {:ok, result} -> - {:ok, result} - - {:error, error} -> - {:error, error} - end - end - - defp get_provider, do: Pleroma.Config.get([__MODULE__, :provider]) - - defp get_cache_key(text, source_language, target_language) do - "#{source_language}/#{target_language}/#{content_hash(text)}" - end - - defp store_result({:ok, result}, cache_key) do - @cachex.put(:translations_cache, cache_key, result) - end - - defp store_result(_, _), do: nil - - defp content_hash(text), do: :crypto.hash(:sha256, text) |> Base.encode64() - - defp scrub_html({:ok, %{content: content} = result}) when is_binary(content) do - scrubbers = Pleroma.Config.get([:markup, :scrub_policy]) - - content - |> Pleroma.HTML.filter_tags(scrubbers) - - {:ok, %{result | content: content}} - end - - defp scrub_html(result), do: result -end diff --git a/lib/pleroma/language/translation/deepl.ex b/lib/pleroma/language/translation/deepl.ex deleted file mode 100644 index aaaac9b0f..000000000 --- a/lib/pleroma/language/translation/deepl.ex +++ /dev/null @@ -1,121 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.Translation.Deepl do - import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1] - - alias Pleroma.Language.Translation.Provider - - use Provider - - @behaviour Provider - - @name "DeepL" - - @impl Provider - def configured?, do: not_empty_string(base_url()) and not_empty_string(api_key()) - - @impl Provider - def translate(content, source_language, target_language) do - endpoint = - base_url() - |> URI.merge("/v2/translate") - |> URI.to_string() - - case Pleroma.HTTP.post( - endpoint, - Jason.encode!(%{ - text: [content], - source_lang: source_language |> String.upcase(), - target_lang: target_language, - tag_handling: "html" - }), - [ - {"Content-Type", "application/json"}, - {"Authorization", "DeepL-Auth-Key #{api_key()}"} - ] - ) do - {:ok, %{status: 429}} -> - {:error, :too_many_requests} - - {:ok, %{status: 456}} -> - {:error, :quota_exceeded} - - {:ok, %{status: 200} = res} -> - %{ - "translations" => [ - %{"text" => content, "detected_source_language" => detected_source_language} - ] - } = Jason.decode!(res.body) - - {:ok, - %{ - content: content, - detected_source_language: detected_source_language, - provider: @name - }} - - _ -> - {:error, :internal_server_error} - end - end - - @impl Provider - def supported_languages(type) when type in [:source, :target] do - endpoint = - base_url() - |> URI.merge("/v2/languages") - |> URI.to_string() - - case Pleroma.HTTP.post( - endpoint <> "?" <> URI.encode_query(%{type: type}), - "", - [ - {"Content-Type", "application/x-www-form-urlencoded"}, - {"Authorization", "DeepL-Auth-Key #{api_key()}"} - ] - ) do - {:ok, %{status: 200} = res} -> - languages = - Jason.decode!(res.body) - |> Enum.map(fn %{"language" => language} -> language |> String.downcase() end) - |> Enum.map(fn language -> - if String.contains?(language, "-") do - [language, language |> String.split("-") |> Enum.at(0)] - else - language - end - end) - |> List.flatten() - |> Enum.uniq() - - {:ok, languages} - - _ -> - {:error, :internal_server_error} - end - end - - @impl Provider - def languages_matrix do - with {:ok, source_languages} <- supported_languages(:source), - {:ok, target_languages} <- supported_languages(:target) do - {:ok, - Map.new(source_languages, fn language -> {language, target_languages -- [language]} end)} - else - {:error, error} -> {:error, error} - end - end - - @impl Provider - def name, do: @name - - defp base_url do - Pleroma.Config.get([__MODULE__, :base_url]) - end - - defp api_key do - Pleroma.Config.get([__MODULE__, :api_key]) - end -end diff --git a/lib/pleroma/language/translation/libretranslate.ex b/lib/pleroma/language/translation/libretranslate.ex deleted file mode 100644 index fd727d1cf..000000000 --- a/lib/pleroma/language/translation/libretranslate.ex +++ /dev/null @@ -1,93 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.Translation.Libretranslate do - import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1] - - alias Pleroma.Language.Translation.Provider - - use Provider - - @behaviour Provider - - @name "LibreTranslate" - - @impl Provider - def configured?, do: not_empty_string(base_url()) and not_empty_string(api_key()) - - @impl Provider - def translate(content, source_language, target_language) do - case Pleroma.HTTP.post( - base_url() <> "/translate", - Jason.encode!(%{ - q: content, - source: source_language |> String.upcase(), - target: target_language, - format: "html", - api_key: api_key() - }), - [ - {"Content-Type", "application/json"} - ] - ) do - {:ok, %{status: 429}} -> - {:error, :too_many_requests} - - {:ok, %{status: 403}} -> - {:error, :quota_exceeded} - - {:ok, %{status: 200} = res} -> - %{ - "translatedText" => content - } = Jason.decode!(res.body) - - {:ok, - %{ - content: content, - detected_source_language: source_language, - provider: @name - }} - - _ -> - {:error, :internal_server_error} - end - end - - @impl Provider - def supported_languages(_) do - case Pleroma.HTTP.get(base_url() <> "/languages") do - {:ok, %{status: 200} = res} -> - languages = - Jason.decode!(res.body) - |> Enum.map(fn %{"code" => code} -> code end) - - {:ok, languages} - - _ -> - {:error, :internal_server_error} - end - end - - @impl Provider - def languages_matrix do - with {:ok, source_languages} <- supported_languages(:source), - {:ok, target_languages} <- supported_languages(:target) do - {:ok, - Map.new(source_languages, fn language -> {language, target_languages -- [language]} end)} - else - {:error, error} -> {:error, error} - end - end - - @impl Provider - def name, do: @name - - defp base_url do - Pleroma.Config.get([__MODULE__, :base_url]) - end - - defp api_key do - Pleroma.Config.get([__MODULE__, :api_key], "") - end -end diff --git a/lib/pleroma/language/translation/provider.ex b/lib/pleroma/language/translation/provider.ex deleted file mode 100644 index 533b5355a..000000000 --- a/lib/pleroma/language/translation/provider.ex +++ /dev/null @@ -1,40 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.Translation.Provider do - alias Pleroma.Language.Translation.Provider - - @callback missing_dependencies() :: [String.t()] - - @callback configured?() :: boolean() - - @callback translate( - content :: String.t(), - source_language :: String.t(), - target_language :: String.t() - ) :: - {:ok, - %{ - content: String.t(), - detected_source_language: String.t(), - provider: String.t() - }} - | {:error, atom()} - - @callback supported_languages(type :: :string | :target) :: - {:ok, [String.t()]} | {:error, atom()} - - @callback languages_matrix() :: {:ok, Map.t()} | {:error, atom()} - - @callback name() :: String.t() - - defmacro __using__(_opts) do - quote do - @impl Provider - def missing_dependencies, do: [] - - defoverridable missing_dependencies: 0 - end - end -end diff --git a/lib/pleroma/otp_version.ex b/lib/pleroma/otp_version.ex new file mode 100644 index 000000000..80b15275a --- /dev/null +++ b/lib/pleroma/otp_version.ex @@ -0,0 +1,28 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.OTPVersion do + @spec version() :: String.t() | nil + def version do + # OTP Version https://erlang.org/doc/system_principles/versions.html#otp-version + [ + Path.join(:code.root_dir(), "OTP_VERSION"), + Path.join([:code.root_dir(), "releases", :erlang.system_info(:otp_release), "OTP_VERSION"]) + ] + |> get_version_from_files() + end + + @spec get_version_from_files([Path.t()]) :: String.t() | nil + def get_version_from_files([]), do: nil + + def get_version_from_files([path | paths]) do + if File.exists?(path) do + path + |> File.read!() + |> String.replace(~r/\r|\n|\s/, "") + else + get_version_from_files(paths) + end + end +end diff --git a/lib/pleroma/search/database_search.ex b/lib/pleroma/search/database_search.ex index e88d632cb..aef5d1e74 100644 --- a/lib/pleroma/search/database_search.ex +++ b/lib/pleroma/search/database_search.ex @@ -102,8 +102,7 @@ defmodule Pleroma.Search.DatabaseSearch do ^tsc, o.data, ^search_query - ), - order_by: [desc: :inserted_at] + ) ) end diff --git a/lib/pleroma/uploaders/local.ex b/lib/pleroma/uploaders/local.ex index 7aab05b36..e4a309cea 100644 --- a/lib/pleroma/uploaders/local.ex +++ b/lib/pleroma/uploaders/local.ex @@ -19,7 +19,7 @@ defmodule Pleroma.Uploaders.Local do [file | folders] -> path = Path.join([upload_path()] ++ Enum.reverse(folders)) - Pleroma.Backports.mkdir_p!(path) + File.mkdir_p!(path) {path, file} end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 84551afd5..d9da9ede1 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -150,7 +150,7 @@ defmodule Pleroma.User do field(:allow_following_move, :boolean, default: true) field(:skip_thread_containment, :boolean, default: false) field(:actor_type, :string, default: "Person") - field(:also_known_as, {:array, ObjectValidators.BareUri}, default: []) + field(:also_known_as, {:array, ObjectValidators.ObjectID}, default: []) field(:inbox, :string) field(:shared_inbox, :string) field(:accepts_chat_messages, :boolean, default: nil) @@ -308,7 +308,7 @@ defmodule Pleroma.User do def binary_id(%User{} = user), do: binary_id(user.id) - @doc "Returns account status" + @doc "Returns status account" @spec account_status(User.t()) :: account_status() def account_status(%User{is_active: false}), do: :deactivated def account_status(%User{password_reset_pending: true}), do: :password_reset_pending @@ -895,7 +895,7 @@ defmodule Pleroma.User do end) end - defp validate_email_not_in_blacklisted_domain(changeset, field) do + def validate_email_not_in_blacklisted_domain(changeset, field) do validate_change(changeset, field, fn _, value -> valid? = Config.get([User, :email_blacklist]) @@ -912,9 +912,9 @@ defmodule Pleroma.User do end) end - defp maybe_validate_required_email(changeset, true), do: changeset + def maybe_validate_required_email(changeset, true), do: changeset - defp maybe_validate_required_email(changeset, _) do + def maybe_validate_required_email(changeset, _) do if Config.get([:instance, :account_activation_required]) do validate_required(changeset, [:email]) else @@ -1109,15 +1109,15 @@ defmodule Pleroma.User do defp maybe_send_registration_email(_), do: {:ok, :noop} - defp needs_update?(%User{local: true}), do: false + def needs_update?(%User{local: true}), do: false - defp needs_update?(%User{local: false, last_refreshed_at: nil}), do: true + def needs_update?(%User{local: false, last_refreshed_at: nil}), do: true - defp needs_update?(%User{local: false} = user) do + def needs_update?(%User{local: false} = user) do NaiveDateTime.diff(NaiveDateTime.utc_now(), user.last_refreshed_at) >= 86_400 end - defp needs_update?(_), do: true + def needs_update?(_), do: true @spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t(), User.t()} | {:error, String.t()} @@ -1708,9 +1708,7 @@ defmodule Pleroma.User do end end - def block(blocker, blocked, params \\ %{}) - - def block(%User{} = blocker, %User{} = blocked, params) do + def block(%User{} = blocker, %User{} = blocked) do # sever any follow relationships to prevent leaks per activitypub (Pleroma issue #213) blocker = if following?(blocker, blocked) do @@ -1740,33 +1738,12 @@ defmodule Pleroma.User do {:ok, blocker} = update_follower_count(blocker) {:ok, blocker, _} = Participation.mark_all_as_read(blocker, blocked) - - duration = Map.get(params, :duration, 0) - - expires_at = - if duration > 0 do - DateTime.utc_now() - |> DateTime.add(duration) - else - nil - end - - user_block = add_to_block(blocker, blocked, expires_at) - - if duration > 0 do - Pleroma.Workers.MuteExpireWorker.new( - %{"op" => "unblock_user", "blocker_id" => blocker.id, "blocked_id" => blocked.id}, - scheduled_at: expires_at - ) - |> Oban.insert() - end - - user_block + add_to_block(blocker, blocked) end # helper to handle the block given only an actor's AP id - def block(%User{} = blocker, %{ap_id: ap_id}, params) do - block(blocker, get_cached_by_ap_id(ap_id), params) + def block(%User{} = blocker, %{ap_id: ap_id}) do + block(blocker, get_cached_by_ap_id(ap_id)) end def unblock(%User{} = blocker, %User{} = blocked) do @@ -2007,7 +1984,7 @@ defmodule Pleroma.User do end @spec purge_user_changeset(User.t()) :: Ecto.Changeset.t() - defp purge_user_changeset(user) do + def purge_user_changeset(user) do # "Right to be forgotten" # https://gdpr.eu/right-to-be-forgotten/ change(user, %{ @@ -2179,7 +2156,7 @@ defmodule Pleroma.User do Repo.all(query) end - defp delete_notifications_from_user_activities(%User{ap_id: ap_id}) do + def delete_notifications_from_user_activities(%User{ap_id: ap_id}) do Notification |> join(:inner, [n], activity in assoc(n, :activity)) |> where([n, a], fragment("? = ?", a.actor, ^ap_id)) @@ -2638,7 +2615,7 @@ defmodule Pleroma.User do end end - # Internal function; public one is `set_activation/2` + # Internal function; public one is `deactivate/2` defp set_activation_status(user, status) do user |> cast(%{is_active: status}, [:is_active]) @@ -2657,7 +2634,7 @@ defmodule Pleroma.User do |> update_and_set_cache() end - defp validate_fields(changeset, remote?) do + def validate_fields(changeset, remote? \\ false) do limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields limit = Config.get([:instance, limit_name], 0) @@ -2802,10 +2779,10 @@ defmodule Pleroma.User do set_domain_blocks(user, List.delete(user.domain_blocks, domain_blocked)) end - @spec add_to_block(User.t(), User.t(), integer() | nil) :: + @spec add_to_block(User.t(), User.t()) :: {:ok, UserRelationship.t()} | {:error, Ecto.Changeset.t()} - defp add_to_block(%User{} = user, %User{} = blocked, expires_at) do - with {:ok, relationship} <- UserRelationship.create_block(user, blocked, expires_at) do + defp add_to_block(%User{} = user, %User{} = blocked) do + with {:ok, relationship} <- UserRelationship.create_block(user, blocked) do @cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}") {:ok, relationship} end diff --git a/lib/pleroma/user/backup.ex b/lib/pleroma/user/backup.ex index 3f67cdf0c..244b08adb 100644 --- a/lib/pleroma/user/backup.ex +++ b/lib/pleroma/user/backup.ex @@ -193,7 +193,7 @@ defmodule Pleroma.User.Backup do backup = Repo.preload(backup, :user) tempfile = Path.join([backup.tempdir, backup.file_name]) - with {_, :ok} <- {:mkdir, Pleroma.Backports.mkdir_p(backup.tempdir)}, + with {_, :ok} <- {:mkdir, File.mkdir_p(backup.tempdir)}, {_, :ok} <- {:actor, actor(backup.tempdir, backup.user)}, {_, :ok} <- {:statuses, statuses(backup.tempdir, backup.user)}, {_, :ok} <- {:likes, likes(backup.tempdir, backup.user)}, diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex index 046316024..2a1e56278 100644 --- a/lib/pleroma/web/activity_pub/builder.ex +++ b/lib/pleroma/web/activity_pub/builder.ex @@ -327,8 +327,8 @@ defmodule Pleroma.Web.ActivityPub.Builder do }, []} end - @spec block(User.t(), User.t(), map()) :: {:ok, map(), keyword()} - def block(blocker, blocked, params \\ %{}) do + @spec block(User.t(), User.t()) :: {:ok, map(), keyword()} + def block(blocker, blocked) do {:ok, %{ "id" => Utils.generate_activity_id(), @@ -336,7 +336,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do "actor" => blocker.ap_id, "object" => blocked.ap_id, "to" => [blocked.ap_id] - }, Keyword.new(params)} + }, []} end @spec announce(User.t(), Object.t(), keyword()) :: {:ok, map(), keyword()} diff --git a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex index 54f0e6bc1..49d17d8b9 100644 --- a/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/steal_emoji_policy.ex @@ -87,7 +87,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do Path.join(Config.get([:instance, :static_dir]), "emoji/stolen") ) - Pleroma.Backports.mkdir_p(emoji_dir_path) + File.mkdir_p(emoji_dir_path) new_emojis = foreign_emojis diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex index 17652a0de..ee12f3ebf 100644 --- a/lib/pleroma/web/activity_pub/object_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validator.ex @@ -200,13 +200,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do end def validate(%{"type" => type} = object, meta) - when type in ~w[Accept Reject Follow Like EmojiReact Announce + when type in ~w[Accept Reject Follow Update Like EmojiReact Announce ChatMessage Answer] do validator = case type do "Accept" -> AcceptRejectValidator "Reject" -> AcceptRejectValidator "Follow" -> FollowValidator + "Update" -> UpdateValidator "Like" -> LikeValidator "EmojiReact" -> EmojiReactValidator "Announce" -> AnnounceValidator @@ -214,19 +215,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do "Answer" -> AnswerValidator end - with {:ok, object} <- - object - |> validator.cast_and_validate() - |> Ecto.Changeset.apply_action(:insert) do - object = stringify_keys(object) - {:ok, object, meta} - end - end + cast_func = + if type == "Update" do + fn o -> validator.cast_and_validate(o, meta) end + else + fn o -> validator.cast_and_validate(o) end + end - def validate(%{"type" => type} = object, meta) when type == "Update" do with {:ok, object} <- object - |> UpdateValidator.cast_and_validate(meta) + |> cast_func.() |> Ecto.Changeset.apply_action(:insert) do object = stringify_keys(object) {:ok, object, meta} diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex index f0f3fef90..87d3e0c8f 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_fixes.ex @@ -4,7 +4,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do alias Pleroma.EctoType.ActivityPub.ObjectValidators - alias Pleroma.Language.LanguageDetector alias Pleroma.Maps alias Pleroma.Object alias Pleroma.Object.Containment @@ -152,19 +151,10 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do def maybe_add_language(object) do language = [ - &get_language_from_context/1, - &get_language_from_content_map/1, - &get_language_from_content/1 + get_language_from_context(object), + get_language_from_content_map(object) ] - |> Enum.find_value(fn get_language -> - language = get_language.(object) - - if good_locale_code?(language) do - language - else - nil - end - end) + |> Enum.find(&good_locale_code?(&1)) if language do Map.put(object, "language", language) @@ -197,12 +187,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFixes do defp get_language_from_content_map(_), do: nil - defp get_language_from_content(%{"content" => content} = object) do - LanguageDetector.detect("#{object["summary"] || ""} #{content}") - end - - defp get_language_from_content(_), do: nil - def maybe_add_content_map(%{"language" => language, "content" => content} = object) when not_empty_string(language) do Map.put(object, "contentMap", Map.put(%{}, language, content)) diff --git a/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex b/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex index dc2770189..47cf7b415 100644 --- a/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex +++ b/lib/pleroma/web/activity_pub/object_validators/tag_validator.ex @@ -50,7 +50,13 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.TagValidator do end def changeset(struct, %{"type" => "Hashtag", "name" => name} = data) do - name = String.downcase(name) + name = + cond do + "#" <> name -> name + name -> name + end + |> String.downcase() + data = Map.put(data, "name", name) struct diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index f160f1e17..0de3a0d43 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -93,20 +93,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do {:ok, data} = Transmogrifier.prepare_outgoing(activity.data) - param_cc = Map.get(params, :cc, []) - - original_cc = Map.get(data, "cc", []) - - public_address = Pleroma.Constants.as_public() - - # Ensure unlisted posts don't lose the public address in the cc - # if the param_cc was set - cc = - if public_address in original_cc and public_address not in param_cc do - [public_address | param_cc] - else - param_cc - end + cc = Map.get(params, :cc, []) json = data diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex index 52cdc3c3f..d6d403671 100644 --- a/lib/pleroma/web/activity_pub/side_effects.ex +++ b/lib/pleroma/web/activity_pub/side_effects.ex @@ -145,7 +145,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do ) do with %User{} = blocker <- User.get_cached_by_ap_id(blocking_user), %User{} = blocked <- User.get_cached_by_ap_id(blocked_user) do - User.block(blocker, blocked, Enum.into(meta, %{})) + User.block(blocker, blocked) end {:ok, object, meta} diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 8819e1596..1e6ee7dc8 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -492,19 +492,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do } # Rewrite misskey likes into EmojiReacts - defp handle_incoming_normalized( - %{ - "type" => "Like", - "content" => content - } = data, - options - ) - when is_binary(content) do - data - |> Map.put("type", "EmojiReact") - |> handle_incoming_normalized(options) - end - defp handle_incoming_normalized( %{ "type" => "Like", @@ -513,6 +500,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do options ) do data + |> Map.put("type", "EmojiReact") |> Map.put("content", @misskey_reactions[reaction] || reaction) |> handle_incoming_normalized(options) end @@ -664,24 +652,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do end end - # Rewrite dislikes into the thumbs down emoji - defp handle_incoming_normalized(%{"type" => "Dislike"} = data, options) do - data - |> Map.put("type", "EmojiReact") - |> Map.put("content", "👎") - |> handle_incoming_normalized(options) - end - - defp handle_incoming_normalized( - %{"type" => "Undo", "object" => %{"type" => "Dislike"}} = data, - options - ) do - data - |> put_in(["object", "type"], "EmojiReact") - |> put_in(["object", "content"], "👎") - |> handle_incoming_normalized(options) - end - defp handle_incoming_normalized(_, _), do: :error @spec get_obj_helper(String.t(), Keyword.t()) :: {:ok, Object.t()} | nil diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex index b35f5cdcd..0f22dd538 100644 --- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex @@ -335,14 +335,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do if params["password"] do User.force_password_reset_async(user) - - ModerationLog.insert_log(%{ - actor: admin, - subject: [user], - action: "force_password_reset" - }) end + ModerationLog.insert_log(%{ + actor: admin, + subject: [user], + action: "force_password_reset" + }) + json(conn, %{status: "success"}) else {:error, changeset} -> diff --git a/lib/pleroma/web/api_spec.ex b/lib/pleroma/web/api_spec.ex index e5339097f..63409870e 100644 --- a/lib/pleroma/web/api_spec.ex +++ b/lib/pleroma/web/api_spec.ex @@ -97,7 +97,7 @@ defmodule Pleroma.Web.ApiSpec do "Frontend management", "Instance configuration", "Instance documents", - "Instance rule management", + "Instance rule managment", "Invites", "MediaProxy cache", "OAuth application management", diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index d63e92d16..21a779dcb 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -284,6 +284,18 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do :query, %Schema{allOf: [BooleanLike], default: true}, "Mute notifications in addition to statuses? Defaults to `true`." + ), + Operation.parameter( + :duration, + :query, + %Schema{type: :integer}, + "Expire the mute in `duration` seconds. Default 0 for infinity" + ), + Operation.parameter( + :expires_in, + :query, + %Schema{type: :integer, default: 0}, + "Deprecated, use `duration` instead" ) ], responses: %{ @@ -311,37 +323,16 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do tags: ["Account actions"], summary: "Block", operationId: "AccountController.block", - requestBody: request_body("Parameters", block_request()), security: [%{"oAuth" => ["follow", "write:blocks"]}], description: "Block the given account. Clients should filter statuses from this account if received (e.g. due to a boost in the Home timeline)", - parameters: [ - %Reference{"$ref": "#/components/parameters/accountIdOrNickname"} - ], + parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}], responses: %{ 200 => Operation.response("Relationship", "application/json", AccountRelationship) } } end - defp block_request do - %Schema{ - title: "AccountBlockRequest", - description: "POST body for blocking an account", - type: :object, - properties: %{ - duration: %Schema{ - type: :integer, - nullable: true, - description: "Expire the mute in `duration` seconds. Default 0 for infinity" - } - }, - example: %{ - "duration" => 86_400 - } - } - end - def unblock_operation do %Operation{ tags: ["Account actions"], diff --git a/lib/pleroma/web/api_spec/operations/admin/rule_operation.ex b/lib/pleroma/web/api_spec/operations/admin/rule_operation.ex index 6d06728f4..c3a3ecc7c 100644 --- a/lib/pleroma/web/api_spec/operations/admin/rule_operation.ex +++ b/lib/pleroma/web/api_spec/operations/admin/rule_operation.ex @@ -16,7 +16,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RuleOperation do def index_operation do %Operation{ - tags: ["Instance rule management"], + tags: ["Instance rule managment"], summary: "Retrieve list of instance rules", operationId: "AdminAPI.RuleController.index", security: [%{"oAuth" => ["admin:read"]}], @@ -33,7 +33,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RuleOperation do def create_operation do %Operation{ - tags: ["Instance rule management"], + tags: ["Instance rule managment"], summary: "Create new rule", operationId: "AdminAPI.RuleController.create", security: [%{"oAuth" => ["admin:write"]}], @@ -49,7 +49,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RuleOperation do def update_operation do %Operation{ - tags: ["Instance rule management"], + tags: ["Instance rule managment"], summary: "Modify existing rule", operationId: "AdminAPI.RuleController.update", security: [%{"oAuth" => ["admin:write"]}], @@ -65,7 +65,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.RuleOperation do def delete_operation do %Operation{ - tags: ["Instance rule management"], + tags: ["Instance rule managment"], summary: "Delete rule", operationId: "AdminAPI.RuleController.delete", parameters: [Operation.parameter(:id, :path, :string, "Rule ID")], diff --git a/lib/pleroma/web/api_spec/operations/instance_operation.ex b/lib/pleroma/web/api_spec/operations/instance_operation.ex index 911ffb994..7d7a5ecc1 100644 --- a/lib/pleroma/web/api_spec/operations/instance_operation.ex +++ b/lib/pleroma/web/api_spec/operations/instance_operation.ex @@ -52,30 +52,7 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do summary: "Retrieve list of instance rules", operationId: "InstanceController.rules", responses: %{ - 200 => Operation.response("Array of rules", "application/json", array_of_rules()) - } - } - end - - def translation_languages_operation do - %Operation{ - tags: ["Instance misc"], - summary: "Retrieve supported languages matrix", - operationId: "InstanceController.translation_languages", - responses: %{ - 200 => - Operation.response( - "Translation languages matrix", - "application/json", - %Schema{ - type: :object, - additionalProperties: %Schema{ - type: :array, - items: %Schema{type: :string}, - description: "Supported target languages for a source language" - } - } - ) + 200 => Operation.response("Array of domains", "application/json", array_of_rules()) } } end diff --git a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex index 6f77584a8..f595583b6 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_scrobble_operation.ex @@ -59,15 +59,11 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do album: %Schema{type: :string, description: "The album of the media playing"}, artist: %Schema{type: :string, description: "The artist of the media playing"}, length: %Schema{type: :integer, description: "The length of the media playing"}, - external_link: %Schema{type: :string, description: "A URL referencing the media playing"}, + externalLink: %Schema{type: :string, description: "A URL referencing the media playing"}, visibility: %Schema{ allOf: [VisibilityScope], default: "public", description: "Scrobble visibility" - }, - externalLink: %Schema{ - type: :string, - description: "Deprecated, use `external_link` instead" } }, example: %{ @@ -75,7 +71,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do "artist" => "Some Artist", "album" => "Some Album", "length" => 180_000, - "external_link" => "https://www.last.fm/music/Some+Artist/_/Some+Title" + "externalLink" => "https://www.last.fm/music/Some+Artist/_/Some+Title" } } end @@ -89,7 +85,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do title: %Schema{type: :string, description: "The title of the media playing"}, album: %Schema{type: :string, description: "The album of the media playing"}, artist: %Schema{type: :string, description: "The artist of the media playing"}, - external_link: %Schema{type: :string, description: "A URL referencing the media playing"}, + externalLink: %Schema{type: :string, description: "A URL referencing the media playing"}, length: %Schema{ type: :integer, description: "The length of the media playing", @@ -104,7 +100,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do "artist" => "Some Artist", "album" => "Some Album", "length" => 180_000, - "external_link" => "https://www.last.fm/music/Some+Artist/_/Some+Title", + "externalLink" => "https://www.last.fm/music/Some+Artist/_/Some+Title", "created_at" => "2019-09-28T12:40:45.000Z" } } diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex index 75ecda321..ef828feee 100644 --- a/lib/pleroma/web/api_spec/operations/status_operation.ex +++ b/lib/pleroma/web/api_spec/operations/status_operation.ex @@ -427,38 +427,6 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do } end - def translate_operation do - %Operation{ - tags: ["Retrieve status information"], - summary: "Translate status", - description: "Translate status with an external API", - operationId: "StatusController.translate", - security: [%{"oAuth" => ["read:statuses"]}], - parameters: [id_param()], - requestBody: - request_body( - "Parameters", - %Schema{ - type: :object, - properties: %{ - lang: %Schema{ - type: :string, - nullable: true, - description: "Translation target language." - } - } - }, - required: false - ), - responses: %{ - 200 => Operation.response("Translation", "application/json", translation()), - 400 => Operation.response("Error", "application/json", ApiError), - 404 => Operation.response("Error", "application/json", ApiError), - 503 => Operation.response("Error", "application/json", ApiError) - } - } - end - def favourites_operation do %Operation{ tags: ["Timelines"], @@ -851,32 +819,4 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do } } end - - defp translation do - %Schema{ - title: "StatusTranslation", - description: "Represents status translation with related information.", - type: :object, - required: [:content, :detected_source_language, :provider], - properties: %{ - content: %Schema{ - type: :string, - description: "Translated status content" - }, - detected_source_language: %Schema{ - type: :string, - description: "Detected source language" - }, - provider: %Schema{ - type: :string, - description: "Translation provider service name" - } - }, - example: %{ - "content" => "Software für die nächste Generation der sozialen Medien.", - "detected_source_language" => "en", - "provider" => "Deepl" - } - } - end end diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex index 19827e996..1f73ef60c 100644 --- a/lib/pleroma/web/api_spec/schemas/account.ex +++ b/lib/pleroma/web/api_spec/schemas/account.ex @@ -34,7 +34,6 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do id: FlakeID, locked: %Schema{type: :boolean}, mute_expires_at: %Schema{type: :string, format: "date-time", nullable: true}, - block_expires_at: %Schema{type: :string, format: "date-time", nullable: true}, note: %Schema{type: :string, format: :html}, statuses_count: %Schema{type: :integer}, url: %Schema{type: :string, format: :uri}, diff --git a/lib/pleroma/web/common_api.ex b/lib/pleroma/web/common_api.ex index ae554d0b9..412424dae 100644 --- a/lib/pleroma/web/common_api.ex +++ b/lib/pleroma/web/common_api.ex @@ -27,9 +27,9 @@ defmodule Pleroma.Web.CommonAPI do require Logger @spec block(User.t(), User.t()) :: {:ok, Activity.t()} | Pipeline.errors() - def block(blocked, blocker, params \\ %{}) do - with {:ok, block_data, meta} <- Builder.block(blocker, blocked, params), - {:ok, block, _} <- Pipeline.common_pipeline(block_data, meta ++ [local: true]) do + def block(blocked, blocker) do + with {:ok, block_data, _} <- Builder.block(blocker, blocked), + {:ok, block, _} <- Pipeline.common_pipeline(block_data, local: true) do {:ok, block} end end diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex index f60ed8b02..4220757df 100644 --- a/lib/pleroma/web/common_api/activity_draft.ex +++ b/lib/pleroma/web/common_api/activity_draft.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do alias Pleroma.Activity alias Pleroma.Conversation.Participation - alias Pleroma.Language.LanguageDetector alias Pleroma.Object alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Visibility @@ -91,8 +90,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do defp listen_object(draft) do object = draft.params - |> Map.take([:album, :artist, :title, :length]) - |> Map.put(:externalLink, Map.get(draft.params, :external_link)) + |> Map.take([:album, :artist, :title, :length, :externalLink]) |> Map.new(fn {key, value} -> {to_string(key), value} end) |> Map.put("type", "Audio") |> Map.put("to", draft.to) @@ -257,15 +255,13 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do end defp language(draft) do - language = - with language <- draft.params[:language], - true <- good_locale_code?(language) do - language - else - _ -> LanguageDetector.detect(draft.content_html <> " " <> draft.summary) - end + language = draft.params[:language] - %__MODULE__{draft | language: language} + if good_locale_code?(language) do + %__MODULE__{draft | language: language} + else + draft + end end defp object(draft) do diff --git a/lib/pleroma/web/federator.ex b/lib/pleroma/web/federator.ex index 676fc5137..58260afa8 100644 --- a/lib/pleroma/web/federator.ex +++ b/lib/pleroma/web/federator.ex @@ -122,10 +122,6 @@ defmodule Pleroma.Web.Federator do Logger.debug("Unhandled actor #{actor}, #{inspect(e)}") {:error, e} - {:reject, reason} = e -> - Logger.debug("Rejected by MRF: #{inspect(reason)}") - {:error, e} - e -> # Just drop those for now Logger.debug(fn -> "Unhandled activity\n" <> Jason.encode!(params, pretty: true) end) diff --git a/lib/pleroma/web/instance_document.ex b/lib/pleroma/web/instance_document.ex index 143a0b0b8..9da3c5008 100644 --- a/lib/pleroma/web/instance_document.ex +++ b/lib/pleroma/web/instance_document.ex @@ -46,7 +46,7 @@ defmodule Pleroma.Web.InstanceDocument do defp put_file(origin_path, destination_path) do with destination <- instance_static_dir(destination_path), - {_, :ok} <- {:mkdir_p, Pleroma.Backports.mkdir_p(Path.dirname(destination))}, + {_, :ok} <- {:mkdir_p, File.mkdir_p(Path.dirname(destination))}, {_, {:ok, _}} <- {:copy, File.copy(origin_path, destination)} do :ok else diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index d374e8c01..68157b0c4 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -501,14 +501,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do end @doc "POST /api/v1/accounts/:id/block" - def block( - %{ - assigns: %{user: blocker, account: blocked}, - private: %{open_api_spex: %{body_params: params}} - } = conn, - _params - ) do - with {:ok, _activity} <- CommonAPI.block(blocked, blocker, params) do + def block(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do + with {:ok, _activity} <- CommonAPI.block(blocked, blocker) do render(conn, "relationship.json", user: blocker, target: blocked) else {:error, message} -> json_response(conn, :forbidden, %{error: message}) @@ -613,8 +607,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do users: users, for: user, as: :user, - embed_relationships: embed_relationships?(params), - blocks: true + embed_relationships: embed_relationships?(params) ) end diff --git a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex index 0f74c1dff..b97b0e476 100644 --- a/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/instance_controller.ex @@ -30,9 +30,4 @@ defmodule Pleroma.Web.MastodonAPI.InstanceController do def rules(conn, _params) do render(conn, "rules.json") end - - @doc "GET /api/v1/instance/translation_languages" - def translation_languages(conn, _params) do - render(conn, "translation_languages.json") - end end diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex index d9a1ba41e..628aa311b 100644 --- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex @@ -190,7 +190,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do f.() rescue error -> - Logger.error(Exception.format(:error, error, __STACKTRACE__)) + Logger.error("#{__MODULE__} search error: #{inspect(error)}") fallback end end diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 10549fb20..d5aef5ad2 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -13,7 +13,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do alias Pleroma.Activity alias Pleroma.Bookmark alias Pleroma.BookmarkFolder - alias Pleroma.Language.Translation alias Pleroma.Object alias Pleroma.Repo alias Pleroma.ScheduledActivity @@ -45,8 +44,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do ] ) - plug(OAuthScopesPlug, %{scopes: ["read:statuses"]} when action == :translate) - plug( OAuthScopesPlug, %{scopes: ["write:statuses"]} @@ -88,7 +85,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do %{scopes: ["write:bookmarks"]} when action in [:bookmark, :unbookmark] ) - @rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete translate)a + @rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a plug( RateLimiter, @@ -552,41 +549,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do end end - @doc "POST /api/v1/statuses/:id/translate" - def translate( - %{ - assigns: %{user: user}, - private: %{open_api_spex: %{body_params: params, params: %{id: status_id}}} - } = conn, - _ - ) do - with %Activity{object: object} <- Activity.get_by_id_with_object(status_id), - {:visibility, visibility} when visibility in ["public", "unlisted"] <- - {:visibility, Visibility.get_visibility(object)}, - {:language, language} when is_binary(language) <- - {:language, Map.get(params, :lang) || user.language}, - {:ok, result} <- - Translation.translate( - object.data["content"], - object.data["language"], - language - ) do - render(conn, "translation.json", result) - else - {:language, nil} -> - render_error(conn, :bad_request, "Language not specified") - - {:visibility, _} -> - render_error(conn, :not_found, "Record not found") - - {:error, :not_found} -> - render_error(conn, :not_found, "Translation service not configured") - - {:error, error} when error in [:unexpected_response, :quota_exceeded, :too_many_requests] -> - render_error(conn, :service_unavailable, "Translation service not available") - end - end - @doc "GET /api/v1/favourites" def favourites( %{assigns: %{user: %User{} = user}, private: %{open_api_spex: %{params: params}}} = conn, diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 8d28dd69a..f6727d29d 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -340,7 +340,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do |> maybe_put_unread_notification_count(user, opts[:for]) |> maybe_put_email_address(user, opts[:for]) |> maybe_put_mute_expires_at(user, opts[:for], opts) - |> maybe_put_block_expires_at(user, opts[:for], opts) |> maybe_show_birthday(user, opts[:for]) end @@ -477,16 +476,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp maybe_put_mute_expires_at(data, _, _, _), do: data - defp maybe_put_block_expires_at(data, %User{} = user, target, %{blocks: true}) do - Map.put( - data, - :block_expires_at, - UserRelationship.get_block_expire_date(target, user) - ) - end - - defp maybe_put_block_expires_at(data, _, _, _), do: data - defp maybe_show_birthday(data, %User{id: user_id} = user, %User{id: user_id}) do data |> Kernel.put_in([:pleroma, :birthday], user.birthday) diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex index 1b6f26af7..913684928 100644 --- a/lib/pleroma/web/mastodon_api/views/instance_view.ex +++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex @@ -90,15 +90,6 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do } end - def render("translation_languages.json", _) do - with true <- Pleroma.Language.Translation.configured?(), - {:ok, languages} <- Pleroma.Language.Translation.languages_matrix() do - languages - else - _ -> %{} - end - end - defp common_information(instance) do %{ languages: Keyword.get(instance, :languages, ["en"]), @@ -154,11 +145,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do end, "pleroma:get:main/ostatus", "pleroma:group_actors", - "pleroma:bookmark_folders", - if Pleroma.Language.LanguageDetector.configured?() do - "pleroma:language_detection" - end, - "pleroma:block_expiration" + "pleroma:bookmark_folders" ] |> Enum.filter(& &1) end @@ -256,27 +243,11 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do }, vapid: %{ public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key) - }, - translation: %{enabled: Pleroma.Language.Translation.configured?()} + } }) end defp pleroma_configuration(instance) do - base_urls = %{} - - base_urls = - if Config.get([:media_proxy, :enabled]) do - Map.put(base_urls, :media_proxy, Config.get([:media_proxy, :base_url])) - else - base_urls - end - - base_urls = - case Config.get([Pleroma.Upload, :base_url]) do - nil -> base_urls - url -> Map.put(base_urls, :upload, url) - end - %{ metadata: %{ account_activation_required: Keyword.get(instance, :account_activation_required), @@ -285,10 +256,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do fields_limits: fields_limits(), post_formats: Config.get([:instance, :allowed_post_formats]), birthday_required: Config.get([:instance, :birthday_required]), - birthday_min_age: Config.get([:instance, :birthday_min_age]), - translation: supported_languages(), - base_urls: base_urls, - markup: markup() + birthday_min_age: Config.get([:instance, :birthday_min_age]) }, stats: %{mau: Pleroma.User.active_user_count()}, vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key) @@ -314,37 +282,4 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do }) }) end - - defp supported_languages do - enabled = Pleroma.Language.Translation.configured?() - - source_languages = - with true <- enabled, - {:ok, languages} <- Pleroma.Language.Translation.supported_languages(:source) do - languages - else - _ -> nil - end - - target_languages = - with true <- enabled, - {:ok, languages} <- Pleroma.Language.Translation.supported_languages(:target) do - languages - else - _ -> nil - end - - %{ - source_languages: source_languages, - target_languages: target_languages - } - end - - defp markup do - %{ - allow_inline_images: Config.get([:markup, :allow_inline_images]), - allow_headings: Config.get([:markup, :allow_headings]), - allow_tables: Config.get([:markup, :allow_tables]) - } - end end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 4b5ac9c3b..10966edd6 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -681,14 +681,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do } end - def render("translation.json", %{ - content: content, - detected_source_language: detected_source_language, - provider: provider - }) do - %{content: content, detected_source_language: detected_source_language, provider: provider} - end - def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do object = Object.normalize(activity, fetch: false) diff --git a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex index 5f5f7643f..bf6dc500c 100644 --- a/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex @@ -24,10 +24,6 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleController do defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaScrobbleOperation def create(%{assigns: %{user: user}, body_params: params} = conn, _) do - params = - params - |> Map.put_new(:external_link, Map.get(params, :externalLink)) - with {:ok, activity} <- CommonAPI.listen(user, params) do render(conn, "show.json", activity: activity, for: user) else diff --git a/lib/pleroma/web/pleroma_api/views/scrobble_view.ex b/lib/pleroma/web/pleroma_api/views/scrobble_view.ex index 51828ad97..edf0a2390 100644 --- a/lib/pleroma/web/pleroma_api/views/scrobble_view.ex +++ b/lib/pleroma/web/pleroma_api/views/scrobble_view.ex @@ -27,10 +27,8 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleView do title: object.data["title"] |> HTML.strip_tags(), artist: object.data["artist"] |> HTML.strip_tags(), album: object.data["album"] |> HTML.strip_tags(), - external_link: object.data["externalLink"], - length: object.data["length"], - # DEPRECATED - externalLink: object.data["externalLink"] + externalLink: object.data["externalLink"], + length: object.data["length"] } end diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex index 9c8ec7a9f..a3a522d7a 100644 --- a/lib/pleroma/web/rich_media/parser.ex +++ b/lib/pleroma/web/rich_media/parser.ex @@ -4,7 +4,6 @@ defmodule Pleroma.Web.RichMedia.Parser do alias Pleroma.Web.RichMedia.Helpers - import Pleroma.Web.Metadata.Utils, only: [scrub_html_and_truncate: 2] require Logger @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config) @@ -64,20 +63,8 @@ defmodule Pleroma.Web.RichMedia.Parser do not match?({:ok, _}, Jason.encode(%{key => val})) end) |> Map.new() - |> truncate_title() - |> truncate_desc() end - defp truncate_title(%{"title" => title} = data) when is_binary(title), - do: %{data | "title" => scrub_html_and_truncate(title, 120)} - - defp truncate_title(data), do: data - - defp truncate_desc(%{"description" => desc} = data) when is_binary(desc), - do: %{data | "description" => scrub_html_and_truncate(desc, 200)} - - defp truncate_desc(data), do: data - @spec validate_page_url(URI.t() | binary()) :: :ok | :error defp validate_page_url(page_url) when is_binary(page_url) do validate_tld = @config_impl.get([Pleroma.Formatter, :validate_tld]) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index dfab1b216..bf8ebf3e4 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -189,7 +189,7 @@ defmodule Pleroma.Web.Router do end pipeline :well_known do - plug(:accepts, ["activity+json", "json", "jrd", "jrd+json", "xml", "xrd+xml", "html"]) + plug(:accepts, ["activity+json", "json", "jrd", "jrd+json", "xml", "xrd+xml"]) end pipeline :config do @@ -740,7 +740,6 @@ defmodule Pleroma.Web.Router do post("/statuses/:id/unbookmark", StatusController, :unbookmark) post("/statuses/:id/mute", StatusController, :mute_conversation) post("/statuses/:id/unmute", StatusController, :unmute_conversation) - post("/statuses/:id/translate", StatusController, :translate) post("/push/subscription", SubscriptionController, :create) get("/push/subscription", SubscriptionController, :show) @@ -788,7 +787,6 @@ defmodule Pleroma.Web.Router do get("/instance", InstanceController, :show) get("/instance/peers", InstanceController, :peers) get("/instance/rules", InstanceController, :rules) - get("/instance/translation_languages", InstanceController, :translation_languages) get("/statuses", StatusController, :index) get("/statuses/:id", StatusController, :show) diff --git a/lib/pleroma/web/templates/email/digest.html.eex b/lib/pleroma/web/templates/email/digest.html.eex index d2918bc6f..1efc76e1a 100644 --- a/lib/pleroma/web/templates/email/digest.html.eex +++ b/lib/pleroma/web/templates/email/digest.html.eex @@ -231,8 +231,8 @@ <%= for %{data: mention, object: object, from: from} <- @mentions do %> - <% # mention START %> - <% # user card START %> + <%# mention START %> + <%# user card START %>
@@ -291,7 +291,7 @@
- <% # user card END %> + <%# user card END %>
- <% # mention END %> + <%# mention END %> <% end %> <%= if @followers != [] do %> - <% # new followers header START %> + <%# new followers header START %>
@@ -397,10 +397,10 @@
- <% # new followers header END %> + <%# new followers header END %> <%= for %{data: follow, from: from} <- @followers do %> - <% # user card START %> + <%# user card START %>
@@ -459,13 +459,13 @@
- <% # user card END %> + <%# user card END %> <% end %> <% end %> - <% # divider start %> + <%# divider start %>
@@ -514,7 +514,7 @@
- <% # divider end %> + <%# divider end %>
diff --git a/lib/pleroma/web/templates/email/new_users_digest.html.eex b/lib/pleroma/web/templates/email/new_users_digest.html.eex index 78b8ac4f9..40d9b8381 100644 --- a/lib/pleroma/web/templates/email/new_users_digest.html.eex +++ b/lib/pleroma/web/templates/email/new_users_digest.html.eex @@ -1,5 +1,5 @@ <%= for {user, total_statuses, latest_status} <- @users_and_statuses do %> - <% # user card START %> + <%# user card START %>
@@ -60,7 +60,7 @@
- <% # user card END %> + <%# user card END %> <%= if latest_status do %>
@@ -104,7 +104,7 @@
<% end %> - <% # divider start %> + <%# divider start %>
@@ -153,6 +153,6 @@
- <% # divider end %> - <% # user card END %> + <%# divider end %> + <%# user card END %> <% end %> diff --git a/lib/pleroma/web/templates/layout/email_styled.html.eex b/lib/pleroma/web/templates/layout/email_styled.html.eex index a1ed4ece3..82cabd889 100644 --- a/lib/pleroma/web/templates/layout/email_styled.html.eex +++ b/lib/pleroma/web/templates/layout/email_styled.html.eex @@ -111,7 +111,7 @@ - <% # header %> + <%# header %>
@@ -145,7 +145,7 @@
- <% # title %> + <%# title %> <%= if @title do %>
<%= for scope <- @available_scopes do %> - <% # Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %> + <%# Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %> <%= if scope in @scopes do %>
<%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %> diff --git a/lib/pleroma/web/web_finger/web_finger_controller.ex b/lib/pleroma/web/web_finger/web_finger_controller.ex index 8a291e28e..021df9bc5 100644 --- a/lib/pleroma/web/web_finger/web_finger_controller.ex +++ b/lib/pleroma/web/web_finger/web_finger_controller.ex @@ -41,10 +41,5 @@ defmodule Pleroma.Web.WebFinger.WebFingerController do end end - # Default to JSON when no format is specified or format is not recognized - def webfinger(%{assigns: %{format: _format}} = conn, %{"resource" => _resource} = params) do - webfinger(put_in(conn.assigns.format, "json"), params) - end - def webfinger(conn, _params), do: send_resp(conn, 400, "Bad Request") end diff --git a/lib/pleroma/workers/mute_expire_worker.ex b/lib/pleroma/workers/mute_expire_worker.ex index 9a04fc486..8356a775d 100644 --- a/lib/pleroma/workers/mute_expire_worker.ex +++ b/lib/pleroma/workers/mute_expire_worker.ex @@ -5,13 +5,9 @@ defmodule Pleroma.Workers.MuteExpireWorker do use Oban.Worker, queue: :background - alias Pleroma.User - @impl true - def perform(%Job{ - args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id} - }) do - User.unmute(muter_id, mutee_id) + def perform(%Job{args: %{"op" => "unmute_user", "muter_id" => muter_id, "mutee_id" => mutee_id}}) do + Pleroma.User.unmute(muter_id, mutee_id) :ok end @@ -22,17 +18,6 @@ defmodule Pleroma.Workers.MuteExpireWorker do :ok end - def perform(%Job{ - args: %{"op" => "unblock_user", "blocker_id" => blocker_id, "blocked_id" => blocked_id} - }) do - Pleroma.Web.CommonAPI.unblock( - User.get_cached_by_id(blocked_id), - User.get_cached_by_id(blocker_id) - ) - - :ok - end - @impl true def timeout(_job), do: :timer.seconds(5) end diff --git a/mix.exs b/mix.exs index 971084f94..808a2b12c 100644 --- a/mix.exs +++ b/mix.exs @@ -37,13 +37,22 @@ defmodule Pleroma.Mixfile do pleroma: [ include_executables_for: [:unix], applications: [ex_syslogger: :load, syslog: :load, eldap: :transient], - steps: [:assemble, ©_files/1, ©_nginx_config/1], + steps: [:assemble, &put_otp_version/1, ©_files/1, ©_nginx_config/1], config_providers: [{Pleroma.Config.ReleaseRuntimeProvider, []}] ] ] ] end + def put_otp_version(%{path: target_path} = release) do + File.write!( + Path.join([target_path, "OTP_VERSION"]), + Pleroma.OTPVersion.version() + ) + + release + end + def copy_files(%{path: target_path} = release) do File.cp_r!("./rel/files", target_path) release @@ -204,7 +213,7 @@ defmodule Pleroma.Mixfile do {:poison, "~> 3.0", only: :test}, {:ex_doc, "~> 0.22", only: :dev, runtime: false}, {:ex_machina, "~> 2.4", only: :test}, - {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, + {:credo, "~> 1.6", only: [:dev, :test], runtime: false}, {:mock, "~> 0.3.5", only: :test}, {:covertool, "~> 2.0", only: :test}, {:hackney, "~> 1.18.0", override: true}, @@ -227,7 +236,7 @@ defmodule Pleroma.Mixfile do "ecto.rollback": ["pleroma.ecto.rollback"], "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.reset": ["ecto.drop", "ecto.setup"], - test: ["ecto.create --quiet", "ecto.migrate", "test --warnings-as-errors"], + test: ["ecto.create --quiet", "ecto.migrate", "test"], docs: ["pleroma.docs", "docs"], analyze: ["credo --strict --only=warnings,todo,fixme,consistency,readability"], copyright: &add_copyright/1, diff --git a/mix.lock b/mix.lock index f7f37b7e1..9b53ede62 100644 --- a/mix.lock +++ b/mix.lock @@ -23,7 +23,7 @@ "cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"}, - "credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"}, + "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, "crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"}, "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, diff --git a/priv/repo/migrations/20240904142434_assign_app_user.exs b/priv/repo/migrations/20240904142434_assign_app_user.exs index 74740220d..11bec529b 100644 --- a/priv/repo/migrations/20240904142434_assign_app_user.exs +++ b/priv/repo/migrations/20240904142434_assign_app_user.exs @@ -1,24 +1,20 @@ defmodule Pleroma.Repo.Migrations.AssignAppUser do use Ecto.Migration - import Ecto.Query - alias Pleroma.Repo alias Pleroma.Web.OAuth.App alias Pleroma.Web.OAuth.Token def up do - Token - |> where([t], not is_nil(t.user_id)) - |> group_by([t], t.app_id) - |> select([t], %{app_id: t.app_id, id: min(t.id)}) - |> order_by(asc: :app_id) - |> Repo.stream() - |> Stream.each(fn %{id: id} -> - token = Token.Query.get_by_id(id) |> Repo.one() + Repo.all(Token) + |> Enum.group_by(fn x -> Map.get(x, :app_id) end) + |> Enum.each(fn {_app_id, tokens} -> + token = + Enum.filter(tokens, fn x -> not is_nil(x.user_id) end) + |> List.first() + App.maybe_update_owner(token) end) - |> Stream.run() end def down, do: :ok diff --git a/priv/repo/migrations/20250314153704_add_activities_actor_type_index.exs b/priv/repo/migrations/20250314153704_add_activities_actor_type_index.exs deleted file mode 100644 index a0fac28a8..000000000 --- a/priv/repo/migrations/20250314153704_add_activities_actor_type_index.exs +++ /dev/null @@ -1,14 +0,0 @@ -defmodule Pleroma.Repo.Migrations.AddActivitiesActorTypeIndex do - use Ecto.Migration - @disable_ddl_transaction true - - def change do - create( - index( - :activities, - ["actor", "(data ->> 'type'::text)", "id DESC NULLS LAST"], - concurrently: true - ) - ) - end -end diff --git a/test/fixtures/friendica-dislike-undo.json b/test/fixtures/friendica-dislike-undo.json deleted file mode 100644 index b258e00be..000000000 --- a/test/fixtures/friendica-dislike-undo.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/ns/activitystreams", - "https://w3id.org/security/v1", - { - "Hashtag": "as:Hashtag", - "PropertyValue": "schema:PropertyValue", - "conversation": "ostatus:conversation", - "dfrn": "http://purl.org/macgirvin/dfrn/1.0/", - "diaspora": "https://diasporafoundation.org/ns/", - "directMessage": "litepub:directMessage", - "discoverable": "toot:discoverable", - "featured": { - "@id": "toot:featured", - "@type": "@id" - }, - "litepub": "http://litepub.social/ns#", - "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", - "ostatus": "http://ostatus.org#", - "quoteUrl": "as:quoteUrl", - "schema": "http://schema.org#", - "sensitive": "as:sensitive", - "toot": "http://joinmastodon.org/ns#", - "value": "schema:value", - "vcard": "http://www.w3.org/2006/vcard/ns#" - } - ], - "actor": "https://my-place.social/profile/vaartis", - "cc": [ - "https://my-place.social/followers/vaartis" - ], - "id": "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182/Undo", - "instrument": { - "id": "https://my-place.social/friendica", - "name": "Friendica 'Interrupted Fern' 2024.12-1576", - "type": "Application", - "url": "https://my-place.social" - }, - "object": { - "actor": "https://my-place.social/profile/vaartis", - "cc": [ - "https://my-place.social/followers/vaartis" - ], - "diaspora:guid": "e599373b-1968-4b20-cd24-80d340160302", - "diaspora:like": "{\"author\":\"vaartis@my-place.social\",\"guid\":\"e599373b-1968-4b20-cd24-80d340160302\",\"parent_guid\":\"cd36feba-c31f3ed3fd5c064a-17c31593\",\"parent_type\":\"Post\",\"positive\":\"false\",\"author_signature\":\"xR2zLJNfc9Nhx1n8LLMWM1kde12my4cqamIsrH\\/UntKzuDwO4DuHBL0fkFhgC\\/dylxm4HqsHD45MQbtwQCVGq6WhC96TrbMuYEK61HIO23dTr3m+qJVtfdH4wyhUNHgiiYPhZpkLDfnR1JiRWmFTlmZC8q8JEkOB5IQsrWia2eOR6IsqDcdKO\\/Urgns9\\/BdQi8KnchBKSEFc1iUtcOEruvhunKGyW5zI\\/Rltfdz3xGH8tlw+YlMXeWXPnqgOJ9GzNA0lwG4U421L6yylYagW7oxIznnBLB4bO46vYZbgXZV1hiI9ZyveHOinLMY1QkmTj5CNvnx3\\/VJwLovd0v+0Nr2vu\\/3ftbpBXc6L1bsNjlRqtsfwJlcgl+tH1DC4W8tKf+Y3tdtzVw0CHXCuacxHLyq5wZd\\/5YfYR9SJQ\\/jInU4PHA5+hIE3PGqNUp5QfFE0umq56H7MQKsIPgM5mMV4fPAA8OpltuMVDvQYUxalrnvoTf00k90x1wCTK71\\/jQGh7r7PmGvSdfPr+65eVTjITD8\\/lTGIb8850v1fl3\\/i2R8Dv17jQIRyX5o9MXPSO6jHo4Swma5RzPA\\/0bRj6qRTyPkM1L9qEIr+2H2I7KKhT2ZE5GhAU7yI9A3VLBWzpTrUPMGbfpd1OjVTEqXAdMjpLDYI3Mh5zQ58p8xCzt+W+t0=\"}", - "id": "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182", - "instrument": { - "id": "https://my-place.social/friendica", - "name": "Friendica 'Interrupted Fern' 2024.12-1576", - "type": "Application", - "url": "https://my-place.social" - }, - "object": "https://pl.kotobank.ch/objects/301bce65-8a1b-4c49-a65c-fe2ce861a213", - "published": "2025-06-12T18:47:41Z", - "to": [ - "https://pl.kotobank.ch/users/vaartis", - "https://mitra.social/users/silverpill", - "https://www.w3.org/ns/activitystreams#Public" - ], - "type": "Dislike" - }, - "published": "2025-06-12T18:41:25Z", - "signature": { - "created": "2025-06-12T18:44:16Z", - "creator": "https://my-place.social/profile/vaartis#main-key", - "nonce": "2d67847d4bd4b1b83a30d61eac6cdc7ad6b980df06a8b9b97217e1d8f7b6cf20", - "signatureValue": "LnoRMZuQGDvTICkShGBq28ynaj2lF1bViJFGS6n4gKn3IbxPWATHxao43gxWRc+HCTrHNg7quzgaW4+PYM7UVUz3jO+bjNKsN845nijOVdyFrPOXbuaij3KQh2OoHhFJWoV/ZQQTFF0kRK1qT4BwG+P8NqOOKAMv+Cw7ruQH+f2w7uDgcNIbCD1gLcwb6cw7WVe5qu8yMkKqp2kBdqW3RCsI85RmmFgwehDgH5nrX7ER1qbeLWrqy7echwD9/fO3rqAu13xDNyiGZHDT7JB3RUt0AyMm0XCfjbwSQ0n+MkYXgE4asvFz81+iiPCLt+6gePWAFc5odF1FxdySBpSuUOs4p92NzP9OhQ0c0qrqrzYI7aYklY7oMfxjkva+X+0bm3up+2IRJdnZa/pXlmwdcqTpyMr1sgzaexMUNBp3dq7zA51eEaakLDX3i2onXJowfmze3+6XgPAFHYamR+pRNtuEoY4uyYEK3fj5GgwJ4RtFJMYVoEs/Q8h3OgYRcK1FE9UlDjSqbQ7QIRn2Ib4wjgmkeM0vrHIwh/1CtqA/M/6WuYFzCaJBc8O9ykpK9ZMbw64ToQXKf2SqhZsDoyTWRWTO1PXOk1XCAAElUh8/WCyeghvgqLXn0LHov4lmBsHA5iMUcLqBKD3GJIHd+ExrOFxMZs4mBLLGyz0p5joJ3NY=", - "type": "RsaSignature2017" - }, - "to": [ - "https://pl.kotobank.ch/users/vaartis", - "https://mitra.social/users/silverpill", - "https://www.w3.org/ns/activitystreams#Public" - ], - "type": "Undo" -} diff --git a/test/fixtures/friendica-dislike.json b/test/fixtures/friendica-dislike.json deleted file mode 100644 index c75939073..000000000 --- a/test/fixtures/friendica-dislike.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/ns/activitystreams", - "https://w3id.org/security/v1", - { - "Hashtag": "as:Hashtag", - "PropertyValue": "schema:PropertyValue", - "conversation": "ostatus:conversation", - "dfrn": "http://purl.org/macgirvin/dfrn/1.0/", - "diaspora": "https://diasporafoundation.org/ns/", - "directMessage": "litepub:directMessage", - "discoverable": "toot:discoverable", - "featured": { - "@id": "toot:featured", - "@type": "@id" - }, - "litepub": "http://litepub.social/ns#", - "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", - "ostatus": "http://ostatus.org#", - "quoteUrl": "as:quoteUrl", - "schema": "http://schema.org#", - "sensitive": "as:sensitive", - "toot": "http://joinmastodon.org/ns#", - "value": "schema:value", - "vcard": "http://www.w3.org/2006/vcard/ns#" - } - ], - "actor": "https://my-place.social/profile/vaartis", - "cc": [ - "https://my-place.social/followers/vaartis" - ], - "diaspora:guid": "e599373b-1968-4b20-cd24-80d340160302", - "diaspora:like": "{\"author\":\"vaartis@my-place.social\",\"guid\":\"e599373b-1968-4b20-cd24-80d340160302\",\"parent_guid\":\"cd36feba-c31f3ed3fd5c064a-17c31593\",\"parent_type\":\"Post\",\"positive\":\"false\",\"author_signature\":\"xR2zLJNfc9Nhx1n8LLMWM1kde12my4cqamIsrH\\/UntKzuDwO4DuHBL0fkFhgC\\/dylxm4HqsHD45MQbtwQCVGq6WhC96TrbMuYEK61HIO23dTr3m+qJVtfdH4wyhUNHgiiYPhZpkLDfnR1JiRWmFTlmZC8q8JEkOB5IQsrWia2eOR6IsqDcdKO\\/Urgns9\\/BdQi8KnchBKSEFc1iUtcOEruvhunKGyW5zI\\/Rltfdz3xGH8tlw+YlMXeWXPnqgOJ9GzNA0lwG4U421L6yylYagW7oxIznnBLB4bO46vYZbgXZV1hiI9ZyveHOinLMY1QkmTj5CNvnx3\\/VJwLovd0v+0Nr2vu\\/3ftbpBXc6L1bsNjlRqtsfwJlcgl+tH1DC4W8tKf+Y3tdtzVw0CHXCuacxHLyq5wZd\\/5YfYR9SJQ\\/jInU4PHA5+hIE3PGqNUp5QfFE0umq56H7MQKsIPgM5mMV4fPAA8OpltuMVDvQYUxalrnvoTf00k90x1wCTK71\\/jQGh7r7PmGvSdfPr+65eVTjITD8\\/lTGIb8850v1fl3\\/i2R8Dv17jQIRyX5o9MXPSO6jHo4Swma5RzPA\\/0bRj6qRTyPkM1L9qEIr+2H2I7KKhT2ZE5GhAU7yI9A3VLBWzpTrUPMGbfpd1OjVTEqXAdMjpLDYI3Mh5zQ58p8xCzt+W+t0=\"}", - "id": "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182", - "instrument": { - "id": "https://my-place.social/friendica", - "name": "Friendica 'Interrupted Fern' 2024.12-1576", - "type": "Application", - "url": "https://my-place.social" - }, - "object": "https://pl.kotobank.ch/objects/301bce65-8a1b-4c49-a65c-fe2ce861a213", - "published": "2025-06-12T18:47:41Z", - "signature": { - "created": "2025-06-12T18:47:42Z", - "creator": "https://my-place.social/profile/vaartis#main-key", - "nonce": "84e496f80b09d7a299c5cc89e8cadd13abf621b3a0a321684fa74278b68a6dd8", - "signatureValue": "qe2WxY+j7daIYLRadCctgal6A1s9XgoiMfM/8KjJm15w0sSizYYqruyQ5gS44e+cj5GHc9v5gP2ieod5v7eHAPzlcDI4bfkcyHVapAXTqU67ZebW+v6Q+21IMDgqrkYCv5TbV7LTxltW59dlqovpHE4TEe/M7xLKWJ3vVchRUcWqH9kDmak0nacoqYVAb5E9jYnQhUWPTCfPV82qQpeWQPOZ4iIvPw6rDkSSY5jL6bCogBZblHGpUjXfe/FPlacaCWiTQdoga3yOBXB1RYPw9nh5FI5Xkv/oi+52WmJrECinlD6AL8/BpiYvKz236zy7p/TR4BXlCx9RR/msjOnSabkQ4kmYFrRr80UDCGF+CdkdzLl8K9rSE3PbF1+nEqD7X0GOWn/DdtixqXJw6IR4bh32YW2SlcrSRBvI1p82Mv68BeqRaYqL6FAhKFwLhX5JpXngZ3k0g7rWWxc498voPWnFZDyCTRNxO9VIIUavDDEQ0BdFk6WDb8zx9tsAg8JoK57eVDcFly7tfVQffYiHpve06d8ag1DtzipqguRsURmuqpGNMq28XBTxwtrP2LnXXHKxoYN/YQ9cDnCKclbx7/uKmOVMLkLZlM0wAVoZpm5z2fG4voKqFiGZ1PoiFY2sN4URMArJtygV3PlTX4ASAQrak0ksvEo9msrBUD0Su9c=", - "type": "RsaSignature2017" - }, - "to": [ - "https://pl.kotobank.ch/users/vaartis", - "https://mitra.social/users/silverpill", - "https://www.w3.org/ns/activitystreams#Public" - ], - "type": "Dislike" -} diff --git a/test/fixtures/misskey-custom-emoji-like.json b/test/fixtures/misskey-custom-emoji-like.json deleted file mode 100644 index 51a825d42..000000000 --- a/test/fixtures/misskey-custom-emoji-like.json +++ /dev/null @@ -1,54 +0,0 @@ - { - "@context": [ - "https://www.w3.org/ns/activitystreams", - "https://w3id.org/security/v1", - { - "Emoji": "toot:Emoji", - "Hashtag": "as:Hashtag", - "PropertyValue": "schema:PropertyValue", - "_misskey_content": "misskey:_misskey_content", - "_misskey_quote": "misskey:_misskey_quote", - "_misskey_reaction": "misskey:_misskey_reaction", - "_misskey_summary": "misskey:_misskey_summary", - "_misskey_votes": "misskey:_misskey_votes", - "backgroundUrl": "sharkey:backgroundUrl", - "discoverable": "toot:discoverable", - "featured": "toot:featured", - "fedibird": "http://fedibird.com/ns#", - "firefish": "https://joinfirefish.org/ns#", - "isCat": "misskey:isCat", - "listenbrainz": "sharkey:listenbrainz", - "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", - "misskey": "https://misskey-hub.net/ns#", - "quoteUri": "fedibird:quoteUri", - "quoteUrl": "as:quoteUrl", - "schema": "http://schema.org#", - "sensitive": "as:sensitive", - "sharkey": "https://joinsharkey.org/ns#", - "speakAsCat": "firefish:speakAsCat", - "toot": "http://joinmastodon.org/ns#", - "value": "schema:value", - "vcard": "http://www.w3.org/2006/vcard/ns#" - } - ], - "_misskey_reaction": ":blobwtfnotlikethis:", - "actor": "https://mai.waifuism.life/users/9otxaeemjqy70001", - "content": ":blobwtfnotlikethis:", - "id": "https://mai.waifuism.life/likes/9q2xifhrdnb0001b", - "object": "https://bungle.online/notes/9q2xi2sy4k", - "tag": [ - { - "icon": { - "mediaType": "image/png", - "type": "Image", - "url": "https://mai.waifuism.life/files/1b0510f2-1fb4-43f5-a399-10053bbd8f0f" - }, - "id": "https://mai.waifuism.life/emojis/blobwtfnotlikethis", - "name": ":blobwtfnotlikethis:", - "type": "Emoji", - "updated": "2024-02-07T02:21:46.497Z" - } - ], - "type": "Like" -} - diff --git a/test/fixtures/mitra-custom-emoji-like.json b/test/fixtures/mitra-custom-emoji-like.json deleted file mode 100644 index 4d727febd..000000000 --- a/test/fixtures/mitra-custom-emoji-like.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/ns/activitystreams", - "https://w3id.org/security/v1", - "https://w3id.org/security/data-integrity/v1", - { - "Emoji": "toot:Emoji", - "Hashtag": "as:Hashtag", - "sensitive": "as:sensitive", - "toot": "http://joinmastodon.org/ns#" - } - ], - "actor": "https://mitra.social/users/silverpill", - "cc": [], - "content": ":ablobcatheartsqueeze:", - "id": "https://mitra.social/activities/like/0195a89a-a3a0-ead4-3a1c-aa6311397cfd", - "object": "https://framapiaf.org/users/peertube/statuses/114182703352270287", - "proof": { - "created": "2025-03-18T09:34:21.610678375Z", - "cryptosuite": "eddsa-jcs-2022", - "proofPurpose": "assertionMethod", - "proofValue": "z5AvpwkXQGFpTneRVDNeF48Jo9qYG6PgrE5HaPPpQNdNyc31ULMN4Vxd4aFXELo4Rk5Y9hd9nDy254xP8v5uGGWp1", - "type": "DataIntegrityProof", - "verificationMethod": "https://mitra.social/users/silverpill#ed25519-key" - }, - "tag": [ - { - "attributedTo": "https://mitra.social/actor", - "icon": { - "mediaType": "image/png", - "type": "Image", - "url": "https://mitra.social/media/a08e153441b25e512ab1b2e8922f5d8cd928322c8b79958cd48297ac722a4117.png" - }, - "id": "https://mitra.social/objects/emojis/ablobcatheartsqueeze", - "name": ":ablobcatheartsqueeze:", - "type": "Emoji", - "updated": "1970-01-01T00:00:00Z" - } - ], - "to": [ - "https://framapiaf.org/users/peertube", - "https://www.w3.org/ns/activitystreams#Public" - ], - "type": "Like" -} - diff --git a/test/fixtures/rich_media/instagram_longtext.html b/test/fixtures/rich_media/instagram_longtext.html deleted file mode 100644 index e833f408c..000000000 --- a/test/fixtures/rich_media/instagram_longtext.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - -CAPTURE THE ATLAS | ✨ A Once-in-a-Lifetime Shot: Total Lunar Eclipse + Aurora Substorm! 🔴💚 - -Last Thursday night, under the freezing skies of Northern Alaska, I... | Instagram - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/fixtures/tesla_mock/deepl-languages-list.json b/test/fixtures/tesla_mock/deepl-languages-list.json deleted file mode 100644 index 03d47d2ec..000000000 --- a/test/fixtures/tesla_mock/deepl-languages-list.json +++ /dev/null @@ -1 +0,0 @@ -[{"language":"BG","name":"Bulgarian","supports_formality":false},{"language":"CS","name":"Czech","supports_formality":false},{"language":"DA","name":"Danish","supports_formality":false},{"language":"DE","name":"German","supports_formality":true},{"language":"EL","name":"Greek","supports_formality":false},{"language":"EN-GB","name":"English (British)","supports_formality":false},{"language":"EN-US","name":"English (American)","supports_formality":false},{"language":"ES","name":"Spanish","supports_formality":true},{"language":"ET","name":"Estonian","supports_formality":false},{"language":"FI","name":"Finnish","supports_formality":false},{"language":"FR","name":"French","supports_formality":true},{"language":"HU","name":"Hungarian","supports_formality":false},{"language":"ID","name":"Indonesian","supports_formality":false},{"language":"IT","name":"Italian","supports_formality":true},{"language":"JA","name":"Japanese","supports_formality":false},{"language":"LT","name":"Lithuanian","supports_formality":false},{"language":"LV","name":"Latvian","supports_formality":false},{"language":"NL","name":"Dutch","supports_formality":true},{"language":"PL","name":"Polish","supports_formality":true},{"language":"PT-BR","name":"Portuguese (Brazilian)","supports_formality":true},{"language":"PT-PT","name":"Portuguese (European)","supports_formality":true},{"language":"RO","name":"Romanian","supports_formality":false},{"language":"RU","name":"Russian","supports_formality":true},{"language":"SK","name":"Slovak","supports_formality":false},{"language":"SL","name":"Slovenian","supports_formality":false},{"language":"SV","name":"Swedish","supports_formality":false},{"language":"TR","name":"Turkish","supports_formality":false},{"language":"UK","name":"Ukrainian","supports_formality":false},{"language":"ZH","name":"Chinese (simplified)","supports_formality":false}] \ No newline at end of file diff --git a/test/fixtures/tesla_mock/deepl-translation.json b/test/fixtures/tesla_mock/deepl-translation.json deleted file mode 100644 index fef7bb215..000000000 --- a/test/fixtures/tesla_mock/deepl-translation.json +++ /dev/null @@ -1 +0,0 @@ -{"translations":[{"detected_source_language":"PL","text":"REMOVE THE FOLLOWER!Paste this on your follower. If we get 70% of nk users...they will remove the follower!!!"}]} \ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/21.1 b/test/fixtures/warnings/otp_version/21.1 new file mode 100644 index 000000000..90cd64c4f --- /dev/null +++ b/test/fixtures/warnings/otp_version/21.1 @@ -0,0 +1 @@ +21.1 \ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/22.1 b/test/fixtures/warnings/otp_version/22.1 new file mode 100644 index 000000000..d9b314368 --- /dev/null +++ b/test/fixtures/warnings/otp_version/22.1 @@ -0,0 +1 @@ +22.1 \ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/22.4 b/test/fixtures/warnings/otp_version/22.4 new file mode 100644 index 000000000..1da8ccd28 --- /dev/null +++ b/test/fixtures/warnings/otp_version/22.4 @@ -0,0 +1 @@ +22.4 \ No newline at end of file diff --git a/test/fixtures/warnings/otp_version/23.0 b/test/fixtures/warnings/otp_version/23.0 new file mode 100644 index 000000000..4266d8634 --- /dev/null +++ b/test/fixtures/warnings/otp_version/23.0 @@ -0,0 +1 @@ +23.0 \ No newline at end of file diff --git a/test/mix/tasks/pleroma/frontend_test.exs b/test/mix/tasks/pleroma/frontend_test.exs index 59ebcec92..6d09f8e36 100644 --- a/test/mix/tasks/pleroma/frontend_test.exs +++ b/test/mix/tasks/pleroma/frontend_test.exs @@ -11,7 +11,7 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do @dir "test/frontend_static_test" setup do - Pleroma.Backports.mkdir_p!(@dir) + File.mkdir_p!(@dir) clear_config([:instance, :static_dir], @dir) on_exit(fn -> @@ -50,7 +50,7 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do folder = Path.join([@dir, "frontends", "pleroma", "fantasy"]) previously_existing = Path.join([folder, "temp"]) - Pleroma.Backports.mkdir_p!(folder) + File.mkdir_p!(folder) File.write!(previously_existing, "yey") assert File.exists?(previously_existing) diff --git a/test/mix/tasks/pleroma/instance_test.exs b/test/mix/tasks/pleroma/instance_test.exs index 5ecb6e445..b1c10e03c 100644 --- a/test/mix/tasks/pleroma/instance_test.exs +++ b/test/mix/tasks/pleroma/instance_test.exs @@ -7,7 +7,7 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do use Pleroma.DataCase setup do - Pleroma.Backports.mkdir_p!(tmp_path()) + File.mkdir_p!(tmp_path()) on_exit(fn -> File.rm_rf(tmp_path()) diff --git a/test/mix/tasks/pleroma/uploads_test.exs b/test/mix/tasks/pleroma/uploads_test.exs index 0aa24807e..f3d5aa64f 100644 --- a/test/mix/tasks/pleroma/uploads_test.exs +++ b/test/mix/tasks/pleroma/uploads_test.exs @@ -62,7 +62,7 @@ defmodule Mix.Tasks.Pleroma.UploadsTest do upload_dir = Config.get([Pleroma.Uploaders.Local, :uploads]) if not File.exists?(upload_dir) || File.ls!(upload_dir) == [] do - Pleroma.Backports.mkdir_p(upload_dir) + File.mkdir_p(upload_dir) Path.join([upload_dir, "file.txt"]) |> File.touch() diff --git a/test/pleroma/emoji/pack_test.exs b/test/pleroma/emoji/pack_test.exs index b458401a7..6ab3e657e 100644 --- a/test/pleroma/emoji/pack_test.exs +++ b/test/pleroma/emoji/pack_test.exs @@ -58,7 +58,7 @@ defmodule Pleroma.Emoji.PackTest do test "skips existing emojis when adding from zip file", %{pack: pack} do # First, let's create a test pack with a "bear" emoji test_pack_path = Path.join(@emoji_path, "test_bear_pack") - Pleroma.Backports.mkdir_p(test_pack_path) + File.mkdir_p(test_pack_path) # Create a pack.json file File.write!(Path.join(test_pack_path, "pack.json"), """ diff --git a/test/pleroma/frontend_test.exs b/test/pleroma/frontend_test.exs index 22e0ffb9a..c89c56c8c 100644 --- a/test/pleroma/frontend_test.exs +++ b/test/pleroma/frontend_test.exs @@ -9,7 +9,7 @@ defmodule Pleroma.FrontendTest do @dir "test/frontend_static_test" setup do - Pleroma.Backports.mkdir_p!(@dir) + File.mkdir_p!(@dir) clear_config([:instance, :static_dir], @dir) on_exit(fn -> @@ -46,7 +46,7 @@ defmodule Pleroma.FrontendTest do folder = Path.join([@dir, "frontends", "pleroma", "fantasy"]) previously_existing = Path.join([folder, "temp"]) - Pleroma.Backports.mkdir_p!(folder) + File.mkdir_p!(folder) File.write!(previously_existing, "yey") assert File.exists?(previously_existing) diff --git a/test/pleroma/language/language_detector_test.exs b/test/pleroma/language/language_detector_test.exs deleted file mode 100644 index ccb81d5bd..000000000 --- a/test/pleroma/language/language_detector_test.exs +++ /dev/null @@ -1,56 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.LanguageDetectorTest do - use Pleroma.DataCase, async: true - - alias Pleroma.Language.LanguageDetector - alias Pleroma.Language.LanguageDetectorMock - alias Pleroma.StaticStubbedConfigMock - - import Mox - - setup do - # Stub the StaticStubbedConfigMock to return our mock for the provider - StaticStubbedConfigMock - |> stub(:get, fn - [Pleroma.Language.LanguageDetector, :provider] -> LanguageDetectorMock - _other -> nil - end) - - # Stub the LanguageDetectorMock with default implementations - LanguageDetectorMock - |> stub(:missing_dependencies, fn -> [] end) - |> stub(:configured?, fn -> true end) - - :ok - end - - test "it detects text language" do - LanguageDetectorMock - |> expect(:detect, fn _text -> "fr" end) - - detected_language = LanguageDetector.detect("Je viens d'atterrir en Tchéquie.") - - assert detected_language == "fr" - end - - test "it returns nil if text is not long enough" do - # No need to set expectations as the word count check happens before the provider is called - - detected_language = LanguageDetector.detect("it returns nil") - - assert detected_language == nil - end - - test "it returns nil if no provider specified" do - # Override the stub to return nil for the provider - StaticStubbedConfigMock - |> expect(:get, fn [Pleroma.Language.LanguageDetector, :provider] -> nil end) - - detected_language = LanguageDetector.detect("this should also return nil") - - assert detected_language == nil - end -end diff --git a/test/pleroma/language/translation/deepl_test.exs b/test/pleroma/language/translation/deepl_test.exs deleted file mode 100644 index 3a7265622..000000000 --- a/test/pleroma/language/translation/deepl_test.exs +++ /dev/null @@ -1,37 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Language.Translation.DeeplTest do - use Pleroma.Web.ConnCase - - alias Pleroma.Language.Translation.Deepl - - test "it translates text" do - Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) - clear_config([Pleroma.Language.Translation.Deepl, :base_url], "https://api-free.deepl.com") - clear_config([Pleroma.Language.Translation.Deepl, :api_key], "API_KEY") - - {:ok, res} = - Deepl.translate( - "USUNĄĆ ŚLEDZIKA!Wklej to na swojego śledzika. Jeżeli uzbieramy 70% użytkowników nk...to usuną śledzika!!!", - "pl", - "en" - ) - - assert %{ - detected_source_language: "PL", - provider: "DeepL" - } = res - end - - test "it returns languages list" do - Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) - clear_config([Pleroma.Language.Translation.Deepl, :base_url], "https://api-free.deepl.com") - clear_config([Pleroma.Language.Translation.Deepl, :api_key], "API_KEY") - - assert {:ok, [language | _languages]} = Deepl.supported_languages(:target) - - assert is_binary(language) - end -end diff --git a/test/pleroma/language/translation_test.exs b/test/pleroma/language/translation_test.exs deleted file mode 100644 index 0be7a8d60..000000000 --- a/test/pleroma/language/translation_test.exs +++ /dev/null @@ -1,28 +0,0 @@ -defmodule Pleroma.Language.TranslationTest do - use Pleroma.Web.ConnCase - - alias Pleroma.Language.Translation - - setup do: clear_config([Pleroma.Language.Translation, :provider], TranslationMock) - - test "it translates text" do - assert {:ok, - %{ - content: "txet emos", - detected_source_language: _, - provider: _ - }} = Translation.translate("some text", "en", "uk") - end - - test "it stores translation result in cache" do - Translation.translate("some text", "en", "uk") - - assert {:ok, result} = - Cachex.get( - :translations_cache, - "en/uk/#{:crypto.hash(:sha256, "some text") |> Base.encode64()}" - ) - - assert result.content == "txet emos" - end -end diff --git a/test/pleroma/object_test.exs b/test/pleroma/object_test.exs index 13e941e4d..ed5c2b6c8 100644 --- a/test/pleroma/object_test.exs +++ b/test/pleroma/object_test.exs @@ -156,7 +156,7 @@ defmodule Pleroma.ObjectTest do uploads_dir = Pleroma.Config.get!([Pleroma.Uploaders.Local, :uploads]) - Pleroma.Backports.mkdir_p!(uploads_dir) + File.mkdir_p!(uploads_dir) file = %Plug.Upload{ content_type: "image/jpeg", diff --git a/test/pleroma/otp_version_test.exs b/test/pleroma/otp_version_test.exs new file mode 100644 index 000000000..21701d5a8 --- /dev/null +++ b/test/pleroma/otp_version_test.exs @@ -0,0 +1,42 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2022 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.OTPVersionTest do + use ExUnit.Case, async: true + + alias Pleroma.OTPVersion + + describe "check/1" do + test "22.4" do + assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/22.4"]) == + "22.4" + end + + test "22.1" do + assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/22.1"]) == + "22.1" + end + + test "21.1" do + assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/21.1"]) == + "21.1" + end + + test "23.0" do + assert OTPVersion.get_version_from_files(["test/fixtures/warnings/otp_version/23.0"]) == + "23.0" + end + + 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" + ]) == "22.4" + end + + test "empty paths" do + assert OTPVersion.get_version_from_files([]) == nil + end + end +end diff --git a/test/pleroma/safe_zip_test.exs b/test/pleroma/safe_zip_test.exs index f07b25675..3312d4e63 100644 --- a/test/pleroma/safe_zip_test.exs +++ b/test/pleroma/safe_zip_test.exs @@ -9,12 +9,12 @@ defmodule Pleroma.SafeZipTest do setup do # Ensure tmp directory exists - Pleroma.Backports.mkdir_p!(@tmp_dir) + File.mkdir_p!(@tmp_dir) on_exit(fn -> # Clean up any files created during tests File.rm_rf!(@tmp_dir) - Pleroma.Backports.mkdir_p!(@tmp_dir) + File.mkdir_p!(@tmp_dir) end) :ok @@ -89,7 +89,7 @@ defmodule Pleroma.SafeZipTest do # For this test, we'll manually check if the file exists in the archive # by extracting it and verifying it exists extract_dir = Path.join(@tmp_dir, "extract_check") - Pleroma.Backports.mkdir_p!(extract_dir) + File.mkdir_p!(extract_dir) {:ok, files} = SafeZip.unzip_file(zip_path, extract_dir) # Verify the root file was extracted @@ -145,7 +145,7 @@ defmodule Pleroma.SafeZipTest do test "can create zip with directories" do # Create a directory structure dir_path = Path.join(@tmp_dir, "test_dir") - Pleroma.Backports.mkdir_p!(dir_path) + File.mkdir_p!(dir_path) file_in_dir_path = Path.join(dir_path, "file_in_dir.txt") File.write!(file_in_dir_path, "file in directory") @@ -428,7 +428,7 @@ defmodule Pleroma.SafeZipTest do # Create a directory and a file in it dir_path = Path.join(@tmp_dir, "file_in_dir") - Pleroma.Backports.mkdir_p!(dir_path) + File.mkdir_p!(dir_path) file_in_dir_path = Path.join(dir_path, "test_file.txt") File.write!(file_in_dir_path, "file in directory content") diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index 0b4dc9197..176e70ef9 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -2669,12 +2669,8 @@ defmodule Pleroma.UserTest do assert {:ok, user} = User.update_last_active_at(user) - assert NaiveDateTime.compare(user.last_active_at, test_started_at) in [:gt, :eq] - - assert NaiveDateTime.compare( - user.last_active_at, - NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) - ) in [:lt, :eq] + assert user.last_active_at >= test_started_at + assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) last_active_at = NaiveDateTime.utc_now() @@ -2686,15 +2682,10 @@ defmodule Pleroma.UserTest do |> cast(%{last_active_at: last_active_at}, [:last_active_at]) |> User.update_and_set_cache() - assert NaiveDateTime.compare(user.last_active_at, last_active_at) == :eq - + assert user.last_active_at == last_active_at assert {:ok, user} = User.update_last_active_at(user) - assert NaiveDateTime.compare(user.last_active_at, test_started_at) in [:gt, :eq] - - assert NaiveDateTime.compare( - user.last_active_at, - NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) - ) in [:lt, :eq] + assert user.last_active_at >= test_started_at + assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) end test "active_user_count/1" do @@ -2792,15 +2783,6 @@ defmodule Pleroma.UserTest do assert user_updated.also_known_as |> length() == 1 assert user2.ap_id in user_updated.also_known_as end - - test "should tolerate non-http(s) aliases" do - user = - insert(:user, %{ - also_known_as: ["at://did:plc:xgvzy7ni6ig6ievcbls5jaxe"] - }) - - assert "at://did:plc:xgvzy7ni6ig6ievcbls5jaxe" in user.also_known_as - end end describe "alias_users/1" do diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index c16f081f6..dbc3aa532 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -826,7 +826,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert object.data["repliesCount"] == 2 end - test "increases quotes count", %{user: user} do + test "increates quotes count", %{user: user} do user2 = insert(:user) {:ok, activity} = CommonAPI.post(user, %{status: "1", visibility: "public"}) diff --git a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs index 3c7ff0eeb..829598246 100644 --- a/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs +++ b/test/pleroma/web/activity_pub/object_validators/article_note_page_validator_test.exs @@ -5,33 +5,12 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest do use Pleroma.DataCase, async: true - alias Pleroma.Language.LanguageDetectorMock - alias Pleroma.StaticStubbedConfigMock alias Pleroma.Web.ActivityPub.ObjectValidator alias Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator alias Pleroma.Web.ActivityPub.Utils - import Mox import Pleroma.Factory - # Setup for all tests - setup do - # Stub the StaticStubbedConfigMock to return our mock for the provider - StaticStubbedConfigMock - |> stub(:get, fn - [Pleroma.Language.LanguageDetector, :provider] -> LanguageDetectorMock - _other -> nil - end) - - # Stub the LanguageDetectorMock with default implementations - LanguageDetectorMock - |> stub(:missing_dependencies, fn -> [] end) - |> stub(:configured?, fn -> true end) - |> stub(:detect, fn _text -> nil end) - - :ok - end - describe "Notes" do setup do user = insert(:user) @@ -255,37 +234,6 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest assert object.language == "pl" end - test "it doesn't call LanguageDetector when language is specified" do - # Set up expectation that detect should not be called - LanguageDetectorMock - |> expect(:detect, 0, fn _ -> flunk("LanguageDetector.detect should not be called") end) - |> stub(:missing_dependencies, fn -> [] end) - |> stub(:configured?, fn -> true end) - - # Stub the StaticStubbedConfigMock to return our mock for the provider - StaticStubbedConfigMock - |> stub(:get, fn - [Pleroma.Language.LanguageDetector, :provider] -> LanguageDetectorMock - _other -> nil - end) - - user = insert(:user) - - note = %{ - "to" => ["https://www.w3.org/ns/activitystreams#Public"], - "cc" => [], - "id" => Utils.generate_object_id(), - "type" => "Note", - "content" => "a post in English", - "contentMap" => %{ - "en" => "a post in English" - }, - "attributedTo" => user.ap_id - } - - ArticleNotePageValidator.cast_and_apply(note) - end - test "it adds contentMap if language is specified" do user = insert(:user) diff --git a/test/pleroma/web/activity_pub/publisher_test.exs b/test/pleroma/web/activity_pub/publisher_test.exs index b7ff0ed5f..99ed42877 100644 --- a/test/pleroma/web/activity_pub/publisher_test.exs +++ b/test/pleroma/web/activity_pub/publisher_test.exs @@ -520,105 +520,4 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do assert decoded["cc"] == [] end - - test "unlisted activities retain public address in cc" do - user = insert(:user) - - # simulate unlistd activity by only having - # public address in cc - activity = - insert(:note_activity, - user: user, - data_attrs: %{ - "cc" => [@as_public], - "to" => [user.follower_address] - } - ) - - assert @as_public in activity.data["cc"] - - prepared = - Publisher.prepare_one(%{ - inbox: "https://remote.instance/users/someone/inbox", - activity_id: activity.id - }) - - {:ok, decoded} = Jason.decode(prepared.json) - - assert @as_public in decoded["cc"] - - # maybe we also have another inbox in cc - # during Publishing - activity = - insert(:note_activity, - user: user, - data_attrs: %{ - "cc" => [@as_public], - "to" => [user.follower_address] - } - ) - - prepared = - Publisher.prepare_one(%{ - inbox: "https://remote.instance/users/someone/inbox", - activity_id: activity.id, - cc: ["https://remote.instance/users/someone_else/inbox"] - }) - - {:ok, decoded} = Jason.decode(prepared.json) - - assert decoded["cc"] == [@as_public, "https://remote.instance/users/someone_else/inbox"] - end - - test "public address in cc parameter is preserved" do - user = insert(:user) - - cc_with_public = [@as_public, "https://example.org/users/other"] - - activity = - insert(:note_activity, - user: user, - data_attrs: %{ - "cc" => cc_with_public, - "to" => [user.follower_address] - } - ) - - assert @as_public in activity.data["cc"] - - prepared = - Publisher.prepare_one(%{ - inbox: "https://remote.instance/users/someone/inbox", - activity_id: activity.id, - cc: cc_with_public - }) - - {:ok, decoded} = Jason.decode(prepared.json) - - assert cc_with_public == decoded["cc"] - end - - test "cc parameter is preserved" do - user = insert(:user) - - activity = - insert(:note_activity, - user: user, - data_attrs: %{ - "cc" => ["https://example.com/specific/user"], - "to" => [user.follower_address] - } - ) - - prepared = - Publisher.prepare_one(%{ - inbox: "https://remote.instance/users/someone/inbox", - activity_id: activity.id, - cc: ["https://example.com/specific/user"] - }) - - {:ok, decoded} = Jason.decode(prepared.json) - - assert decoded["cc"] == ["https://example.com/specific/user"] - end end diff --git a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs index 27f8522ce..c02f66d77 100644 --- a/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs +++ b/test/pleroma/web/activity_pub/transmogrifier/like_handling_test.exs @@ -6,7 +6,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do use Pleroma.DataCase, async: true alias Pleroma.Activity - alias Pleroma.Object alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.CommonAPI @@ -76,107 +75,4 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.LikeHandlingTest do assert activity_data["object"] == activity.data["object"] assert activity_data["content"] == "⭐" end - - test "it works for misskey likes with custom emoji" do - user = insert(:user) - - {:ok, activity} = CommonAPI.post(user, %{status: "hello"}) - - data = - File.read!("test/fixtures/misskey-custom-emoji-like.json") - |> Jason.decode!() - |> Map.put("object", activity.data["object"]) - - _actor = insert(:user, ap_id: data["actor"], local: false) - - {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data) - - assert activity_data["actor"] == data["actor"] - assert activity_data["type"] == "EmojiReact" - assert activity_data["id"] == data["id"] - assert activity_data["object"] == activity.data["object"] - assert activity_data["content"] == ":blobwtfnotlikethis:" - - assert [["blobwtfnotlikethis", _, _]] = - Object.get_by_ap_id(activity.data["object"]) - |> Object.get_emoji_reactions() - end - - test "it works for mitra likes with custom emoji" do - user = insert(:user) - - {:ok, activity} = CommonAPI.post(user, %{status: "hello"}) - - data = - File.read!("test/fixtures/mitra-custom-emoji-like.json") - |> Jason.decode!() - |> Map.put("object", activity.data["object"]) - - _actor = insert(:user, ap_id: data["actor"], local: false) - - {:ok, %Activity{data: activity_data, local: false}} = Transmogrifier.handle_incoming(data) - - assert activity_data["actor"] == data["actor"] - assert activity_data["type"] == "EmojiReact" - assert activity_data["id"] == data["id"] - assert activity_data["object"] == activity.data["object"] - assert activity_data["content"] == ":ablobcatheartsqueeze:" - - assert [["ablobcatheartsqueeze", _, _]] = - Object.get_by_ap_id(activity.data["object"]) - |> Object.get_emoji_reactions() - end - - test "it works for likes with wrong content" do - user = insert(:user) - - {:ok, activity} = CommonAPI.post(user, %{status: "hello"}) - - data = - File.read!("test/fixtures/mitra-custom-emoji-like.json") - |> Jason.decode!() - |> Map.put("object", activity.data["object"]) - |> Map.put("content", 1) - - _actor = insert(:user, ap_id: data["actor"], local: false) - - assert {:ok, activity} = Transmogrifier.handle_incoming(data) - assert activity.data["type"] == "Like" - end - - test "it changes incoming dislikes into emoji reactions" do - user = insert(:user) - - {:ok, activity} = CommonAPI.post(user, %{status: "hello"}) - - data = - File.read!("test/fixtures/friendica-dislike.json") - |> Jason.decode!() - |> Map.put("object", activity.data["object"]) - - _actor = insert(:user, ap_id: data["actor"], local: false) - - {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data) - - refute Enum.empty?(activity.recipients) - - assert data["actor"] == "https://my-place.social/profile/vaartis" - assert data["type"] == "EmojiReact" - assert data["content"] == "👎" - assert data["id"] == "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182" - assert data["object"] == activity.data["object"] - - data = - File.read!("test/fixtures/friendica-dislike-undo.json") - |> Jason.decode!() - |> put_in(["object", "object"], activity.data["object"]) - - {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) - - assert data["actor"] == "https://my-place.social/profile/vaartis" - assert data["type"] == "Undo" - - assert data["object"] == - "https://my-place.social/objects/e599373b-1368-4b20-cd24-837166957182" - end end diff --git a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs index a6b8dba46..0d1a4999e 100644 --- a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs @@ -13,7 +13,7 @@ defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do setup do clear_config([:instance, :static_dir], @dir) - Pleroma.Backports.mkdir_p!(Pleroma.Frontend.dir()) + File.mkdir_p!(Pleroma.Frontend.dir()) on_exit(fn -> File.rm_rf(@dir) diff --git a/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs b/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs index 344c908fe..9511dccea 100644 --- a/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs @@ -10,7 +10,7 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentControllerTest do @default_instance_panel ~s(

Welcome to Pleroma!

) setup do - Pleroma.Backports.mkdir_p!(@dir) + File.mkdir_p!(@dir) on_exit(fn -> File.rm_rf(@dir) end) end diff --git a/test/pleroma/web/common_api_test.exs b/test/pleroma/web/common_api_test.exs index 6b5d31537..73230a58c 100644 --- a/test/pleroma/web/common_api_test.exs +++ b/test/pleroma/web/common_api_test.exs @@ -111,17 +111,6 @@ defmodule Pleroma.Web.CommonAPITest do end end - test "add expiring block", %{blocker: blocker, blocked: blocked} do - {:ok, _} = CommonAPI.block(blocked, blocker, %{expires_in: 60}) - assert User.blocks?(blocker, blocked) - - worker = Pleroma.Workers.MuteExpireWorker - args = %{"op" => "unblock_user", "blocker_id" => blocker.id, "blocked_id" => blocked.id} - - assert :ok = perform_job(worker, args) - refute User.blocks?(blocker, blocked) - end - test "it blocks and does not federate if outgoing blocks are disabled", %{ blocker: blocker, blocked: blocked diff --git a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs index 8a0fe5259..373a84303 100644 --- a/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/instance_controller_test.exs @@ -152,46 +152,4 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do } ] = result["rules"] end - - test "translation languages matrix", %{conn: conn} do - clear_config([Pleroma.Language.Translation, :provider], TranslationMock) - - assert %{"en" => ["pl"], "pl" => ["en"]} = - conn - |> get("/api/v1/instance/translation_languages") - |> json_response_and_validate_schema(200) - end - - test "base_urls in pleroma metadata", %{conn: conn} do - media_proxy_base_url = "https://media.example.org" - upload_base_url = "https://uploads.example.org" - - clear_config([:media_proxy, :enabled], true) - clear_config([:media_proxy, :base_url], media_proxy_base_url) - clear_config([Pleroma.Upload, :base_url], upload_base_url) - - conn = get(conn, "/api/v1/instance") - - assert result = json_response_and_validate_schema(conn, 200) - assert result["pleroma"]["metadata"]["base_urls"]["media_proxy"] == media_proxy_base_url - assert result["pleroma"]["metadata"]["base_urls"]["upload"] == upload_base_url - - # Test when media_proxy is disabled - clear_config([:media_proxy, :enabled], false) - - conn = get(conn, "/api/v1/instance") - - assert result = json_response_and_validate_schema(conn, 200) - refute Map.has_key?(result["pleroma"]["metadata"]["base_urls"], "media_proxy") - assert result["pleroma"]["metadata"]["base_urls"]["upload"] == upload_base_url - - # Test when upload base_url is not set - clear_config([Pleroma.Upload, :base_url], nil) - - conn = get(conn, "/api/v1/instance") - - assert result = json_response_and_validate_schema(conn, 200) - refute Map.has_key?(result["pleroma"]["metadata"]["base_urls"], "media_proxy") - refute Map.has_key?(result["pleroma"]["metadata"]["base_urls"], "upload") - end end diff --git a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs index 25a17d5c1..a4bca6cf9 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -2483,62 +2483,4 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do |> json_response_and_validate_schema(:not_found) end end - - describe "translating statuses" do - setup do: clear_config([Pleroma.Language.Translation, :provider], TranslationMock) - - test "it translates a status to user language" do - user = insert(:user, language: "fr") - %{conn: conn} = oauth_access(["read:statuses"], user: user) - another_user = insert(:user) - - {:ok, activity} = - CommonAPI.post(another_user, %{ - status: "Cześć!", - visibility: "public", - language: "pl" - }) - - response = - conn - |> post("/api/v1/statuses/#{activity.id}/translate") - |> json_response_and_validate_schema(200) - - assert response == %{ - "content" => "!ćśezC", - "detected_source_language" => "pl", - "provider" => "TranslationMock" - } - end - - test "it returns an error if no target language provided" do - %{conn: conn} = oauth_access(["read:statuses"]) - another_user = insert(:user) - - {:ok, activity} = - CommonAPI.post(another_user, %{ - status: "Cześć!", - language: "pl" - }) - - assert conn - |> post("/api/v1/statuses/#{activity.id}/translate") - |> json_response_and_validate_schema(400) - end - - test "it doesn't translate non-public statuses" do - %{conn: conn, user: user} = oauth_access(["read:statuses"]) - - {:ok, activity} = - CommonAPI.post(user, %{ - status: "Cześć!", - visibility: "private", - language: "pl" - }) - - assert conn - |> post("/api/v1/statuses/#{activity.id}/translate") - |> json_response_and_validate_schema(404) - end - end end diff --git a/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs index bcc25b83e..be94a02ad 100644 --- a/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/scrobble_controller_test.exs @@ -19,33 +19,10 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do "artist" => "lain", "album" => "lain radio", "length" => "180000", - "external_link" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1" + "externalLink" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1" }) - assert %{ - "title" => "lain radio episode 1", - "external_link" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1" - } = json_response_and_validate_schema(conn, 200) - end - - test "external_link fallback" do - %{conn: conn} = oauth_access(["write"]) - - conn = - conn - |> put_req_header("content-type", "application/json") - |> post("/api/v1/pleroma/scrobble", %{ - "title" => "lain radio episode 2", - "artist" => "lain", - "album" => "lain radio", - "length" => "180000", - "externalLink" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2" - }) - - assert %{ - "title" => "lain radio episode 2", - "external_link" => "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2" - } = json_response_and_validate_schema(conn, 200) + assert %{"title" => "lain radio episode 1"} = json_response_and_validate_schema(conn, 200) end end @@ -58,7 +35,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do title: "lain radio episode 1", artist: "lain", album: "lain radio", - external_link: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1" + externalLink: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+1" }) {:ok, _activity} = @@ -66,7 +43,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do title: "lain radio episode 2", artist: "lain", album: "lain radio", - external_link: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2" + externalLink: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+2" }) {:ok, _activity} = @@ -74,7 +51,7 @@ defmodule Pleroma.Web.PleromaAPI.ScrobbleControllerTest do title: "lain radio episode 3", artist: "lain", album: "lain radio", - external_link: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+3" + externalLink: "https://www.last.fm/music/lain/lain+radio/lain+radio+episode+3" }) conn = get(conn, "/api/v1/pleroma/accounts/#{user.id}/scrobbles") diff --git a/test/pleroma/web/plugs/frontend_static_plug_test.exs b/test/pleroma/web/plugs/frontend_static_plug_test.exs index a7af3e74e..6f4d24d9e 100644 --- a/test/pleroma/web/plugs/frontend_static_plug_test.exs +++ b/test/pleroma/web/plugs/frontend_static_plug_test.exs @@ -13,7 +13,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do @dir "test/tmp/instance_static" setup do - Pleroma.Backports.mkdir_p!(@dir) + File.mkdir_p!(@dir) on_exit(fn -> File.rm_rf(@dir) end) end @@ -38,7 +38,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do clear_config([:frontends, :primary], %{"name" => name, "ref" => ref}) path = "#{@dir}/frontends/#{name}/#{ref}" - Pleroma.Backports.mkdir_p!(path) + File.mkdir_p!(path) File.write!("#{path}/index.html", "from frontend plug") index = get(conn, "/") @@ -52,7 +52,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do clear_config([:frontends, :admin], %{"name" => name, "ref" => ref}) path = "#{@dir}/frontends/#{name}/#{ref}" - Pleroma.Backports.mkdir_p!(path) + File.mkdir_p!(path) File.write!("#{path}/index.html", "from frontend plug") index = get(conn, "/pleroma/admin/") @@ -67,7 +67,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do clear_config([:frontends, :primary], %{"name" => name, "ref" => ref}) path = "#{@dir}/frontends/#{name}/#{ref}" - Pleroma.Backports.mkdir_p!("#{path}/proxy/rr/ss") + File.mkdir_p!("#{path}/proxy/rr/ss") File.write!("#{path}/proxy/rr/ss/Ek7w8WPVcAApOvN.jpg:large", "FB image") ConfigMock diff --git a/test/pleroma/web/plugs/instance_static_test.exs b/test/pleroma/web/plugs/instance_static_test.exs index b5a5a3334..33b74dcf0 100644 --- a/test/pleroma/web/plugs/instance_static_test.exs +++ b/test/pleroma/web/plugs/instance_static_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.Web.Plugs.InstanceStaticTest do @dir "test/tmp/instance_static" setup do - Pleroma.Backports.mkdir_p!(@dir) + File.mkdir_p!(@dir) on_exit(fn -> File.rm_rf(@dir) end) end @@ -34,7 +34,7 @@ defmodule Pleroma.Web.Plugs.InstanceStaticTest do refute html_response(bundled_index, 200) == "from frontend plug" path = "#{@dir}/frontends/#{name}/#{ref}" - Pleroma.Backports.mkdir_p!(path) + File.mkdir_p!(path) File.write!("#{path}/index.html", "from frontend plug") index = get(conn, "/") diff --git a/test/pleroma/web/plugs/user_tracking_plug_test.exs b/test/pleroma/web/plugs/user_tracking_plug_test.exs index cd9c66448..742f04fea 100644 --- a/test/pleroma/web/plugs/user_tracking_plug_test.exs +++ b/test/pleroma/web/plugs/user_tracking_plug_test.exs @@ -21,12 +21,8 @@ defmodule Pleroma.Web.Plugs.UserTrackingPlugTest do |> assign(:user, user) |> UserTrackingPlug.call(%{}) - assert NaiveDateTime.compare(user.last_active_at, test_started_at) in [:gt, :eq] - - assert NaiveDateTime.compare( - user.last_active_at, - NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) - ) in [:lt, :eq] + assert user.last_active_at >= test_started_at + assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) end test "doesn't update last_active_at if it was updated recently", %{conn: conn} do @@ -42,7 +38,7 @@ defmodule Pleroma.Web.Plugs.UserTrackingPlugTest do |> assign(:user, user) |> UserTrackingPlug.call(%{}) - assert NaiveDateTime.compare(user.last_active_at, last_active_at) == :eq + assert user.last_active_at == last_active_at end test "skips updating last_active_at if user ID is nil", %{conn: conn} do diff --git a/test/pleroma/web/rich_media/parser_test.exs b/test/pleroma/web/rich_media/parser_test.exs index 1f01d657a..20f61badc 100644 --- a/test/pleroma/web/rich_media/parser_test.exs +++ b/test/pleroma/web/rich_media/parser_test.exs @@ -61,13 +61,6 @@ defmodule Pleroma.Web.RichMedia.ParserTest do }} end - test "truncates title and description fields" do - {:ok, parsed} = Parser.parse("https://instagram.com/longtext") - - assert String.length(parsed["title"]) == 120 - assert String.length(parsed["description"]) == 200 - end - test "parses OEmbed and filters HTML tags" do assert Parser.parse("https://example.com/oembed") == {:ok, diff --git a/test/pleroma/web/web_finger/web_finger_controller_test.exs b/test/pleroma/web/web_finger/web_finger_controller_test.exs index be44e3a8b..80e072163 100644 --- a/test/pleroma/web/web_finger/web_finger_controller_test.exs +++ b/test/pleroma/web/web_finger/web_finger_controller_test.exs @@ -5,6 +5,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do use Pleroma.Web.ConnCase + import ExUnit.CaptureLog import Pleroma.Factory import Tesla.Mock @@ -54,26 +55,6 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do ] end - test "Webfinger defaults to JSON when no Accept header is provided" do - user = - insert(:user, - ap_id: "https://hyrule.world/users/zelda", - also_known_as: ["https://mushroom.kingdom/users/toad"] - ) - - response = - build_conn() - |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") - |> json_response(200) - - assert response["subject"] == "acct:#{user.nickname}@localhost" - - assert response["aliases"] == [ - "https://hyrule.world/users/zelda", - "https://mushroom.kingdom/users/toad" - ] - end - test "reach user on tld, while pleroma is running on subdomain" do clear_config([Pleroma.Web.Endpoint, :url, :host], "sub.example.com") @@ -128,25 +109,16 @@ defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do assert result == "Couldn't find user" end - test "Returns JSON when format is not supported" do - user = - insert(:user, - ap_id: "https://hyrule.world/users/zelda", - also_known_as: ["https://mushroom.kingdom/users/toad"] - ) + test "Sends a 404 when invalid format" do + user = insert(:user) - response = - build_conn() - |> put_req_header("accept", "text/html") - |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") - |> json_response(200) - - assert response["subject"] == "acct:#{user.nickname}@localhost" - - assert response["aliases"] == [ - "https://hyrule.world/users/zelda", - "https://mushroom.kingdom/users/toad" - ] + assert capture_log(fn -> + assert_raise Phoenix.NotAcceptableError, fn -> + build_conn() + |> put_req_header("accept", "text/html") + |> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost") + end + end) =~ "no supported media type in accept header" end test "Sends a 400 when resource param is missing" do diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index f8d11e602..1c472fca9 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -1494,11 +1494,6 @@ defmodule HttpRequestMock do {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/twitter_card.html")}} end - def get("https://instagram.com/longtext", _, _, _) do - {:ok, - %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/instagram_longtext.html")}} - end - def get("https://example.com/non-ogp", _, _, _) do {:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/non_ogp_embed.html")}} @@ -1706,24 +1701,6 @@ defmodule HttpRequestMock do }} end - def post("https://api-free.deepl.com/v2/translate" <> _, _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/deepl-translation.json"), - headers: [{"content-type", "application/json"}] - }} - end - - def post("https://api-free.deepl.com/v2/languages" <> _, _, _, _) do - {:ok, - %Tesla.Env{ - status: 200, - body: File.read!("test/fixtures/tesla_mock/deepl-languages-list.json"), - headers: [{"content-type", "application/json"}] - }} - end - def post(url, query, body, headers) do {:error, "Mock response not implemented for POST #{inspect(url)}, #{query}, #{inspect(body)}, #{inspect(headers)}"} @@ -1743,8 +1720,7 @@ defmodule HttpRequestMock do "https://example.com/twitter-card", "https://google.com/", "https://pleroma.local/notice/9kCP7V", - "https://yahoo.com/", - "https://instagram.com/longtext" + "https://yahoo.com/" ] def head(url, _query, _body, _headers) when url in @rich_media_mocks do diff --git a/test/support/mocks.ex b/test/support/mocks.ex index b26834871..ca2974504 100644 --- a/test/support/mocks.ex +++ b/test/support/mocks.ex @@ -34,9 +34,5 @@ Mox.defmock(Pleroma.LoggerMock, for: Pleroma.Logging) Mox.defmock(Pleroma.Uploaders.S3.ExAwsMock, for: Pleroma.Uploaders.S3.ExAwsAPI) -Mox.defmock(Pleroma.Language.LanguageDetectorMock, - for: Pleroma.Language.LanguageDetector.Provider -) - Mox.defmock(Pleroma.DateTimeMock, for: Pleroma.DateTime) Mox.defmock(Pleroma.MogrifyMock, for: Pleroma.MogrifyBehaviour) diff --git a/test/support/translation_mock.ex b/test/support/translation_mock.ex deleted file mode 100644 index 84ed8f696..000000000 --- a/test/support/translation_mock.ex +++ /dev/null @@ -1,43 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2022 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule TranslationMock do - alias Pleroma.Language.Translation.Provider - - use Provider - - @behaviour Provider - - @name "TranslationMock" - - @impl Provider - def configured?, do: true - - @impl Provider - def translate(content, source_language, _target_language) do - {:ok, - %{ - content: content |> String.reverse(), - detected_source_language: source_language, - provider: @name - }} - end - - @impl Provider - def supported_languages(_) do - {:ok, ["en", "pl"]} - end - - @impl Provider - def languages_matrix do - {:ok, - %{ - "en" => ["pl"], - "pl" => ["en"] - }} - end - - @impl Provider - def name, do: @name -end diff --git a/test/test_helper.exs b/test/test_helper.exs index dc6c05a74..94661353b 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -2,6 +2,8 @@ # Copyright © 2017-2022 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only +Code.put_compiler_option(:warnings_as_errors, true) + ExUnit.configure(capture_log: true, max_cases: System.schedulers_online()) ExUnit.start(exclude: [:federated])