From c9304962c3a91f7e38e3d519637b5617a2df4e30 Mon Sep 17 00:00:00 2001 From: duponin Date: Sun, 11 Dec 2022 22:54:47 +0100 Subject: [PATCH 01/41] Uploading an avatar media exceeding max size returns a 413 Until now it was returning a 500 because the upload plug were going through the changeset and ending in the JSON encoder, which raised because struct has to @derive the encoder. --- lib/pleroma/user.ex | 8 +++++- .../api_spec/operations/account_operation.ex | 3 +- .../controllers/account_controller.ex | 6 +++- .../mastodon_api/update_credentials_test.exs | 28 +++++++++++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index e32dd161e..ba30769bb 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -599,7 +599,13 @@ defp put_change_if_present(changeset, map_field, value_function) do {:ok, new_value} <- value_function.(value) do put_change(changeset, map_field, new_value) else - _ -> changeset + {:error, :file_too_large} -> + Ecto.Changeset.validate_change(changeset, map_field, fn map_field, _value -> + [{map_field, "file is too large"}] + end) + + _ -> + changeset end end diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex index e20f57fec..a89f9570e 100644 --- a/lib/pleroma/web/api_spec/operations/account_operation.ex +++ b/lib/pleroma/web/api_spec/operations/account_operation.ex @@ -64,7 +64,8 @@ def update_credentials_operation do requestBody: request_body("Parameters", update_credentials_request(), required: true), responses: %{ 200 => Operation.response("Account", "application/json", Account), - 403 => Operation.response("Error", "application/json", ApiError) + 403 => Operation.response("Error", "application/json", ApiError), + 413 => Operation.response("Error", "application/json", ApiError) } } end diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index a3648c458..0ec805357 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -251,7 +251,11 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p with_pleroma_settings: true ) else - _e -> render_error(conn, :forbidden, "Invalid request") + {:error, %Ecto.Changeset{errors: [avatar: {"file is too large", _}]}} -> + render_error(conn, :request_entity_too_large, "File is too large") + + _e -> + render_error(conn, :forbidden, "Invalid request") end end diff --git a/test/pleroma/web/mastodon_api/update_credentials_test.exs b/test/pleroma/web/mastodon_api/update_credentials_test.exs index a5403f360..98fd0ae59 100644 --- a/test/pleroma/web/mastodon_api/update_credentials_test.exs +++ b/test/pleroma/web/mastodon_api/update_credentials_test.exs @@ -272,6 +272,34 @@ test "updates the user's avatar", %{user: user, conn: conn} do assert user.avatar == nil end + test "updates the user's avatar, upload_limit, returns a HTTP 413", %{conn: conn, user: user} do + upload_limit = Config.get([:instance, :upload_limit]) * 8 + 8 + + assert :ok == + File.write(Path.absname("test/tmp/large_binary.data"), <<0::size(upload_limit)>>) + + new_avatar_oversized = %Plug.Upload{ + content_type: nil, + path: Path.absname("test/tmp/large_binary.data"), + filename: "large_binary.data" + } + + assert user.avatar == %{} + + res = + patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar_oversized}) + + assert user_response = json_response_and_validate_schema(res, 413) + assert user_response["avatar"] != User.avatar_url(user) + + user = User.get_by_id(user.id) + assert user.avatar == %{} + + clear_config([:instance, :upload_limit], upload_limit) + + assert :ok == File.rm(Path.absname("test/tmp/large_binary.data")) + end + test "updates the user's banner", %{user: user, conn: conn} do new_header = %Plug.Upload{ content_type: "image/jpeg", From 3e9c0b380a02011770ee28a6938f5bbec05cc093 Mon Sep 17 00:00:00 2001 From: duponin Date: Sun, 11 Dec 2022 23:15:08 +0100 Subject: [PATCH 02/41] Return 413 when an actor's banner or background exceeds the size limit --- .../controllers/account_controller.ex | 6 +++ .../mastodon_api/update_credentials_test.exs | 54 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 0ec805357..5afbcd0dd 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -254,6 +254,12 @@ def update_credentials(%{assigns: %{user: user}, body_params: params} = conn, _p {:error, %Ecto.Changeset{errors: [avatar: {"file is too large", _}]}} -> render_error(conn, :request_entity_too_large, "File is too large") + {:error, %Ecto.Changeset{errors: [banner: {"file is too large", _}]}} -> + render_error(conn, :request_entity_too_large, "File is too large") + + {:error, %Ecto.Changeset{errors: [background: {"file is too large", _}]}} -> + render_error(conn, :request_entity_too_large, "File is too large") + _e -> render_error(conn, :forbidden, "Invalid request") end diff --git a/test/pleroma/web/mastodon_api/update_credentials_test.exs b/test/pleroma/web/mastodon_api/update_credentials_test.exs index 98fd0ae59..130cbe8d1 100644 --- a/test/pleroma/web/mastodon_api/update_credentials_test.exs +++ b/test/pleroma/web/mastodon_api/update_credentials_test.exs @@ -319,6 +319,32 @@ test "updates the user's banner", %{user: user, conn: conn} do assert user.banner == nil end + test "updates the user's banner, upload_limit, returns a HTTP 413", %{conn: conn, user: user} do + upload_limit = Config.get([:instance, :upload_limit]) * 8 + 8 + + assert :ok == + File.write(Path.absname("test/tmp/large_binary.data"), <<0::size(upload_limit)>>) + + new_header_oversized = %Plug.Upload{ + content_type: nil, + path: Path.absname("test/tmp/large_binary.data"), + filename: "large_binary.data" + } + + res = + patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header_oversized}) + + assert user_response = json_response_and_validate_schema(res, 413) + assert user_response["header"] != User.banner_url(user) + + user = User.get_by_id(user.id) + assert user.banner == %{} + + clear_config([:instance, :upload_limit], upload_limit) + + assert :ok == File.rm(Path.absname("test/tmp/large_binary.data")) + end + test "updates the user's background", %{conn: conn, user: user} do new_header = %Plug.Upload{ content_type: "image/jpeg", @@ -342,6 +368,34 @@ test "updates the user's background", %{conn: conn, user: user} do assert user.background == nil end + test "updates the user's background, upload_limit, returns a HTTP 413", %{ + conn: conn, + user: user + } do + upload_limit = Config.get([:instance, :upload_limit]) * 8 + 8 + + assert :ok == + File.write(Path.absname("test/tmp/large_binary.data"), <<0::size(upload_limit)>>) + + new_background_oversized = %Plug.Upload{ + content_type: nil, + path: Path.absname("test/tmp/large_binary.data"), + filename: "large_binary.data" + } + + res = + patch(conn, "/api/v1/accounts/update_credentials", %{ + "pleroma_background_image" => new_background_oversized + }) + + assert user_response = json_response_and_validate_schema(res, 413) + assert user.background == %{} + + clear_config([:instance, :upload_limit], upload_limit) + + assert :ok == File.rm(Path.absname("test/tmp/large_binary.data")) + end + test "requires 'write:accounts' permission" do token1 = insert(:oauth_token, scopes: ["read"]) token2 = insert(:oauth_token, scopes: ["write", "follow"]) From 8104f460310d371e45835746675debc7fce0f835 Mon Sep 17 00:00:00 2001 From: Norm Date: Sun, 11 Dec 2022 22:57:43 +0000 Subject: [PATCH 03/41] Update 'CHANGELOG.md' --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1dd50ddc..103b060e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased -## Removed +### Removed - Non-finch HTTP adapters - -## Upgrade notes +### Upgrade notes - Ensure `config :tesla, :adapter` is either unset, or set to `{Tesla.Adapter.Finch, name: MyFinch}` in your .exs config +### Changed +- Return HTTP error 413 when uploading an avatar or banner that's above the configured upload limit instead of a 500. ## 2022.12 From 53f21489a2f9737dc2a7f55417f9d9901f750107 Mon Sep 17 00:00:00 2001 From: Norm Date: Wed, 14 Dec 2022 03:03:08 +0000 Subject: [PATCH 04/41] Update the "Updating your instance" docs (#361) This makes them consistent with the update instructions that are in the release announcements. Also adds in the command to update the frontend as well. Co-authored-by: Francis Dinh Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/361 Co-authored-by: Norm Co-committed-by: Norm --- docs/docs/administration/updating.md | 60 ++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/docs/docs/administration/updating.md b/docs/docs/administration/updating.md index 2d9e77075..52979a1f5 100644 --- a/docs/docs/administration/updating.md +++ b/docs/docs/administration/updating.md @@ -3,15 +3,34 @@ You should **always check the [release notes/changelog](https://akkoma.dev/AkkomaGang/akkoma/src/branch/develop/CHANGELOG.md)** in case there are config deprecations, special update steps, etc. Besides that, doing the following is generally enough: +## Switch to the akkoma user +```sh +# Using sudo +sudo -su akkoma + +# Using doas +doas -su akkoma + +# Using su +su -s "$SHELL" akkoma +``` ## For OTP installations - ```sh -# Download the new release -su akkoma -s $SHELL -lc "./bin/pleroma_ctl update" +# Download latest stable release +./bin/pleroma_ctl update --branch stable -# Migrate the database, you are advised to stop the instance before doing that -su akkoma -s $SHELL -lc "./bin/pleroma_ctl migrate" +# Stop akkoma +./bin/pleroma stop # or using the system service manager (e.g. systemctl stop akkoma) + +# Run database migrations +./bin/pleroma_ctl migrate + +# Update frontend(s). See Frontend Configuration doc for more information. +./bin/pleroma_ctl frontend install pleroma-fe --ref stable + +# Start akkoma +./bin/pleroma daemon # or using the system service manager (e.g. systemctl start akkoma) ``` If you selected an alternate flavour on installation, @@ -19,13 +38,28 @@ you _may_ need to specify `--flavour`, in the same way as [when installing](../../installation/otp_en#detecting-flavour). ## For from source installations (using git) +Run as the `akkoma` user: -1. Go to the working directory of Akkoma (default is `/opt/akkoma`) -2. Run `git pull` [^1]. This pulls the latest changes from upstream. -3. Run `mix deps.get` [^1]. This pulls in any new dependencies. -4. Stop the Akkoma service. -5. Run `mix ecto.migrate` [^1] [^2]. This task performs database migrations, if there were any. -6. Start the Akkoma service. +```sh +# Pull in new changes +git pull -[^1]: Depending on which install guide you followed (for example on Debian/Ubuntu), you want to run `git` and `mix` tasks as `akkoma` user by adding `sudo -Hu akkoma` before the command. -[^2]: Prefix with `MIX_ENV=prod` to run it using the production config file. +# Run with production configuration +export MIX_ENV=prod + +# Download and compile dependencies +mix deps.get +mix compile + +# Stop akkoma (replace with your system service manager's equivalent if different) +sudo systemctl stop akkoma + +# Run database migrations +mix ecto.migrate + +# Update frontend(s). See Frontend Configration doc for more information. +mix pleroma.frontend install pleroma-fe --ref stable + +# Start akkoma (replace with your system service manager's equivalent if different) +sudo systemctl start akkoma +``` From 07a48b9293e4046c50b5d424d60a1bf16c7cc198 Mon Sep 17 00:00:00 2001 From: floatingghost Date: Wed, 14 Dec 2022 12:38:48 +0000 Subject: [PATCH 05/41] giant massive dep upgrade and dialyxir-found error emporium (#371) Co-authored-by: FloatingGhost Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/371 --- CHANGELOG.md | 7 +- lib/mix/tasks/pleroma/activity.ex | 1 + lib/mix/tasks/pleroma/database.ex | 1 - lib/mix/tasks/pleroma/diagnostics.ex | 1 + lib/mix/tasks/pleroma/instance.ex | 12 +- lib/mix/tasks/pleroma/search.ex | 11 +- lib/mix/tasks/pleroma/user.ex | 11 +- lib/pleroma/activity/html.ex | 6 +- .../akkoma/{translators => }/translator.ex | 0 lib/pleroma/announcement.ex | 4 +- lib/pleroma/application.ex | 3 + lib/pleroma/application_requirements.ex | 2 - lib/pleroma/emoji/pack.ex | 8 +- lib/pleroma/following_relationship.ex | 10 +- lib/pleroma/helpers/media_helper.ex | 6 +- lib/pleroma/http/adapter_helper.ex | 8 +- .../migrators/support/base_migrator.ex | 2 +- lib/pleroma/moderation_log.ex | 3 +- lib/pleroma/object.ex | 4 +- lib/pleroma/release_tasks.ex | 3 - lib/pleroma/reverse_proxy/client/tesla.ex | 1 + lib/pleroma/search/elasticsearch.ex | 30 ++-- .../document_mappings/activity.ex | 2 +- lib/pleroma/search/meilisearch.ex | 5 +- lib/pleroma/search/search_backend.ex | 4 +- lib/pleroma/signature.ex | 2 +- lib/pleroma/upload.ex | 2 +- lib/pleroma/upload/filter/analyze_metadata.ex | 1 - lib/pleroma/upload/filter/exiftool.ex | 2 +- lib/pleroma/upload/filter/mogrifun.ex | 2 +- lib/pleroma/user.ex | 37 ++++- lib/pleroma/user/backup.ex | 3 +- lib/pleroma/web.ex | 5 +- lib/pleroma/web/activity_pub/activity_pub.ex | 5 + .../controllers/translation_controller.ex | 10 +- .../pleroma_emoji_pack_operation.ex | 13 +- lib/pleroma/web/auth/pleroma_authenticator.ex | 4 + lib/pleroma/web/controller_helper.ex | 14 +- lib/pleroma/web/endpoint.ex | 2 +- .../legacy_pleroma_api_rerouter_plug.ex | 26 ---- lib/pleroma/web/metadata/utils.ex | 4 + lib/pleroma/web/o_auth/o_auth_controller.ex | 3 +- lib/pleroma/web/plugs/parsers/multipart.ex | 21 +++ lib/pleroma/web/plugs/remote_ip.ex | 26 ++-- lib/pleroma/web/router.ex | 2 - .../controllers/util_controller.ex | 5 +- lib/pleroma/web/web_finger.ex | 1 + .../web/web_finger/web_finger_controller.ex | 2 +- mix.exs | 49 +++---- mix.lock | 21 +-- test/credo/check/consistency/file_location.ex | 4 + test/pleroma/signature_test.exs | 2 +- .../controllers/admin_api_controller_test.exs | 111 +++++++------- .../controllers/frontend_controller_test.exs | 18 +-- .../controllers/instance_controller_test.exs | 14 +- .../instance_document_controller_test.exs | 20 +-- .../controllers/invite_controller_test.exs | 36 ++--- .../media_proxy_cache_controller_test.exs | 20 +-- .../o_auth_app_controller_test.exs | 32 ++-- .../controllers/relay_controller_test.exs | 8 +- .../controllers/report_controller_test.exs | 40 ++--- .../controllers/status_controller_test.exs | 34 ++--- .../controllers/user_controller_test.exs | 110 +++++++------- test/pleroma/web/fallback_test.exs | 6 - .../controllers/status_controller_test.exs | 24 +-- .../controllers/timeline_controller_test.exs | 14 +- .../mastodon_api/update_credentials_test.exs | 32 ++-- .../controllers/account_controller_test.exs | 2 +- .../emoji_file_controller_test.exs | 42 +++--- .../emoji_pack_controller_test.exs | 138 ++++++++++-------- ..._factor_authentication_controller_test.exs | 25 +++- test/pleroma/web/plugs/remote_ip_test.exs | 60 +++++--- .../twitter_api/password_controller_test.exs | 16 +- .../web/twitter_api/util_controller_test.exs | 23 +-- test/support/cluster.ex | 5 +- 75 files changed, 688 insertions(+), 555 deletions(-) rename lib/pleroma/akkoma/{translators => }/translator.ex (100%) delete mode 100644 lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex create mode 100644 lib/pleroma/web/plugs/parsers/multipart.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index 103b060e1..0ec7e29b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Removed - Non-finch HTTP adapters -### Upgrade notes -- Ensure `config :tesla, :adapter` is either unset, or set to `{Tesla.Adapter.Finch, name: MyFinch}` in your .exs config +- Legacy redirect from /api/pleroma/admin to /api/v1/pleroma/admin + ### Changed - Return HTTP error 413 when uploading an avatar or banner that's above the configured upload limit instead of a 500. +### Upgrade notes +- Ensure `config :tesla, :adapter` is either unset, or set to `{Tesla.Adapter.Finch, name: MyFinch}` in your .exs config + ## 2022.12 ## Added diff --git a/lib/mix/tasks/pleroma/activity.ex b/lib/mix/tasks/pleroma/activity.ex index 3a79d8f20..84b9c16f9 100644 --- a/lib/mix/tasks/pleroma/activity.ex +++ b/lib/mix/tasks/pleroma/activity.ex @@ -1,3 +1,4 @@ +# credo:disable-for-this-file # Pleroma: A lightweight social networking server # Copyright © 2017-2018 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index 0881974ee..272c9e3e5 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -115,7 +115,6 @@ def run(["prune_task"]) do nil |> Pleroma.Workers.Cron.PruneDatabaseWorker.perform() - |> IO.inspect() end def run(["fix_likes_collections"]) do diff --git a/lib/mix/tasks/pleroma/diagnostics.ex b/lib/mix/tasks/pleroma/diagnostics.ex index b8d8167bb..3914540ca 100644 --- a/lib/mix/tasks/pleroma/diagnostics.ex +++ b/lib/mix/tasks/pleroma/diagnostics.ex @@ -1,3 +1,4 @@ +# credo:disable-for-this-file defmodule Mix.Tasks.Pleroma.Diagnostics do alias Pleroma.Repo alias Pleroma.User diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex index 0647c330f..52fd184b5 100644 --- a/lib/mix/tasks/pleroma/instance.ex +++ b/lib/mix/tasks/pleroma/instance.ex @@ -247,9 +247,13 @@ def run(["gen" | rest]) do config_dir = Path.dirname(config_path) psql_dir = Path.dirname(psql_path) - [config_dir, psql_dir, static_dir, uploads_dir] - |> Enum.reject(&File.exists?/1) - |> Enum.map(&File.mkdir_p!/1) + to_create = + [config_dir, psql_dir, static_dir, uploads_dir] + |> Enum.reject(&File.exists?/1) + + for dir <- to_create do + File.mkdir_p!(dir) + end shell_info("Writing config to #{config_path}.") @@ -319,6 +323,4 @@ defp upload_filters(filters) when is_map(filters) do enabled_filters end - - defp upload_filters(_), do: [] end diff --git a/lib/mix/tasks/pleroma/search.ex b/lib/mix/tasks/pleroma/search.ex index 67aba79db..102bc5b63 100644 --- a/lib/mix/tasks/pleroma/search.ex +++ b/lib/mix/tasks/pleroma/search.ex @@ -10,14 +10,11 @@ defmodule Mix.Tasks.Pleroma.Search do def run(["import", "activities" | _rest]) do start_pleroma() - IO.inspect(Pleroma.Config.get([Pleroma.Search.Elasticsearch.Cluster, :indexes, :activities])) - IO.inspect( - Elasticsearch.Index.Bulk.upload( - Pleroma.Search.Elasticsearch.Cluster, - "activities", - Pleroma.Config.get([Pleroma.Search.Elasticsearch.Cluster, :indexes, :activities]) - ) + Elasticsearch.Index.Bulk.upload( + Pleroma.Search.Elasticsearch.Cluster, + "activities", + Pleroma.Config.get([Pleroma.Search.Elasticsearch.Cluster, :indexes, :activities]) ) end end diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index dd1cdca5b..4ca1c28eb 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -378,9 +378,11 @@ def run(["change_email", nickname, email]) do def run(["show", nickname]) do start_pleroma() - nickname - |> User.get_cached_by_nickname() - |> IO.inspect() + user = + nickname + |> User.get_cached_by_nickname() + + shell_info("#{inspect(user)}") end def run(["send_confirmation", nickname]) do @@ -389,7 +391,6 @@ def run(["send_confirmation", nickname]) do with %User{} = user <- User.get_cached_by_nickname(nickname) do user |> Pleroma.Emails.UserEmail.account_confirmation_email() - |> IO.inspect() |> Pleroma.Emails.Mailer.deliver!() shell_info("#{nickname}'s email sent") @@ -465,7 +466,7 @@ def run(["blocking", nickname]) do with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do blocks = User.following_ap_ids(user) - IO.inspect(blocks, limit: :infinity) + IO.puts("#{inspect(blocks)}") end end diff --git a/lib/pleroma/activity/html.ex b/lib/pleroma/activity/html.ex index 30409d93d..e4aaad523 100644 --- a/lib/pleroma/activity/html.ex +++ b/lib/pleroma/activity/html.ex @@ -38,7 +38,11 @@ defp add_cache_key_for(activity_id, additional_key) do def invalidate_cache_for(activity_id) do keys = get_cache_keys_for(activity_id) - Enum.map(keys, &@cachex.del(:scrubber_cache, &1)) + + for key <- keys do + @cachex.del(:scrubber_cache, key) + end + @cachex.del(:scrubber_management_cache, activity_id) end diff --git a/lib/pleroma/akkoma/translators/translator.ex b/lib/pleroma/akkoma/translator.ex similarity index 100% rename from lib/pleroma/akkoma/translators/translator.ex rename to lib/pleroma/akkoma/translator.ex diff --git a/lib/pleroma/announcement.ex b/lib/pleroma/announcement.ex index d97c5e728..6dc1a9c7b 100644 --- a/lib/pleroma/announcement.ex +++ b/lib/pleroma/announcement.ex @@ -24,8 +24,10 @@ defmodule Pleroma.Announcement do end def change(struct, params \\ %{}) do + params = validate_params(struct, params) + struct - |> cast(validate_params(struct, params), [:data, :starts_at, :ends_at, :rendered]) + |> cast(params, [:data, :starts_at, :ends_at, :rendered]) |> validate_required([:data]) end diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index ec8839e0f..48a2623ce 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -198,6 +198,8 @@ defp background_migrators do ] end + @spec task_children(atom()) :: [map()] + defp task_children(:test) do [ %{ @@ -223,6 +225,7 @@ defp task_children(_) do ] end + @spec elasticsearch_children :: [Pleroma.Search.Elasticsearch.Cluster] def elasticsearch_children do config = Config.get([Pleroma.Search, :module]) diff --git a/lib/pleroma/application_requirements.ex b/lib/pleroma/application_requirements.ex index a56311a65..19236aaa2 100644 --- a/lib/pleroma/application_requirements.ex +++ b/lib/pleroma/application_requirements.ex @@ -194,8 +194,6 @@ defp check_system_commands!(:ok) do end end - defp check_system_commands!(result), do: result - defp check_repo_pool_size!(:ok) do if Pleroma.Config.get([Pleroma.Repo, :pool_size], 10) != 10 and not Pleroma.Config.get([:dangerzone, :override_repo_pool_size], false) do diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index 8d233d5e4..2ca174c1f 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -209,7 +209,9 @@ def list_remote(opts) do with :ok <- validate_shareable_packs_available(uri) do uri - |> URI.merge("/api/pleroma/emoji/packs?page=#{opts[:page]}&page_size=#{opts[:page_size]}") + |> URI.merge( + "/api/v1/pleroma/emoji/packs?page=#{opts[:page]}&page_size=#{opts[:page_size]}" + ) |> http_get() end end @@ -250,7 +252,7 @@ def download(name, url, as) do with :ok <- validate_shareable_packs_available(uri), {:ok, remote_pack} <- - uri |> URI.merge("/api/pleroma/emoji/pack?name=#{name}") |> http_get(), + uri |> URI.merge("/api/v1/pleroma/emoji/pack?name=#{name}") |> http_get(), {:ok, %{sha: sha, url: url} = pack_info} <- fetch_pack_info(remote_pack, uri, name), {:ok, archive} <- download_archive(url, sha), pack <- copy_as(remote_pack, as || name), @@ -591,7 +593,7 @@ defp fetch_pack_info(remote_pack, uri, name) do {:ok, %{ sha: sha, - url: URI.merge(uri, "/api/pleroma/emoji/packs/archive?name=#{name}") |> to_string() + url: URI.merge(uri, "/api/v1/pleroma/emoji/packs/archive?name=#{name}") |> to_string() }} %{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) -> diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex index 42db9463d..c489ccbbe 100644 --- a/lib/pleroma/following_relationship.ex +++ b/lib/pleroma/following_relationship.ex @@ -14,6 +14,8 @@ defmodule Pleroma.FollowingRelationship do alias Pleroma.Repo alias Pleroma.User + @type follow_state :: :follow_pending | :follow_accept | :follow_reject | :unfollow + schema "following_relationships" do field(:state, State, default: :follow_pending) @@ -72,6 +74,7 @@ def update(%User{} = follower, %User{} = following, state) do end end + @spec follow(User.t(), User.t()) :: {:ok, User.t(), User.t()} | {:error, any} def follow(%User{} = follower, %User{} = following, state \\ :follow_accept) do with {:ok, _following_relationship} <- %__MODULE__{} @@ -81,6 +84,7 @@ def follow(%User{} = follower, %User{} = following, state \\ :follow_accept) do end end + @spec unfollow(User.t(), User.t()) :: {:ok, User.t(), User.t()} | {:error, any} def unfollow(%User{} = follower, %User{} = following) do case get(follower, following) do %__MODULE__{} = following_relationship -> @@ -89,10 +93,12 @@ def unfollow(%User{} = follower, %User{} = following) do end _ -> - {:ok, nil} + {:ok, follower, following} end end + @spec after_update(follow_state(), User.t(), User.t()) :: + {:ok, User.t(), User.t()} | {:error, any()} defp after_update(state, %User{} = follower, %User{} = following) do with {:ok, following} <- User.update_follower_count(following), {:ok, follower} <- User.update_following_count(follower) do @@ -103,6 +109,8 @@ defp after_update(state, %User{} = follower, %User{} = following) do }) {:ok, follower, following} + else + err -> {:error, err} end end diff --git a/lib/pleroma/helpers/media_helper.ex b/lib/pleroma/helpers/media_helper.ex index d0c3ab5cc..cb95d0e68 100644 --- a/lib/pleroma/helpers/media_helper.ex +++ b/lib/pleroma/helpers/media_helper.ex @@ -104,10 +104,10 @@ defp run_fifo(fifo_path, env, executable, args) do args: args ]) - fifo = Port.open(to_charlist(fifo_path), [:eof, :binary, :stream, :out]) + fifo = File.open!(fifo_path, [:append, :binary]) fix = Pleroma.Helpers.QtFastStart.fix(env.body) - true = Port.command(fifo, fix) - :erlang.port_close(fifo) + IO.binwrite(fifo, fix) + File.close(fifo) loop_recv(pid) after File.rm(fifo_path) diff --git a/lib/pleroma/http/adapter_helper.ex b/lib/pleroma/http/adapter_helper.ex index e837ac8d4..77b854b5d 100644 --- a/lib/pleroma/http/adapter_helper.ex +++ b/lib/pleroma/http/adapter_helper.ex @@ -14,9 +14,7 @@ defmodule Pleroma.HTTP.AdapterHelper do alias Pleroma.HTTP.AdapterHelper require Logger - @type proxy :: - {Connection.host(), pos_integer()} - | {Connection.proxy_type(), Connection.host(), pos_integer()} + @type proxy :: {Connection.proxy_type(), Connection.host(), pos_integer(), list()} @callback options(keyword(), URI.t()) :: keyword() @@ -25,7 +23,6 @@ def format_proxy(nil), do: nil def format_proxy(proxy_url) do case parse_proxy(proxy_url) do - {:ok, host, port} -> {:http, host, port, []} {:ok, type, host, port} -> {type, host, port, []} _ -> nil end @@ -94,8 +91,7 @@ defp proxy_type("https"), do: {:ok, :https} defp proxy_type(_), do: {:error, :unknown} @spec parse_proxy(String.t() | tuple() | nil) :: - {:ok, host(), pos_integer()} - | {:ok, proxy_type(), host(), pos_integer()} + {:ok, proxy_type(), host(), pos_integer()} | {:error, atom()} | nil def parse_proxy(nil), do: nil diff --git a/lib/pleroma/migrators/support/base_migrator.ex b/lib/pleroma/migrators/support/base_migrator.ex index 1f8a5402b..2ffb35081 100644 --- a/lib/pleroma/migrators/support/base_migrator.ex +++ b/lib/pleroma/migrators/support/base_migrator.ex @@ -14,7 +14,7 @@ defmodule Pleroma.Migrators.Support.BaseMigrator do @callback fault_rate_allowance() :: integer() | float() defmacro __using__(_opts) do - quote do + quote generated: true do use GenServer require Logger diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex index 7da8d0c63..b94d53913 100644 --- a/lib/pleroma/moderation_log.ex +++ b/lib/pleroma/moderation_log.ex @@ -237,7 +237,8 @@ def insert_log(%{actor: %User{}, action: action, target: target} = attrs) insert_log_entry_with_message(%ModerationLog{data: data}) end - @spec insert_log_entry_with_message(ModerationLog) :: {:ok, ModerationLog} | {:error, any} + @spec insert_log_entry_with_message(ModerationLog.t()) :: + {:ok, ModerationLog.t()} | {:error, any} defp insert_log_entry_with_message(entry) do entry.data["message"] |> put_in(get_log_entry_message(entry)) diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index a75d85c47..844251a18 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -240,7 +240,7 @@ def delete(%Object{data: %{"id" => id}} = object) do {:ok, _} <- invalid_object_cache(object) do cleanup_attachments( Config.get([:instance, :cleanup_attachments]), - %{"object" => object} + %{object: object} ) {:ok, object, deleted_activity} @@ -249,7 +249,7 @@ def delete(%Object{data: %{"id" => id}} = object) do @spec cleanup_attachments(boolean(), %{required(:object) => map()}) :: {:ok, Oban.Job.t() | nil} - def cleanup_attachments(true, %{"object" => _} = params) do + def cleanup_attachments(true, %{object: _} = params) do AttachmentsCleanupWorker.enqueue("cleanup_attachments", params) end diff --git a/lib/pleroma/release_tasks.ex b/lib/pleroma/release_tasks.ex index e43eef070..75c027137 100644 --- a/lib/pleroma/release_tasks.ex +++ b/lib/pleroma/release_tasks.ex @@ -61,9 +61,6 @@ def create do IO.puts("The database for #{inspect(@repo)} has already been created") {:error, term} when is_binary(term) -> - IO.puts(:stderr, "The database for #{inspect(@repo)} couldn't be created: #{term}") - - {:error, term} -> IO.puts( :stderr, "The database for #{inspect(@repo)} couldn't be created: #{inspect(term)}" diff --git a/lib/pleroma/reverse_proxy/client/tesla.ex b/lib/pleroma/reverse_proxy/client/tesla.ex index 59fd5493c..a4fc1ebc2 100644 --- a/lib/pleroma/reverse_proxy/client/tesla.ex +++ b/lib/pleroma/reverse_proxy/client/tesla.ex @@ -66,6 +66,7 @@ defp read_chunk!(%{pid: pid, stream: stream, opts: opts}) do @impl true @spec close(map) :: :ok | no_return() def close(%{pid: _pid}) do + :ok end defp check_adapter do diff --git a/lib/pleroma/search/elasticsearch.ex b/lib/pleroma/search/elasticsearch.ex index 16b01101a..20e03e1f0 100644 --- a/lib/pleroma/search/elasticsearch.ex +++ b/lib/pleroma/search/elasticsearch.ex @@ -13,25 +13,21 @@ defmodule Pleroma.Search.Elasticsearch do def es_query(:activity, query, offset, limit) do must = Parsers.Activity.parse(query) - if must == [] do - :skip - else - %{ - size: limit, - from: offset, - terminate_after: 50, - timeout: "5s", - sort: [ - "_score", - %{"_timestamp" => %{order: "desc", format: "basic_date_time"}} - ], - query: %{ - bool: %{ - must: must - } + %{ + size: limit, + from: offset, + terminate_after: 50, + timeout: "5s", + sort: [ + "_score", + %{"_timestamp" => %{order: "desc", format: "basic_date_time"}} + ], + query: %{ + bool: %{ + must: must } } - end + } end defp maybe_fetch(:activity, search_query) do diff --git a/lib/pleroma/search/elasticsearch/document_mappings/activity.ex b/lib/pleroma/search/elasticsearch/document_mappings/activity.ex index b77c6e0d2..71ef75634 100644 --- a/lib/pleroma/search/elasticsearch/document_mappings/activity.ex +++ b/lib/pleroma/search/elasticsearch/document_mappings/activity.ex @@ -57,5 +57,5 @@ def encode(activity) do defimpl Elasticsearch.Document, for: Pleroma.Object do def id(obj), do: obj.id def routing(_), do: false - def encode(_), do: nil + def encode(_), do: %{} end diff --git a/lib/pleroma/search/meilisearch.ex b/lib/pleroma/search/meilisearch.ex index c36b8f751..8fcf9310a 100644 --- a/lib/pleroma/search/meilisearch.ex +++ b/lib/pleroma/search/meilisearch.ex @@ -154,10 +154,11 @@ def add_to_index(activity) do with {:ok, res} <- result, true <- Map.has_key?(res, "taskUid") do - # Do nothing + {:ok, res} else - _ -> + err -> Logger.error("Failed to add activity #{activity.id} to index: #{inspect(result)}") + {:error, err} end end end diff --git a/lib/pleroma/search/search_backend.ex b/lib/pleroma/search/search_backend.ex index ed6bfd329..56e3b7de5 100644 --- a/lib/pleroma/search/search_backend.ex +++ b/lib/pleroma/search/search_backend.ex @@ -4,7 +4,7 @@ defmodule Pleroma.Search.SearchBackend do The whole activity is passed, to allow filtering on things such as scope. """ - @callback add_to_index(activity :: Pleroma.Activity.t()) :: nil + @callback add_to_index(activity :: Pleroma.Activity.t()) :: {:ok, any()} | {:error, any()} @doc """ Remove the object from the index. @@ -13,5 +13,5 @@ defmodule Pleroma.Search.SearchBackend do is what contains the actual content and there is no need for fitlering when removing from index. """ - @callback remove_from_index(object :: Pleroma.Object.t()) :: nil + @callback remove_from_index(object :: Pleroma.Object.t()) :: {:ok, any()} | {:error, any()} end diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex index 043a0643e..1c59be9c7 100644 --- a/lib/pleroma/signature.ex +++ b/lib/pleroma/signature.ex @@ -27,7 +27,7 @@ def key_id_to_actor_id(key_id) do _ -> case Pleroma.Web.WebFinger.finger(maybe_ap_id) do - %{"ap_id" => ap_id} -> {:ok, ap_id} + {:ok, %{"ap_id" => ap_id}} -> {:ok, ap_id} _ -> {:error, maybe_ap_id} end end diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 9bf8e03df..3b5419db7 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -162,7 +162,7 @@ defp prepare_upload(%Plug.Upload{} = file, opts) do defp prepare_upload(%{img: "data:image/" <> image_data}, opts) do parsed = Regex.named_captures(~r/(?jpeg|png|gif);base64,(?.*)/, image_data) data = Base.decode64!(parsed["data"], ignore: :whitespace) - hash = Base.encode16(:crypto.hash(:sha256, data), lower: true) + hash = Base.encode16(:crypto.hash(:sha256, data), case: :lower) with :ok <- check_binary_size(data, opts.size_limit), tmp_path <- tempfile_for_image(data), diff --git a/lib/pleroma/upload/filter/analyze_metadata.ex b/lib/pleroma/upload/filter/analyze_metadata.ex index c89c30fc1..8990e97c0 100644 --- a/lib/pleroma/upload/filter/analyze_metadata.ex +++ b/lib/pleroma/upload/filter/analyze_metadata.ex @@ -77,7 +77,6 @@ defp media_dimensions(file) do %{width: width, height: height} else nil -> {:error, {:ffprobe, :command_not_found}} - {:error, _} = error -> error end end end diff --git a/lib/pleroma/upload/filter/exiftool.ex b/lib/pleroma/upload/filter/exiftool.ex index a2bfbbf61..9e82cf8a7 100644 --- a/lib/pleroma/upload/filter/exiftool.ex +++ b/lib/pleroma/upload/filter/exiftool.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Upload.Filter.Exiftool do """ @behaviour Pleroma.Upload.Filter - @spec filter(Pleroma.Upload.t()) :: {:ok, any()} | {:error, String.t()} + @spec filter(Pleroma.Upload.t()) :: {:ok, :noop} | {:ok, :filtered} | {:error, String.t()} # Formats not compatible with exiftool at this time def filter(%Pleroma.Upload{content_type: "image/heic"}), do: {:ok, :noop} diff --git a/lib/pleroma/upload/filter/mogrifun.ex b/lib/pleroma/upload/filter/mogrifun.ex index 01126aaeb..69885a0bd 100644 --- a/lib/pleroma/upload/filter/mogrifun.ex +++ b/lib/pleroma/upload/filter/mogrifun.ex @@ -38,7 +38,7 @@ defmodule Pleroma.Upload.Filter.Mogrifun do [{"fill", "yellow"}, {"tint", "40"}] ] - @spec filter(Pleroma.Upload.t()) :: {:ok, atom()} | {:error, String.t()} + @spec filter(Pleroma.Upload.t()) :: {:ok, :filtered | :noop} | {:error, String.t()} def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do try do Filter.Mogrify.do_filter(file, [Enum.random(@filters)]) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index ba30769bb..d7c1511ce 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -3,6 +3,10 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.User do + @moduledoc """ + A user, local or remote + """ + use Ecto.Schema import Ecto.Changeset @@ -549,9 +553,17 @@ def update_changeset(struct, params \\ %{}) do end defp put_fields(changeset) do + # These fields are inconsistent in tests when it comes to binary/atom keys if raw_fields = get_change(changeset, :raw_fields) do raw_fields = raw_fields + |> Enum.map(fn + %{name: name, value: value} -> + %{"name" => name, "value" => value} + + %{"name" => _} = field -> + field + end) |> Enum.filter(fn %{"name" => n} -> n != "" end) fields = @@ -705,7 +717,8 @@ def register_changeset_ldap(struct, params = %{password: password}) |> put_private_key() end - def register_changeset(struct, params \\ %{}, opts \\ []) do + @spec register_changeset(User.t(), map(), keyword()) :: Changeset.t() + def register_changeset(%User{} = struct, params \\ %{}, opts \\ []) do bio_limit = Config.get([:instance, :user_bio_length], 5000) name_limit = Config.get([:instance, :user_name_length], 100) reason_limit = Config.get([:instance, :registration_reason_length], 500) @@ -819,12 +832,14 @@ defp autofollowing_users(user) do end @doc "Inserts provided changeset, performs post-registration actions (confirmation email sending etc.)" + @spec register(Changeset.t()) :: {:ok, User.t()} | {:error, any} | nil def register(%Ecto.Changeset{} = changeset) do with {:ok, user} <- Repo.insert(changeset) do post_register_action(user) end end + @spec post_register_action(User.t()) :: {:error, any} | {:ok, User.t()} def post_register_action(%User{is_confirmed: false} = user) do with {:ok, _} <- maybe_send_confirmation_email(user) do {:ok, user} @@ -939,7 +954,8 @@ def needs_update?(%User{local: false} = user) do def needs_update?(_), do: true - @spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t()} | {:error, String.t()} + @spec maybe_direct_follow(User.t(), User.t()) :: + {:ok, User.t(), User.t()} | {:error, String.t()} # "Locked" (self-locked) users demand explicit authorization of follow requests def maybe_direct_follow(%User{} = follower, %User{local: true, is_locked: true} = followed) do @@ -1072,6 +1088,11 @@ def get_by_guessed_nickname(ap_id) do get_cached_by_nickname(nickname) end + @spec set_cache( + {:error, any} + | {:ok, User.t()} + | User.t() + ) :: {:ok, User.t()} | {:error, any} def set_cache({:ok, user}), do: set_cache(user) def set_cache({:error, err}), do: {:error, err} @@ -1082,12 +1103,14 @@ def set_cache(%User{} = user) do {:ok, user} end + @spec update_and_set_cache(User.t(), map()) :: {:ok, User.t()} | {:error, any} def update_and_set_cache(struct, params) do struct |> update_changeset(params) |> update_and_set_cache() end + @spec update_and_set_cache(Changeset.t()) :: {:ok, User.t()} | {:error, any} def update_and_set_cache(%{data: %Pleroma.User{} = user} = changeset) do was_superuser_before_update = User.superuser?(user) @@ -1142,6 +1165,7 @@ def get_cached_by_ap_id(ap_id) do end end + @spec get_cached_by_id(String.t()) :: nil | Pleroma.User.t() def get_cached_by_id(id) do key = "id:#{id}" @@ -2302,6 +2326,7 @@ def add_alias(user, new_alias_user) do end end + @spec delete_alias(User.t(), User.t()) :: {:error, :no_such_alias} def delete_alias(user, alias_user) do current_aliases = user.also_known_as || [] alias_ap_id = alias_user.ap_id @@ -2417,7 +2442,7 @@ def confirmation_changeset(user, set_confirmation: confirmed?) do cast(user, params, [:is_confirmed, :confirmation_token]) end - @spec approval_changeset(User.t(), keyword()) :: Changeset.t() + @spec approval_changeset(Changeset.t(), keyword()) :: Changeset.t() def approval_changeset(user, set_approval: approved?) do cast(user, %{is_approved: approved?}, [:is_approved]) end @@ -2492,15 +2517,19 @@ 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} + else + err -> err end end - @spec add_to_block(User.t(), User.t()) :: + @spec remove_from_block(User.t(), User.t()) :: {:ok, UserRelationship.t()} | {:ok, nil} | {:error, Ecto.Changeset.t()} defp remove_from_block(%User{} = user, %User{} = blocked) do with {:ok, relationship} <- UserRelationship.delete_block(user, blocked) do @cachex.del(:user_cache, "blocked_users_ap_ids:#{user.ap_id}") {:ok, relationship} + else + err -> err end end diff --git a/lib/pleroma/user/backup.ex b/lib/pleroma/user/backup.ex index 2c6378265..63709a484 100644 --- a/lib/pleroma/user/backup.ex +++ b/lib/pleroma/user/backup.ex @@ -130,7 +130,8 @@ def export(%__MODULE__{} = backup) do :ok <- statuses(dir, backup.user), :ok <- likes(dir, backup.user), :ok <- bookmarks(dir, backup.user), - {:ok, zip_path} <- :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: dir), + {:ok, zip_path} <- + :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: String.to_charlist(dir)), {:ok, _} <- File.rm_rf(dir) do {:ok, to_string(zip_path)} end diff --git a/lib/pleroma/web.ex b/lib/pleroma/web.ex index 5761e3b38..24560d4a3 100644 --- a/lib/pleroma/web.ex +++ b/lib/pleroma/web.ex @@ -56,7 +56,10 @@ defp skip_plug(conn, plug_modules) do plug_module.skip_plug(conn) rescue UndefinedFunctionError -> - raise "`#{plug_module}` is not skippable. Append `use Pleroma.Web, :plug` to its code." + reraise( + "`#{plug_module}` is not skippable. Append `use Pleroma.Web, :plug` to its code.", + __STACKTRACE__ + ) end end ) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 3adb4ab54..8e55df0d8 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1531,6 +1531,10 @@ defp normalize_image(%{"url" => url}) do defp normalize_image(urls) when is_list(urls), do: urls |> List.first() |> normalize_image() defp normalize_image(_), do: nil + defp normalize_also_known_as(aka) when is_list(aka), do: aka + defp normalize_also_known_as(aka) when is_binary(aka), do: [aka] + defp normalize_also_known_as(nil), do: [] + defp object_to_user_data(data, additional) do fields = data @@ -1576,6 +1580,7 @@ defp object_to_user_data(data, additional) do also_known_as = data |> Map.get("alsoKnownAs", []) + |> normalize_also_known_as() |> Enum.filter(fn url -> case URI.parse(url) do %URI{scheme: "http"} -> true diff --git a/lib/pleroma/web/akkoma_api/controllers/translation_controller.ex b/lib/pleroma/web/akkoma_api/controllers/translation_controller.ex index ca9b4b64a..022da3198 100644 --- a/lib/pleroma/web/akkoma_api/controllers/translation_controller.ex +++ b/lib/pleroma/web/akkoma_api/controllers/translation_controller.ex @@ -3,6 +3,8 @@ defmodule Pleroma.Web.AkkomaAPI.TranslationController do alias Pleroma.Web.Plugs.OAuthScopesPlug + require Logger + @cachex Pleroma.Config.get([:cachex, :provider], Cachex) @unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []} @@ -26,8 +28,12 @@ def languages(conn, _params) do conn |> json(%{source: source_languages, target: dest_languages}) else - {:enabled, false} -> json(conn, %{}) - e -> IO.inspect(e) + {:enabled, false} -> + json(conn, %{}) + + e -> + Logger.error("Translation language list error: #{inspect(e)}") + {:error, e} end end diff --git a/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex index 49247d9b6..c38349486 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_emoji_pack_operation.ex @@ -231,9 +231,18 @@ defp emoji_packs_response do "application/json", %Schema{ type: :object, - additionalProperties: emoji_pack(), + properties: %{ + count: %Schema{type: :integer}, + packs: %Schema{ + type: :object, + additionalProperties: emoji_pack() + } + }, example: %{ - "emojos" => emoji_pack().example + "count" => 4, + "packs" => %{ + "emojos" => emoji_pack().example + } } } ) diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex index 68472e75f..bb377d686 100644 --- a/lib/pleroma/web/auth/pleroma_authenticator.ex +++ b/lib/pleroma/web/auth/pleroma_authenticator.ex @@ -60,6 +60,8 @@ def get_registration(%Plug.Conn{ def get_registration(%Plug.Conn{} = _conn), do: {:error, :missing_credentials} @doc "Creates Pleroma.User record basing on params and Pleroma.Registration record." + @spec create_from_registration(Plug.Conn.t(), Registration.t()) :: + {:ok, User.t()} | {:error, any()} def create_from_registration( %Plug.Conn{params: %{"authorization" => registration_attrs}}, %Registration{} = registration @@ -89,6 +91,8 @@ def create_from_registration( {:ok, _} <- Registration.changeset(registration, %{user_id: new_user.id}) |> Repo.update() do {:ok, new_user} + else + err -> err end end diff --git a/lib/pleroma/web/controller_helper.ex b/lib/pleroma/web/controller_helper.ex index 7b84b43e4..6acc8f078 100644 --- a/lib/pleroma/web/controller_helper.ex +++ b/lib/pleroma/web/controller_helper.ex @@ -87,16 +87,18 @@ def get_pagination_fields(conn, entries, extra_params \\ %{}) do def assign_account_by_id(conn, _) do case Pleroma.User.get_cached_by_id(conn.params.id) do - %Pleroma.User{} = account -> assign(conn, :account, account) - nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt() + %Pleroma.User{} = account -> + assign(conn, :account, account) + + nil -> + Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) + |> halt() end end + @spec try_render(Plug.Conn.t(), any, any) :: Plug.Conn.t() def try_render(conn, target, params) when is_binary(target) do - case render(conn, target, params) do - nil -> render_error(conn, :not_implemented, "Can't display this activity") - res -> res - end + render(conn, target, params) end def try_render(conn, _, _) do diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 6dd66a424..baf0c5651 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -123,7 +123,7 @@ defmodule Pleroma.Web.Endpoint do plug(Plug.Parsers, parsers: [ :urlencoded, - {:multipart, length: {Config, :get, [[:instance, :upload_limit]]}}, + Pleroma.Web.Plugs.Parsers.Multipart, :json ], pass: ["*/*"], diff --git a/lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex b/lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex deleted file mode 100644 index f86d6b52b..000000000 --- a/lib/pleroma/web/fallback/legacy_pleroma_api_rerouter_plug.ex +++ /dev/null @@ -1,26 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2021 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.Fallback.LegacyPleromaApiRerouterPlug do - alias Pleroma.Web.Endpoint - alias Pleroma.Web.Fallback.RedirectController - - def init(opts), do: opts - - def call(%{path_info: ["api", "pleroma" | path_info_rest]} = conn, _opts) do - new_path_info = ["api", "v1", "pleroma" | path_info_rest] - new_request_path = Enum.join(new_path_info, "/") - - conn - |> Map.merge(%{ - path_info: new_path_info, - request_path: new_request_path - }) - |> Endpoint.call(conn.params) - end - - def call(conn, _opts) do - RedirectController.api_not_implemented(conn, %{}) - end -end diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex index 8990bef54..7308726f5 100644 --- a/lib/pleroma/web/metadata/utils.ex +++ b/lib/pleroma/web/metadata/utils.ex @@ -30,6 +30,10 @@ def scrub_html_and_truncate(%{data: %{"content" => content}} = object) do |> scrub_html_and_truncate_object_field(object) end + def scrub_html_and_truncate(%{data: _}) do + "" + end + def scrub_html_and_truncate(content, max_length \\ 200) when is_binary(content) do content |> scrub_html diff --git a/lib/pleroma/web/o_auth/o_auth_controller.ex b/lib/pleroma/web/o_auth/o_auth_controller.ex index 455af11d7..8f32e7219 100644 --- a/lib/pleroma/web/o_auth/o_auth_controller.ex +++ b/lib/pleroma/web/o_auth/o_auth_controller.ex @@ -558,10 +558,9 @@ def register(%Plug.Conn{} = conn, %{"authorization" => _, "op" => "register"} = else {:error, changeset} -> message = - Enum.map(changeset.errors, fn {field, {error, _}} -> + Enum.map_join(changeset.errors, "; ", fn {field, {error, _}} -> "#{field} #{error}" end) - |> Enum.join("; ") message = String.replace( diff --git a/lib/pleroma/web/plugs/parsers/multipart.ex b/lib/pleroma/web/plugs/parsers/multipart.ex new file mode 100644 index 000000000..6b5ab6af4 --- /dev/null +++ b/lib/pleroma/web/plugs/parsers/multipart.ex @@ -0,0 +1,21 @@ +defmodule Pleroma.Web.Plugs.Parsers.Multipart do + @multipart Plug.Parsers.MULTIPART + + alias Pleroma.Config + + def init(opts) do + opts + end + + def parse(conn, "multipart", subtype, headers, opts) do + length = Config.get([:instance, :upload_limit]) + + opts = @multipart.init([length: length] ++ opts) + + @multipart.parse(conn, "multipart", subtype, headers, opts) + end + + def parse(conn, _type, _subtype, _headers, _opts) do + {:next, conn} + end +end diff --git a/lib/pleroma/web/plugs/remote_ip.ex b/lib/pleroma/web/plugs/remote_ip.ex index 4d7daca56..d992dea63 100644 --- a/lib/pleroma/web/plugs/remote_ip.ex +++ b/lib/pleroma/web/plugs/remote_ip.ex @@ -8,7 +8,6 @@ defmodule Pleroma.Web.Plugs.RemoteIp do """ alias Pleroma.Config - import Plug.Conn @behaviour Plug @@ -16,15 +15,21 @@ def init(_), do: nil def call(%{remote_ip: original_remote_ip} = conn, _) do if Config.get([__MODULE__, :enabled]) do - %{remote_ip: new_remote_ip} = conn = RemoteIp.call(conn, remote_ip_opts()) - assign(conn, :remote_ip_found, original_remote_ip != new_remote_ip) + {headers, proxies} = remote_ip_opts() + new_remote_ip = RemoteIp.from(conn.req_headers, headers: headers, proxies: proxies) + + if new_remote_ip != original_remote_ip do + Map.put(conn, :remote_ip, new_remote_ip) + else + conn + end else conn end end defp remote_ip_opts do - headers = Config.get([__MODULE__, :headers], []) |> MapSet.new() + headers = Config.get([__MODULE__, :headers], []) reserved = Config.get([__MODULE__, :reserved], []) proxies = @@ -36,13 +41,10 @@ defp remote_ip_opts do end defp maybe_add_cidr(proxy) when is_binary(proxy) do - proxy = - cond do - "/" in String.codepoints(proxy) -> proxy - InetCidr.v4?(InetCidr.parse_address!(proxy)) -> proxy <> "/32" - InetCidr.v6?(InetCidr.parse_address!(proxy)) -> proxy <> "/128" - end - - InetCidr.parse(proxy, true) + cond do + "/" in String.codepoints(proxy) -> proxy + InetCidr.v4?(InetCidr.parse_address!(proxy)) -> proxy <> "/32" + InetCidr.v6?(InetCidr.parse_address!(proxy)) -> proxy <> "/128" + end end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index f2ea679a0..e790b1cdb 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -906,8 +906,6 @@ defmodule Pleroma.Web.Router do scope "/", Pleroma.Web.Fallback do get("/registration/:token", RedirectController, :registration_page) get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta) - match(:*, "/api/pleroma*path", LegacyPleromaApiRerouterPlug, []) - get("/api*path", RedirectController, :api_not_implemented) get("/*path", RedirectController, :redirector_with_preload) options("/*path", RedirectController, :empty) diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex index a0c3e5c52..f2b571fff 100644 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@ -150,7 +150,10 @@ def remote_subscribe(conn, %{"status" => %{"status_id" => id, "profile" => profi end end - def remote_interaction(%{body_params: %{ap_id: ap_id, profile: profile}} = conn, _params) do + def remote_interaction( + %Plug.Conn{body_params: %{ap_id: ap_id, profile: profile}} = conn, + _params + ) do with {:ok, %{"subscribe_address" => template}} <- WebFinger.finger(profile) do conn |> json(%{url: String.replace(template, "{uri}", ap_id)}) diff --git a/lib/pleroma/web/web_finger.ex b/lib/pleroma/web/web_finger.ex index f5a46ce25..364d0e0e6 100644 --- a/lib/pleroma/web/web_finger.ex +++ b/lib/pleroma/web/web_finger.ex @@ -100,6 +100,7 @@ defp domain do Pleroma.Config.get([__MODULE__, :domain]) || Pleroma.Web.Endpoint.host() end + @spec webfinger_from_xml(binary()) :: {:ok, map()} | nil defp webfinger_from_xml(body) do with {:ok, doc} <- XML.parse_document(body) do subject = XML.string_from_xpath("//Subject", doc) diff --git a/lib/pleroma/web/web_finger/web_finger_controller.ex b/lib/pleroma/web/web_finger/web_finger_controller.ex index 7944c50ad..f8b3c84a1 100644 --- a/lib/pleroma/web/web_finger/web_finger_controller.ex +++ b/lib/pleroma/web/web_finger/web_finger_controller.ex @@ -36,7 +36,7 @@ def webfinger(%{assigns: %{format: format}} = conn, %{"resource" => resource}) else _e -> conn - |> put_status(404) + |> put_status(:not_found) |> json("Couldn't find user") end end diff --git a/mix.exs b/mix.exs index dbfa6263f..00a250002 100644 --- a/mix.exs +++ b/mix.exs @@ -7,7 +7,7 @@ def project do version: version("3.5.0"), elixir: "~> 1.12", elixirc_paths: elixirc_paths(Mix.env()), - compilers: [:phoenix, :gettext] ++ Mix.compilers(), + compilers: [:phoenix] ++ Mix.compilers(), elixirc_options: [warnings_as_errors: warnings_as_errors()], xref: [exclude: [:eldap]], start_permanent: Mix.env() == :prod, @@ -94,7 +94,8 @@ defp warnings_as_errors, do: System.get_env("CI") == "true" # Specifies OAuth dependencies. defp oauth_deps do oauth_strategy_packages = - System.get_env("OAUTH_CONSUMER_STRATEGIES") + "OAUTH_CONSUMER_STRATEGIES" + |> System.get_env() |> to_string() |> String.split() |> Enum.map(fn strategy_entry -> @@ -113,32 +114,29 @@ defp oauth_deps do # Type `mix help deps` for examples and options. defp deps do [ - {:phoenix, "~> 1.6.11"}, + {:phoenix, "~> 1.6.15"}, {:tzdata, "~> 1.1.1"}, - {:plug_cowboy, "~> 2.5"}, + {:plug_cowboy, "~> 2.6"}, {:phoenix_pubsub, "~> 2.1"}, {:phoenix_ecto, "~> 4.4"}, + {:inet_cidr, "~> 1.0.0"}, {:ecto_enum, "~> 1.4"}, {:ecto_sql, "~> 3.9.0"}, {:postgrex, ">= 0.16.3"}, {:oban, "~> 2.12.1"}, - {:gettext, - git: "https://github.com/tusooa/gettext.git", - ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808", - override: true}, + {:gettext, "~> 0.20.0"}, {:bcrypt_elixir, "~> 2.2"}, - {:trailing_format_plug, "~> 0.0.7"}, {:fast_sanitize, "~> 0.2.3"}, - {:html_entities, "~> 0.5", override: true}, - {:phoenix_html, "~> 3.1", override: true}, + {:html_entities, "~> 0.5"}, + {:phoenix_html, "~> 3.2"}, {:calendar, "~> 1.0"}, {:cachex, "~> 3.4"}, - {:poison, "~> 5.0", override: true}, - {:tesla, "~> 1.4.4", override: true}, + {:tesla, "~> 1.4.4"}, {:castore, "~> 0.1"}, - {:cowlib, "~> 2.9", override: true}, + {:cowlib, "~> 2.9"}, {:finch, "~> 0.14.0"}, {:jason, "~> 1.2"}, + {:trailing_format_plug, "~> 0.0.7"}, {:mogrify, "~> 0.9.1"}, {:ex_aws, "~> 2.1.6"}, {:ex_aws_s3, "~> 2.0"}, @@ -172,39 +170,40 @@ defp deps do {:plug_static_index_html, "~> 1.0.0"}, {:flake_id, "~> 0.1.0"}, {:concurrent_limiter, "~> 0.1.1"}, - {:remote_ip, - git: "https://git.pleroma.social/pleroma/remote_ip.git", - ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"}, + {:remote_ip, "~> 1.1.0"}, {:captcha, git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"}, {:restarter, path: "./restarter"}, {:majic, "~> 1.0"}, {:eblurhash, "~> 1.2.2"}, - {:open_api_spex, "3.10.0"}, + {:open_api_spex, "~> 3.16.0"}, {:search_parser, git: "https://github.com/FloatingGhost/pleroma-contrib-search-parser.git", ref: "08971a81e68686f9ac465cfb6661d51c5e4e1e7f"}, {:nimble_parsec, "~> 1.0", override: true}, - {:phoenix_live_dashboard, "~> 0.6.2"}, + {:phoenix_live_dashboard, "~> 0.7.2"}, {:ecto_psql_extras, "~> 0.6"}, {:elasticsearch, git: "https://akkoma.dev/AkkomaGang/elasticsearch-elixir.git", ref: "main"}, {:mfm_parser, git: "https://akkoma.dev/AkkomaGang/mfm-parser.git", ref: "912fba81152d4d572e457fd5427f9875b2bc3dbe"}, - - # indirect dependency version override - {:plug, "~> 1.10.4", override: true}, + {:poison, ">= 0.0.0"}, ## dev & test {:ex_doc, "~> 0.22", only: :dev, runtime: false}, {:ex_machina, "~> 2.4", only: :test}, - {:credo, "~> 1.6", only: [:dev, :test], runtime: false}, + {:credo, + git: "https://github.com/rrrene/credo.git", + ref: "1c1b99ea41a457761383d81aaf6a606913996fe7", + only: [:dev, :test], + runtime: false}, {:mock, "~> 0.3.5", only: :test}, {:excoveralls, "0.15.1", only: :test}, {:mox, "~> 1.0", only: :test}, - {:websockex, "~> 0.4.3", only: :test} + {:websockex, "~> 0.4.3", only: :test}, + {:dialyxir, "~> 1.0", only: [:dev], runtime: false} ] ++ oauth_deps() end @@ -336,7 +335,7 @@ defp add_copyright(_) do # Pleroma: A lightweight social networking server # Copyright © 2017-#{year} Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only -# Akkoma: The cooler pleroma +# Akkoma: Magically expressive social media # Copyright © 2022-#{year} Akkoma Authors # SPDX-License-Identifier: AGPL-3.0-only diff --git a/mix.lock b/mix.lock index e86a58427..0e3ac3514 100644 --- a/mix.lock +++ b/mix.lock @@ -17,13 +17,14 @@ "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"}, "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, - "credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"}, + "credo": {:git, "https://github.com/rrrene/credo.git", "1c1b99ea41a457761383d81aaf6a606913996fe7", [ref: "1c1b99ea41a457761383d81aaf6a606913996fe7"]}, "crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]}, "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, "db_connection": {:hex, :db_connection, "2.4.3", "3b9aac9f27347ec65b271847e6baeb4443d8474289bd18c1d6f4de655b70c94d", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c127c15b0fa6cfb32eed07465e05da6c815b032508d4ed7c116122871df73c12"}, "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, - "earmark": {:hex, :earmark, "1.4.33", "2b33a505180583f98bfa17317f03973b52081bdb24a11be05a7f4fa6d64dd8bf", [:mix], [{:earmark_parser, "~> 1.4.29", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "21b31363d6a0a70802cfbaf2de88355778aa76654298a072bce2e01d1858ae06"}, + "dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"}, + "earmark": {:hex, :earmark, "1.4.34", "d7f89d3bbd7567a0bffc465e0a949f8f8dcbe43909c3acf96f4761a302cea10c", [:mix], [{:earmark_parser, "~> 1.4.29", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "90b106f3dad85b133b10d7d628167c88246123fd1cecb4557d83d21ec9e65504"}, "earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"}, "eblurhash": {:hex, :eblurhash, "1.2.2", "7da4255aaea984b31bb71155f673257353b0e0554d0d30dcf859547e74602582", [:rebar3], [], "hexpm", "8c20ca00904de023a835a9dcb7b7762fed32264c85a80c3cafa85288e405044c"}, "ecto": {:hex, :ecto, "3.9.2", "017db3bc786ff64271108522c01a5d3f6ba0aea5c84912cfb0dd73bf13684108", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "21466d5177e09e55289ac7eade579a642578242c7a3a9f91ad5c6583337a9d15"}, @@ -32,6 +33,7 @@ "ecto_sql": {:hex, :ecto_sql, "3.9.1", "9bd5894eecc53d5b39d0c95180d4466aff00e10679e13a5cfa725f6f85c03c22", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fd470a4fff2e829bbf9dcceb7f3f9f6d1e49b4241e802f614de6b8b67c51118"}, "elasticsearch": {:git, "https://akkoma.dev/AkkomaGang/elasticsearch-elixir.git", "6cd946f75f6ab9042521a009d1d32d29a90113ca", [ref: "main"]}, "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"}, + "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "ex_aws": {:hex, :ex_aws, "2.1.9", "dc4865ecc20a05190a34a0ac5213e3e5e2b0a75a0c2835e923ae7bfeac5e3c31", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "3e6c776703c9076001fbe1f7c049535f042cb2afa0d2cbd3b47cbc4e92ac0d10"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.3.3", "61412e524616ea31d3f31675d8bc4c73f277e367dee0ae8245610446f9b778aa", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "0044f0b6f9ce925666021eafd630de64c2b3404d79c85245cc7c8a9a32d7f104"}, @@ -47,7 +49,7 @@ "flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"}, "floki": {:hex, :floki, "0.34.0", "002d0cc194b48794d74711731db004fafeb328fe676976f160685262d43706a8", [:mix], [], "hexpm", "9c3a9f43f40dde00332a589bd9d389b90c1f518aef500364d00636acc5ebc99c"}, "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"}, - "gettext": {:git, "https://github.com/tusooa/gettext.git", "72fb2496b6c5280ed911bdc3756890e7f38a4808", [ref: "72fb2496b6c5280ed911bdc3756890e7f38a4808"]}, + "gettext": {:hex, :gettext, "0.20.0", "75ad71de05f2ef56991dbae224d35c68b098dd0e26918def5bb45591d5c8d429", [:mix], [], "hexpm", "1c03b177435e93a47441d7f681a7040bd2a816ece9e2666d1c9001035121eb3d"}, "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~> 2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, @@ -78,18 +80,18 @@ "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, "nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"}, "oban": {:hex, :oban, "2.12.1", "f604d7e6a8be9fda4a9b0f6cebbd633deba569f85dbff70c4d25d99a6f023177", [:mix], [{:ecto_sql, "~> 3.6", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b1844c2b74e0d788b73e5144b0c9d5674cb775eae29d88a36f3c3b48d42d058"}, - "open_api_spex": {:hex, :open_api_spex, "3.10.0", "94e9521ad525b3fcf6dc77da7c45f87fdac24756d4de588cb0816b413e7c1844", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.1", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "2dbb2bde3d2b821f06936e8dfaf3284331186556291946d84eeba3750ac28765"}, + "open_api_spex": {:hex, :open_api_spex, "3.16.0", "9843af4e87550cd8ac5821b10e4c74f1d51f0d4e3310f824d780614743423b25", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "bb0be24a648b73e8fc8cbda17f514b8486262275e8b33e8b5ae66283df972129"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, - "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.5", "1495bb014be12c9a9252eca04b9af54246f6b5c1e4cd1f30210cd00ec540cf8e", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.7", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "ef4fa50dd78364409039c99cf6f98ab5209b4c5f8796c17f4db118324f0db852"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.12", "74f4c0ad02d7deac2d04f50b52827a5efdc5c6e7fac5cede145f5f0e4183aedc", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.0 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "af6dd5e0aac16ff43571f527a8e0616d62cb80b10eb87aac82170243e50d99c8"}, + "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.18.3", "2e3d009422addf8b15c3dccc65ce53baccbe26f7cfd21d264680b5867789a9c1", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c8845177a866e017dcb7083365393c8f00ab061b8b6b2bda575891079dce81b2"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, "phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.4", "615f8f393135de7e0cbb4bd00ba238b1e0cd324b0d90efbaee613c2f02ca5e5c", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "3971221846232021ab5e3c7489fd62ec5bfd6a2e01cae10a317ccf6fb350571c"}, "phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"}, "phoenix_view": {:hex, :phoenix_view, "2.0.2", "6bd4d2fd595ef80d33b439ede6a19326b78f0f1d8d62b9a318e3d9c1af351098", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "a929e7230ea5c7ee0e149ffcf44ce7cf7f4b6d2bfe1752dd7c084cdff152d36f"}, - "plug": {:hex, :plug, "1.10.4", "41eba7d1a2d671faaf531fa867645bd5a3dce0957d8e2a3f398ccff7d2ef017f", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad1e233fe73d2eec56616568d260777b67f53148a999dc2d048f4eb9778fe4a0"}, + "plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"}, "plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"}, "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, "plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "79fd4fcf34d110605c26560cbae8f23c603ec4158c08298bd4360fdea90bb5cf"}, @@ -97,16 +99,15 @@ "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, "postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"}, "pot": {:hex, :pot, "1.0.2", "13abb849139fdc04ab8154986abbcb63bdee5de6ed2ba7e1713527e33df923dd", [:rebar3], [], "hexpm", "78fe127f5a4f5f919d6ea5a2a671827bd53eb9d37e5b4128c0ad3df99856c2e0"}, - "quack": {:hex, :quack, "0.1.1", "cca7b4da1a233757fdb44b3334fce80c94785b3ad5a602053b7a002b5a8967bf", [:mix], [{:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "d736bfa7444112eb840027bb887832a0e403a4a3437f48028c3b29a2dbbd2543"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "recon": {:hex, :recon, "2.5.2", "cba53fa8db83ad968c9a652e09c3ed7ddcc4da434f27c3eaa9ca47ffb2b1ff03", [:mix, :rebar3], [], "hexpm", "2c7523c8dee91dff41f6b3d63cba2bd49eb6d2fe5bf1eec0df7f87eb5e230e1c"}, - "remote_ip": {:git, "https://git.pleroma.social/pleroma/remote_ip.git", "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8", [ref: "b647d0deecaa3acb140854fe4bda5b7e1dc6d1c8"]}, + "remote_ip": {:hex, :remote_ip, "1.1.0", "cb308841595d15df3f9073b7c39243a1dd6ca56e5020295cb012c76fbec50f2d", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "616ffdf66aaad6a72fc546dabf42eed87e2a99e97b09cbd92b10cc180d02ed74"}, "search_parser": {:git, "https://github.com/FloatingGhost/pleroma-contrib-search-parser.git", "08971a81e68686f9ac465cfb6661d51c5e4e1e7f", [ref: "08971a81e68686f9ac465cfb6661d51c5e4e1e7f"]}, "sleeplocks": {:hex, :sleeplocks, "1.1.2", "d45aa1c5513da48c888715e3381211c859af34bee9b8290490e10c90bb6ff0ca", [:rebar3], [], "hexpm", "9fe5d048c5b781d6305c1a3a0f40bb3dfc06f49bf40571f3d2d0c57eaa7f59a5"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, "sweet_xml": {:hex, :sweet_xml, "0.7.3", "debb256781c75ff6a8c5cbf7981146312b66f044a2898f453709a53e5031b45b", [:mix], [], "hexpm", "e110c867a1b3fe74bfc7dd9893aa851f0eed5518d0d7cad76d7baafd30e4f5ba"}, - "swoosh": {:hex, :swoosh, "1.8.2", "af9a22ab2c0d20b266f61acca737fa11a121902de9466a39e91bacdce012101c", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d058ba750eafadb6c09a84a352c14c5d1eeeda6e84945fcc95785b7f3067b7db"}, + "swoosh": {:hex, :swoosh, "1.8.3", "733357d9a65da19c162171f08d1e42a6259236cf44d02a64711b776afbbbaa78", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c699abbac7a296c205055a7501c5d5261320ea1f08bde2392699a9e899815bc7"}, "syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"}, "table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"}, "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, diff --git a/test/credo/check/consistency/file_location.ex b/test/credo/check/consistency/file_location.ex index abc55fffc..a457c59a6 100644 --- a/test/credo/check/consistency/file_location.ex +++ b/test/credo/check/consistency/file_location.ex @@ -163,4 +163,8 @@ defp error(issue_meta, module, expected_file) do line_no: 1 ) end + + defp append_issues_and_timings(_issues, exec) do + exec + end end diff --git a/test/pleroma/signature_test.exs b/test/pleroma/signature_test.exs index e3ae36b46..59674bbc0 100644 --- a/test/pleroma/signature_test.exs +++ b/test/pleroma/signature_test.exs @@ -116,7 +116,7 @@ test "it deduces the actor id for gotoSocial" do test "it calls webfinger for 'acct:' accounts" do with_mock(Pleroma.Web.WebFinger, - finger: fn _ -> %{"ap_id" => "https://gensokyo.2hu/users/raymoo"} end + finger: fn _ -> {:ok, %{"ap_id" => "https://gensokyo.2hu/users/raymoo"}} end ) do assert Signature.key_id_to_actor_id("acct:raymoo@gensokyo.2hu") == {:ok, "https://gensokyo.2hu/users/raymoo"} diff --git a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs index 7c001ada3..e423b2311 100644 --- a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs @@ -41,15 +41,16 @@ test "with valid `admin_token` query parameter, skips OAuth scopes check" do user = insert(:user) - conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123") + conn = + get(build_conn(), "/api/v1/pleroma/admin/users/#{user.nickname}?admin_token=password123") assert json_response(conn, 200) end - test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope", + test "GET /api/v1/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope", %{admin: admin} do user = insert(:user) - url = "/api/pleroma/admin/users/#{user.nickname}" + url = "/api/v1/pleroma/admin/users/#{user.nickname}" good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"]) good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"]) @@ -90,7 +91,7 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro end end - describe "PUT /api/pleroma/admin/users/tag" do + describe "PUT /api/v1/pleroma/admin/users/tag" do setup %{conn: conn} do user1 = insert(:user, %{tags: ["x"]}) user2 = insert(:user, %{tags: ["y"]}) @@ -100,7 +101,7 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro conn |> put_req_header("accept", "application/json") |> put( - "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> + "/api/v1/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> "#{user2.nickname}&tags[]=foo&tags[]=bar" ) @@ -136,7 +137,7 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user end end - describe "DELETE /api/pleroma/admin/users/tag" do + describe "DELETE /api/v1/pleroma/admin/users/tag" do setup %{conn: conn} do user1 = insert(:user, %{tags: ["x"]}) user2 = insert(:user, %{tags: ["y", "z"]}) @@ -146,7 +147,7 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user conn |> put_req_header("accept", "application/json") |> delete( - "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> + "/api/v1/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> "#{user2.nickname}&tags[]=x&tags[]=z" ) @@ -182,12 +183,12 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user end end - describe "/api/pleroma/admin/users/:nickname/permission_group" do + describe "/api/v1/pleroma/admin/users/:nickname/permission_group" do test "GET is giving user_info", %{admin: admin, conn: conn} do conn = conn |> put_req_header("accept", "application/json") - |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/") + |> get("/api/v1/pleroma/admin/users/#{admin.nickname}/permission_group/") assert json_response(conn, 200) == %{ "is_admin" => true, @@ -201,7 +202,7 @@ test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} conn = conn |> put_req_header("accept", "application/json") - |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") + |> post("/api/v1/pleroma/admin/users/#{user.nickname}/permission_group/admin") assert json_response(conn, 200) == %{ "is_admin" => true @@ -220,7 +221,7 @@ test "/:right POST, can add to a permission group (multiple)", %{admin: admin, c conn = conn |> put_req_header("accept", "application/json") - |> post("/api/pleroma/admin/users/permission_group/admin", %{ + |> post("/api/v1/pleroma/admin/users/permission_group/admin", %{ nicknames: [user_one.nickname, user_two.nickname] }) @@ -238,7 +239,7 @@ test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn = conn |> put_req_header("accept", "application/json") - |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") + |> delete("/api/v1/pleroma/admin/users/#{user.nickname}/permission_group/admin") assert json_response(conn, 200) == %{"is_admin" => false} @@ -258,7 +259,7 @@ test "/:right DELETE, can remove from a permission group (multiple)", %{ conn = conn |> put_req_header("accept", "application/json") - |> delete("/api/pleroma/admin/users/permission_group/admin", %{ + |> delete("/api/v1/pleroma/admin/users/permission_group/admin", %{ nicknames: [user_one.nickname, user_two.nickname] }) @@ -271,13 +272,13 @@ test "/:right DELETE, can remove from a permission group (multiple)", %{ end end - test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do + test "/api/v1/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do user = insert(:user) conn = conn |> put_req_header("accept", "application/json") - |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset") + |> get("/api/v1/pleroma/admin/users/#{user.nickname}/password_reset") resp = json_response(conn, 200) @@ -296,7 +297,7 @@ test "returns 200 and disable 2fa", %{conn: conn} do response = conn - |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: user.nickname}) + |> put("/api/v1/pleroma/admin/users/disable_mfa", %{nickname: user.nickname}) |> json_response(200) assert response == user.nickname @@ -309,19 +310,19 @@ test "returns 200 and disable 2fa", %{conn: conn} do test "returns 404 if user not found", %{conn: conn} do response = conn - |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"}) + |> put("/api/v1/pleroma/admin/users/disable_mfa", %{nickname: "nickname"}) |> json_response(404) assert response == %{"error" => "Not found"} end end - describe "GET /api/pleroma/admin/restart" do + describe "GET /api/v1/pleroma/admin/restart" do setup do: clear_config(:configurable_from_database, true) test "pleroma restarts", %{conn: conn} do capture_log(fn -> - assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{} + assert conn |> get("/api/v1/pleroma/admin/restart") |> json_response(200) == %{} end) =~ "pleroma restarted" refute Restarter.Pleroma.need_reboot?() @@ -330,19 +331,19 @@ test "pleroma restarts", %{conn: conn} do test "need_reboot flag", %{conn: conn} do assert conn - |> get("/api/pleroma/admin/need_reboot") + |> get("/api/v1/pleroma/admin/need_reboot") |> json_response(200) == %{"need_reboot" => false} Restarter.Pleroma.need_reboot() assert conn - |> get("/api/pleroma/admin/need_reboot") + |> get("/api/v1/pleroma/admin/need_reboot") |> json_response(200) == %{"need_reboot" => true} on_exit(fn -> Restarter.Pleroma.refresh() end) end - describe "GET /api/pleroma/admin/users/:nickname/statuses" do + describe "GET /api/v1/pleroma/admin/users/:nickname/statuses" do setup do user = insert(:user) @@ -354,7 +355,7 @@ test "need_reboot flag", %{conn: conn} do end test "renders user's statuses", %{conn: conn, user: user} do - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses") + conn = get(conn, "/api/v1/pleroma/admin/users/#{user.nickname}/statuses") assert %{"total" => 3, "activities" => activities} = json_response(conn, 200) assert length(activities) == 3 @@ -363,12 +364,12 @@ test "renders user's statuses", %{conn: conn, user: user} do test "renders user's statuses with pagination", %{conn: conn, user: user} do %{"total" => 3, "activities" => [activity1]} = conn - |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=1") + |> get("/api/v1/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=1") |> json_response(200) %{"total" => 3, "activities" => [activity2]} = conn - |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=2") + |> get("/api/v1/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=2") |> json_response(200) refute activity1 == activity2 @@ -381,7 +382,7 @@ test "doesn't return private statuses by default", %{conn: conn, user: user} do %{"total" => 4, "activities" => activities} = conn - |> get("/api/pleroma/admin/users/#{user.nickname}/statuses") + |> get("/api/v1/pleroma/admin/users/#{user.nickname}/statuses") |> json_response(200) assert length(activities) == 4 @@ -394,7 +395,7 @@ test "returns private statuses with godmode on", %{conn: conn, user: user} do %{"total" => 5, "activities" => activities} = conn - |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true") + |> get("/api/v1/pleroma/admin/users/#{user.nickname}/statuses?godmode=true") |> json_response(200) assert length(activities) == 5 @@ -407,19 +408,19 @@ test "excludes reblogs by default", %{conn: conn, user: user} do assert %{"total" => 0, "activities" => []} == conn - |> get("/api/pleroma/admin/users/#{other_user.nickname}/statuses") + |> get("/api/v1/pleroma/admin/users/#{other_user.nickname}/statuses") |> json_response(200) assert %{"total" => 1, "activities" => [_]} = conn |> get( - "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true" + "/api/v1/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true" ) |> json_response(200) end end - describe "GET /api/pleroma/admin/moderation_log" do + describe "GET /api/v1/pleroma/admin/moderation_log" do setup do moderator = insert(:user, is_moderator: true) @@ -453,7 +454,7 @@ test "returns the log", %{conn: conn, admin: admin} do inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second) }) - conn = get(conn, "/api/pleroma/admin/moderation_log") + conn = get(conn, "/api/v1/pleroma/admin/moderation_log") response = json_response(conn, 200) [first_entry, second_entry] = response["items"] @@ -497,7 +498,7 @@ test "returns the log with pagination", %{conn: conn, admin: admin} do inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second) }) - conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1") + conn1 = get(conn, "/api/v1/pleroma/admin/moderation_log?page_size=1&page=1") response1 = json_response(conn1, 200) [first_entry] = response1["items"] @@ -509,7 +510,7 @@ test "returns the log with pagination", %{conn: conn, admin: admin} do assert first_entry["message"] == "@#{admin.nickname} unfollowed relay: https://example.org/relay" - conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2") + conn2 = get(conn, "/api/v1/pleroma/admin/moderation_log?page_size=1&page=2") response2 = json_response(conn2, 200) [second_entry] = response2["items"] @@ -555,7 +556,7 @@ test "filters log by date", %{conn: conn, admin: admin} do conn1 = get( conn, - "/api/pleroma/admin/moderation_log?start_date=#{second_date}" + "/api/v1/pleroma/admin/moderation_log?start_date=#{second_date}" ) response1 = json_response(conn1, 200) @@ -593,7 +594,7 @@ test "returns log filtered by user", %{conn: conn, admin: admin, moderator: mode } }) - conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}") + conn1 = get(conn, "/api/v1/pleroma/admin/moderation_log?user_id=#{moderator.id}") response1 = json_response(conn1, 200) [first_entry] = response1["items"] @@ -615,7 +616,7 @@ test "returns log filtered by search", %{conn: conn, moderator: moderator} do target: "https://example.org/relay" }) - conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo") + conn1 = get(conn, "/api/v1/pleroma/admin/moderation_log?search=unfo") response1 = json_response(conn1, 200) [first_entry] = response1["items"] @@ -631,7 +632,7 @@ test "gets a remote users when [:instance, :limit_to_local_content] is set to :u %{conn: conn} do clear_config(Pleroma.Config.get([:instance, :limit_to_local_content]), :unauthenticated) user = insert(:user, %{local: false, nickname: "u@peer1.com"}) - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials") + conn = get(conn, "/api/v1/pleroma/admin/users/#{user.nickname}/credentials") assert json_response(conn, 200) end @@ -639,7 +640,7 @@ test "gets a remote users when [:instance, :limit_to_local_content] is set to :u describe "GET /users/:nickname/credentials" do test "gets the user credentials", %{conn: conn} do user = insert(:user) - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials") + conn = get(conn, "/api/v1/pleroma/admin/users/#{user.nickname}/credentials") response = assert json_response(conn, 200) assert response["email"] == user.email @@ -651,7 +652,7 @@ test "returns 403 if requested by a non-admin" do conn = build_conn() |> assign(:user, user) - |> get("/api/pleroma/admin/users/#{user.nickname}/credentials") + |> get("/api/v1/pleroma/admin/users/#{user.nickname}/credentials") assert json_response(conn, :forbidden) end @@ -667,7 +668,7 @@ test "changes password and email", %{conn: conn, admin: admin, user: user} do assert user.password_reset_pending == false conn = - patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{ + patch(conn, "/api/v1/pleroma/admin/users/#{user.nickname}/credentials", %{ "password" => "new_password", "email" => "new_email@example.com", "name" => "new_name" @@ -697,7 +698,7 @@ test "returns 403 if requested by a non-admin", %{user: user} do conn = build_conn() |> assign(:user, user) - |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{ + |> patch("/api/v1/pleroma/admin/users/#{user.nickname}/credentials", %{ "password" => "new_password", "email" => "new_email@example.com", "name" => "new_name" @@ -709,7 +710,7 @@ test "returns 403 if requested by a non-admin", %{user: user} do test "changes actor type from permitted list", %{conn: conn, user: user} do assert user.actor_type == "Person" - assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{ + assert patch(conn, "/api/v1/pleroma/admin/users/#{user.nickname}/credentials", %{ "actor_type" => "Service" }) |> json_response(200) == %{"status" => "success"} @@ -718,14 +719,14 @@ test "changes actor type from permitted list", %{conn: conn, user: user} do assert updated_user.actor_type == "Service" - assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{ + assert patch(conn, "/api/v1/pleroma/admin/users/#{user.nickname}/credentials", %{ "actor_type" => "Application" }) |> json_response(400) == %{"errors" => %{"actor_type" => "is invalid"}} end test "update non existing user", %{conn: conn} do - assert patch(conn, "/api/pleroma/admin/users/non-existing/credentials", %{ + assert patch(conn, "/api/v1/pleroma/admin/users/non-existing/credentials", %{ "password" => "new_password" }) |> json_response(404) == %{"error" => "Not found"} @@ -738,7 +739,9 @@ test "sets password_reset_pending to true", %{conn: conn} do assert user.password_reset_pending == false conn = - patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]}) + patch(conn, "/api/v1/pleroma/admin/users/force_password_reset", %{ + nicknames: [user.nickname] + }) assert empty_json_response(conn) == "" @@ -756,7 +759,7 @@ test "it confirms emails of two users", %{conn: conn, admin: admin} do refute second_user.is_confirmed ret_conn = - patch(conn, "/api/pleroma/admin/users/confirm_email", %{ + patch(conn, "/api/v1/pleroma/admin/users/confirm_email", %{ nicknames: [ first_user.nickname, second_user.nickname @@ -783,7 +786,7 @@ test "it resend emails for two users", %{conn: conn, admin: admin} do [first_user, second_user] = insert_pair(:user, is_confirmed: false) ret_conn = - patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{ + patch(conn, "/api/v1/pleroma/admin/users/resend_confirmation_email", %{ nicknames: [ first_user.nickname, second_user.nickname @@ -804,7 +807,7 @@ test "it resend emails for two users", %{conn: conn, admin: admin} do end end - describe "/api/pleroma/admin/stats" do + describe "/api/v1/pleroma/admin/stats" do test "status visibility count", %{conn: conn} do user = insert(:user) CommonAPI.post(user, %{visibility: "public", status: "hey"}) @@ -813,7 +816,7 @@ test "status visibility count", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/stats") + |> get("/api/v1/pleroma/admin/stats") |> json_response(200) assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} = @@ -831,7 +834,7 @@ test "by instance", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/stats", instance: instance2) + |> get("/api/v1/pleroma/admin/stats", instance: instance2) |> json_response(200) assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} = @@ -839,7 +842,7 @@ test "by instance", %{conn: conn} do end end - describe "/api/pleroma/backups" do + describe "/api/v1/pleroma/backups" do test "it creates a backup", %{conn: conn} do admin = %{id: admin_id, nickname: admin_nickname} = insert(:user, is_admin: true) token = insert(:oauth_admin_token, user: admin) @@ -849,7 +852,7 @@ test "it creates a backup", %{conn: conn} do conn |> assign(:user, admin) |> assign(:token, token) - |> post("/api/pleroma/admin/backups", %{nickname: user.nickname}) + |> post("/api/v1/pleroma/admin/backups", %{nickname: user.nickname}) |> json_response(200) assert [backup] = Repo.all(Pleroma.User.Backup) @@ -890,7 +893,7 @@ test "it doesn't limit admins", %{conn: conn} do conn |> assign(:user, admin) |> assign(:token, token) - |> post("/api/pleroma/admin/backups", %{nickname: user.nickname}) + |> post("/api/v1/pleroma/admin/backups", %{nickname: user.nickname}) |> json_response(200) assert [_backup] = Repo.all(Pleroma.User.Backup) @@ -899,7 +902,7 @@ test "it doesn't limit admins", %{conn: conn} do conn |> assign(:user, admin) |> assign(:token, token) - |> post("/api/pleroma/admin/backups", %{nickname: user.nickname}) + |> post("/api/v1/pleroma/admin/backups", %{nickname: user.nickname}) |> json_response(200) assert Repo.aggregate(Pleroma.User.Backup, :count) == 2 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 200682ba9..c84624aff 100644 --- a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs @@ -30,11 +30,11 @@ defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do {:ok, %{admin: admin, token: token, conn: conn}} end - describe "GET /api/pleroma/admin/frontends" do + describe "GET /api/v1/pleroma/admin/frontends" do test "it lists available frontends", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/frontends") + |> get("/api/v1/pleroma/admin/frontends") |> json_response_and_validate_schema(:ok) assert Enum.map(response, & &1["name"]) == @@ -48,7 +48,7 @@ test "it lists available frontends when no frontend folder was created yet", %{c response = conn - |> get("/api/pleroma/admin/frontends") + |> get("/api/v1/pleroma/admin/frontends") |> json_response_and_validate_schema(:ok) assert Enum.map(response, & &1["name"]) == @@ -58,7 +58,7 @@ test "it lists available frontends when no frontend folder was created yet", %{c end end - describe "POST /api/pleroma/admin/frontends/install" do + describe "POST /api/v1/pleroma/admin/frontends/install" do test "from available frontends", %{conn: conn} do clear_config([:frontends, :available], %{ "pleroma" => %{ @@ -74,14 +74,14 @@ test "from available frontends", %{conn: conn} do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/frontends/install", %{name: "pleroma"}) + |> post("/api/v1/pleroma/admin/frontends/install", %{name: "pleroma"}) |> json_response_and_validate_schema(:ok) assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"])) response = conn - |> get("/api/pleroma/admin/frontends") + |> get("/api/v1/pleroma/admin/frontends") |> json_response_and_validate_schema(:ok) assert response == [ @@ -106,7 +106,7 @@ test "from a file", %{conn: conn} do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/frontends/install", %{ + |> post("/api/v1/pleroma/admin/frontends/install", %{ name: "pleroma", file: "test/fixtures/tesla_mock/frontend.zip" }) @@ -122,7 +122,7 @@ test "from an URL", %{conn: conn} do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/frontends/install", %{ + |> post("/api/v1/pleroma/admin/frontends/install", %{ name: "unknown", ref: "baka", build_url: "http://gensokyo.2hu/madeup.zip", @@ -141,7 +141,7 @@ test "failing returns an error", %{conn: conn} do result = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/frontends/install", %{ + |> post("/api/v1/pleroma/admin/frontends/install", %{ name: "unknown", ref: "baka", build_url: "http://gensokyo.2hu/madeup.zip", diff --git a/test/pleroma/web/admin_api/controllers/instance_controller_test.exs b/test/pleroma/web/admin_api/controllers/instance_controller_test.exs index c78307fc8..08920a541 100644 --- a/test/pleroma/web/admin_api/controllers/instance_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/instance_controller_test.exs @@ -37,26 +37,28 @@ test "GET /instances/:instance/statuses", %{conn: conn} do activity = insert(:note_activity, user: user2) %{"total" => 2, "activities" => activities} = - conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200) + conn |> get("/api/v1/pleroma/admin/instances/archae.me/statuses") |> json_response(200) assert length(activities) == 2 %{"total" => 1, "activities" => [_]} = - conn |> get("/api/pleroma/admin/instances/test.com/statuses") |> json_response(200) + conn |> get("/api/v1/pleroma/admin/instances/test.com/statuses") |> json_response(200) %{"total" => 0, "activities" => []} = - conn |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") |> json_response(200) + conn + |> get("/api/v1/pleroma/admin/instances/nonexistent.com/statuses") + |> json_response(200) CommonAPI.repeat(activity.id, user) %{"total" => 2, "activities" => activities} = - conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200) + conn |> get("/api/v1/pleroma/admin/instances/archae.me/statuses") |> json_response(200) assert length(activities) == 2 %{"total" => 3, "activities" => activities} = conn - |> get("/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true") + |> get("/api/v1/pleroma/admin/instances/archae.me/statuses?with_reblogs=true") |> json_response(200) assert length(activities) == 3 @@ -68,7 +70,7 @@ test "DELETE /instances/:instance", %{conn: conn} do response = conn - |> delete("/api/pleroma/admin/instances/lain.com") + |> delete("/api/v1/pleroma/admin/instances/lain.com") |> json_response(200) [:ok] = ObanHelpers.perform_all() 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 4d388a1e2..97deb5f82 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 @@ -28,9 +28,9 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentControllerTest do {:ok, %{admin: admin, token: token, conn: conn}} end - describe "GET /api/pleroma/admin/instance_document/:name" do + describe "GET /api/v1/pleroma/admin/instance_document/:name" do test "return the instance document url", %{conn: conn} do - conn = get(conn, "/api/pleroma/admin/instance_document/instance-panel") + conn = get(conn, "/api/v1/pleroma/admin/instance_document/instance-panel") assert content = html_response(conn, 200) assert String.contains?(content, @default_instance_panel) @@ -44,7 +44,7 @@ test "it returns 403 if requested by a non-admin" do build_conn() |> assign(:user, non_admin_user) |> assign(:token, token) - |> get("/api/pleroma/admin/instance_document/instance-panel") + |> get("/api/v1/pleroma/admin/instance_document/instance-panel") assert json_response(conn, :forbidden) end @@ -52,13 +52,13 @@ test "it returns 403 if requested by a non-admin" do test "it returns 404 if the instance document with the given name doesn't exist", %{ conn: conn } do - conn = get(conn, "/api/pleroma/admin/instance_document/1234") + conn = get(conn, "/api/v1/pleroma/admin/instance_document/1234") assert json_response_and_validate_schema(conn, 404) end end - describe "PATCH /api/pleroma/admin/instance_document/:name" do + describe "PATCH /api/v1/pleroma/admin/instance_document/:name" do test "uploads the instance document", %{conn: conn} do image = %Plug.Upload{ content_type: "text/html", @@ -69,7 +69,7 @@ test "uploads the instance document", %{conn: conn} do conn = conn |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/admin/instance_document/instance-panel", %{ + |> patch("/api/v1/pleroma/admin/instance_document/instance-panel", %{ "file" => image }) @@ -79,24 +79,24 @@ test "uploads the instance document", %{conn: conn} do end end - describe "DELETE /api/pleroma/admin/instance_document/:name" do + describe "DELETE /api/v1/pleroma/admin/instance_document/:name" do test "deletes the instance document", %{conn: conn} do File.mkdir!(@dir <> "/instance/") File.write!(@dir <> "/instance/panel.html", "Custom instance panel") conn_resp = conn - |> get("/api/pleroma/admin/instance_document/instance-panel") + |> get("/api/v1/pleroma/admin/instance_document/instance-panel") assert html_response(conn_resp, 200) == "Custom instance panel" conn - |> delete("/api/pleroma/admin/instance_document/instance-panel") + |> delete("/api/v1/pleroma/admin/instance_document/instance-panel") |> json_response_and_validate_schema(200) conn_resp = conn - |> get("/api/pleroma/admin/instance_document/instance-panel") + |> get("/api/v1/pleroma/admin/instance_document/instance-panel") assert content = html_response(conn_resp, 200) assert String.contains?(content, @default_instance_panel) diff --git a/test/pleroma/web/admin_api/controllers/invite_controller_test.exs b/test/pleroma/web/admin_api/controllers/invite_controller_test.exs index 6366061c8..d384c3580 100644 --- a/test/pleroma/web/admin_api/controllers/invite_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/invite_controller_test.exs @@ -22,7 +22,7 @@ defmodule Pleroma.Web.AdminAPI.InviteControllerTest do {:ok, %{admin: admin, token: token, conn: conn}} end - describe "POST /api/pleroma/admin/users/email_invite, with valid config" do + describe "POST /api/v1/pleroma/admin/users/email_invite, with valid config" do setup do: clear_config([:instance, :registrations_open], false) setup do: clear_config([:instance, :invites_enabled], true) @@ -33,7 +33,7 @@ test "sends invitation and returns 204", %{admin: admin, conn: conn} do conn = conn |> put_req_header("content-type", "application/json;charset=utf-8") - |> post("/api/pleroma/admin/users/email_invite", %{ + |> post("/api/v1/pleroma/admin/users/email_invite", %{ email: recipient_email, name: recipient_name }) @@ -71,7 +71,7 @@ test "it returns 403 if requested by a non-admin" do |> assign(:user, non_admin_user) |> assign(:token, token) |> put_req_header("content-type", "application/json;charset=utf-8") - |> post("/api/pleroma/admin/users/email_invite", %{ + |> post("/api/v1/pleroma/admin/users/email_invite", %{ email: "foo@bar.com", name: "JD" }) @@ -84,7 +84,7 @@ test "email with +", %{conn: conn, admin: admin} do conn |> put_req_header("content-type", "application/json;charset=utf-8") - |> post("/api/pleroma/admin/users/email_invite", %{email: recipient_email}) + |> post("/api/v1/pleroma/admin/users/email_invite", %{email: recipient_email}) |> json_response_and_validate_schema(:no_content) token_record = @@ -113,7 +113,7 @@ test "email with +", %{conn: conn, admin: admin} do end end - describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do + describe "POST /api/v1/pleroma/admin/users/email_invite, with invalid config" do setup do: clear_config([:instance, :registrations_open]) setup do: clear_config([:instance, :invites_enabled]) @@ -124,7 +124,7 @@ test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/email_invite", %{ + |> post("/api/v1/pleroma/admin/users/email_invite", %{ email: "foo@bar.com", name: "JD" }) @@ -143,7 +143,7 @@ test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/email_invite", %{ + |> post("/api/v1/pleroma/admin/users/email_invite", %{ email: "foo@bar.com", name: "JD" }) @@ -156,12 +156,12 @@ test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do end end - describe "POST /api/pleroma/admin/users/invite_token" do + describe "POST /api/v1/pleroma/admin/users/invite_token" do test "without options", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/invite_token") + |> post("/api/v1/pleroma/admin/users/invite_token") invite_json = json_response_and_validate_schema(conn, 200) invite = UserInviteToken.find_by_token!(invite_json["token"]) @@ -175,7 +175,7 @@ test "with expires_at", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/invite_token", %{ + |> post("/api/v1/pleroma/admin/users/invite_token", %{ "expires_at" => Date.to_string(Date.utc_today()) }) @@ -192,7 +192,7 @@ test "with max_use", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/invite_token", %{"max_use" => 150}) + |> post("/api/v1/pleroma/admin/users/invite_token", %{"max_use" => 150}) invite_json = json_response_and_validate_schema(conn, 200) invite = UserInviteToken.find_by_token!(invite_json["token"]) @@ -206,7 +206,7 @@ test "with max use and expires_at", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/invite_token", %{ + |> post("/api/v1/pleroma/admin/users/invite_token", %{ "max_use" => 150, "expires_at" => Date.to_string(Date.utc_today()) }) @@ -220,9 +220,9 @@ test "with max use and expires_at", %{conn: conn} do end end - describe "GET /api/pleroma/admin/users/invites" do + describe "GET /api/v1/pleroma/admin/users/invites" do test "no invites", %{conn: conn} do - conn = get(conn, "/api/pleroma/admin/users/invites") + conn = get(conn, "/api/v1/pleroma/admin/users/invites") assert json_response_and_validate_schema(conn, 200) == %{"invites" => []} end @@ -230,7 +230,7 @@ test "no invites", %{conn: conn} do test "with invite", %{conn: conn} do {:ok, invite} = UserInviteToken.create_invite() - conn = get(conn, "/api/pleroma/admin/users/invites") + conn = get(conn, "/api/v1/pleroma/admin/users/invites") assert json_response_and_validate_schema(conn, 200) == %{ "invites" => [ @@ -248,14 +248,14 @@ test "with invite", %{conn: conn} do end end - describe "POST /api/pleroma/admin/users/revoke_invite" do + describe "POST /api/v1/pleroma/admin/users/revoke_invite" do test "with token", %{conn: conn} do {:ok, invite} = UserInviteToken.create_invite() conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token}) + |> post("/api/v1/pleroma/admin/users/revoke_invite", %{"token" => invite.token}) assert json_response_and_validate_schema(conn, 200) == %{ "expires_at" => nil, @@ -272,7 +272,7 @@ test "with invalid token", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"}) + |> post("/api/v1/pleroma/admin/users/revoke_invite", %{"token" => "foo"}) assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"} end diff --git a/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs b/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs index 1818c8a8e..30e941869 100644 --- a/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/media_proxy_cache_controller_test.exs @@ -28,7 +28,7 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheControllerTest do {:ok, %{admin: admin, token: token, conn: conn}} end - describe "GET /api/pleroma/admin/media_proxy_caches" do + describe "GET /api/v1/pleroma/admin/media_proxy_caches" do test "shows banned MediaProxy URLs", %{conn: conn} do MediaProxy.put_in_banned_urls([ "http://localhost:4001/media/a688346.jpg", @@ -41,7 +41,7 @@ test "shows banned MediaProxy URLs", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/media_proxy_caches?page_size=2") + |> get("/api/v1/pleroma/admin/media_proxy_caches?page_size=2") |> json_response_and_validate_schema(200) assert response["page_size"] == 2 @@ -51,7 +51,7 @@ test "shows banned MediaProxy URLs", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=2") + |> get("/api/v1/pleroma/admin/media_proxy_caches?page_size=2&page=2") |> json_response_and_validate_schema(200) assert response["page_size"] == 2 @@ -61,7 +61,7 @@ test "shows banned MediaProxy URLs", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&page=3") + |> get("/api/v1/pleroma/admin/media_proxy_caches?page_size=2&page=3") |> json_response_and_validate_schema(200) results = results ++ response["urls"] @@ -89,7 +89,7 @@ test "search banned MediaProxy URLs", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/media_proxy_caches?page_size=2&query=F44") + |> get("/api/v1/pleroma/admin/media_proxy_caches?page_size=2&query=F44") |> json_response_and_validate_schema(200) assert response["urls"] |> Enum.sort() == [ @@ -102,7 +102,7 @@ test "search banned MediaProxy URLs", %{conn: conn} do end end - describe "POST /api/pleroma/admin/media_proxy_caches/delete" do + describe "POST /api/v1/pleroma/admin/media_proxy_caches/delete" do test "deleted MediaProxy URLs from banned", %{conn: conn} do MediaProxy.put_in_banned_urls([ "http://localhost:4001/media/a688346.jpg", @@ -111,7 +111,7 @@ test "deleted MediaProxy URLs from banned", %{conn: conn} do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/media_proxy_caches/delete", %{ + |> post("/api/v1/pleroma/admin/media_proxy_caches/delete", %{ urls: ["http://localhost:4001/media/a688346.jpg"] }) |> json_response_and_validate_schema(200) @@ -121,7 +121,7 @@ test "deleted MediaProxy URLs from banned", %{conn: conn} do end end - describe "POST /api/pleroma/admin/media_proxy_caches/purge" do + describe "POST /api/v1/pleroma/admin/media_proxy_caches/purge" do test "perform invalidates cache of MediaProxy", %{conn: conn} do urls = [ "http://example.com/media/a688346.jpg", @@ -136,7 +136,7 @@ test "perform invalidates cache of MediaProxy", %{conn: conn} do ] do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/media_proxy_caches/purge", %{urls: urls, ban: false}) + |> post("/api/v1/pleroma/admin/media_proxy_caches/purge", %{urls: urls, ban: false}) |> json_response_and_validate_schema(200) refute MediaProxy.in_banned_urls("http://example.com/media/a688346.jpg") @@ -154,7 +154,7 @@ test "perform invalidates cache of MediaProxy and adds url to banned", %{conn: c conn |> put_req_header("content-type", "application/json") |> post( - "/api/pleroma/admin/media_proxy_caches/purge", + "/api/v1/pleroma/admin/media_proxy_caches/purge", %{urls: urls, ban: true} ) |> json_response_and_validate_schema(200) diff --git a/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs b/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs index d9b25719a..62f156993 100644 --- a/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs @@ -22,12 +22,12 @@ defmodule Pleroma.Web.AdminAPI.OAuthAppControllerTest do {:ok, %{admin: admin, token: token, conn: conn}} end - describe "POST /api/pleroma/admin/oauth_app" do + describe "POST /api/v1/pleroma/admin/oauth_app" do test "errors", %{conn: conn} do response = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/oauth_app", %{}) + |> post("/api/v1/pleroma/admin/oauth_app", %{}) |> json_response_and_validate_schema(400) assert %{ @@ -42,7 +42,7 @@ test "success", %{conn: conn} do response = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/oauth_app", %{ + |> post("/api/v1/pleroma/admin/oauth_app", %{ name: app_name, redirect_uris: base_url }) @@ -64,7 +64,7 @@ test "with trusted", %{conn: conn} do response = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/oauth_app", %{ + |> post("/api/v1/pleroma/admin/oauth_app", %{ name: app_name, redirect_uris: base_url, trusted: true @@ -81,7 +81,7 @@ test "with trusted", %{conn: conn} do end end - describe "GET /api/pleroma/admin/oauth_app" do + describe "GET /api/v1/pleroma/admin/oauth_app" do setup do app = insert(:oauth_app) {:ok, app: app} @@ -90,7 +90,7 @@ test "with trusted", %{conn: conn} do test "list", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/oauth_app") + |> get("/api/v1/pleroma/admin/oauth_app") |> json_response_and_validate_schema(200) assert %{"apps" => apps, "count" => count, "page_size" => _} = response @@ -104,7 +104,7 @@ test "with page size", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/oauth_app?page_size=#{page_size}") + |> get("/api/v1/pleroma/admin/oauth_app?page_size=#{page_size}") |> json_response_and_validate_schema(200) assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response @@ -115,7 +115,7 @@ test "with page size", %{conn: conn} do test "search by client name", %{conn: conn, app: app} do response = conn - |> get("/api/pleroma/admin/oauth_app?name=#{app.client_name}") + |> get("/api/v1/pleroma/admin/oauth_app?name=#{app.client_name}") |> json_response_and_validate_schema(200) assert %{"apps" => [returned], "count" => _, "page_size" => _} = response @@ -127,7 +127,7 @@ test "search by client name", %{conn: conn, app: app} do test "search by client id", %{conn: conn, app: app} do response = conn - |> get("/api/pleroma/admin/oauth_app?client_id=#{app.client_id}") + |> get("/api/v1/pleroma/admin/oauth_app?client_id=#{app.client_id}") |> json_response_and_validate_schema(200) assert %{"apps" => [returned], "count" => _, "page_size" => _} = response @@ -141,7 +141,7 @@ test "only trusted", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/oauth_app?trusted=true") + |> get("/api/v1/pleroma/admin/oauth_app?trusted=true") |> json_response_and_validate_schema(200) assert %{"apps" => [returned], "count" => _, "page_size" => _} = response @@ -151,13 +151,13 @@ test "only trusted", %{conn: conn} do end end - describe "DELETE /api/pleroma/admin/oauth_app/:id" do + describe "DELETE /api/v1/pleroma/admin/oauth_app/:id" do test "with id", %{conn: conn} do app = insert(:oauth_app) response = conn - |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id)) + |> delete("/api/v1/pleroma/admin/oauth_app/" <> to_string(app.id)) |> json_response_and_validate_schema(:no_content) assert response == "" @@ -166,14 +166,14 @@ test "with id", %{conn: conn} do test "with non existance id", %{conn: conn} do response = conn - |> delete("/api/pleroma/admin/oauth_app/0") + |> delete("/api/v1/pleroma/admin/oauth_app/0") |> json_response_and_validate_schema(:bad_request) assert response == "" end end - describe "PATCH /api/pleroma/admin/oauth_app/:id" do + describe "PATCH /api/v1/pleroma/admin/oauth_app/:id" do test "with id", %{conn: conn} do app = insert(:oauth_app) @@ -186,7 +186,7 @@ test "with id", %{conn: conn} do response = conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/oauth_app/#{id}", %{ + |> patch("/api/v1/pleroma/admin/oauth_app/#{id}", %{ name: name, trusted: true, redirect_uris: url, @@ -210,7 +210,7 @@ test "without id", %{conn: conn} do response = conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/oauth_app/0") + |> patch("/api/v1/pleroma/admin/oauth_app/0") |> json_response_and_validate_schema(:bad_request) assert response == "" diff --git a/test/pleroma/web/admin_api/controllers/relay_controller_test.exs b/test/pleroma/web/admin_api/controllers/relay_controller_test.exs index 11a480cc0..c86339dbd 100644 --- a/test/pleroma/web/admin_api/controllers/relay_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/relay_controller_test.exs @@ -34,7 +34,7 @@ test "POST /relay", %{conn: conn, admin: admin} do conn = conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/relay", %{ + |> post("/api/v1/pleroma/admin/relay", %{ relay_url: "http://mastodon.example.org/users/admin" }) @@ -58,7 +58,7 @@ test "GET /relay", %{conn: conn} do User.follow(relay_user, user) end) - conn = get(conn, "/api/pleroma/admin/relay") + conn = get(conn, "/api/v1/pleroma/admin/relay") assert json_response_and_validate_schema(conn, 200)["relays"] |> Enum.sort() == [ %{ @@ -72,14 +72,14 @@ test "GET /relay", %{conn: conn} do test "DELETE /relay", %{conn: conn, admin: admin} do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/relay", %{ + |> post("/api/v1/pleroma/admin/relay", %{ relay_url: "http://mastodon.example.org/users/admin" }) conn = conn |> put_req_header("content-type", "application/json") - |> delete("/api/pleroma/admin/relay", %{ + |> delete("/api/v1/pleroma/admin/relay", %{ relay_url: "http://mastodon.example.org/users/admin" }) diff --git a/test/pleroma/web/admin_api/controllers/report_controller_test.exs b/test/pleroma/web/admin_api/controllers/report_controller_test.exs index 2d526527b..dd859f34f 100644 --- a/test/pleroma/web/admin_api/controllers/report_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/report_controller_test.exs @@ -25,7 +25,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do {:ok, %{admin: admin, token: token, conn: conn}} end - describe "GET /api/pleroma/admin/reports/:id" do + describe "GET /api/v1/pleroma/admin/reports/:id" do test "returns report by its id", %{conn: conn} do [reporter, target_user] = insert_pair(:user) activity = insert(:note_activity, user: target_user) @@ -39,13 +39,13 @@ test "returns report by its id", %{conn: conn} do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{ + |> post("/api/v1/pleroma/admin/reports/#{report_id}/notes", %{ content: "this is an admin note" }) response = conn - |> get("/api/pleroma/admin/reports/#{report_id}") + |> get("/api/v1/pleroma/admin/reports/#{report_id}") |> json_response_and_validate_schema(:ok) assert response["id"] == report_id @@ -55,13 +55,13 @@ test "returns report by its id", %{conn: conn} do end test "returns 404 when report id is invalid", %{conn: conn} do - conn = get(conn, "/api/pleroma/admin/reports/test") + conn = get(conn, "/api/v1/pleroma/admin/reports/test") assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"} end end - describe "PATCH /api/pleroma/admin/reports" do + describe "PATCH /api/v1/pleroma/admin/reports" do setup do [reporter, target_user] = insert_pair(:user) activity = insert(:note_activity, user: target_user) @@ -94,7 +94,7 @@ test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} d conn |> assign(:token, read_token) |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/reports", %{ + |> patch("/api/v1/pleroma/admin/reports", %{ "reports" => [%{"state" => "resolved", "id" => id}] }) |> json_response_and_validate_schema(403) @@ -106,7 +106,7 @@ test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} d conn |> assign(:token, write_token) |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/reports", %{ + |> patch("/api/v1/pleroma/admin/reports", %{ "reports" => [%{"state" => "resolved", "id" => id}] }) |> json_response_and_validate_schema(:no_content) @@ -115,7 +115,7 @@ test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} d test "mark report as resolved", %{conn: conn, id: id, admin: admin} do conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/reports", %{ + |> patch("/api/v1/pleroma/admin/reports", %{ "reports" => [ %{"state" => "resolved", "id" => id} ] @@ -134,7 +134,7 @@ test "mark report as resolved", %{conn: conn, id: id, admin: admin} do test "closes report", %{conn: conn, id: id, admin: admin} do conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/reports", %{ + |> patch("/api/v1/pleroma/admin/reports", %{ "reports" => [ %{"state" => "closed", "id" => id} ] @@ -154,7 +154,7 @@ test "returns 400 when state is unknown", %{conn: conn, id: id} do conn = conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/reports", %{ + |> patch("/api/v1/pleroma/admin/reports", %{ "reports" => [ %{"state" => "test", "id" => id} ] @@ -168,7 +168,7 @@ test "returns 404 when report is not exist", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/reports", %{ + |> patch("/api/v1/pleroma/admin/reports", %{ "reports" => [ %{"state" => "closed", "id" => "test"} ] @@ -185,7 +185,7 @@ test "updates state of multiple reports", %{ } do conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/reports", %{ + |> patch("/api/v1/pleroma/admin/reports", %{ "reports" => [ %{"state" => "resolved", "id" => id}, %{"state" => "closed", "id" => second_report_id} @@ -208,7 +208,7 @@ test "updates state of multiple reports", %{ end end - describe "GET /api/pleroma/admin/reports" do + describe "GET /api/v1/pleroma/admin/reports" do test "returns empty response when no reports created", %{conn: conn} do response = conn @@ -300,14 +300,14 @@ test "returns 403 when requested by a non-admin" do build_conn() |> assign(:user, user) |> assign(:token, token) - |> get("/api/pleroma/admin/reports") + |> get("/api/v1/pleroma/admin/reports") assert json_response(conn, :forbidden) == %{"error" => "User is not a staff member."} end test "returns 403 when requested by anonymous" do - conn = get(build_conn(), "/api/pleroma/admin/reports") + conn = get(build_conn(), "/api/v1/pleroma/admin/reports") assert json_response(conn, :forbidden) == %{ "error" => "Invalid credentials." @@ -315,7 +315,7 @@ test "returns 403 when requested by anonymous" do end end - describe "POST /api/pleroma/admin/reports/:id/notes" do + describe "POST /api/v1/pleroma/admin/reports/:id/notes" do setup %{conn: conn, admin: admin} do [reporter, target_user] = insert_pair(:user) activity = insert(:note_activity, user: target_user) @@ -329,13 +329,13 @@ test "returns 403 when requested by anonymous" do conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{ + |> post("/api/v1/pleroma/admin/reports/#{report_id}/notes", %{ content: "this is disgusting!" }) conn |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{ + |> post("/api/v1/pleroma/admin/reports/#{report_id}/notes", %{ content: "this is disgusting2!" }) @@ -356,7 +356,7 @@ test "it creates report note", %{admin_id: admin_id, report_id: report_id} do end test "it returns reports with notes", %{conn: conn, admin: admin} do - conn = get(conn, "/api/pleroma/admin/reports") + conn = get(conn, "/api/v1/pleroma/admin/reports") response = json_response_and_validate_schema(conn, 200) notes = hd(response["reports"])["notes"] @@ -379,7 +379,7 @@ test "it deletes the note", %{conn: conn, report_id: report_id} do assert ReportNote |> Repo.all() |> length() == 2 assert [note, _] = Repo.all(ReportNote) - delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}") + delete(conn, "/api/v1/pleroma/admin/reports/#{report_id}/notes/#{note.id}") assert ReportNote |> Repo.all() |> length() == 1 end diff --git a/test/pleroma/web/admin_api/controllers/status_controller_test.exs b/test/pleroma/web/admin_api/controllers/status_controller_test.exs index 3fdf23ba2..370a4953f 100644 --- a/test/pleroma/web/admin_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/status_controller_test.exs @@ -25,10 +25,10 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do {:ok, %{admin: admin, token: token, conn: conn}} end - describe "GET /api/pleroma/admin/statuses/:id" do + describe "GET /api/v1/pleroma/admin/statuses/:id" do test "not found", %{conn: conn} do assert conn - |> get("/api/pleroma/admin/statuses/not_found") + |> get("/api/v1/pleroma/admin/statuses/not_found") |> json_response_and_validate_schema(:not_found) end @@ -37,7 +37,7 @@ test "shows activity", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/statuses/#{activity.id}") + |> get("/api/v1/pleroma/admin/statuses/#{activity.id}") |> json_response_and_validate_schema(200) assert response["id"] == activity.id @@ -52,7 +52,7 @@ test "shows activity", %{conn: conn} do end end - describe "PUT /api/pleroma/admin/statuses/:id" do + describe "PUT /api/v1/pleroma/admin/statuses/:id" do setup do activity = insert(:note_activity) @@ -63,7 +63,7 @@ test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do response = conn |> put_req_header("content-type", "application/json") - |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"}) + |> put("/api/v1/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"}) |> json_response_and_validate_schema(:ok) assert response["sensitive"] @@ -76,7 +76,7 @@ test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do response = conn |> put_req_header("content-type", "application/json") - |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"}) + |> put("/api/v1/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"}) |> json_response_and_validate_schema(:ok) refute response["sensitive"] @@ -86,7 +86,7 @@ test "change visibility flag", %{conn: conn, id: id, admin: admin} do response = conn |> put_req_header("content-type", "application/json") - |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "public"}) + |> put("/api/v1/pleroma/admin/statuses/#{id}", %{visibility: "public"}) |> json_response_and_validate_schema(:ok) assert response["visibility"] == "public" @@ -99,7 +99,7 @@ test "change visibility flag", %{conn: conn, id: id, admin: admin} do response = conn |> put_req_header("content-type", "application/json") - |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "private"}) + |> put("/api/v1/pleroma/admin/statuses/#{id}", %{visibility: "private"}) |> json_response_and_validate_schema(:ok) assert response["visibility"] == "private" @@ -107,7 +107,7 @@ test "change visibility flag", %{conn: conn, id: id, admin: admin} do response = conn |> put_req_header("content-type", "application/json") - |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "unlisted"}) + |> put("/api/v1/pleroma/admin/statuses/#{id}", %{visibility: "unlisted"}) |> json_response_and_validate_schema(:ok) assert response["visibility"] == "unlisted" @@ -117,14 +117,14 @@ test "returns 400 when visibility is unknown", %{conn: conn, id: id} do conn = conn |> put_req_header("content-type", "application/json") - |> put("/api/pleroma/admin/statuses/#{id}", %{visibility: "test"}) + |> put("/api/v1/pleroma/admin/statuses/#{id}", %{visibility: "test"}) assert %{"error" => "test - Invalid value for enum."} = json_response_and_validate_schema(conn, :bad_request) end end - describe "DELETE /api/pleroma/admin/statuses/:id" do + describe "DELETE /api/v1/pleroma/admin/statuses/:id" do setup do activity = insert(:note_activity) @@ -133,7 +133,7 @@ test "returns 400 when visibility is unknown", %{conn: conn, id: id} do test "deletes status", %{conn: conn, id: id, admin: admin} do conn - |> delete("/api/pleroma/admin/statuses/#{id}") + |> delete("/api/v1/pleroma/admin/statuses/#{id}") |> json_response_and_validate_schema(:ok) refute Activity.get_by_id(id) @@ -145,13 +145,13 @@ test "deletes status", %{conn: conn, id: id, admin: admin} do end test "returns 404 when the status does not exist", %{conn: conn} do - conn = delete(conn, "/api/pleroma/admin/statuses/test") + conn = delete(conn, "/api/v1/pleroma/admin/statuses/test") assert json_response_and_validate_schema(conn, :not_found) == %{"error" => "Not found"} end end - describe "GET /api/pleroma/admin/statuses" do + describe "GET /api/v1/pleroma/admin/statuses" do test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do blocked = insert(:user) user = insert(:user) @@ -166,7 +166,7 @@ test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do response = conn - |> get("/api/pleroma/admin/statuses") + |> get("/api/v1/pleroma/admin/statuses") |> json_response_and_validate_schema(200) refute "private" in Enum.map(response, & &1["visibility"]) @@ -181,7 +181,7 @@ test "returns only local statuses with local_only on", %{conn: conn} do response = conn - |> get("/api/pleroma/admin/statuses?local_only=true") + |> get("/api/v1/pleroma/admin/statuses?local_only=true") |> json_response_and_validate_schema(200) assert length(response) == 1 @@ -194,7 +194,7 @@ test "returns private and direct statuses with godmode on", %{conn: conn, admin: {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "private"}) {:ok, _} = CommonAPI.post(user, %{status: ".", visibility: "public"}) - conn = get(conn, "/api/pleroma/admin/statuses?godmode=true") + conn = get(conn, "/api/v1/pleroma/admin/statuses?godmode=true") assert json_response_and_validate_schema(conn, 200) |> length() == 3 end end diff --git a/test/pleroma/web/admin_api/controllers/user_controller_test.exs b/test/pleroma/web/admin_api/controllers/user_controller_test.exs index b199fa704..68876078d 100644 --- a/test/pleroma/web/admin_api/controllers/user_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/user_controller_test.exs @@ -42,15 +42,16 @@ test "with valid `admin_token` query parameter, skips OAuth scopes check" do user = insert(:user) - conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123") + conn = + get(build_conn(), "/api/v1/pleroma/admin/users/#{user.nickname}?admin_token=password123") assert json_response_and_validate_schema(conn, 200) end - test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope", + test "GET /api/v1/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope", %{admin: admin} do user = insert(:user) - url = "/api/pleroma/admin/users/#{user.nickname}" + url = "/api/v1/pleroma/admin/users/#{user.nickname}" good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"]) good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"]) @@ -91,7 +92,7 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro end end - describe "DELETE /api/pleroma/admin/users" do + describe "DELETE /api/v1/pleroma/admin/users" do test "single user", %{admin: admin, conn: conn} do clear_config([:instance, :federating], true) @@ -120,7 +121,7 @@ test "single user", %{admin: admin, conn: conn} do conn = conn |> put_req_header("accept", "application/json") - |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}") + |> delete("/api/v1/pleroma/admin/users?nickname=#{user.nickname}") ObanHelpers.perform_all() @@ -156,7 +157,7 @@ test "multiple users", %{admin: admin, conn: conn} do conn |> put_req_header("accept", "application/json") |> put_req_header("content-type", "application/json") - |> delete("/api/pleroma/admin/users", %{ + |> delete("/api/v1/pleroma/admin/users", %{ nicknames: [user_one.nickname, user_two.nickname] }) |> json_response_and_validate_schema(200) @@ -170,13 +171,13 @@ test "multiple users", %{admin: admin, conn: conn} do end end - describe "/api/pleroma/admin/users" do + describe "/api/v1/pleroma/admin/users" do test "Create", %{conn: conn} do response = conn |> put_req_header("accept", "application/json") |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users", %{ + |> post("/api/v1/pleroma/admin/users", %{ "users" => [ %{ "nickname" => "lain", @@ -207,7 +208,7 @@ test "Cannot create user with existing email", %{conn: conn} do conn |> put_req_header("accept", "application/json") |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users", %{ + |> post("/api/v1/pleroma/admin/users", %{ "users" => [ %{ "nickname" => "lain", @@ -237,7 +238,7 @@ test "Cannot create user with existing nickname", %{conn: conn} do conn |> put_req_header("accept", "application/json") |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users", %{ + |> post("/api/v1/pleroma/admin/users", %{ "users" => [ %{ "nickname" => user.nickname, @@ -267,7 +268,7 @@ test "Multiple user creation works in transaction", %{conn: conn} do conn |> put_req_header("accept", "application/json") |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users", %{ + |> post("/api/v1/pleroma/admin/users", %{ "users" => [ %{ "nickname" => "newuser", @@ -307,11 +308,11 @@ test "Multiple user creation works in transaction", %{conn: conn} do end end - describe "/api/pleroma/admin/users/:nickname" do + describe "/api/v1/pleroma/admin/users/:nickname" do test "Show", %{conn: conn} do user = insert(:user) - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") + conn = get(conn, "/api/v1/pleroma/admin/users/#{user.nickname}") assert user_response(user) == json_response_and_validate_schema(conn, 200) end @@ -319,13 +320,13 @@ test "Show", %{conn: conn} do test "when the user doesn't exist", %{conn: conn} do user = build(:user) - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") + conn = get(conn, "/api/v1/pleroma/admin/users/#{user.nickname}") assert %{"error" => "Not found"} == json_response_and_validate_schema(conn, 404) end end - describe "/api/pleroma/admin/users/follow" do + describe "/api/v1/pleroma/admin/users/follow" do test "allows to force-follow another user", %{admin: admin, conn: conn} do user = insert(:user) follower = insert(:user) @@ -333,7 +334,7 @@ test "allows to force-follow another user", %{admin: admin, conn: conn} do conn |> put_req_header("accept", "application/json") |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/follow", %{ + |> post("/api/v1/pleroma/admin/users/follow", %{ "follower" => follower.nickname, "followed" => user.nickname }) @@ -350,7 +351,7 @@ test "allows to force-follow another user", %{admin: admin, conn: conn} do end end - describe "/api/pleroma/admin/users/unfollow" do + describe "/api/v1/pleroma/admin/users/unfollow" do test "allows to force-unfollow another user", %{admin: admin, conn: conn} do user = insert(:user) follower = insert(:user) @@ -360,7 +361,7 @@ test "allows to force-unfollow another user", %{admin: admin, conn: conn} do conn |> put_req_header("accept", "application/json") |> put_req_header("content-type", "application/json") - |> post("/api/pleroma/admin/users/unfollow", %{ + |> post("/api/v1/pleroma/admin/users/unfollow", %{ "follower" => follower.nickname, "followed" => user.nickname }) @@ -377,12 +378,12 @@ test "allows to force-unfollow another user", %{admin: admin, conn: conn} do end end - describe "GET /api/pleroma/admin/users" do + describe "GET /api/v1/pleroma/admin/users" do test "renders users array for the first page", %{conn: conn, admin: admin} do user = insert(:user, local: false, tags: ["foo", "bar"]) user2 = insert(:user, is_approved: false, registration_reason: "I'm a chill dude") - conn = get(conn, "/api/pleroma/admin/users?page=1") + conn = get(conn, "/api/v1/pleroma/admin/users?page=1") users = [ user_response( @@ -415,7 +416,7 @@ test "pagination works correctly with service users", %{conn: conn} do assert %{"count" => 26, "page_size" => 10, "users" => users1} = conn - |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"}) + |> get("/api/v1/pleroma/admin/users?page=1&filters=", %{page_size: "10"}) |> json_response_and_validate_schema(200) assert Enum.count(users1) == 10 @@ -423,7 +424,7 @@ test "pagination works correctly with service users", %{conn: conn} do assert %{"count" => 26, "page_size" => 10, "users" => users2} = conn - |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"}) + |> get("/api/v1/pleroma/admin/users?page=2&filters=", %{page_size: "10"}) |> json_response_and_validate_schema(200) assert Enum.count(users2) == 10 @@ -431,7 +432,7 @@ test "pagination works correctly with service users", %{conn: conn} do assert %{"count" => 26, "page_size" => 10, "users" => users3} = conn - |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"}) + |> get("/api/v1/pleroma/admin/users?page=3&filters=", %{page_size: "10"}) |> json_response_and_validate_schema(200) assert Enum.count(users3) == 6 @@ -441,7 +442,7 @@ test "pagination works correctly with service users", %{conn: conn} do test "renders empty array for the second page", %{conn: conn} do insert(:user) - conn = get(conn, "/api/pleroma/admin/users?page=2") + conn = get(conn, "/api/v1/pleroma/admin/users?page=2") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 2, @@ -453,7 +454,7 @@ test "renders empty array for the second page", %{conn: conn} do test "regular search", %{conn: conn} do user = insert(:user, nickname: "bob") - conn = get(conn, "/api/pleroma/admin/users?query=bo") + conn = get(conn, "/api/v1/pleroma/admin/users?query=bo") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -466,7 +467,7 @@ test "search by domain", %{conn: conn} do user = insert(:user, nickname: "nickname@domain.com") insert(:user) - conn = get(conn, "/api/pleroma/admin/users?query=domain.com") + conn = get(conn, "/api/v1/pleroma/admin/users?query=domain.com") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -479,7 +480,7 @@ test "search by full nickname", %{conn: conn} do user = insert(:user, nickname: "nickname@domain.com") insert(:user) - conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com") + conn = get(conn, "/api/v1/pleroma/admin/users?query=nickname@domain.com") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -492,7 +493,7 @@ test "search by display name", %{conn: conn} do user = insert(:user, name: "Display name") insert(:user) - conn = get(conn, "/api/pleroma/admin/users?name=display") + conn = get(conn, "/api/v1/pleroma/admin/users?name=display") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -505,7 +506,7 @@ test "search by email", %{conn: conn} do user = insert(:user, email: "email@example.com") insert(:user) - conn = get(conn, "/api/pleroma/admin/users?email=email@example.com") + conn = get(conn, "/api/v1/pleroma/admin/users?email=email@example.com") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -518,7 +519,7 @@ test "regular search with page size", %{conn: conn} do user = insert(:user, nickname: "aalice") user2 = insert(:user, nickname: "alice") - conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1") + conn1 = get(conn, "/api/v1/pleroma/admin/users?query=a&page_size=1&page=1") assert json_response_and_validate_schema(conn1, 200) == %{ "count" => 2, @@ -526,7 +527,7 @@ test "regular search with page size", %{conn: conn} do "users" => [user_response(user2)] } - conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2") + conn2 = get(conn, "/api/v1/pleroma/admin/users?query=a&page_size=1&page=2") assert json_response_and_validate_schema(conn2, 200) == %{ "count" => 2, @@ -546,7 +547,7 @@ test "only local users" do build_conn() |> assign(:user, admin) |> assign(:token, token) - |> get("/api/pleroma/admin/users?query=bo&filters=local") + |> get("/api/v1/pleroma/admin/users?query=bo&filters=local") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -561,7 +562,7 @@ test "only local users with no query", %{conn: conn, admin: old_admin} do insert(:user, nickname: "bobb", local: false) - conn = get(conn, "/api/pleroma/admin/users?filters=local") + conn = get(conn, "/api/v1/pleroma/admin/users?filters=local") users = [ user_response(user), @@ -590,7 +591,7 @@ test "only unconfirmed users", %{conn: conn} do result = conn - |> get("/api/pleroma/admin/users?filters=unconfirmed") + |> get("/api/v1/pleroma/admin/users?filters=unconfirmed") |> json_response_and_validate_schema(200) users = @@ -614,7 +615,7 @@ test "only unapproved users", %{conn: conn} do insert(:user, nickname: "happyboy", is_approved: true) - conn = get(conn, "/api/pleroma/admin/users?filters=need_approval") + conn = get(conn, "/api/v1/pleroma/admin/users?filters=need_approval") users = [ user_response( @@ -635,7 +636,7 @@ test "load only admins", %{conn: conn, admin: admin} do insert(:user) insert(:user) - conn = get(conn, "/api/pleroma/admin/users?filters=is_admin") + conn = get(conn, "/api/v1/pleroma/admin/users?filters=is_admin") users = [ user_response(second_admin, %{ @@ -660,7 +661,7 @@ test "load only moderators", %{conn: conn} do insert(:user) insert(:user) - conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator") + conn = get(conn, "/api/v1/pleroma/admin/users?filters=is_moderator") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -739,7 +740,7 @@ test "load users with tags list", %{conn: conn} do insert(:user) insert(:user) - conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second") + conn = get(conn, "/api/v1/pleroma/admin/users?tags[]=first&tags[]=second") users = [ user_response(user2, %{"tags" => ["second"]}), @@ -762,7 +763,7 @@ test "`active` filters out users pending approval", %{token: token} do build_conn() |> assign(:user, token.user) |> assign(:token, token) - |> get("/api/pleroma/admin/users?filters=active") + |> get("/api/v1/pleroma/admin/users?filters=active") assert %{ "count" => 2, @@ -786,7 +787,7 @@ test "it works with multiple filters" do build_conn() |> assign(:user, admin) |> assign(:token, token) - |> get("/api/pleroma/admin/users?filters=deactivated,external") + |> get("/api/v1/pleroma/admin/users?filters=deactivated,external") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -798,7 +799,7 @@ test "it works with multiple filters" do test "it omits relay user", %{admin: admin, conn: conn} do assert %User{} = Relay.get_actor() - conn = get(conn, "/api/pleroma/admin/users") + conn = get(conn, "/api/v1/pleroma/admin/users") assert json_response_and_validate_schema(conn, 200) == %{ "count" => 1, @@ -810,7 +811,7 @@ test "it omits relay user", %{admin: admin, conn: conn} do end end - test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do + test "PATCH /api/v1/pleroma/admin/users/activate", %{admin: admin, conn: conn} do user_one = insert(:user, is_active: false) user_two = insert(:user, is_active: false) @@ -818,7 +819,7 @@ test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do conn |> put_req_header("content-type", "application/json") |> patch( - "/api/pleroma/admin/users/activate", + "/api/v1/pleroma/admin/users/activate", %{nicknames: [user_one.nickname, user_two.nickname]} ) @@ -831,7 +832,7 @@ test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}" end - test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do + test "PATCH /api/v1/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do user_one = insert(:user, is_active: true) user_two = insert(:user, is_active: true) @@ -839,7 +840,7 @@ test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do conn |> put_req_header("content-type", "application/json") |> patch( - "/api/pleroma/admin/users/deactivate", + "/api/v1/pleroma/admin/users/deactivate", %{nicknames: [user_one.nickname, user_two.nickname]} ) @@ -852,7 +853,7 @@ test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}" end - test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do + test "PATCH /api/v1/pleroma/admin/users/approve", %{admin: admin, conn: conn} do user_one = insert(:user, is_approved: false) user_two = insert(:user, is_approved: false) @@ -860,7 +861,7 @@ test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do conn |> put_req_header("content-type", "application/json") |> patch( - "/api/pleroma/admin/users/approve", + "/api/v1/pleroma/admin/users/approve", %{nicknames: [user_one.nickname, user_two.nickname]} ) @@ -873,7 +874,7 @@ test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do "@#{admin.nickname} approved users: @#{user_one.nickname}, @#{user_two.nickname}" end - test "PATCH /api/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do + test "PATCH /api/v1/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do user1 = insert(:user, is_suggested: false) user2 = insert(:user, is_suggested: false) @@ -881,7 +882,7 @@ test "PATCH /api/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do conn |> put_req_header("content-type", "application/json") |> patch( - "/api/pleroma/admin/users/suggest", + "/api/v1/pleroma/admin/users/suggest", %{nicknames: [user1.nickname, user2.nickname]} ) |> json_response_and_validate_schema(200) @@ -898,7 +899,7 @@ test "PATCH /api/pleroma/admin/users/suggest", %{admin: admin, conn: conn} do "@#{admin.nickname} added suggested users: @#{user1.nickname}, @#{user2.nickname}" end - test "PATCH /api/pleroma/admin/users/unsuggest", %{admin: admin, conn: conn} do + test "PATCH /api/v1/pleroma/admin/users/unsuggest", %{admin: admin, conn: conn} do user1 = insert(:user, is_suggested: true) user2 = insert(:user, is_suggested: true) @@ -906,7 +907,7 @@ test "PATCH /api/pleroma/admin/users/unsuggest", %{admin: admin, conn: conn} do conn |> put_req_header("content-type", "application/json") |> patch( - "/api/pleroma/admin/users/unsuggest", + "/api/v1/pleroma/admin/users/unsuggest", %{nicknames: [user1.nickname, user2.nickname]} ) |> json_response_and_validate_schema(200) @@ -923,13 +924,16 @@ test "PATCH /api/pleroma/admin/users/unsuggest", %{admin: admin, conn: conn} do "@#{admin.nickname} removed suggested users: @#{user1.nickname}, @#{user2.nickname}" end - test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do + test "PATCH /api/v1/pleroma/admin/users/:nickname/toggle_activation", %{ + admin: admin, + conn: conn + } do user = insert(:user) conn = conn |> put_req_header("content-type", "application/json") - |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation") + |> patch("/api/v1/pleroma/admin/users/#{user.nickname}/toggle_activation") assert json_response_and_validate_schema(conn, 200) == user_response( diff --git a/test/pleroma/web/fallback_test.exs b/test/pleroma/web/fallback_test.exs index 512baf813..cf573cd00 100644 --- a/test/pleroma/web/fallback_test.exs +++ b/test/pleroma/web/fallback_test.exs @@ -72,12 +72,6 @@ test "GET /main/all", %{conn: conn} do end end - test "GET /api*path", %{conn: conn} do - assert conn - |> get("/api/foo") - |> json_response(404) == %{"error" => "Not implemented"} - end - test "GET /pleroma/admin -> /pleroma/admin/", %{conn: conn} do assert redirected_to(get(conn, "/pleroma/admin")) =~ "/pleroma/admin/" 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 cda4c9e03..d76db0c0d 100644 --- a/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/status_controller_test.exs @@ -38,7 +38,7 @@ test "posting a status does not increment reblog_count when relaying", %{conn: c response = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{ + |> post("/api/v1/statuses", %{ "content_type" => "text/plain", "source" => "Pleroma FE", "status" => "Hello world", @@ -51,7 +51,7 @@ test "posting a status does not increment reblog_count when relaying", %{conn: c response = conn - |> get("api/v1/statuses/#{response["id"]}", %{}) + |> get("/api/v1/statuses/#{response["id"]}", %{}) |> json_response_and_validate_schema(200) assert response["reblogs_count"] == 0 @@ -110,7 +110,7 @@ test "posting a status", %{conn: conn} do conn_four = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{ + |> post("/api/v1/statuses", %{ "status" => "oolong", "expires_in" => expires_in }) @@ -133,7 +133,7 @@ test "automatically setting a post expiry if status_ttl_days is set" do conn = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{ + |> post("/api/v1/statuses", %{ "status" => "aa chikichiki banban" }) @@ -164,7 +164,7 @@ test "it fails to create a status if `expires_in` is less or equal than an hour" assert %{"error" => "Expiry date is too soon"} = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{ + |> post("/api/v1/statuses", %{ "status" => "oolong", "expires_in" => expires_in }) @@ -176,7 +176,7 @@ test "it fails to create a status if `expires_in` is less or equal than an hour" assert %{"error" => "Expiry date is too soon"} = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{ + |> post("/api/v1/statuses", %{ "status" => "oolong", "expires_in" => expires_in }) @@ -190,7 +190,7 @@ test "Get MRF reason when posting a status is rejected by one", %{conn: conn} do assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{"status" => "GNO/Linux"}) + |> post("/api/v1/statuses", %{"status" => "GNO/Linux"}) |> json_response_and_validate_schema(422) end @@ -383,7 +383,7 @@ test "posting a direct status", %{conn: conn} do conn = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"}) + |> post("/api/v1/statuses", %{"status" => content, "visibility" => "direct"}) assert %{"id" => id} = response = json_response_and_validate_schema(conn, 200) assert response["visibility"] == "direct" @@ -420,7 +420,7 @@ test "discloses application metadata when enabled" do result = conn - |> get("api/v1/statuses/#{activity}") + |> get("/api/v1/statuses/#{activity}") assert %{ "content" => "cofe is my copilot", @@ -449,7 +449,7 @@ test "hides application metadata when disabled" do result = conn - |> get("api/v1/statuses/#{activity}") + |> get("/api/v1/statuses/#{activity}") assert %{ "content" => "club mate is my wingman", @@ -1342,7 +1342,7 @@ test "on pin removes deletion job, on unpin reschedule deletion" do assert %{"id" => id} = conn |> put_req_header("content-type", "application/json") - |> post("api/v1/statuses", %{ + |> post("/api/v1/statuses", %{ "status" => "oolong", "expires_in" => expires_in }) @@ -1511,7 +1511,7 @@ test "Repeated posts that are replies incorrectly have in_reply_to_id null", %{c conn |> assign(:user, user3) |> assign(:token, insert(:oauth_token, user: user3, scopes: ["read:statuses"])) - |> get("api/v1/timelines/home") + |> get("/api/v1/timelines/home") [reblogged_activity] = json_response_and_validate_schema(conn3, 200) diff --git a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs index f609db7a4..aa9006681 100644 --- a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs @@ -288,7 +288,7 @@ test "doesn't return posts from users who blocked you when :blockers_visible is get(conn, "/api/v1/timelines/public") |> json_response_and_validate_schema(200) - assert length(response) == 0 + assert response == [] end test "doesn't return replies if follow is posting with users from blocked domain" do @@ -527,7 +527,7 @@ test "direct timeline", %{conn: conn} do |> assign(:token, insert(:oauth_token, user: user_two, scopes: ["read:statuses"])) # Only direct should be visible here - res_conn = get(conn_user_two, "api/v1/timelines/direct") + res_conn = get(conn_user_two, "/api/v1/timelines/direct") assert [status] = json_response_and_validate_schema(res_conn, :ok) @@ -539,14 +539,14 @@ test "direct timeline", %{conn: conn} do build_conn() |> assign(:user, user_one) |> assign(:token, insert(:oauth_token, user: user_one, scopes: ["read:statuses"])) - |> get("api/v1/timelines/direct") + |> get("/api/v1/timelines/direct") [status] = json_response_and_validate_schema(res_conn, :ok) assert %{"visibility" => "direct"} = status # Both should be visible here - res_conn = get(conn_user_two, "api/v1/timelines/home") + res_conn = get(conn_user_two, "/api/v1/timelines/home") [_s1, _s2] = json_response_and_validate_schema(res_conn, :ok) @@ -559,14 +559,14 @@ test "direct timeline", %{conn: conn} do }) end) - res_conn = get(conn_user_two, "api/v1/timelines/direct") + res_conn = get(conn_user_two, "/api/v1/timelines/direct") statuses = json_response_and_validate_schema(res_conn, :ok) assert length(statuses) == 20 max_id = List.last(statuses)["id"] - res_conn = get(conn_user_two, "api/v1/timelines/direct?max_id=#{max_id}") + res_conn = get(conn_user_two, "/api/v1/timelines/direct?max_id=#{max_id}") assert [status] = json_response_and_validate_schema(res_conn, :ok) @@ -591,7 +591,7 @@ test "doesn't include DMs from blocked users" do visibility: "direct" }) - res_conn = get(conn, "api/v1/timelines/direct") + res_conn = get(conn, "/api/v1/timelines/direct") [status] = json_response_and_validate_schema(res_conn, :ok) assert status["id"] == direct.id diff --git a/test/pleroma/web/mastodon_api/update_credentials_test.exs b/test/pleroma/web/mastodon_api/update_credentials_test.exs index 130cbe8d1..2ba909dad 100644 --- a/test/pleroma/web/mastodon_api/update_credentials_test.exs +++ b/test/pleroma/web/mastodon_api/update_credentials_test.exs @@ -388,7 +388,7 @@ test "updates the user's background, upload_limit, returns a HTTP 413", %{ "pleroma_background_image" => new_background_oversized }) - assert user_response = json_response_and_validate_schema(res, 413) + assert json_response_and_validate_schema(res, 413) assert user.background == %{} clear_config([:instance, :upload_limit], upload_limit) @@ -439,13 +439,13 @@ test "updates profile emojos", %{user: user, conn: conn} do test "update fields", %{conn: conn} do fields = [ - %{"name" => "foo", "value" => ""}, - %{"name" => "link.io", "value" => "cofe.io"} + %{name: "foo", value: ""}, + %{name: "link.io", value: "cofe.io"} ] account_data = conn - |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) + |> patch("/api/v1/accounts/update_credentials", %{fields_attributes: fields}) |> json_response_and_validate_schema(200) assert account_data["fields"] == [ @@ -467,13 +467,13 @@ test "update fields", %{conn: conn} do test "emojis in fields labels", %{conn: conn} do fields = [ - %{"name" => ":firefox:", "value" => "is best 2hu"}, - %{"name" => "they wins", "value" => ":blank:"} + %{name: ":firefox:", value: "is best 2hu"}, + %{name: "they wins", value: ":blank:"} ] account_data = conn - |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) + |> patch("/api/v1/accounts/update_credentials", %{fields_attributes: fields}) |> json_response_and_validate_schema(200) assert account_data["fields"] == [ @@ -521,13 +521,13 @@ test "update fields via x-www-form-urlencoded", %{conn: conn} do test "update fields with empty name", %{conn: conn} do fields = [ - %{"name" => "foo", "value" => ""}, - %{"name" => "", "value" => "bar"} + %{name: "foo", value: ""}, + %{name: "", value: "bar"} ] account = conn - |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) + |> patch("/api/v1/accounts/update_credentials", %{fields_attributes: fields}) |> json_response_and_validate_schema(200) assert account["fields"] == [ @@ -542,30 +542,30 @@ test "update fields when invalid request", %{conn: conn} do long_name = Enum.map(0..name_limit, fn _ -> "x" end) |> Enum.join() long_value = Enum.map(0..value_limit, fn _ -> "x" end) |> Enum.join() - fields = [%{"name" => "foo", "value" => long_value}] + fields = [%{name: "foo", value: long_value}] assert %{"error" => "Invalid request"} == conn - |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) + |> patch("/api/v1/accounts/update_credentials", %{fields_attributes: fields}) |> json_response_and_validate_schema(403) - fields = [%{"name" => long_name, "value" => "bar"}] + fields = [%{name: long_name, value: "bar"}] assert %{"error" => "Invalid request"} == conn - |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) + |> patch("/api/v1/accounts/update_credentials", %{fields_attributes: fields}) |> json_response_and_validate_schema(403) clear_config([:instance, :max_account_fields], 1) fields = [ - %{"name" => "foo", "value" => "bar"}, + %{name: "foo", value: "bar"}, %{"name" => "link", "value" => "cofe.io"} ] assert %{"error" => "Invalid request"} == conn - |> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields}) + |> patch("/api/v1/accounts/update_credentials", %{fields_attributes: fields}) |> json_response_and_validate_schema(403) end end diff --git a/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs index ad271c31b..89a2cf634 100644 --- a/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/account_controller_test.exs @@ -133,7 +133,7 @@ test "returns favorited DM only when user is logged in and he is one of recipien |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") |> json_response_and_validate_schema(200) - assert length(response) == 0 + assert response == [] end test "does not return others' favorited DM when user is not one of recipients", %{ diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs index 61a44b8ba..0d3d38b33 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_file_controller_test.exs @@ -28,7 +28,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileControllerTest do {:ok, %{admin_conn: admin_conn}} end - describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/files?name=:name" do + describe "POST/PATCH/DELETE /api/v1/pleroma/emoji/packs/files?name=:name" do setup do pack_file = "#{@emoji_path}/test_pack/pack.json" original_content = File.read!(pack_file) @@ -55,7 +55,7 @@ test "upload zip file with emojies", %{admin_conn: admin_conn} do resp = admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ file: %Plug.Upload{ content_type: "application/zip", filename: "emojis.zip", @@ -82,7 +82,7 @@ test "upload zip file with emojies", %{admin_conn: admin_conn} do test "create shortcode exists", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank", filename: "dir/blank.png", file: %Plug.Upload{ @@ -100,7 +100,7 @@ test "don't rewrite old emoji", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", filename: "dir/blank.png", file: %Plug.Upload{ @@ -118,7 +118,7 @@ test "don't rewrite old emoji", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> patch("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank", new_shortcode: "blank2", new_filename: "dir_2/blank_3.png" @@ -134,7 +134,7 @@ test "rewrite old emoji with force option", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", filename: "dir/blank.png", file: %Plug.Upload{ @@ -152,7 +152,7 @@ test "rewrite old emoji with force option", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> patch("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", new_shortcode: "blank4", new_filename: "dir_2/blank_3.png", @@ -170,7 +170,7 @@ test "rewrite old emoji with force option", %{admin_conn: admin_conn} do test "with empty filename", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank2", filename: "", file: %Plug.Upload{ @@ -186,7 +186,7 @@ test "with empty filename", %{admin_conn: admin_conn} do test "add file with not loaded pack", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=not_loaded", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=not_loaded", %{ shortcode: "blank3", filename: "dir/blank.png", file: %Plug.Upload{ @@ -209,7 +209,7 @@ test "returns an error on add file when file system is not writable", %{ ]) do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=not_loaded", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=not_loaded", %{ shortcode: "blank3", filename: "dir/blank.png", file: %Plug.Upload{ @@ -226,7 +226,7 @@ test "returns an error on add file when file system is not writable", %{ test "remove file with not loaded pack", %{admin_conn: admin_conn} do assert admin_conn - |> delete("/api/pleroma/emoji/packs/files?name=not_loaded&shortcode=blank3") + |> delete("/api/v1/pleroma/emoji/packs/files?name=not_loaded&shortcode=blank3") |> json_response_and_validate_schema(:not_found) == %{ "error" => "pack \"not_loaded\" is not found" } @@ -234,7 +234,7 @@ test "remove file with not loaded pack", %{admin_conn: admin_conn} do test "remove file with empty shortcode", %{admin_conn: admin_conn} do assert admin_conn - |> delete("/api/pleroma/emoji/packs/files?name=not_loaded&shortcode=") + |> delete("/api/v1/pleroma/emoji/packs/files?name=not_loaded&shortcode=") |> json_response_and_validate_schema(:not_found) == %{ "error" => "pack \"not_loaded\" is not found" } @@ -243,7 +243,7 @@ test "remove file with empty shortcode", %{admin_conn: admin_conn} do test "update file with not loaded pack", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/packs/files?name=not_loaded", %{ + |> patch("/api/v1/pleroma/emoji/packs/files?name=not_loaded", %{ shortcode: "blank4", new_shortcode: "blank3", new_filename: "dir_2/blank_3.png" @@ -256,7 +256,7 @@ test "update file with not loaded pack", %{admin_conn: admin_conn} do test "new with shortcode as file with update", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank4", filename: "dir/blank.png", file: %Plug.Upload{ @@ -274,7 +274,7 @@ test "new with shortcode as file with update", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> patch("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank4", new_shortcode: "blank3", new_filename: "dir_2/blank_3.png" @@ -289,7 +289,7 @@ test "new with shortcode as file with update", %{admin_conn: admin_conn} do assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png") assert admin_conn - |> delete("/api/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") + |> delete("/api/v1/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") |> json_response_and_validate_schema(200) == %{ "blank" => "blank.png", "blank2" => "blank2.png" @@ -311,7 +311,7 @@ test "new with shortcode from url", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank_url", file: "https://test-blank/blank_url.png" }) @@ -331,7 +331,7 @@ test "new without shortcode", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> post("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ file: %Plug.Upload{ filename: "shortcode.png", path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png" @@ -346,7 +346,7 @@ test "new without shortcode", %{admin_conn: admin_conn} do test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do assert admin_conn - |> delete("/api/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") + |> delete("/api/v1/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "Emoji \"blank3\" does not exist" } @@ -355,7 +355,7 @@ test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do test "update non existing emoji", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> patch("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", new_shortcode: "blank4", new_filename: "dir_2/blank_3.png" @@ -371,7 +371,7 @@ test "update with empty shortcode", %{admin_conn: admin_conn} do } = admin_conn |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ + |> patch("/api/v1/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank", new_filename: "dir_2/blank_3.png" }) diff --git a/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs index d1ba067b8..b86418196 100644 --- a/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/emoji_pack_controller_test.exs @@ -29,13 +29,16 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do {:ok, %{admin_conn: admin_conn}} end - test "GET /api/pleroma/emoji/packs when :public: false", %{conn: conn} do + test "GET /api/v1/pleroma/emoji/packs when :public: false", %{conn: conn} do clear_config([:instance, :public], false) - conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200) + conn |> get("/api/v1/pleroma/emoji/packs") |> json_response_and_validate_schema(200) end - test "GET /api/pleroma/emoji/packs", %{conn: conn} do - resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200) + test "GET /api/v1/pleroma/emoji/packs", %{conn: conn} do + resp = + conn + |> get("/api/v1/pleroma/emoji/packs") + |> json_response_and_validate_schema(200) assert resp["count"] == 4 @@ -55,7 +58,7 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs?page_size=1") + |> get("/api/v1/pleroma/emoji/packs?page_size=1") |> json_response_and_validate_schema(200) assert resp["count"] == 4 @@ -68,7 +71,7 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs?page_size=1&page=2") + |> get("/api/v1/pleroma/emoji/packs?page_size=1&page=2") |> json_response_and_validate_schema(200) assert resp["count"] == 4 @@ -78,7 +81,7 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs?page_size=1&page=3") + |> get("/api/v1/pleroma/emoji/packs?page_size=1&page=3") |> json_response_and_validate_schema(200) assert resp["count"] == 4 @@ -88,7 +91,7 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs?page_size=1&page=4") + |> get("/api/v1/pleroma/emoji/packs?page_size=1&page=4") |> json_response_and_validate_schema(200) assert resp["count"] == 4 @@ -98,11 +101,11 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do assert [pack1, pack2, pack3, pack4] |> Enum.uniq() |> length() == 4 end - describe "GET /api/pleroma/emoji/packs/remote" do + describe "GET /api/v1/pleroma/emoji/packs/remote" do test "shareable instance", %{admin_conn: admin_conn, conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs?page=2&page_size=1") + |> get("/api/v1/pleroma/emoji/packs?page=2&page_size=1") |> json_response_and_validate_schema(200) mock(fn @@ -112,12 +115,17 @@ test "shareable instance", %{admin_conn: admin_conn, conn: conn} do %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} -> json(%{metadata: %{features: ["shareable_emoji_packs"]}}) - %{method: :get, url: "https://example.com/api/pleroma/emoji/packs?page=2&page_size=1"} -> + %{ + method: :get, + url: "https://example.com/api/v1/pleroma/emoji/packs?page=2&page_size=1" + } -> json(resp) end) assert admin_conn - |> get("/api/pleroma/emoji/packs/remote?url=https://example.com&page=2&page_size=1") + |> get( + "/api/v1/pleroma/emoji/packs/remote?url=https://example.com&page=2&page_size=1" + ) |> json_response_and_validate_schema(200) == resp end @@ -131,18 +139,18 @@ test "non shareable instance", %{admin_conn: admin_conn} do end) assert admin_conn - |> get("/api/pleroma/emoji/packs/remote?url=https://example.com") + |> get("/api/v1/pleroma/emoji/packs/remote?url=https://example.com") |> json_response_and_validate_schema(500) == %{ "error" => "The requested instance does not support sharing emoji packs" } end end - describe "GET /api/pleroma/emoji/packs/archive?name=:name" do + describe "GET /api/v1/pleroma/emoji/packs/archive?name=:name" do test "download shared pack", %{conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs/archive?name=test_pack") + |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack") |> response(200) {:ok, arch} = :zip.unzip(resp, [:memory]) @@ -153,7 +161,7 @@ test "download shared pack", %{conn: conn} do test "non existing pack", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/packs/archive?name=test_pack_for_import") + |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack_for_import") |> json_response_and_validate_schema(:not_found) == %{ "error" => "Pack test_pack_for_import does not exist" } @@ -161,7 +169,7 @@ test "non existing pack", %{conn: conn} do test "non downloadable pack", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/packs/archive?name=test_pack_nonshared") + |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack_nonshared") |> json_response_and_validate_schema(:forbidden) == %{ "error" => "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing" @@ -169,7 +177,7 @@ test "non downloadable pack", %{conn: conn} do end end - describe "POST /api/pleroma/emoji/packs/download" do + describe "POST /api/v1/pleroma/emoji/packs/download" do test "shared pack from remote and non shared from fallback-src", %{ admin_conn: admin_conn, conn: conn @@ -183,28 +191,28 @@ test "shared pack from remote and non shared from fallback-src", %{ %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=test_pack" + url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack" } -> conn - |> get("/api/pleroma/emoji/pack?name=test_pack") + |> get("/api/v1/pleroma/emoji/pack?name=test_pack") |> json_response_and_validate_schema(200) |> json() %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/archive?name=test_pack" + url: "https://example.com/api/v1/pleroma/emoji/packs/archive?name=test_pack" } -> conn - |> get("/api/pleroma/emoji/packs/archive?name=test_pack") + |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack") |> response(200) |> text() %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=test_pack_nonshared" + url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack_nonshared" } -> conn - |> get("/api/pleroma/emoji/pack?name=test_pack_nonshared") + |> get("/api/v1/pleroma/emoji/pack?name=test_pack_nonshared") |> json_response_and_validate_schema(200) |> json() @@ -217,7 +225,7 @@ test "shared pack from remote and non shared from fallback-src", %{ assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/download", %{ + |> post("/api/v1/pleroma/emoji/packs/download", %{ url: "https://example.com", name: "test_pack", as: "test_pack2" @@ -228,7 +236,7 @@ test "shared pack from remote and non shared from fallback-src", %{ assert File.exists?("#{@emoji_path}/test_pack2/blank.png") assert admin_conn - |> delete("/api/pleroma/emoji/pack?name=test_pack2") + |> delete("/api/v1/pleroma/emoji/pack?name=test_pack2") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_pack2") @@ -236,7 +244,7 @@ test "shared pack from remote and non shared from fallback-src", %{ assert admin_conn |> put_req_header("content-type", "multipart/form-data") |> post( - "/api/pleroma/emoji/packs/download", + "/api/v1/pleroma/emoji/packs/download", %{ url: "https://example.com", name: "test_pack_nonshared", @@ -249,7 +257,7 @@ test "shared pack from remote and non shared from fallback-src", %{ assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png") assert admin_conn - |> delete("/api/pleroma/emoji/pack?name=test_pack_nonshared2") + |> delete("/api/v1/pleroma/emoji/pack?name=test_pack_nonshared2") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_pack_nonshared2") @@ -267,7 +275,7 @@ test "nonshareable instance", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") |> post( - "/api/pleroma/emoji/packs/download", + "/api/v1/pleroma/emoji/packs/download", %{ url: "https://old-instance", name: "test_pack", @@ -289,14 +297,14 @@ test "checksum fail", %{admin_conn: admin_conn} do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=pack_bad_sha" + url: "https://example.com/api/v1/pleroma/emoji/pack?name=pack_bad_sha" } -> {:ok, pack} = Pleroma.Emoji.Pack.load_pack("pack_bad_sha") %Tesla.Env{status: 200, body: Jason.encode!(pack)} %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/archive?name=pack_bad_sha" + url: "https://example.com/api/v1/pleroma/emoji/packs/archive?name=pack_bad_sha" } -> %Tesla.Env{ status: 200, @@ -306,7 +314,7 @@ test "checksum fail", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/download", %{ + |> post("/api/v1/pleroma/emoji/packs/download", %{ url: "https://example.com", name: "pack_bad_sha", as: "pack_bad_sha2" @@ -326,7 +334,7 @@ test "other error", %{admin_conn: admin_conn} do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/pack?name=test_pack" + url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack" } -> {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack") %Tesla.Env{status: 200, body: Jason.encode!(pack)} @@ -334,7 +342,7 @@ test "other error", %{admin_conn: admin_conn} do assert admin_conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/emoji/packs/download", %{ + |> post("/api/v1/pleroma/emoji/packs/download", %{ url: "https://example.com", name: "test_pack", as: "test_pack2" @@ -346,7 +354,7 @@ test "other error", %{admin_conn: admin_conn} do end end - describe "PATCH/update /api/pleroma/emoji/pack?name=:name" do + describe "PATCH/update /api/v1/pleroma/emoji/pack?name=:name" do setup do pack_file = "#{@emoji_path}/test_pack/pack.json" original_content = File.read!(pack_file) @@ -372,7 +380,7 @@ test "returns error when file system not writable", %{admin_conn: conn} = ctx do assert conn |> put_req_header("content-type", "multipart/form-data") |> patch( - "/api/pleroma/emoji/pack?name=test_pack", + "/api/v1/pleroma/emoji/pack?name=test_pack", %{"metadata" => ctx[:new_data]} ) |> json_response_and_validate_schema(500) @@ -382,7 +390,7 @@ test "returns error when file system not writable", %{admin_conn: conn} = ctx do test "for a pack without a fallback source", ctx do assert ctx[:admin_conn] |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/pack?name=test_pack", %{ + |> patch("/api/v1/pleroma/emoji/pack?name=test_pack", %{ "metadata" => ctx[:new_data] }) |> json_response_and_validate_schema(200) == ctx[:new_data] @@ -410,7 +418,7 @@ test "for a pack with a fallback source", ctx do assert ctx[:admin_conn] |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/pack?name=test_pack", %{metadata: new_data}) + |> patch("/api/v1/pleroma/emoji/pack?name=test_pack", %{metadata: new_data}) |> json_response_and_validate_schema(200) == new_data_with_sha assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha @@ -430,14 +438,14 @@ test "when the fallback source doesn't have all the files", ctx do assert ctx[:admin_conn] |> put_req_header("content-type", "multipart/form-data") - |> patch("/api/pleroma/emoji/pack?name=test_pack", %{metadata: new_data}) + |> patch("/api/v1/pleroma/emoji/pack?name=test_pack", %{metadata: new_data}) |> json_response_and_validate_schema(:bad_request) == %{ "error" => "The fallback archive does not have all files specified in pack.json" } end end - describe "POST/DELETE /api/pleroma/emoji/pack?name=:name" do + describe "POST/DELETE /api/v1/pleroma/emoji/pack?name=:name" do test "returns an error on creates pack when file system not writable", %{ admin_conn: admin_conn } do @@ -447,7 +455,7 @@ test "returns an error on creates pack when file system not writable", %{ {File, [:passthrough], [mkdir: fn ^path_pack -> {:error, :eacces} end]} ]) do assert admin_conn - |> post("/api/pleroma/emoji/pack?name=test_pack") + |> post("/api/v1/pleroma/emoji/pack?name=test_pack") |> json_response_and_validate_schema(500) == %{ "error" => "Unexpected error occurred while creating pack. (POSIX error: Permission denied)" @@ -467,7 +475,7 @@ test "returns an error on deletes pack when the file system is not writable", %{ {File, [:passthrough], [rm_rf: fn ^path_pack -> {:error, :eacces, path_pack} end]} ]) do assert admin_conn - |> delete("/api/pleroma/emoji/pack?name=test_emoji_pack") + |> delete("/api/v1/pleroma/emoji/pack?name=test_emoji_pack") |> json_response_and_validate_schema(500) == %{ "error" => "Couldn't delete the `test_emoji_pack` pack (POSIX error: Permission denied)" @@ -480,7 +488,7 @@ test "returns an error on deletes pack when the file system is not writable", %{ test "creating and deleting a pack", %{admin_conn: admin_conn} do assert admin_conn - |> post("/api/pleroma/emoji/pack?name=test_created") + |> post("/api/v1/pleroma/emoji/pack?name=test_created") |> json_response_and_validate_schema(200) == "ok" assert File.exists?("#{@emoji_path}/test_created/pack.json") @@ -492,7 +500,7 @@ test "creating and deleting a pack", %{admin_conn: admin_conn} do } assert admin_conn - |> delete("/api/pleroma/emoji/pack?name=test_created") + |> delete("/api/v1/pleroma/emoji/pack?name=test_created") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_created/pack.json") @@ -505,7 +513,7 @@ test "if pack exists", %{admin_conn: admin_conn} do File.write!(Path.join(path, "pack.json"), pack_file) assert admin_conn - |> post("/api/pleroma/emoji/pack?name=test_created") + |> post("/api/v1/pleroma/emoji/pack?name=test_created") |> json_response_and_validate_schema(:conflict) == %{ "error" => "A pack named \"test_created\" already exists" } @@ -515,7 +523,7 @@ test "if pack exists", %{admin_conn: admin_conn} do test "with empty name", %{admin_conn: admin_conn} do assert admin_conn - |> post("/api/pleroma/emoji/pack?name= ") + |> post("/api/v1/pleroma/emoji/pack?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } @@ -524,7 +532,7 @@ test "with empty name", %{admin_conn: admin_conn} do test "deleting nonexisting pack", %{admin_conn: admin_conn} do assert admin_conn - |> delete("/api/pleroma/emoji/pack?name=non_existing") + |> delete("/api/v1/pleroma/emoji/pack?name=non_existing") |> json_response_and_validate_schema(:not_found) == %{ "error" => "Pack non_existing does not exist" } @@ -532,7 +540,7 @@ test "deleting nonexisting pack", %{admin_conn: admin_conn} do test "deleting with empty name", %{admin_conn: admin_conn} do assert admin_conn - |> delete("/api/pleroma/emoji/pack?name= ") + |> delete("/api/v1/pleroma/emoji/pack?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } @@ -544,15 +552,22 @@ test "filesystem import", %{admin_conn: admin_conn, conn: conn} do File.rm!("#{@emoji_path}/test_pack_for_import/pack.json") end) - resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200) + resp = + conn + |> get("/api/v1/pleroma/emoji/packs") + |> json_response_and_validate_schema(200) refute Map.has_key?(resp["packs"], "test_pack_for_import") assert admin_conn - |> get("/api/pleroma/emoji/packs/import") + |> get("/api/v1/pleroma/emoji/packs/import") |> json_response_and_validate_schema(200) == ["test_pack_for_import"] - resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200) + resp = + conn + |> get("/api/v1/pleroma/emoji/packs") + |> json_response_and_validate_schema(200) + assert resp["packs"]["test_pack_for_import"]["files"] == %{"blank" => "blank.png"} File.rm!("#{@emoji_path}/test_pack_for_import/pack.json") @@ -568,10 +583,13 @@ test "filesystem import", %{admin_conn: admin_conn, conn: conn} do File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content) assert admin_conn - |> get("/api/pleroma/emoji/packs/import") + |> get("/api/v1/pleroma/emoji/packs/import") |> json_response_and_validate_schema(200) == ["test_pack_for_import"] - resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200) + resp = + conn + |> get("/api/v1/pleroma/emoji/packs") + |> json_response_and_validate_schema(200) assert resp["packs"]["test_pack_for_import"]["files"] == %{ "blank" => "blank.png", @@ -580,7 +598,7 @@ test "filesystem import", %{admin_conn: admin_conn, conn: conn} do } end - describe "GET /api/pleroma/emoji/pack?name=:name" do + describe "GET /api/v1/pleroma/emoji/pack?name=:name" do test "shows pack.json", %{conn: conn} do assert %{ "files" => files, @@ -595,7 +613,7 @@ test "shows pack.json", %{conn: conn} do } } = conn - |> get("/api/pleroma/emoji/pack?name=test_pack") + |> get("/api/v1/pleroma/emoji/pack?name=test_pack") |> json_response_and_validate_schema(200) assert files == %{"blank" => "blank.png", "blank2" => "blank2.png"} @@ -605,7 +623,7 @@ test "shows pack.json", %{conn: conn} do "files_count" => 2 } = conn - |> get("/api/pleroma/emoji/pack?name=test_pack&page_size=1") + |> get("/api/v1/pleroma/emoji/pack?name=test_pack&page_size=1") |> json_response_and_validate_schema(200) assert files |> Map.keys() |> length() == 1 @@ -615,7 +633,7 @@ test "shows pack.json", %{conn: conn} do "files_count" => 2 } = conn - |> get("/api/pleroma/emoji/pack?name=test_pack&page_size=1&page=2") + |> get("/api/v1/pleroma/emoji/pack?name=test_pack&page_size=1&page=2") |> json_response_and_validate_schema(200) assert files |> Map.keys() |> length() == 1 @@ -635,13 +653,13 @@ test "for pack name with special chars", %{conn: conn} do } } = conn - |> get("/api/pleroma/emoji/pack?name=blobs.gg") + |> get("/api/v1/pleroma/emoji/pack?name=blobs.gg") |> json_response_and_validate_schema(200) end test "non existing pack", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/pack?name=non_existing") + |> get("/api/v1/pleroma/emoji/pack?name=non_existing") |> json_response_and_validate_schema(:not_found) == %{ "error" => "Pack non_existing does not exist" } @@ -649,7 +667,7 @@ test "non existing pack", %{conn: conn} do test "error name", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/pack?name= ") + |> get("/api/v1/pleroma/emoji/pack?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } diff --git a/test/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs index 24074f4e5..3716fcdec 100644 --- a/test/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller_test.exs @@ -151,7 +151,10 @@ test "returns success result", %{conn: conn} do assert conn |> put_req_header("authorization", "Bearer #{token.token}") - |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code}) + |> post("/api/pleroma/accounts/mfa/confirm/totp", %{ + password: "test", + code: code + }) |> json_response(:ok) settings = refresh_record(user).multi_factor_authentication_settings @@ -162,7 +165,10 @@ test "returns success result", %{conn: conn} do assert conn |> put_req_header("authorization", "Bearer #{token2.token}") - |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code}) + |> post("/api/pleroma/accounts/mfa/confirm/totp", %{ + password: "test", + code: code + }) |> json_response(403) == %{ "error" => "Insufficient permissions: write:security." } @@ -185,7 +191,10 @@ test "returns error if password incorrect", %{conn: conn} do response = conn |> put_req_header("authorization", "Bearer #{token.token}") - |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "xxx", code: code}) + |> post("/api/pleroma/accounts/mfa/confirm/totp", %{ + password: "xxx", + code: code + }) |> json_response(422) settings = refresh_record(user).multi_factor_authentication_settings @@ -212,7 +221,10 @@ test "returns error if code incorrect", %{conn: conn} do response = conn |> put_req_header("authorization", "Bearer #{token.token}") - |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"}) + |> post("/api/pleroma/accounts/mfa/confirm/totp", %{ + password: "test", + code: "code" + }) |> json_response(422) settings = refresh_record(user).multi_factor_authentication_settings @@ -223,7 +235,10 @@ test "returns error if code incorrect", %{conn: conn} do assert conn |> put_req_header("authorization", "Bearer #{token2.token}") - |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"}) + |> post("/api/pleroma/accounts/mfa/confirm/totp", %{ + password: "test", + code: "code" + }) |> json_response(403) == %{ "error" => "Insufficient permissions: write:security." } diff --git a/test/pleroma/web/plugs/remote_ip_test.exs b/test/pleroma/web/plugs/remote_ip_test.exs index 4d98de2bd..b77fa25f2 100644 --- a/test/pleroma/web/plugs/remote_ip_test.exs +++ b/test/pleroma/web/plugs/remote_ip_test.exs @@ -10,28 +10,32 @@ defmodule Pleroma.Web.Plugs.RemoteIpTest do import Pleroma.Tests.Helpers, only: [clear_config: 2] - setup do: - clear_config(RemoteIp, - enabled: true, - headers: ["x-forwarded-for"], - proxies: [], - reserved: [ - "127.0.0.0/8", - "::1/128", - "fc00::/7", - "10.0.0.0/8", - "172.16.0.0/12", - "192.168.0.0/16" - ] - ) + setup do + clear_config([RemoteIp, :enabled], true) + clear_config([RemoteIp, :headers], ["x-forwarded-for"]) + clear_config([RemoteIp, :proxies], []) + + clear_config( + [RemoteIp, :reserved], + [ + "127.0.0.0/8", + "::1/128", + "fc00::/7", + "10.0.0.0/8", + "172.16.0.0/12", + "192.168.0.0/16" + ] + ) + end test "disabled" do - clear_config(RemoteIp, enabled: false) + clear_config([RemoteIp, :enabled], false) %{remote_ip: remote_ip} = conn(:get, "/") conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("x-forwarded-for", "1.1.1.1") |> RemoteIp.call(nil) @@ -40,7 +44,8 @@ test "disabled" do test "enabled" do conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("x-forwarded-for", "1.1.1.1") |> RemoteIp.call(nil) @@ -48,17 +53,20 @@ test "enabled" do end test "custom headers" do - clear_config(RemoteIp, enabled: true, headers: ["cf-connecting-ip"]) + clear_config([RemoteIp, :enabled], true) + clear_config([RemoteIp, :headers], ["cf-connecting-ip"]) conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("x-forwarded-for", "1.1.1.1") |> RemoteIp.call(nil) refute conn.remote_ip == {1, 1, 1, 1} conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("cf-connecting-ip", "1.1.1.1") |> RemoteIp.call(nil) @@ -67,7 +75,8 @@ test "custom headers" do test "custom proxies" do conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1, 173.245.48.2") |> RemoteIp.call(nil) @@ -76,7 +85,8 @@ test "custom proxies" do clear_config([RemoteIp, :proxies], ["173.245.48.0/20"]) conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1, 173.245.48.2") |> RemoteIp.call(nil) @@ -87,7 +97,8 @@ test "proxies set without CIDR format" do clear_config([RemoteIp, :proxies], ["173.245.48.1"]) conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("x-forwarded-for", "173.245.48.1, 1.1.1.1") |> RemoteIp.call(nil) @@ -99,7 +110,8 @@ test "proxies set `nonsensical` CIDR" do clear_config([RemoteIp, :proxies], ["10.0.0.3/24"]) conn = - conn(:get, "/") + :get + |> conn("/") |> put_req_header("x-forwarded-for", "10.0.0.3, 1.1.1.1") |> RemoteIp.call(nil) diff --git a/test/pleroma/web/twitter_api/password_controller_test.exs b/test/pleroma/web/twitter_api/password_controller_test.exs index 45ab10a8a..05c3561bf 100644 --- a/test/pleroma/web/twitter_api/password_controller_test.exs +++ b/test/pleroma/web/twitter_api/password_controller_test.exs @@ -14,11 +14,11 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do import Pleroma.Factory import Swoosh.TestAssertions - describe "GET /api/pleroma/password_reset/token" do + describe "GET /api/v1/pleroma/password_reset/token" do test "it returns error when token invalid", %{conn: conn} do response = conn - |> get("/api/pleroma/password_reset/token") + |> get("/api/v1/pleroma/password_reset/token") |> html_response(:ok) assert response =~ "

Invalid Token

" @@ -30,7 +30,7 @@ test "it shows password reset form", %{conn: conn} do response = conn - |> get("/api/pleroma/password_reset/#{token.token}") + |> get("/api/v1/pleroma/password_reset/#{token.token}") |> html_response(:ok) assert response =~ "

Password Reset for #{user.nickname}

" @@ -45,14 +45,14 @@ test "it returns an error when the token has expired", %{conn: conn} do response = conn - |> get("/api/pleroma/password_reset/#{token.token}") + |> get("/api/v1/pleroma/password_reset/#{token.token}") |> html_response(:ok) assert response =~ "

Invalid Token

" end end - describe "POST /api/pleroma/password_reset" do + describe "POST /api/v1/pleroma/password_reset" do test "it fails for an expired token", %{conn: conn} do clear_config([:instance, :password_reset_token_validity], 0) @@ -70,7 +70,7 @@ test "it fails for an expired token", %{conn: conn} do response = conn |> assign(:user, user) - |> post("/api/pleroma/password_reset", %{data: params}) + |> post("/api/v1/pleroma/password_reset", %{data: params}) |> html_response(:ok) refute response =~ "

Password changed!

" @@ -90,7 +90,7 @@ test "it returns HTTP 200", %{conn: conn} do response = conn |> assign(:user, user) - |> post("/api/pleroma/password_reset", %{data: params}) + |> post("/api/v1/pleroma/password_reset", %{data: params}) |> html_response(:ok) assert response =~ "

Password changed!

" @@ -114,7 +114,7 @@ test "it sets password_reset_pending to false", %{conn: conn} do conn |> assign(:user, user) - |> post("/api/pleroma/password_reset", %{data: params}) + |> post("/api/v1/pleroma/password_reset", %{data: params}) |> html_response(:ok) assert User.get_by_id(user.id).password_reset_pending == false diff --git a/test/pleroma/web/twitter_api/util_controller_test.exs b/test/pleroma/web/twitter_api/util_controller_test.exs index d669cd0fe..3f839568d 100644 --- a/test/pleroma/web/twitter_api/util_controller_test.exs +++ b/test/pleroma/web/twitter_api/util_controller_test.exs @@ -77,11 +77,11 @@ test "returns everything in :pleroma, :frontend_configurations", %{conn: conn} d end end - describe "/api/pleroma/emoji" do + describe "/api/v1/pleroma/emoji" do test "returns json with custom emoji with tags", %{conn: conn} do emoji = conn - |> get("/api/pleroma/emoji") + |> get("/api/v1/pleroma/emoji") |> json_response_and_validate_schema(200) assert Enum.all?(emoji, fn @@ -95,7 +95,7 @@ test "returns json with custom emoji with tags", %{conn: conn} do end end - describe "GET /api/pleroma/healthcheck" do + describe "GET /api/v1/pleroma/healthcheck" do setup do: clear_config([:instance, :healthcheck]) test "returns 503 when healthcheck disabled", %{conn: conn} do @@ -103,7 +103,7 @@ test "returns 503 when healthcheck disabled", %{conn: conn} do response = conn - |> get("/api/pleroma/healthcheck") + |> get("/api/v1/pleroma/healthcheck") |> json_response_and_validate_schema(503) assert response == %{} @@ -116,7 +116,7 @@ test "returns 200 when healthcheck enabled and all ok", %{conn: conn} do system_info: fn -> %Pleroma.Healthcheck{healthy: true} end do response = conn - |> get("/api/pleroma/healthcheck") + |> get("/api/v1/pleroma/healthcheck") |> json_response_and_validate_schema(200) assert %{ @@ -136,7 +136,7 @@ test "returns 503 when healthcheck enabled and health is false", %{conn: conn} d system_info: fn -> %Pleroma.Healthcheck{healthy: false} end do response = conn - |> get("/api/pleroma/healthcheck") + |> get("/api/v1/pleroma/healthcheck") |> json_response_and_validate_schema(503) assert %{ @@ -334,7 +334,7 @@ test "it returns new captcha", %{conn: conn} do new: fn -> "test_captcha" end do resp = conn - |> get("/api/pleroma/captcha") + |> get("/api/v1/pleroma/captcha") |> response(200) assert resp == "\"test_captcha\"" @@ -459,7 +459,10 @@ test "with proper permissions, valid password and valid email", %{ conn = conn |> put_req_header("content-type", "multipart/form-data") - |> post("/api/pleroma/change_email", %{password: "test", email: "cofe@foobar.com"}) + |> post("/api/pleroma/change_email", %{ + password: "test", + email: "cofe@foobar.com" + }) assert json_response_and_validate_schema(conn, 200) == %{"status" => "success"} end @@ -961,7 +964,9 @@ test "with permissions, account does not have such alias", %{ conn = conn |> put_req_header("content-type", "application/json") - |> delete("/api/pleroma/aliases", %{alias: non_alias_user |> User.full_nickname()}) + |> delete("/api/pleroma/aliases", %{ + alias: non_alias_user |> User.full_nickname() + }) assert %{"error" => "Account has no such alias."} = json_response_and_validate_schema(conn, 404) diff --git a/test/support/cluster.ex b/test/support/cluster.ex index 7e41631c5..682643988 100644 --- a/test/support/cluster.ex +++ b/test/support/cluster.ex @@ -123,7 +123,10 @@ def eval_quoted(block, binding) do defp start_peer({node_host, override_configs}) do log(node_host, "booting federated VM") - {:ok, node} = :peer.start(%{host: ~c"127.0.0.1", name: node_name(node_host), args: vm_args()}) + + {:ok, _pid, node} = + :peer.start(%{host: ~c"127.0.0.1", name: node_name(node_host), args: vm_args()}) + add_code_paths(node) load_apps_and_transfer_configuration(node, override_configs) ensure_apps_started(node) From 33243c56e5560f99bd886ed44bcb50c9f679ccc2 Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 11:14:16 +0100 Subject: [PATCH 06/41] Start adding telemetry --- lib/pleroma/application.ex | 1 + lib/pleroma/web/router.ex | 2 +- lib/pleroma/web/telemetry.ex | 90 ++++++++++++++++++++++++++++++++++++ mix.exs | 3 ++ mix.lock | 5 +- 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 lib/pleroma/web/telemetry.ex diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 48a2623ce..ad768b0e0 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -64,6 +64,7 @@ def start(_type, _args) do Config.TransferTask, Pleroma.Emoji, Pleroma.Web.Plugs.RateLimiter.Supervisor, + Pleroma.Web.Telemetry, {Task.Supervisor, name: Pleroma.TaskSupervisor} ] ++ cachex_children() ++ diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index e790b1cdb..bcb5fb15e 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -867,7 +867,7 @@ defmodule Pleroma.Web.Router do scope "/" do pipe_through([:pleroma_html, :authenticate, :require_admin]) - live_dashboard("/phoenix/live_dashboard") + live_dashboard("/phoenix/live_dashboard", metrics: Pleroma.Web.Telemetry) end # Test-only routes needed to test action dispatching and plug chain execution diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex new file mode 100644 index 000000000..f7e9d5ca7 --- /dev/null +++ b/lib/pleroma/web/telemetry.ex @@ -0,0 +1,90 @@ +defmodule Pleroma.Web.Telemetry do + use Supervisor + import Telemetry.Metrics + + def start_link(arg) do + Supervisor.start_link(__MODULE__, arg, name: __MODULE__) + end + + @impl true + def init(_arg) do + children = [ + # Telemetry poller will execute the given period measurements + # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics + {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}, + # Add reporters as children of your supervision tree. + # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}, + {TelemetryMetricsPrometheus, metrics: metrics()} + ] + + Supervisor.init(children, strategy: :one_for_one) + end + + def metrics do + [ + # Phoenix Metrics + summary("phoenix.endpoint.stop.duration", + unit: {:native, :millisecond} + ), + summary("phoenix.router_dispatch.stop.duration", + tags: [:route], + unit: {:native, :millisecond} + ), + distribution( + "phoenix.router_dispatch.stop.duration", + # event_name: [:pleroma, :repo, :query, :total_time], + measurement: :duration, + unit: {:native, :second}, + tags: [:route], + reporter_options: [ + buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + ] + ), + + # Database Time Metrics + distribution( + "pleroma.repo.query.total_time", + # event_name: [:pleroma, :repo, :query, :total_time], + measurement: :total_time, + unit: {:native, :millisecond}, + reporter_options: [ + buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + ] + ), + distribution( + "pleroma.repo.query.queue_time", + # event_name: [:pleroma, :repo, :query, :total_time], + measurement: :queue_time, + unit: {:native, :millisecond}, + reporter_options: [ + buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + ] + ), + summary("pleroma.repo.query.total_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.decode_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.query_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.queue_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.idle_time", unit: {:native, :millisecond}), + + # VM Metrics + summary("vm.memory.total", unit: {:byte, :kilobyte}), + summary("vm.total_run_queue_lengths.total"), + summary("vm.total_run_queue_lengths.cpu"), + summary("vm.total_run_queue_lengths.io"), + distribution( + "oban.job.stop", + event_name: [:oban, :job, :stop], + measurement: :duration, + tags: [:job], + unit: {:native, :second}, + reporter_options: [ + buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + ] + ) + ] + end + + defp periodic_measurements do + [] + end +end diff --git a/mix.exs b/mix.exs index 00a250002..b5b7efd0c 100644 --- a/mix.exs +++ b/mix.exs @@ -161,6 +161,9 @@ defp deps do git: "https://akkoma.dev/AkkomaGang/linkify.git", branch: "bugfix/line-ending-buffer"}, {:http_signatures, "~> 0.1.1"}, {:telemetry, "~> 0.3"}, + {:telemetry_poller, "~> 0.4"}, + {:telemetry_metrics, "~> 0.4"}, + {:telemetry_metrics_prometheus, "~> 1.1.0"}, {:poolboy, "~> 1.5"}, {:recon, "~> 2.5"}, {:joken, "~> 2.0"}, diff --git a/mix.lock b/mix.lock index 0e3ac3514..01c628c29 100644 --- a/mix.lock +++ b/mix.lock @@ -17,7 +17,7 @@ "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"}, "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, - "credo": {:git, "https://github.com/rrrene/credo.git", "1c1b99ea41a457761383d81aaf6a606913996fe7", [ref: "1c1b99ea41a457761383d81aaf6a606913996fe7"]}, + "credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"}, "crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]}, "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, "db_connection": {:hex, :db_connection, "2.4.3", "3b9aac9f27347ec65b271847e6baeb4443d8474289bd18c1d6f4de655b70c94d", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c127c15b0fa6cfb32eed07465e05da6c815b032508d4ed7c116122871df73c12"}, @@ -112,6 +112,9 @@ "table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"}, "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, + "telemetry_metrics_prometheus": {:hex, :telemetry_metrics_prometheus, "1.1.0", "1cc23e932c1ef9aa3b91db257ead31ea58d53229d407e059b29bb962c1505a13", [:mix], [{:plug_cowboy, "~> 2.1", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.0", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}], "hexpm", "d43b3659b3244da44fe0275b717701542365d4519b79d9ce895b9719c1ce4d26"}, + "telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.1.0", "4e15f6d7dbedb3a4e3aed2262b7e1407f166fcb9c30ca3f96635dfbbef99965c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0dd10e7fe8070095df063798f82709b0a1224c31b8baf6278b423898d591a069"}, + "telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"}, "temple": {:git, "https://akkoma.dev/AkkomaGang/temple.git", "066a699ade472d8fa42a9d730b29a61af9bc8b59", [ref: "066a699ade472d8fa42a9d730b29a61af9bc8b59"]}, "tesla": {:hex, :tesla, "1.4.4", "bb89aa0c9745190930366f6a2ac612cdf2d0e4d7fff449861baa7875afd797b2", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "d5503a49f9dec1b287567ea8712d085947e247cb11b06bc54adb05bfde466457"}, "timex": {:hex, :timex, "3.7.9", "790cdfc4acfce434e442f98c02ea6d84d0239073bfd668968f82ac63e9a6788d", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "64691582e5bb87130f721fc709acfb70f24405833998fabf35be968984860ce1"}, From 1e9c2cd8ef1da5cf6803d690b14e4b956b0b2c38 Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 11:23:44 +0100 Subject: [PATCH 07/41] Fix buckets for query timing --- lib/pleroma/web/telemetry.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index f7e9d5ca7..546c39f05 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -37,7 +37,7 @@ def metrics do unit: {:native, :second}, tags: [:route], reporter_options: [ - buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + buckets: [0.1, 0.2, 0.5, 1, 2.5, 5, 10, 25, 50, 100, 250, 500, 1000] ] ), @@ -48,7 +48,7 @@ def metrics do measurement: :total_time, unit: {:native, :millisecond}, reporter_options: [ - buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + buckets: [0.1, 0.2, 0.5, 1, 2.5, 5, 10, 25, 50, 100, 250, 500, 1000] ] ), distribution( From a06bb694c1776a9144746237991a43f53c63e634 Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 11:31:03 +0100 Subject: [PATCH 08/41] Listen to loopback --- lib/pleroma/web/telemetry.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index 546c39f05..2ca188e1a 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -14,7 +14,7 @@ def init(_arg) do {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}, # Add reporters as children of your supervision tree. # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}, - {TelemetryMetricsPrometheus, metrics: metrics()} + {TelemetryMetricsPrometheus, metrics: metrics(), plug_cowboy_opts: [ip: {127, 0, 0, 1}]} ] Supervisor.init(children, strategy: :one_for_one) From f8d338317918cd62ebe45c3ea6433425b1cb1b28 Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 11:54:35 +0100 Subject: [PATCH 09/41] Fix oban tags --- lib/pleroma/web/telemetry.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index 2ca188e1a..505ee382c 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -75,7 +75,8 @@ def metrics do "oban.job.stop", event_name: [:oban, :job, :stop], measurement: :duration, - tags: [:job], + tags: [:worker], + tag_values: fn tags -> Map.put(tags, :worker, tags.job.worker) end, unit: {:native, :second}, reporter_options: [ buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] From 8f58eb4a183e97e28850d7030beeb7b13294d318 Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 12:38:25 +0100 Subject: [PATCH 10/41] Revert "Bump live-dashboard" This reverts commit c196d79aafd51b671aa19032b32e4cd416dab720. --- mix.exs | 2 +- mix.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mix.exs b/mix.exs index b5b7efd0c..cb46e8da3 100644 --- a/mix.exs +++ b/mix.exs @@ -185,7 +185,7 @@ defp deps do git: "https://github.com/FloatingGhost/pleroma-contrib-search-parser.git", ref: "08971a81e68686f9ac465cfb6661d51c5e4e1e7f"}, {:nimble_parsec, "~> 1.0", override: true}, - {:phoenix_live_dashboard, "~> 0.7.2"}, + {:phoenix_live_dashboard, "~> 0.6.2"}, {:ecto_psql_extras, "~> 0.6"}, {:elasticsearch, git: "https://akkoma.dev/AkkomaGang/elasticsearch-elixir.git", ref: "main"}, diff --git a/mix.lock b/mix.lock index 01c628c29..62f481d83 100644 --- a/mix.lock +++ b/mix.lock @@ -85,8 +85,8 @@ "phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, - "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "0.18.3", "2e3d009422addf8b15c3dccc65ce53baccbe26f7cfd21d264680b5867789a9c1", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c8845177a866e017dcb7083365393c8f00ab061b8b6b2bda575891079dce81b2"}, + "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.5", "1495bb014be12c9a9252eca04b9af54246f6b5c1e4cd1f30210cd00ec540cf8e", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.7", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "ef4fa50dd78364409039c99cf6f98ab5209b4c5f8796c17f4db118324f0db852"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.12", "74f4c0ad02d7deac2d04f50b52827a5efdc5c6e7fac5cede145f5f0e4183aedc", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.0 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "af6dd5e0aac16ff43571f527a8e0616d62cb80b10eb87aac82170243e50d99c8"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, "phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.4", "615f8f393135de7e0cbb4bd00ba238b1e0cd324b0d90efbaee613c2f02ca5e5c", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "3971221846232021ab5e3c7489fd62ec5bfd6a2e01cae10a317ccf6fb350571c"}, "phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"}, From 0995fa141062f2aef1ee017ca03c7f9522dc3da8 Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 12:42:53 +0100 Subject: [PATCH 11/41] Track oban failures --- lib/pleroma/web/telemetry.ex | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index 505ee382c..d9c54c28f 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -72,7 +72,7 @@ def metrics do summary("vm.total_run_queue_lengths.cpu"), summary("vm.total_run_queue_lengths.io"), distribution( - "oban.job.stop", + "oban_job_completion", event_name: [:oban, :job, :stop], measurement: :duration, tags: [:worker], @@ -81,6 +81,17 @@ def metrics do reporter_options: [ buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] ] + ), + distribution( + "oban_job_exception", + event_name: [:oban, :job, :exception], + measurement: :duration, + tags: [:worker], + tag_values: fn tags -> Map.put(tags, :worker, tags.job.worker) end, + unit: {:native, :second}, + reporter_options: [ + buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + ] ) ] end From 63be819661cd28514207bbc19be6d4964235685b Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 16:11:38 +0100 Subject: [PATCH 12/41] Take tesla telemetry --- lib/pleroma/http.ex | 2 +- lib/pleroma/web/telemetry.ex | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/http.ex b/lib/pleroma/http.ex index d8028651c..6ae1cdebb 100644 --- a/lib/pleroma/http.ex +++ b/lib/pleroma/http.ex @@ -65,7 +65,7 @@ def request(method, url, body, headers, options) when is_binary(url) do options = put_in(options[:adapter], adapter_opts) params = options[:params] || [] request = build_request(method, headers, options, url, body, params) - client = Tesla.client([Tesla.Middleware.FollowRedirects]) + client = Tesla.client([Tesla.Middleware.FollowRedirects, Tesla.Middleware.Telemetry]) request(client, request) end diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index d9c54c28f..46b5865f7 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -92,6 +92,17 @@ def metrics do reporter_options: [ buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] ] + ), + distribution( + "tesla_request_completed", + event_name: [:tesla, :request, :stop], + measurement: :duration, + tags: [:response_code], + tag_values: fn tags -> Map.put(tags, :response_code, tags.env.status) end, + unit: {:native, :second}, + reporter_options: [ + buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + ] ) ] end From 29584197bb53a6fb5f980cc8d2566b0492196def Mon Sep 17 00:00:00 2001 From: Tim Buchwaldt Date: Sat, 12 Nov 2022 17:13:39 +0100 Subject: [PATCH 13/41] Measure stats-data --- lib/pleroma/application.ex | 4 ++-- lib/pleroma/web/telemetry.ex | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index ad768b0e0..02336d6d1 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -64,7 +64,6 @@ def start(_type, _args) do Config.TransferTask, Pleroma.Emoji, Pleroma.Web.Plugs.RateLimiter.Supervisor, - Pleroma.Web.Telemetry, {Task.Supervisor, name: Pleroma.TaskSupervisor} ] ++ cachex_children() ++ @@ -74,7 +73,8 @@ def start(_type, _args) do Pleroma.JobQueueMonitor, {Majic.Pool, [name: Pleroma.MajicPool, pool_size: Config.get([:majic_pool, :size], 2)]}, {Oban, Config.get(Oban)}, - Pleroma.Web.Endpoint + Pleroma.Web.Endpoint, + Pleroma.Web.Telemetry ] ++ elasticsearch_children() ++ task_children(@mix_env) ++ diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index 46b5865f7..73ce6a85c 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -1,6 +1,7 @@ defmodule Pleroma.Web.Telemetry do use Supervisor import Telemetry.Metrics + alias Pleroma.Stats def start_link(arg) do Supervisor.start_link(__MODULE__, arg, name: __MODULE__) @@ -103,11 +104,23 @@ def metrics do reporter_options: [ buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] ] - ) + ), + last_value("pleroma.local_users.total"), + last_value("pleroma.domains.total"), + last_value("pleroma.local_statuses.total") ] end defp periodic_measurements do - [] + [ + {__MODULE__, :instance_stats, []} + ] + end + + def instance_stats do + stats = Stats.get_stats() + :telemetry.execute([:pleroma, :local_users], %{total: stats.user_count}, %{}) + :telemetry.execute([:pleroma, :domains], %{total: stats.domain_count}, %{}) + :telemetry.execute([:pleroma, :local_statuses], %{total: stats.status_count}, %{}) end end From e2320f870e6ef4e8fc9f63282cbd459e819d740a Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Thu, 15 Dec 2022 02:02:07 +0000 Subject: [PATCH 14/41] Add prometheus metrics to router --- .../controllers/metrics_controller.ex | 16 ++++ lib/pleroma/web/endpoint.ex | 1 + lib/pleroma/web/plugs/csp_nonce_plug.ex | 21 +++++ lib/pleroma/web/plugs/http_security_plug.ex | 23 ++++-- lib/pleroma/web/router.ex | 3 +- lib/pleroma/web/telemetry.ex | 82 +++++++++++-------- mix.exs | 2 +- mix.lock | 6 +- 8 files changed, 104 insertions(+), 50 deletions(-) create mode 100644 lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex create mode 100644 lib/pleroma/web/plugs/csp_nonce_plug.ex diff --git a/lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex b/lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex new file mode 100644 index 000000000..c8d3d8948 --- /dev/null +++ b/lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex @@ -0,0 +1,16 @@ +defmodule Pleroma.Web.AkkomaAPI.MetricsController do + use Pleroma.Web, :controller + + alias Pleroma.Web.Plugs.OAuthScopesPlug + + @unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []} + plug(:skip_auth) + + + def show(conn, _params) do + stats = TelemetryMetricsPrometheus.Core.scrape() + + conn + |> text(stats) + end +end diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index baf0c5651..e3a251ca1 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -13,6 +13,7 @@ defmodule Pleroma.Web.Endpoint do plug(Pleroma.Web.Plugs.SetLocalePlug) plug(CORSPlug) + plug(Pleroma.Web.Plugs.CSPNoncePlug) plug(Pleroma.Web.Plugs.HTTPSecurityPlug) plug(Pleroma.Web.Plugs.UploadedMedia) diff --git a/lib/pleroma/web/plugs/csp_nonce_plug.ex b/lib/pleroma/web/plugs/csp_nonce_plug.ex new file mode 100644 index 000000000..bc2c6fcd8 --- /dev/null +++ b/lib/pleroma/web/plugs/csp_nonce_plug.ex @@ -0,0 +1,21 @@ +defmodule Pleroma.Web.Plugs.CSPNoncePlug do + import Plug.Conn + + def init(opts) do + opts + end + + def call(conn, _opts) do + assign_csp_nonce(conn) + end + + defp assign_csp_nonce(conn) do + nonce = + :crypto.strong_rand_bytes(128) + |> Base.url_encode64() + |> binary_part(0, 15) + + conn + |> assign(:csp_nonce, nonce) + end +end diff --git a/lib/pleroma/web/plugs/http_security_plug.ex b/lib/pleroma/web/plugs/http_security_plug.ex index 47874a980..6593347ca 100644 --- a/lib/pleroma/web/plugs/http_security_plug.ex +++ b/lib/pleroma/web/plugs/http_security_plug.ex @@ -13,7 +13,7 @@ def init(opts), do: opts def call(conn, _options) do if Config.get([:http_security, :enabled]) do conn - |> merge_resp_headers(headers()) + |> merge_resp_headers(headers(conn)) |> maybe_send_sts_header(Config.get([:http_security, :sts])) else conn @@ -36,7 +36,8 @@ def custom_http_frontend_headers do end end - def headers do + @spec headers(Plug.Conn.t()) :: [{String.t(), String.t()}] + def headers(conn) do referrer_policy = Config.get([:http_security, :referrer_policy]) report_uri = Config.get([:http_security, :report_uri]) custom_http_frontend_headers = custom_http_frontend_headers() @@ -47,7 +48,7 @@ def headers do {"x-frame-options", "DENY"}, {"x-content-type-options", "nosniff"}, {"referrer-policy", referrer_policy}, - {"content-security-policy", csp_string()}, + {"content-security-policy", csp_string(conn)}, {"permissions-policy", "interest-cohort=()"} ] @@ -77,19 +78,18 @@ def headers do "default-src 'none'", "base-uri 'none'", "frame-ancestors 'none'", - "style-src 'self' 'unsafe-inline'", - "font-src 'self'", "manifest-src 'self'" ] @csp_start [Enum.join(static_csp_rules, ";") <> ";"] - defp csp_string do + defp csp_string(conn) do scheme = Config.get([Pleroma.Web.Endpoint, :url])[:scheme] static_url = Pleroma.Web.Endpoint.static_url() websocket_url = Pleroma.Web.Endpoint.websocket_url() report_uri = Config.get([:http_security, :report_uri]) - + %{assigns: %{csp_nonce: nonce}} = conn + nonce_tag = "nonce-" <> nonce img_src = "img-src 'self' data: blob:" media_src = "media-src 'self'" @@ -111,11 +111,14 @@ defp csp_string do ["connect-src 'self' blob: ", static_url, ?\s, websocket_url] end + style_src = "style-src 'self' '#{nonce_tag}'" + font_src = "font-src 'self' '#{nonce_tag}' data:" + script_src = if Config.get(:env) == :dev do - "script-src 'self' 'unsafe-eval'" + "script-src 'self' 'unsafe-eval' '#{nonce_tag}'" else - "script-src 'self'" + "script-src 'self' '#{nonce_tag}'" end report = if report_uri, do: ["report-uri ", report_uri, ";report-to csp-endpoint"] @@ -126,6 +129,8 @@ defp csp_string do |> add_csp_param(media_src) |> add_csp_param(connect_src) |> add_csp_param(script_src) + |> add_csp_param(font_src) + |> add_csp_param(style_src) |> add_csp_param(insecure) |> add_csp_param(report) |> :erlang.iolist_to_binary() diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index bcb5fb15e..c0ce645c4 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -467,6 +467,7 @@ defmodule Pleroma.Web.Router do scope "/api/v1/akkoma", Pleroma.Web.AkkomaAPI do pipe_through(:authenticated_api) + get("/metrics", MetricsController, :show) get("/translation/languages", TranslationController, :languages) get("/frontend_settings/:frontend_name", FrontendSettingsController, :list_profiles) @@ -867,7 +868,7 @@ defmodule Pleroma.Web.Router do scope "/" do pipe_through([:pleroma_html, :authenticate, :require_admin]) - live_dashboard("/phoenix/live_dashboard", metrics: Pleroma.Web.Telemetry) + live_dashboard("/phoenix/live_dashboard", metrics: {Pleroma.Web.Telemetry, :live_dashboard_metrics}, csp_nonce_assign_key: :csp_nonce) end # Test-only routes needed to test action dispatching and plug chain execution diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index 73ce6a85c..435f55799 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -10,27 +10,19 @@ def start_link(arg) do @impl true def init(_arg) do children = [ - # Telemetry poller will execute the given period measurements - # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}, - # Add reporters as children of your supervision tree. - # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}, - {TelemetryMetricsPrometheus, metrics: metrics(), plug_cowboy_opts: [ip: {127, 0, 0, 1}]} + {TelemetryMetricsPrometheus, metrics: prometheus_metrics(), plug_cowboy_opts: [ip: {127, 0, 0, 1}]} ] Supervisor.init(children, strategy: :one_for_one) end - def metrics do + @doc """ + A seperate set of metrics for distributions because phoenix dashboard does NOT handle + them well + """ + defp distribution_metrics do [ - # Phoenix Metrics - summary("phoenix.endpoint.stop.duration", - unit: {:native, :millisecond} - ), - summary("phoenix.router_dispatch.stop.duration", - tags: [:route], - unit: {:native, :millisecond} - ), distribution( "phoenix.router_dispatch.stop.duration", # event_name: [:pleroma, :repo, :query, :total_time], @@ -61,28 +53,6 @@ def metrics do buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] ] ), - summary("pleroma.repo.query.total_time", unit: {:native, :millisecond}), - summary("pleroma.repo.query.decode_time", unit: {:native, :millisecond}), - summary("pleroma.repo.query.query_time", unit: {:native, :millisecond}), - summary("pleroma.repo.query.queue_time", unit: {:native, :millisecond}), - summary("pleroma.repo.query.idle_time", unit: {:native, :millisecond}), - - # VM Metrics - summary("vm.memory.total", unit: {:byte, :kilobyte}), - summary("vm.total_run_queue_lengths.total"), - summary("vm.total_run_queue_lengths.cpu"), - summary("vm.total_run_queue_lengths.io"), - distribution( - "oban_job_completion", - event_name: [:oban, :job, :stop], - measurement: :duration, - tags: [:worker], - tag_values: fn tags -> Map.put(tags, :worker, tags.job.worker) end, - unit: {:native, :second}, - reporter_options: [ - buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] - ] - ), distribution( "oban_job_exception", event_name: [:oban, :job, :exception], @@ -105,12 +75,52 @@ def metrics do buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] ] ), + distribution( + "oban_job_completion", + event_name: [:oban, :job, :stop], + measurement: :duration, + tags: [:worker], + tag_values: fn tags -> Map.put(tags, :worker, tags.job.worker) end, + unit: {:native, :second}, + reporter_options: [ + buckets: [0.01, 0.025, 0.05, 0.1, 0.2, 0.5, 1, 2.5, 5, 10] + ] + ) + ] + end + + defp summary_metrics do + [ + # Phoenix Metrics + summary("phoenix.endpoint.stop.duration", + unit: {:native, :millisecond} + ), + summary("phoenix.router_dispatch.stop.duration", + tags: [:route], + unit: {:native, :millisecond} + ), + summary("pleroma.repo.query.total_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.decode_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.query_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.queue_time", unit: {:native, :millisecond}), + summary("pleroma.repo.query.idle_time", unit: {:native, :millisecond}), + + # VM Metrics + summary("vm.memory.total", unit: {:byte, :kilobyte}), + summary("vm.total_run_queue_lengths.total"), + summary("vm.total_run_queue_lengths.cpu"), + summary("vm.total_run_queue_lengths.io"), + + last_value("pleroma.local_users.total"), last_value("pleroma.domains.total"), last_value("pleroma.local_statuses.total") ] end + def prometheus_metrics, do: summary_metrics() ++ distribution_metrics() + def live_dashboard_metrics, do: summary_metrics() + defp periodic_measurements do [ {__MODULE__, :instance_stats, []} diff --git a/mix.exs b/mix.exs index cb46e8da3..b5b7efd0c 100644 --- a/mix.exs +++ b/mix.exs @@ -185,7 +185,7 @@ defp deps do git: "https://github.com/FloatingGhost/pleroma-contrib-search-parser.git", ref: "08971a81e68686f9ac465cfb6661d51c5e4e1e7f"}, {:nimble_parsec, "~> 1.0", override: true}, - {:phoenix_live_dashboard, "~> 0.6.2"}, + {:phoenix_live_dashboard, "~> 0.7.2"}, {:ecto_psql_extras, "~> 0.6"}, {:elasticsearch, git: "https://akkoma.dev/AkkomaGang/elasticsearch-elixir.git", ref: "main"}, diff --git a/mix.lock b/mix.lock index 62f481d83..4fa4c05ec 100644 --- a/mix.lock +++ b/mix.lock @@ -17,7 +17,7 @@ "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"}, "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, - "credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"}, + "credo": {:git, "https://github.com/rrrene/credo.git", "1c1b99ea41a457761383d81aaf6a606913996fe7", [ref: "1c1b99ea41a457761383d81aaf6a606913996fe7"]}, "crypt": {:git, "https://github.com/msantos/crypt.git", "f75cd55325e33cbea198fb41fe41871392f8fb76", [ref: "f75cd55325e33cbea198fb41fe41871392f8fb76"]}, "custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"}, "db_connection": {:hex, :db_connection, "2.4.3", "3b9aac9f27347ec65b271847e6baeb4443d8474289bd18c1d6f4de655b70c94d", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c127c15b0fa6cfb32eed07465e05da6c815b032508d4ed7c116122871df73c12"}, @@ -85,8 +85,8 @@ "phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"}, "phoenix_html": {:hex, :phoenix_html, "3.2.0", "1c1219d4b6cb22ac72f12f73dc5fad6c7563104d083f711c3fcd8551a1f4ae11", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "36ec97ba56d25c0136ef1992c37957e4246b649d620958a1f9fa86165f8bc54f"}, - "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.6.5", "1495bb014be12c9a9252eca04b9af54246f6b5c1e4cd1f30210cd00ec540cf8e", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.3", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.17.7", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "ef4fa50dd78364409039c99cf6f98ab5209b4c5f8796c17f4db118324f0db852"}, - "phoenix_live_view": {:hex, :phoenix_live_view, "0.17.12", "74f4c0ad02d7deac2d04f50b52827a5efdc5c6e7fac5cede145f5f0e4183aedc", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.0 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "af6dd5e0aac16ff43571f527a8e0616d62cb80b10eb87aac82170243e50d99c8"}, + "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.18.3", "2e3d009422addf8b15c3dccc65ce53baccbe26f7cfd21d264680b5867789a9c1", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c8845177a866e017dcb7083365393c8f00ab061b8b6b2bda575891079dce81b2"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"}, "phoenix_swoosh": {:hex, :phoenix_swoosh, "0.3.4", "615f8f393135de7e0cbb4bd00ba238b1e0cd324b0d90efbaee613c2f02ca5e5c", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 1.0", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm", "3971221846232021ab5e3c7489fd62ec5bfd6a2e01cae10a317ccf6fb350571c"}, "phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"}, From b8be8192fbfe8c27b457094e8d64ccb1c3a29f7f Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Fri, 16 Dec 2022 03:25:14 +0000 Subject: [PATCH 15/41] do not allow non-admins to register tokens with admin scopes this didn't actually _do_ anything in the past, the users would be prevented from accessing the resource, but they shouldn't be able to even create them --- lib/pleroma/web/o_auth/o_auth_controller.ex | 17 +-- lib/pleroma/web/o_auth/scopes.ex | 16 ++- .../web/o_auth/o_auth_controller_test.exs | 119 +++++++++++++----- 3 files changed, 110 insertions(+), 42 deletions(-) diff --git a/lib/pleroma/web/o_auth/o_auth_controller.ex b/lib/pleroma/web/o_auth/o_auth_controller.ex index 8f32e7219..3943ca449 100644 --- a/lib/pleroma/web/o_auth/o_auth_controller.ex +++ b/lib/pleroma/web/o_auth/o_auth_controller.ex @@ -211,11 +211,11 @@ defp handle_create_authorization_error( {:error, scopes_issue}, %{"authorization" => _} = params ) - when scopes_issue in [:unsupported_scopes, :missing_scopes] do + when scopes_issue in [:unsupported_scopes, :missing_scopes, :user_is_not_an_admin] do # Per https://github.com/tootsuite/mastodon/blob/ # 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L39 conn - |> put_flash(:error, dgettext("errors", "This action is outside the authorized scopes")) + |> put_flash(:error, dgettext("errors", "This action is outside of authorized scopes")) |> put_status(:unauthorized) |> authorize(params) end @@ -605,7 +605,7 @@ defp do_create_authorization( defp do_create_authorization(%User{} = user, %App{} = app, requested_scopes) when is_list(requested_scopes) do with {:account_status, :active} <- {:account_status, User.account_status(user)}, - {:ok, scopes} <- validate_scopes(app, requested_scopes), + {:ok, scopes} <- validate_scopes(user, app, requested_scopes), {:ok, auth} <- Authorization.create_authorization(app, user, scopes) do {:ok, auth} end @@ -637,15 +637,16 @@ defp build_and_response_mfa_token(user, auth) do end end - @spec validate_scopes(App.t(), map() | list()) :: + @spec validate_scopes(User.t(), App.t(), map() | list()) :: {:ok, list()} | {:error, :missing_scopes | :unsupported_scopes} - defp validate_scopes(%App{} = app, params) when is_map(params) do + defp validate_scopes(%User{} = user, %App{} = app, params) when is_map(params) do requested_scopes = Scopes.fetch_scopes(params, app.scopes) - validate_scopes(app, requested_scopes) + validate_scopes(user, app, requested_scopes) end - defp validate_scopes(%App{} = app, requested_scopes) when is_list(requested_scopes) do - Scopes.validate(requested_scopes, app.scopes) + defp validate_scopes(%User{} = user, %App{} = app, requested_scopes) + when is_list(requested_scopes) do + Scopes.validate(requested_scopes, app.scopes, user) end def default_redirect_uri(%App{} = app) do diff --git a/lib/pleroma/web/o_auth/scopes.ex b/lib/pleroma/web/o_auth/scopes.ex index ada43eae9..7fe04b912 100644 --- a/lib/pleroma/web/o_auth/scopes.ex +++ b/lib/pleroma/web/o_auth/scopes.ex @@ -56,12 +56,20 @@ def to_string(scopes), do: Enum.join(scopes, " ") @doc """ Validates scopes. """ - @spec validate(list() | nil, list()) :: - {:ok, list()} | {:error, :missing_scopes | :unsupported_scopes} - def validate(blank_scopes, _app_scopes) when blank_scopes in [nil, []], + @spec validate(list() | nil, list(), Pleroma.User.t()) :: + {:ok, list()} | {:error, :missing_scopes | :unsupported_scopes, :user_is_not_an_admin} + def validate(blank_scopes, _app_scopes, _user) when blank_scopes in [nil, []], do: {:error, :missing_scopes} - def validate(scopes, app_scopes) do + def validate(scopes, app_scopes, %Pleroma.User{is_admin: is_admin}) do + if !is_admin && contains_admin_scopes?(scopes) do + {:error, :user_is_not_an_admin} + else + validate_scopes_are_supported(scopes, app_scopes) + end + end + + defp validate_scopes_are_supported(scopes, app_scopes) do case OAuthScopesPlug.filter_descendants(scopes, app_scopes) do ^scopes -> {:ok, scopes} _ -> {:error, :unsupported_scopes} diff --git a/test/pleroma/web/o_auth/o_auth_controller_test.exs b/test/pleroma/web/o_auth/o_auth_controller_test.exs index 5a1258ec3..19a7dea60 100644 --- a/test/pleroma/web/o_auth/o_auth_controller_test.exs +++ b/test/pleroma/web/o_auth/o_auth_controller_test.exs @@ -693,45 +693,76 @@ test "with existing authentication and OOB `redirect_uri`, redirects to app with describe "POST /oauth/authorize" do test "redirects with oauth authorization, " <> - "granting requested app-supported scopes to both admin- and non-admin users" do + "granting requested app-supported scopes to both admin users" do app_scopes = ["read", "write", "admin", "secret_scope"] app = insert(:oauth_app, scopes: app_scopes) redirect_uri = OAuthController.default_redirect_uri(app) + scopes_subset = ["read:subscope", "write", "admin"] + admin = insert(:user, is_admin: true) + + # In case scope param is missing, expecting _all_ app-supported scopes to be granted + conn = + post( + build_conn(), + "/oauth/authorize", + %{ + "authorization" => %{ + "name" => admin.nickname, + "password" => "test", + "client_id" => app.client_id, + "redirect_uri" => redirect_uri, + "scope" => scopes_subset, + "state" => "statepassed" + } + } + ) + + target = redirected_to(conn) + assert target =~ redirect_uri + + query = URI.parse(target).query |> URI.query_decoder() |> Map.new() + + assert %{"state" => "statepassed", "code" => code} = query + auth = Repo.get_by(Authorization, token: code) + assert auth + assert auth.scopes == scopes_subset + end + + test "redirects with oauth authorization, " <> + "granting requested app-supported scopes for non-admin users" do + app_scopes = ["read", "write", "secret_scope", "admin"] + app = insert(:oauth_app, scopes: app_scopes) + redirect_uri = OAuthController.default_redirect_uri(app) non_admin = insert(:user, is_admin: false) - admin = insert(:user, is_admin: true) - scopes_subset = ["read:subscope", "write", "admin"] + scopes_subset = ["read:subscope", "write"] # In case scope param is missing, expecting _all_ app-supported scopes to be granted - for user <- [non_admin, admin], - {requested_scopes, expected_scopes} <- - %{scopes_subset => scopes_subset, nil: app_scopes} do - conn = - post( - build_conn(), - "/oauth/authorize", - %{ - "authorization" => %{ - "name" => user.nickname, - "password" => "test", - "client_id" => app.client_id, - "redirect_uri" => redirect_uri, - "scope" => requested_scopes, - "state" => "statepassed" - } + conn = + post( + build_conn(), + "/oauth/authorize", + %{ + "authorization" => %{ + "name" => non_admin.nickname, + "password" => "test", + "client_id" => app.client_id, + "redirect_uri" => redirect_uri, + "scope" => scopes_subset, + "state" => "statepassed" } - ) + } + ) - target = redirected_to(conn) - assert target =~ redirect_uri + target = redirected_to(conn) + assert target =~ redirect_uri - query = URI.parse(target).query |> URI.query_decoder() |> Map.new() + query = URI.parse(target).query |> URI.query_decoder() |> Map.new() - assert %{"state" => "statepassed", "code" => code} = query - auth = Repo.get_by(Authorization, token: code) - assert auth - assert auth.scopes == expected_scopes - end + assert %{"state" => "statepassed", "code" => code} = query + auth = Repo.get_by(Authorization, token: code) + assert auth + assert auth.scopes == scopes_subset end test "authorize from cookie" do @@ -739,6 +770,7 @@ test "authorize from cookie" do app = insert(:oauth_app) oauth_token = insert(:oauth_token, user: user, app: app) redirect_uri = OAuthController.default_redirect_uri(app) + IO.inspect(app) conn = build_conn() @@ -831,6 +863,33 @@ test "returns 401 for wrong credentials", %{conn: conn} do assert result =~ "Invalid Username/Password" end + test "returns 401 when attempting to use an admin scope with a non-admin", %{conn: conn} do + user = insert(:user) + app = insert(:oauth_app, scopes: ["admin"]) + redirect_uri = OAuthController.default_redirect_uri(app) + + result = + conn + |> post("/oauth/authorize", %{ + "authorization" => %{ + "name" => user.nickname, + "password" => "test", + "client_id" => app.client_id, + "redirect_uri" => redirect_uri, + "state" => "statepassed", + "scope" => Enum.join(app.scopes, " ") + } + }) + |> html_response(:unauthorized) + + # Keep the details + assert result =~ app.client_id + assert result =~ redirect_uri + + # Error message + assert result =~ "outside of authorized scopes" + end + test "returns 401 for missing scopes" do user = insert(:user, is_admin: false) app = insert(:oauth_app, scopes: ["read", "write", "admin"]) @@ -855,7 +914,7 @@ test "returns 401 for missing scopes" do assert result =~ redirect_uri # Error message - assert result =~ "This action is outside the authorized scopes" + assert result =~ "This action is outside of authorized scopes" end test "returns 401 for scopes beyond app scopes hierarchy", %{conn: conn} do @@ -882,7 +941,7 @@ test "returns 401 for scopes beyond app scopes hierarchy", %{conn: conn} do assert result =~ redirect_uri # Error message - assert result =~ "This action is outside the authorized scopes" + assert result =~ "This action is outside of authorized scopes" end end From c2054f82abbd67045de21e232e0731e6dbac55a0 Mon Sep 17 00:00:00 2001 From: FloatingGhost Date: Fri, 16 Dec 2022 03:32:51 +0000 Subject: [PATCH 16/41] allow users with admin:metrics to read app metrics --- .gitignore | 1 + .../controllers/metrics_controller.ex | 10 +- lib/pleroma/web/plugs/rate_limiter.ex | 6 +- lib/pleroma/web/router.ex | 7 +- lib/pleroma/web/telemetry.ex | 9 +- lib/pleroma/web/templates/layout/app.html.eex | 32 +++-- .../web/templates/layout/static_fe.html.eex | 4 +- .../o_auth/oob_authorization_created.html.eex | 10 +- .../web/templates/o_auth/o_auth/show.html.eex | 4 +- mix.exs | 2 +- priv/static/static-fe/forms.css | 114 ++++++++++++++++++ priv/static/static-fe/static-fe.css | 61 +++++++--- scripts/create_metrics_app.sh | 65 ++++++++++ test/support/factory.ex | 2 +- 14 files changed, 283 insertions(+), 44 deletions(-) create mode 100644 priv/static/static-fe/forms.css create mode 100755 scripts/create_metrics_app.sh diff --git a/.gitignore b/.gitignore index 14373fb8c..95b236af6 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ docs/site # docker stuff docker-db +*.iml diff --git a/lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex b/lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex index c8d3d8948..8d413bf58 100644 --- a/lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex +++ b/lib/pleroma/web/akkoma_api/controllers/metrics_controller.ex @@ -3,9 +3,13 @@ defmodule Pleroma.Web.AkkomaAPI.MetricsController do alias Pleroma.Web.Plugs.OAuthScopesPlug - @unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []} - plug(:skip_auth) - + plug( + OAuthScopesPlug, + %{scopes: ["admin:metrics"]} + when action in [ + :show + ] + ) def show(conn, _params) do stats = TelemetryMetricsPrometheus.Core.scrape() diff --git a/lib/pleroma/web/plugs/rate_limiter.ex b/lib/pleroma/web/plugs/rate_limiter.ex index 5bebe0ad5..f5ca27f0c 100644 --- a/lib/pleroma/web/plugs/rate_limiter.ex +++ b/lib/pleroma/web/plugs/rate_limiter.ex @@ -197,7 +197,11 @@ defp incorporate_conn_info(action_settings, %{params: params} = conn) do }) end - defp ip(%{remote_ip: remote_ip}) do + defp ip(%{remote_ip: remote_ip}) when is_binary(remote_ip) do + remote_ip + end + + defp ip(%{remote_ip: remote_ip}) when is_tuple(remote_ip) do remote_ip |> Tuple.to_list() |> Enum.join(".") diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index c0ce645c4..f47041b0b 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -868,7 +868,11 @@ defmodule Pleroma.Web.Router do scope "/" do pipe_through([:pleroma_html, :authenticate, :require_admin]) - live_dashboard("/phoenix/live_dashboard", metrics: {Pleroma.Web.Telemetry, :live_dashboard_metrics}, csp_nonce_assign_key: :csp_nonce) + + live_dashboard("/phoenix/live_dashboard", + metrics: {Pleroma.Web.Telemetry, :live_dashboard_metrics}, + csp_nonce_assign_key: :csp_nonce + ) end # Test-only routes needed to test action dispatching and plug chain execution @@ -907,6 +911,7 @@ defmodule Pleroma.Web.Router do scope "/", Pleroma.Web.Fallback do get("/registration/:token", RedirectController, :registration_page) get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta) + get("/api/*path", RedirectController, :api_not_implemented) get("/*path", RedirectController, :redirector_with_preload) options("/*path", RedirectController, :empty) diff --git a/lib/pleroma/web/telemetry.ex b/lib/pleroma/web/telemetry.ex index 435f55799..5b01ee14d 100644 --- a/lib/pleroma/web/telemetry.ex +++ b/lib/pleroma/web/telemetry.ex @@ -11,16 +11,13 @@ def start_link(arg) do def init(_arg) do children = [ {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}, - {TelemetryMetricsPrometheus, metrics: prometheus_metrics(), plug_cowboy_opts: [ip: {127, 0, 0, 1}]} + {TelemetryMetricsPrometheus.Core, metrics: prometheus_metrics()} ] Supervisor.init(children, strategy: :one_for_one) end - @doc """ - A seperate set of metrics for distributions because phoenix dashboard does NOT handle - them well - """ + # A seperate set of metrics for distributions because phoenix dashboard does NOT handle them well defp distribution_metrics do [ distribution( @@ -110,8 +107,6 @@ defp summary_metrics do summary("vm.total_run_queue_lengths.total"), summary("vm.total_run_queue_lengths.cpu"), summary("vm.total_run_queue_lengths.io"), - - last_value("pleroma.local_users.total"), last_value("pleroma.domains.total"), last_value("pleroma.local_statuses.total") diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex index e33bada85..31e6ec52b 100644 --- a/lib/pleroma/web/templates/layout/app.html.eex +++ b/lib/pleroma/web/templates/layout/app.html.eex @@ -4,17 +4,33 @@ <%= Pleroma.Config.get([:instance, :name]) %> - + + - + +
+
- <%= @inner_content %> +
+
+
+ <%= @inner_content %> +
+
+ + diff --git a/lib/pleroma/web/templates/layout/static_fe.html.eex b/lib/pleroma/web/templates/layout/static_fe.html.eex index 3d55393f0..d159eb901 100644 --- a/lib/pleroma/web/templates/layout/static_fe.html.eex +++ b/lib/pleroma/web/templates/layout/static_fe.html.eex @@ -20,8 +20,8 @@
-
- <%= @inner_content %> +
+ <%= @inner_content %>