From 9b6d89ff8c798079f4db18eb2b5c66a7426ecbc5 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Sat, 27 Jun 2020 13:43:25 +0300 Subject: [PATCH 01/10] support for special chars in pack name --- docs/API/pleroma_api.md | 49 +++++++-- lib/pleroma/emoji/pack.ex | 5 +- .../pleroma_emoji_pack_operation.ex | 2 +- lib/pleroma/web/router.ex | 16 +-- test/instance_static/emoji/blobs.gg/blank.png | Bin 0 -> 95 bytes test/instance_static/emoji/blobs.gg/pack.json | 11 ++ .../emoji_pack_controller_test.exs | 104 +++++++++++------- 7 files changed, 128 insertions(+), 59 deletions(-) create mode 100644 test/instance_static/emoji/blobs.gg/blank.png create mode 100644 test/instance_static/emoji/blobs.gg/pack.json diff --git a/docs/API/pleroma_api.md b/docs/API/pleroma_api.md index 94b6a4fda..350849687 100644 --- a/docs/API/pleroma_api.md +++ b/docs/API/pleroma_api.md @@ -379,14 +379,18 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa * Response: JSON, returns a list of Mastodon Conversation entities that were marked as read (200 - healthy, 503 unhealthy). ## `GET /api/pleroma/emoji/packs/import` + ### Imports packs from filesystem + * Method `GET` * Authentication: required * Params: None * Response: JSON, returns a list of imported packs. ## `GET /api/pleroma/emoji/packs/remote` + ### Make request to another instance for packs list + * Method `GET` * Authentication: required * Params: @@ -394,7 +398,9 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa * Response: JSON with the pack list, hashmap with pack name and pack contents ## `POST /api/pleroma/emoji/packs/download` + ### Download pack from another instance + * Method `POST` * Authentication: required * Params: @@ -404,18 +410,24 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa * Response: JSON, "ok" with 200 status if the pack was downloaded, or 500 if there were errors downloading the pack -## `POST /api/pleroma/emoji/packs/:name` +## `POST /api/pleroma/emoji/packs/create?name=:name` + ### Creates an empty pack + * Method `POST` * Authentication: required -* Params: None +* Params: + * `name`: pack name * Response: JSON, "ok" and 200 status or 409 if the pack with that name already exists -## `PATCH /api/pleroma/emoji/packs/:name` +## `PATCH /api/pleroma/emoji/packs/update?name=:name` + ### Updates (replaces) pack metadata + * Method `PATCH` * Authentication: required * Params: + * `name`: pack name * `metadata`: metadata to replace the old one * `license`: Pack license * `homepage`: Pack home page url @@ -426,39 +438,51 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa * Response: JSON, updated "metadata" section of the pack and 200 status or 400 if there was a problem with the new metadata (the error is specified in the "error" part of the response JSON) -## `DELETE /api/pleroma/emoji/packs/:name` +## `DELETE /api/pleroma/emoji/packs/delete?name=:name` + ### Delete a custom emoji pack + * Method `DELETE` * Authentication: required -* Params: None +* Params: + * `name`: pack name * Response: JSON, "ok" and 200 status or 500 if there was an error deleting the pack -## `POST /api/pleroma/emoji/packs/:name/files` +## `POST /api/pleroma/emoji/packs/files?name=:name` + ### Add new file to the pack + * Method `POST` * Authentication: required * Params: + * `name`: pack name * `file`: file needs to be uploaded with the multipart request or link to remote file. * `shortcode`: (*optional*) shortcode for new emoji, must be unique for all emoji. If not sended, shortcode will be taken from original filename. * `filename`: (*optional*) new emoji file name. If not specified will be taken from original filename. * Response: JSON, list of files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message. -## `PATCH /api/pleroma/emoji/packs/:name/files` +## `PATCH /api/pleroma/emoji/packs/files?name=:name` + ### Update emoji file from pack + * Method `PATCH` * Authentication: required * Params: + * `name`: pack name * `shortcode`: emoji file shortcode * `new_shortcode`: new emoji file shortcode * `new_filename`: new filename for emoji file * `force`: (*optional*) with true value to overwrite existing emoji with new shortcode * Response: JSON, list with updated files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message. -## `DELETE /api/pleroma/emoji/packs/:name/files` +## `DELETE /api/pleroma/emoji/packs/files?name=:name` + ### Delete emoji file from pack + * Method `DELETE` * Authentication: required * Params: + * `name`: pack name * `shortcode`: emoji file shortcode * Response: JSON, list with updated files for updated pack (hashmap -> shortcode => filename) with status 200, either error status with error message. @@ -483,7 +507,7 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa } ``` -## `GET /api/pleroma/emoji/packs/:name` +## `GET /api/pleroma/emoji/packs/show?name=:name` ### Get pack.json for the pack @@ -502,11 +526,14 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa } ``` -## `GET /api/pleroma/emoji/packs/:name/archive` +## `GET /api/pleroma/emoji/packs/archive?name=:name` + ### Requests a local pack archive from the instance + * Method `GET` * Authentication: not required -* Params: None +* Params: + * `name`: pack name * Response: the archive of the pack with a 200 status code, 403 if the pack is not set as shared, 404 if the pack does not exist diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index 0b3f8f00b..9901aa832 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -244,7 +244,8 @@ def download(name, url, as) do uri = url |> String.trim() |> URI.parse() with :ok <- validate_shareable_packs_available(uri), - {:ok, remote_pack} <- uri |> URI.merge("/api/pleroma/emoji/packs/#{name}") |> http_get(), + {:ok, remote_pack} <- + uri |> URI.merge("/api/pleroma/emoji/packs/show?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), @@ -572,7 +573,7 @@ defp fetch_pack_info(remote_pack, uri, name) do {:ok, %{ sha: sha, - url: URI.merge(uri, "/api/pleroma/emoji/packs/#{name}/archive") |> to_string() + url: URI.merge(uri, "/api/pleroma/emoji/packs/archive?name=#{name}") |> to_string() }} %{"fallback-src" => src, "fallback-src-sha256" => sha} when is_binary(src) -> 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 59548af13..87ee5feb4 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 @@ -192,7 +192,7 @@ def import_from_filesystem_operation do end defp name_param do - Operation.parameter(:name, :path, :string, "Pack Name", example: "cofe", required: true) + Operation.parameter(:name, :query, :string, "Pack Name", example: "cofe", required: true) end defp url_param do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 42a9db21d..6f591b12f 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -234,21 +234,21 @@ defmodule Pleroma.Web.Router do get("/remote", EmojiPackController, :remote) post("/download", EmojiPackController, :download) - post("/:name", EmojiPackController, :create) - patch("/:name", EmojiPackController, :update) - delete("/:name", EmojiPackController, :delete) + post("/create", EmojiPackController, :create) + patch("/update", EmojiPackController, :update) + delete("/delete", EmojiPackController, :delete) - post("/:name/files", EmojiFileController, :create) - patch("/:name/files", EmojiFileController, :update) - delete("/:name/files", EmojiFileController, :delete) + post("/files", EmojiFileController, :add_file) + patch("/files", EmojiFileController, :update_file) + delete("/files", EmojiFileController, :delete_file) end # Pack info / downloading scope "/packs" do pipe_through(:api) get("/", EmojiPackController, :index) - get("/:name", EmojiPackController, :show) - get("/:name/archive", EmojiPackController, :archive) + get("/show", EmojiPackController, :show) + get("/archive", EmojiPackController, :archive) end end diff --git a/test/instance_static/emoji/blobs.gg/blank.png b/test/instance_static/emoji/blobs.gg/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..8f50fa02340e7e09e562f86e00b6e4bd6ad1d565 GIT binary patch literal 95 zcmeAS@N?(olHy`uVBq!ia0vp^4Is=2Bp6=1#-sr$rjj7PU get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200) - assert resp["count"] == 3 + assert resp["count"] == 4 assert resp["packs"] |> Map.keys() - |> length() == 3 + |> length() == 4 shared = resp["packs"]["test_pack"] assert shared["files"] == %{"blank" => "blank.png", "blank2" => "blank2.png"} @@ -58,7 +58,7 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do |> get("/api/pleroma/emoji/packs?page_size=1") |> json_response_and_validate_schema(200) - assert resp["count"] == 3 + assert resp["count"] == 4 packs = Map.keys(resp["packs"]) @@ -71,7 +71,7 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do |> get("/api/pleroma/emoji/packs?page_size=1&page=2") |> json_response_and_validate_schema(200) - assert resp["count"] == 3 + assert resp["count"] == 4 packs = Map.keys(resp["packs"]) assert length(packs) == 1 [pack2] = packs @@ -81,11 +81,21 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do |> get("/api/pleroma/emoji/packs?page_size=1&page=3") |> json_response_and_validate_schema(200) - assert resp["count"] == 3 + assert resp["count"] == 4 packs = Map.keys(resp["packs"]) assert length(packs) == 1 [pack3] = packs - assert [pack1, pack2, pack3] |> Enum.uniq() |> length() == 3 + + resp = + conn + |> get("/api/pleroma/emoji/packs?page_size=1&page=4") + |> json_response_and_validate_schema(200) + + assert resp["count"] == 4 + packs = Map.keys(resp["packs"]) + assert length(packs) == 1 + [pack4] = packs + assert [pack1, pack2, pack3, pack4] |> Enum.uniq() |> length() == 4 end describe "GET /api/pleroma/emoji/packs/remote" do @@ -128,11 +138,11 @@ test "non shareable instance", %{admin_conn: admin_conn} do end end - describe "GET /api/pleroma/emoji/packs/:name/archive" do + describe "GET /api/pleroma/emoji/packs/archive?name=:name" do test "download shared pack", %{conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs/test_pack/archive") + |> get("/api/pleroma/emoji/packs/archive?name=test_pack") |> response(200) {:ok, arch} = :zip.unzip(resp, [:memory]) @@ -143,7 +153,7 @@ test "download shared pack", %{conn: conn} do test "non existing pack", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/packs/test_pack_for_import/archive") + |> get("/api/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" } @@ -151,7 +161,7 @@ test "non existing pack", %{conn: conn} do test "non downloadable pack", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/packs/test_pack_nonshared/archive") + |> get("/api/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" @@ -173,28 +183,28 @@ test "shared pack from remote and non shared from fallback-src", %{ %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/test_pack" + url: "https://example.com/api/pleroma/emoji/packs/show?name=test_pack" } -> conn - |> get("/api/pleroma/emoji/packs/test_pack") + |> get("/api/pleroma/emoji/packs/show?name=test_pack") |> json_response_and_validate_schema(200) |> json() %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/test_pack/archive" + url: "https://example.com/api/pleroma/emoji/packs/archive?name=test_pack" } -> conn - |> get("/api/pleroma/emoji/packs/test_pack/archive") + |> get("/api/pleroma/emoji/packs/archive?name=test_pack") |> response(200) |> text() %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/test_pack_nonshared" + url: "https://example.com/api/pleroma/emoji/packs/show?name=test_pack_nonshared" } -> conn - |> get("/api/pleroma/emoji/packs/test_pack_nonshared") + |> get("/api/pleroma/emoji/packs/show?name=test_pack_nonshared") |> json_response_and_validate_schema(200) |> json() @@ -218,7 +228,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/packs/test_pack2") + |> delete("/api/pleroma/emoji/packs/delete?name=test_pack2") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_pack2") @@ -239,7 +249,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/packs/test_pack_nonshared2") + |> delete("/api/pleroma/emoji/packs/delete?name=test_pack_nonshared2") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_pack_nonshared2") @@ -279,14 +289,14 @@ test "checksum fail", %{admin_conn: admin_conn} do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha" + url: "https://example.com/api/pleroma/emoji/packs/show?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/pack_bad_sha/archive" + url: "https://example.com/api/pleroma/emoji/packs/archive?name=pack_bad_sha" } -> %Tesla.Env{ status: 200, @@ -316,7 +326,7 @@ test "other error", %{admin_conn: admin_conn} do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/test_pack" + url: "https://example.com/api/pleroma/emoji/packs/show?name=test_pack" } -> {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack") %Tesla.Env{status: 200, body: Jason.encode!(pack)} @@ -336,7 +346,7 @@ test "other error", %{admin_conn: admin_conn} do end end - describe "PATCH /api/pleroma/emoji/packs/:name" do + describe "PATCH /api/pleroma/emoji/packs/update?name=:name" do setup do pack_file = "#{@emoji_path}/test_pack/pack.json" original_content = File.read!(pack_file) @@ -358,7 +368,9 @@ test "other error", %{admin_conn: admin_conn} 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/packs/test_pack", %{"metadata" => ctx[:new_data]}) + |> patch("/api/pleroma/emoji/packs/update?name=test_pack", %{ + "metadata" => ctx[:new_data] + }) |> json_response_and_validate_schema(200) == ctx[:new_data] assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data] @@ -384,7 +396,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/packs/test_pack", %{metadata: new_data}) + |> patch("/api/pleroma/emoji/packs/update?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 @@ -404,17 +416,17 @@ 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/packs/test_pack", %{metadata: new_data}) + |> patch("/api/pleroma/emoji/packs/update?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/packs/:name" do + describe "POST/DELETE /api/pleroma/emoji/packs/?name=:name" do test "creating and deleting a pack", %{admin_conn: admin_conn} do assert admin_conn - |> post("/api/pleroma/emoji/packs/test_created") + |> post("/api/pleroma/emoji/packs/create?name=test_created") |> json_response_and_validate_schema(200) == "ok" assert File.exists?("#{@emoji_path}/test_created/pack.json") @@ -426,7 +438,7 @@ test "creating and deleting a pack", %{admin_conn: admin_conn} do } assert admin_conn - |> delete("/api/pleroma/emoji/packs/test_created") + |> delete("/api/pleroma/emoji/packs/delete?name=test_created") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_created/pack.json") @@ -439,7 +451,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/packs/test_created") + |> post("/api/pleroma/emoji/packs/create?name=test_created") |> json_response_and_validate_schema(:conflict) == %{ "error" => "A pack named \"test_created\" already exists" } @@ -449,7 +461,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/packs/ ") + |> post("/api/pleroma/emoji/packs/create?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } @@ -458,7 +470,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/packs/non_existing") + |> delete("/api/pleroma/emoji/packs/delete?name=non_existing") |> json_response_and_validate_schema(:not_found) == %{ "error" => "Pack non_existing does not exist" } @@ -466,7 +478,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/packs/ ") + |> delete("/api/pleroma/emoji/packs/delete?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } @@ -529,7 +541,7 @@ test "shows pack.json", %{conn: conn} do } } = conn - |> get("/api/pleroma/emoji/packs/test_pack") + |> get("/api/pleroma/emoji/packs/show?name=test_pack") |> json_response_and_validate_schema(200) assert files == %{"blank" => "blank.png", "blank2" => "blank2.png"} @@ -539,7 +551,7 @@ test "shows pack.json", %{conn: conn} do "files_count" => 2 } = conn - |> get("/api/pleroma/emoji/packs/test_pack?page_size=1") + |> get("/api/pleroma/emoji/packs/show?name=test_pack&page_size=1") |> json_response_and_validate_schema(200) assert files |> Map.keys() |> length() == 1 @@ -549,15 +561,33 @@ test "shows pack.json", %{conn: conn} do "files_count" => 2 } = conn - |> get("/api/pleroma/emoji/packs/test_pack?page_size=1&page=2") + |> get("/api/pleroma/emoji/packs/show?name=test_pack&page_size=1&page=2") |> json_response_and_validate_schema(200) assert files |> Map.keys() |> length() == 1 end + test "for pack name with special chars", %{conn: conn} do + assert %{ + "files" => files, + "files_count" => 1, + "pack" => %{ + "can-download" => true, + "description" => "Test description", + "download-sha256" => _, + "homepage" => "https://pleroma.social", + "license" => "Test license", + "share-files" => true + } + } = + conn + |> get("/api/pleroma/emoji/packs/show?name=blobs.gg") + |> json_response_and_validate_schema(200) + end + test "non existing pack", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/packs/non_existing") + |> get("/api/pleroma/emoji/packs/show?name=non_existing") |> json_response_and_validate_schema(:not_found) == %{ "error" => "Pack non_existing does not exist" } @@ -565,7 +595,7 @@ test "non existing pack", %{conn: conn} do test "error name", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/packs/ ") + |> get("/api/pleroma/emoji/packs/show?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } From dbbc8016670166c24a29dcc3e2f0d66bb2f4e35f Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Sat, 27 Jun 2020 14:33:49 +0300 Subject: [PATCH 02/10] pagination for remote emoji packs --- lib/pleroma/emoji/pack.ex | 8 ++++---- .../operations/pleroma_emoji_pack_operation.ex | 16 +++++++++++++++- .../controllers/emoji_pack_controller.ex | 5 +++-- .../controllers/emoji_pack_controller_test.exs | 6 +++--- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index 9901aa832..4420eff5a 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -198,13 +198,13 @@ def import_from_filesystem do end end - @spec list_remote(String.t()) :: {:ok, map()} | {:error, atom()} - def list_remote(url) do - uri = url |> String.trim() |> URI.parse() + @spec list_remote(keyword()) :: {:ok, map()} | {:error, atom()} + def list_remote(opts) do + uri = opts[:url] |> String.trim() |> URI.parse() with :ok <- validate_shareable_packs_available(uri) do uri - |> URI.merge("/api/pleroma/emoji/packs") + |> URI.merge("/api/pleroma/emoji/packs?page=#{opts[:page]}&page_size=#{opts[:page_size]}") |> http_get() 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 87ee5feb4..79f52dcb3 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 @@ -19,7 +19,21 @@ def remote_operation do tags: ["Emoji Packs"], summary: "Make request to another instance for emoji packs list", security: [%{"oAuth" => ["write"]}], - parameters: [url_param()], + parameters: [ + url_param(), + Operation.parameter( + :page, + :query, + %Schema{type: :integer, default: 1}, + "Page" + ), + Operation.parameter( + :page_size, + :query, + %Schema{type: :integer, default: 30}, + "Number of emoji to return" + ) + ], operationId: "PleromaAPI.EmojiPackController.remote", responses: %{ 200 => emoji_packs_response(), diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex index e3969fee1..6696f8b92 100644 --- a/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex @@ -23,8 +23,9 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PleromaEmojiPackOperation - def remote(conn, %{url: url}) do - with {:ok, packs} <- Pack.list_remote(url) do + def remote(conn, params) do + with {:ok, packs} <- + Pack.list_remote(url: params.url, page_size: params.page_size, page: params.page) do json(conn, packs) else {:error, :not_shareable} -> diff --git a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs index 068755936..95fd78c7e 100644 --- a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs +++ b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs @@ -102,7 +102,7 @@ test "GET /api/pleroma/emoji/packs", %{conn: conn} do test "shareable instance", %{admin_conn: admin_conn, conn: conn} do resp = conn - |> get("/api/pleroma/emoji/packs") + |> get("/api/pleroma/emoji/packs?page=2&page_size=1") |> json_response_and_validate_schema(200) mock(fn @@ -112,12 +112,12 @@ 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"} -> + %{method: :get, url: "https://example.com/api/pleroma/emoji/packs?page=2&page_size=1"} -> json(resp) end) assert admin_conn - |> get("/api/pleroma/emoji/packs/remote?url=https://example.com") + |> get("/api/pleroma/emoji/packs/remote?url=https://example.com&page=2&page_size=1") |> json_response_and_validate_schema(200) == resp end From 958008cc14ef74050d340dcc1865d25f069cf232 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Mon, 17 Aug 2020 11:19:49 +0300 Subject: [PATCH 03/10] changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f5d01af3..46962b6ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -120,6 +120,7 @@ switched to a new configuration mechanism, however it was not officially removed - Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone` - Mastodon API: Make notifications about statuses from muted users and threads read automatically - Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value. +- Pleroma API: Pagination for remote/local packs and emoji. From 8c6ec4c111081b34f68363ce20423e2f338fa2dd Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Sun, 20 Sep 2020 09:51:36 +0300 Subject: [PATCH 04/10] pack routes change --- docs/API/pleroma_api.md | 108 +++++++++--------- lib/pleroma/emoji/pack.ex | 4 +- lib/pleroma/web/router.ex | 16 ++- .../emoji_pack_controller_test.exs | 52 ++++----- 4 files changed, 97 insertions(+), 83 deletions(-) diff --git a/docs/API/pleroma_api.md b/docs/API/pleroma_api.md index 350849687..96fd4da73 100644 --- a/docs/API/pleroma_api.md +++ b/docs/API/pleroma_api.md @@ -378,54 +378,41 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa * Params: None * Response: JSON, returns a list of Mastodon Conversation entities that were marked as read (200 - healthy, 503 unhealthy). -## `GET /api/pleroma/emoji/packs/import` +## `GET /api/pleroma/emoji/pack?name=:name` -### Imports packs from filesystem +### Get pack.json for the pack * Method `GET` -* Authentication: required -* Params: None -* Response: JSON, returns a list of imported packs. - -## `GET /api/pleroma/emoji/packs/remote` - -### Make request to another instance for packs list - -* Method `GET` -* Authentication: required +* Authentication: not required * Params: - * `url`: url of the instance to get packs from -* Response: JSON with the pack list, hashmap with pack name and pack contents + * `page`: page number for files (default 1) + * `page_size`: page size for files (default 30) +* Response: JSON, pack json with `files`, `files_count` and `pack` keys with 200 status or 404 if the pack does not exist. -## `POST /api/pleroma/emoji/packs/download` +```json +{ + "files": {...}, + "files_count": 0, // emoji count in pack + "pack": {...} +} +``` -### Download pack from another instance - -* Method `POST` -* Authentication: required -* Params: - * `url`: url of the instance to download from - * `name`: pack to download from that instance - * `as`: (*optional*) name how to save pack -* Response: JSON, "ok" with 200 status if the pack was downloaded, or 500 if there were - errors downloading the pack - -## `POST /api/pleroma/emoji/packs/create?name=:name` +## `POST /api/pleroma/emoji/pack?name=:name` ### Creates an empty pack * Method `POST` -* Authentication: required +* Authentication: required (admin) * Params: * `name`: pack name * Response: JSON, "ok" and 200 status or 409 if the pack with that name already exists -## `PATCH /api/pleroma/emoji/packs/update?name=:name` +## `PATCH /api/pleroma/emoji/pack?name=:name` ### Updates (replaces) pack metadata * Method `PATCH` -* Authentication: required +* Authentication: required (admin) * Params: * `name`: pack name * `metadata`: metadata to replace the old one @@ -438,22 +425,54 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa * Response: JSON, updated "metadata" section of the pack and 200 status or 400 if there was a problem with the new metadata (the error is specified in the "error" part of the response JSON) -## `DELETE /api/pleroma/emoji/packs/delete?name=:name` +## `DELETE /api/pleroma/emoji/pack?name=:name` ### Delete a custom emoji pack * Method `DELETE` -* Authentication: required +* Authentication: required (admin) * Params: * `name`: pack name * Response: JSON, "ok" and 200 status or 500 if there was an error deleting the pack +## `GET /api/pleroma/emoji/packs/import` + +### Imports packs from filesystem + +* Method `GET` +* Authentication: required (admin) +* Params: None +* Response: JSON, returns a list of imported packs. + +## `GET /api/pleroma/emoji/packs/remote` + +### Make request to another instance for packs list + +* Method `GET` +* Authentication: required (admin) +* Params: + * `url`: url of the instance to get packs from +* Response: JSON with the pack list, hashmap with pack name and pack contents + +## `POST /api/pleroma/emoji/packs/download` + +### Download pack from another instance + +* Method `POST` +* Authentication: required (admin) +* Params: + * `url`: url of the instance to download from + * `name`: pack to download from that instance + * `as`: (*optional*) name how to save pack +* Response: JSON, "ok" with 200 status if the pack was downloaded, or 500 if there were + errors downloading the pack + ## `POST /api/pleroma/emoji/packs/files?name=:name` ### Add new file to the pack * Method `POST` -* Authentication: required +* Authentication: required (admin) * Params: * `name`: pack name * `file`: file needs to be uploaded with the multipart request or link to remote file. @@ -466,7 +485,7 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa ### Update emoji file from pack * Method `PATCH` -* Authentication: required +* Authentication: required (admin) * Params: * `name`: pack name * `shortcode`: emoji file shortcode @@ -480,7 +499,7 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa ### Delete emoji file from pack * Method `DELETE` -* Authentication: required +* Authentication: required (admin) * Params: * `name`: pack name * `shortcode`: emoji file shortcode @@ -507,25 +526,6 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa } ``` -## `GET /api/pleroma/emoji/packs/show?name=:name` - -### Get pack.json for the pack - -* Method `GET` -* Authentication: not required -* Params: - * `page`: page number for files (default 1) - * `page_size`: page size for files (default 30) -* Response: JSON, pack json with `files`, `files_count` and `pack` keys with 200 status or 404 if the pack does not exist. - -```json -{ - "files": {...}, - "files_count": 0, // emoji count in pack - "pack": {...} -} -``` - ## `GET /api/pleroma/emoji/packs/archive?name=:name` ### Requests a local pack archive from the instance diff --git a/lib/pleroma/emoji/pack.ex b/lib/pleroma/emoji/pack.ex index 4420eff5a..8f1989ada 100644 --- a/lib/pleroma/emoji/pack.ex +++ b/lib/pleroma/emoji/pack.ex @@ -245,7 +245,7 @@ def download(name, url, as) do with :ok <- validate_shareable_packs_available(uri), {:ok, remote_pack} <- - uri |> URI.merge("/api/pleroma/emoji/packs/show?name=#{name}") |> http_get(), + uri |> URI.merge("/api/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), @@ -524,7 +524,7 @@ defp get_filename(pack, shortcode) do defp http_get(%URI{} = url), do: url |> to_string() |> http_get() defp http_get(url) do - with {:ok, %{body: body}} <- url |> Pleroma.HTTP.get() do + with {:ok, %{body: body}} <- Pleroma.HTTP.get(url, [], pool: :default) do Jason.decode(body) end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 6f591b12f..707d5e1c4 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -226,6 +226,20 @@ defmodule Pleroma.Web.Router do end scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do + scope "/pack" do + pipe_through(:admin_api) + + post("/", EmojiPackController, :create) + patch("/", EmojiPackController, :update) + delete("/", EmojiPackController, :delete) + end + + scope "/pack" do + pipe_through(:api) + + get("/", EmojiPackController, :show) + end + # Modifying packs scope "/packs" do pipe_through(:admin_api) @@ -246,8 +260,8 @@ defmodule Pleroma.Web.Router do # Pack info / downloading scope "/packs" do pipe_through(:api) + get("/", EmojiPackController, :index) - get("/show", EmojiPackController, :show) get("/archive", EmojiPackController, :archive) end end diff --git a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs index 95fd78c7e..386ad8634 100644 --- a/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs +++ b/test/web/pleroma_api/controllers/emoji_pack_controller_test.exs @@ -183,10 +183,10 @@ test "shared pack from remote and non shared from fallback-src", %{ %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/show?name=test_pack" + url: "https://example.com/api/pleroma/emoji/pack?name=test_pack" } -> conn - |> get("/api/pleroma/emoji/packs/show?name=test_pack") + |> get("/api/pleroma/emoji/pack?name=test_pack") |> json_response_and_validate_schema(200) |> json() @@ -201,10 +201,10 @@ test "shared pack from remote and non shared from fallback-src", %{ %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/show?name=test_pack_nonshared" + url: "https://example.com/api/pleroma/emoji/pack?name=test_pack_nonshared" } -> conn - |> get("/api/pleroma/emoji/packs/show?name=test_pack_nonshared") + |> get("/api/pleroma/emoji/pack?name=test_pack_nonshared") |> json_response_and_validate_schema(200) |> json() @@ -228,7 +228,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/packs/delete?name=test_pack2") + |> delete("/api/pleroma/emoji/pack?name=test_pack2") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_pack2") @@ -249,7 +249,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/packs/delete?name=test_pack_nonshared2") + |> delete("/api/pleroma/emoji/pack?name=test_pack_nonshared2") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_pack_nonshared2") @@ -289,7 +289,7 @@ test "checksum fail", %{admin_conn: admin_conn} do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/show?name=pack_bad_sha" + url: "https://example.com/api/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)} @@ -326,7 +326,7 @@ test "other error", %{admin_conn: admin_conn} do %{ method: :get, - url: "https://example.com/api/pleroma/emoji/packs/show?name=test_pack" + url: "https://example.com/api/pleroma/emoji/pack?name=test_pack" } -> {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack") %Tesla.Env{status: 200, body: Jason.encode!(pack)} @@ -346,7 +346,7 @@ test "other error", %{admin_conn: admin_conn} do end end - describe "PATCH /api/pleroma/emoji/packs/update?name=:name" do + describe "PATCH /api/pleroma/emoji/pack?name=:name" do setup do pack_file = "#{@emoji_path}/test_pack/pack.json" original_content = File.read!(pack_file) @@ -368,7 +368,7 @@ test "other error", %{admin_conn: admin_conn} 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/packs/update?name=test_pack", %{ + |> patch("/api/pleroma/emoji/pack?name=test_pack", %{ "metadata" => ctx[:new_data] }) |> json_response_and_validate_schema(200) == ctx[:new_data] @@ -396,7 +396,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/packs/update?name=test_pack", %{metadata: new_data}) + |> patch("/api/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 @@ -416,17 +416,17 @@ 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/packs/update?name=test_pack", %{metadata: new_data}) + |> patch("/api/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/packs/?name=:name" do + describe "POST/DELETE /api/pleroma/emoji/pack?name=:name" do test "creating and deleting a pack", %{admin_conn: admin_conn} do assert admin_conn - |> post("/api/pleroma/emoji/packs/create?name=test_created") + |> post("/api/pleroma/emoji/pack?name=test_created") |> json_response_and_validate_schema(200) == "ok" assert File.exists?("#{@emoji_path}/test_created/pack.json") @@ -438,7 +438,7 @@ test "creating and deleting a pack", %{admin_conn: admin_conn} do } assert admin_conn - |> delete("/api/pleroma/emoji/packs/delete?name=test_created") + |> delete("/api/pleroma/emoji/pack?name=test_created") |> json_response_and_validate_schema(200) == "ok" refute File.exists?("#{@emoji_path}/test_created/pack.json") @@ -451,7 +451,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/packs/create?name=test_created") + |> post("/api/pleroma/emoji/pack?name=test_created") |> json_response_and_validate_schema(:conflict) == %{ "error" => "A pack named \"test_created\" already exists" } @@ -461,7 +461,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/packs/create?name= ") + |> post("/api/pleroma/emoji/pack?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } @@ -470,7 +470,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/packs/delete?name=non_existing") + |> delete("/api/pleroma/emoji/pack?name=non_existing") |> json_response_and_validate_schema(:not_found) == %{ "error" => "Pack non_existing does not exist" } @@ -478,7 +478,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/packs/delete?name= ") + |> delete("/api/pleroma/emoji/pack?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } @@ -526,7 +526,7 @@ test "filesystem import", %{admin_conn: admin_conn, conn: conn} do } end - describe "GET /api/pleroma/emoji/packs/:name" do + describe "GET /api/pleroma/emoji/pack?name=:name" do test "shows pack.json", %{conn: conn} do assert %{ "files" => files, @@ -541,7 +541,7 @@ test "shows pack.json", %{conn: conn} do } } = conn - |> get("/api/pleroma/emoji/packs/show?name=test_pack") + |> get("/api/pleroma/emoji/pack?name=test_pack") |> json_response_and_validate_schema(200) assert files == %{"blank" => "blank.png", "blank2" => "blank2.png"} @@ -551,7 +551,7 @@ test "shows pack.json", %{conn: conn} do "files_count" => 2 } = conn - |> get("/api/pleroma/emoji/packs/show?name=test_pack&page_size=1") + |> get("/api/pleroma/emoji/pack?name=test_pack&page_size=1") |> json_response_and_validate_schema(200) assert files |> Map.keys() |> length() == 1 @@ -561,7 +561,7 @@ test "shows pack.json", %{conn: conn} do "files_count" => 2 } = conn - |> get("/api/pleroma/emoji/packs/show?name=test_pack&page_size=1&page=2") + |> get("/api/pleroma/emoji/pack?name=test_pack&page_size=1&page=2") |> json_response_and_validate_schema(200) assert files |> Map.keys() |> length() == 1 @@ -581,13 +581,13 @@ test "for pack name with special chars", %{conn: conn} do } } = conn - |> get("/api/pleroma/emoji/packs/show?name=blobs.gg") + |> get("/api/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/packs/show?name=non_existing") + |> get("/api/pleroma/emoji/pack?name=non_existing") |> json_response_and_validate_schema(:not_found) == %{ "error" => "Pack non_existing does not exist" } @@ -595,7 +595,7 @@ test "non existing pack", %{conn: conn} do test "error name", %{conn: conn} do assert conn - |> get("/api/pleroma/emoji/packs/show?name= ") + |> get("/api/pleroma/emoji/pack?name= ") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "pack name cannot be empty" } From 871fac3e4c9d8b1a138204ac754b2a9633bd9eaa Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Thu, 24 Sep 2020 09:41:40 +0300 Subject: [PATCH 05/10] docs update --- docs/API/pleroma_api.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/API/pleroma_api.md b/docs/API/pleroma_api.md index 96fd4da73..3fd141bd2 100644 --- a/docs/API/pleroma_api.md +++ b/docs/API/pleroma_api.md @@ -452,6 +452,8 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa * Authentication: required (admin) * Params: * `url`: url of the instance to get packs from + * `page`: page number for packs (default 1) + * `page_size`: page size for packs (default 50) * Response: JSON with the pack list, hashmap with pack name and pack contents ## `POST /api/pleroma/emoji/packs/download` From 5d7ec00bedc61e8899941c374604ae5854c62f4c Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Thu, 24 Sep 2020 09:42:30 +0300 Subject: [PATCH 06/10] fixes after rebase --- .../pleroma_emoji_file_operation.ex | 2 +- lib/pleroma/web/router.ex | 10 ++--- test/utils_test.exs | 2 +- .../emoji_file_controller_test.exs | 40 +++++++++---------- 4 files changed, 25 insertions(+), 29 deletions(-) diff --git a/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex index efbfce75f..a56641426 100644 --- a/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex +++ b/lib/pleroma/web/api_spec/operations/pleroma_emoji_file_operation.ex @@ -126,7 +126,7 @@ def delete_operation do end defp name_param do - Operation.parameter(:name, :path, :string, "Pack Name", example: "cofe", required: true) + Operation.parameter(:name, :query, :string, "Pack Name", example: "cofe", required: true) end defp files_object do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 707d5e1c4..e22b31b4c 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -248,13 +248,9 @@ defmodule Pleroma.Web.Router do get("/remote", EmojiPackController, :remote) post("/download", EmojiPackController, :download) - post("/create", EmojiPackController, :create) - patch("/update", EmojiPackController, :update) - delete("/delete", EmojiPackController, :delete) - - post("/files", EmojiFileController, :add_file) - patch("/files", EmojiFileController, :update_file) - delete("/files", EmojiFileController, :delete_file) + post("/files", EmojiFileController, :create) + patch("/files", EmojiFileController, :update) + delete("/files", EmojiFileController, :delete) end # Pack info / downloading diff --git a/test/utils_test.exs b/test/utils_test.exs index 3a730d545..460f7e0b5 100644 --- a/test/utils_test.exs +++ b/test/utils_test.exs @@ -8,7 +8,7 @@ defmodule Pleroma.UtilsTest do describe "tmp_dir/1" do test "returns unique temporary directory" do {:ok, path} = Pleroma.Utils.tmp_dir("emoji") - assert path =~ ~r/\/tmp\/emoji-(.*)-#{:os.getpid()}-(.*)/ + assert path =~ ~r/\/emoji-(.*)-#{:os.getpid()}-(.*)/ File.rm_rf(path) end end diff --git a/test/web/pleroma_api/controllers/emoji_file_controller_test.exs b/test/web/pleroma_api/controllers/emoji_file_controller_test.exs index 39b4e1dac..82de86ee3 100644 --- a/test/web/pleroma_api/controllers/emoji_file_controller_test.exs +++ b/test/web/pleroma_api/controllers/emoji_file_controller_test.exs @@ -29,7 +29,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileControllerTest do {:ok, %{admin_conn: admin_conn}} end - describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/:name/files" do + describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/files?name=:name" do setup do pack_file = "#{@emoji_path}/test_pack/pack.json" original_content = File.read!(pack_file) @@ -56,7 +56,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ file: %Plug.Upload{ content_type: "application/zip", filename: "emojis.zip", @@ -83,7 +83,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank", filename: "dir/blank.png", file: %Plug.Upload{ @@ -101,7 +101,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", filename: "dir/blank.png", file: %Plug.Upload{ @@ -119,7 +119,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/test_pack/files", %{ + |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank", new_shortcode: "blank2", new_filename: "dir_2/blank_3.png" @@ -135,7 +135,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", filename: "dir/blank.png", file: %Plug.Upload{ @@ -153,7 +153,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/test_pack/files", %{ + |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", new_shortcode: "blank4", new_filename: "dir_2/blank_3.png", @@ -171,7 +171,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank2", filename: "", file: %Plug.Upload{ @@ -187,7 +187,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/not_loaded/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=not_loaded", %{ shortcode: "blank3", filename: "dir/blank.png", file: %Plug.Upload{ @@ -202,7 +202,7 @@ test "add file with not loaded pack", %{admin_conn: admin_conn} do test "remove file with not loaded pack", %{admin_conn: admin_conn} do assert admin_conn - |> delete("/api/pleroma/emoji/packs/not_loaded/files?shortcode=blank3") + |> delete("/api/pleroma/emoji/packs/files?name=not_loaded&shortcode=blank3") |> json_response_and_validate_schema(:not_found) == %{ "error" => "pack \"not_loaded\" is not found" } @@ -210,7 +210,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/not_loaded/files?shortcode=") + |> delete("/api/pleroma/emoji/packs/files?name=not_loaded&shortcode=") |> json_response_and_validate_schema(:not_found) == %{ "error" => "pack \"not_loaded\" is not found" } @@ -219,7 +219,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/not_loaded/files", %{ + |> patch("/api/pleroma/emoji/packs/files?name=not_loaded", %{ shortcode: "blank4", new_shortcode: "blank3", new_filename: "dir_2/blank_3.png" @@ -232,7 +232,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank4", filename: "dir/blank.png", file: %Plug.Upload{ @@ -250,7 +250,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/test_pack/files", %{ + |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank4", new_shortcode: "blank3", new_filename: "dir_2/blank_3.png" @@ -265,7 +265,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/test_pack/files?shortcode=blank3") + |> delete("/api/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") |> json_response_and_validate_schema(200) == %{ "blank" => "blank.png", "blank2" => "blank2.png" @@ -287,7 +287,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank_url", file: "https://test-blank/blank_url.png" }) @@ -307,7 +307,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/test_pack/files", %{ + |> post("/api/pleroma/emoji/packs/files?name=test_pack", %{ file: %Plug.Upload{ filename: "shortcode.png", path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png" @@ -322,7 +322,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/test_pack/files?shortcode=blank3") + |> delete("/api/pleroma/emoji/packs/files?name=test_pack&shortcode=blank3") |> json_response_and_validate_schema(:bad_request) == %{ "error" => "Emoji \"blank3\" does not exist" } @@ -331,7 +331,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/test_pack/files", %{ + |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank3", new_shortcode: "blank4", new_filename: "dir_2/blank_3.png" @@ -347,7 +347,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/test_pack/files", %{ + |> patch("/api/pleroma/emoji/packs/files?name=test_pack", %{ shortcode: "blank", new_filename: "dir_2/blank_3.png" }) From 727a0556a996a4b990366c6f7ad45f78b0b34c4a Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Thu, 24 Sep 2020 09:47:23 +0300 Subject: [PATCH 07/10] fix --- test/emoji_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/emoji_test.exs b/test/emoji_test.exs index b36047578..1dd3c58c6 100644 --- a/test/emoji_test.exs +++ b/test/emoji_test.exs @@ -3,7 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.EmojiTest do - use ExUnit.Case, async: true + use ExUnit.Case alias Pleroma.Emoji describe "is_unicode_emoji?/1" do From 3f201475e099aecf0c77ca5396b114433ea58224 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Thu, 24 Sep 2020 09:54:10 +0300 Subject: [PATCH 08/10] changelog entry --- CHANGELOG.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46962b6ff..af267face 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed +- **Breaking:** Pleroma API: packs and files routes changed. - Renamed `:await_up_timeout` in `:connections_pool` namespace to `:connect_timeout`, old name is deprecated. - Renamed `:timeout` in `pools` namespace to `:recv_timeout`, old name is deprecated. - The `discoverable` field in the `User` struct will now add a NOINDEX metatag to profile pages when false. @@ -14,10 +15,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Minimum lifetime for ephmeral activities changed to 10 minutes and made configurable (`:min_lifetime` option). ### Added + - Media preview proxy (requires media proxy be enabled; see `:media_preview_proxy` config for more details). -- Pleroma API: Importing the mutes users from CSV files. - Experimental websocket-based federation between Pleroma instances. + +
+ API Changes + +- Pleroma API: Importing the mutes users from CSV files. - Admin API: Importing emoji from a zip file +- Pleroma API: Pagination for remote/local packs and emoji. + +
### Removed @@ -120,7 +129,6 @@ switched to a new configuration mechanism, however it was not officially removed - Mastodon API (legacy): Allow query parameters for `/api/v1/domain_blocks`, e.g. `/api/v1/domain_blocks?domain=badposters.zone` - Mastodon API: Make notifications about statuses from muted users and threads read automatically - Pleroma API: `/api/pleroma/captcha` responses now include `seconds_valid` with an integer value. -- Pleroma API: Pagination for remote/local packs and emoji. From 006b62fd12adadbf698419990ab13bf6f1e901b2 Mon Sep 17 00:00:00 2001 From: rinpatch Date: Tue, 29 Sep 2020 21:49:04 +0300 Subject: [PATCH 09/10] OpenAPI CastAndValidate: filter out empty params Closes #2198 --- CHANGELOG.md | 5 +++++ lib/pleroma/web/api_spec/cast_and_validate.ex | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80fbc078d..983ddd628 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,11 @@ switched to a new configuration mechanism, however it was not officially removed - Add documented-but-missing chat pagination. - Allow sending out emails again. +## Unreleased (Patch) + +### Changed +- API: Empty parameter values for integer parameters are now ignored in non-strict validaton mode. + ## [2.1.2] - 2020-09-17 ### Security diff --git a/lib/pleroma/web/api_spec/cast_and_validate.ex b/lib/pleroma/web/api_spec/cast_and_validate.ex index fbfc27d6f..6d1a7ebbc 100644 --- a/lib/pleroma/web/api_spec/cast_and_validate.ex +++ b/lib/pleroma/web/api_spec/cast_and_validate.ex @@ -115,6 +115,10 @@ defp cast_and_validate(spec, operation, conn, content_type, false = _strict) do %{reason: :unexpected_field, name: name, path: [name]}, params -> Map.delete(params, name) + # Filter out empty params + %{reason: :invalid_type, path: [name_atom], value: ""}, params -> + Map.delete(params, to_string(name_atom)) + %{reason: :invalid_enum, name: nil, path: path, value: value}, params -> path = path |> Enum.reverse() |> tl() |> Enum.reverse() |> list_items_to_string() update_in(params, path, &List.delete(&1, value)) From 8d093a68a6b54eff232566dfd7f52e9c8682398a Mon Sep 17 00:00:00 2001 From: lain Date: Mon, 5 Oct 2020 13:58:12 +0200 Subject: [PATCH 10/10] Docs: Modify docs so the postgres config is harder to get wrong. --- docs/installation/otp_en.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md index f6b05c887..92584d80d 100644 --- a/docs/installation/otp_en.md +++ b/docs/installation/otp_en.md @@ -101,6 +101,8 @@ It is encouraged to check [Optimizing your PostgreSQL performance](../configurat If you are using PostgreSQL 12 or higher, add this to your Ecto database configuration ```elixir +# +config :pleroma, Pleroma.Repo, prepare: :named, parameters: [ plan_cache_mode: "force_custom_plan"