return data only for updated emoji

This commit is contained in:
Alexander Strizhakov 2020-02-06 18:01:12 +03:00
parent 4c4344b7b1
commit 5839e67eb8
No known key found for this signature in database
GPG key ID: 022896A53AEF1381
5 changed files with 149 additions and 115 deletions

View file

@ -125,13 +125,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
<details> <details>
<summary>API Changes</summary> <summary>API Changes</summary>
- **Breaking** EmojiReactions: Change endpoints and responses to align with Mastodon - **Breaking:** EmojiReactions: Change endpoints and responses to align with Mastodon
- **Breaking** Admin API: `PATCH /api/pleroma/admin/users/:nickname/force_password_reset` is now `PATCH /api/pleroma/admin/users/force_password_reset` (accepts `nicknames` array in the request body) - **Breaking:** Admin API: `PATCH /api/pleroma/admin/users/:nickname/force_password_reset` is now `PATCH /api/pleroma/admin/users/force_password_reset` (accepts `nicknames` array in the request body)
- **Breaking:** Admin API: Return link alongside with token on password reset - **Breaking:** Admin API: Return link alongside with token on password reset
- **Breaking:** Admin API: `PUT /api/pleroma/admin/reports/:id` is now `PATCH /api/pleroma/admin/reports`, see admin_api.md for details - **Breaking:** Admin API: `PUT /api/pleroma/admin/reports/:id` is now `PATCH /api/pleroma/admin/reports`, see admin_api.md for details
- **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string. - **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string.
- **Breaking** replying to reports is now "report notes", enpoint changed from `POST /api/pleroma/admin/reports/:id/respond` to `POST /api/pleroma/admin/reports/:id/notes` - **Breaking:** replying to reports is now "report notes", endpoint changed from `POST /api/pleroma/admin/reports/:id/respond` to `POST /api/pleroma/admin/reports/:id/notes`
- Mastodon API: stopped sanitizing display names, field names and subject fields since they are supposed to be treated as plaintext - Mastodon API: stopped sanitizing display names, field names and subject fields since they are supposed to be treated as plaintext
- **Breaking:** Pleroma API: `/api/pleroma/emoji/packs/:name/update_file` endpoint returns only updated emoji data.
- Admin API: Return `total` when querying for reports - Admin API: Return `total` when querying for reports
- Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`) - Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
- Admin API: Return link alongside with token on password reset - Admin API: Return link alongside with token on password reset

View file

@ -357,7 +357,7 @@ The status posting endpoint takes an additional parameter, `in_reply_to_conversa
* if the `action` is `update`, changes emoji shortcode * if the `action` is `update`, changes emoji shortcode
(from `shortcode` to `new_shortcode` or moves the file (from the current filename to `new_filename`) (from `shortcode` to `new_shortcode` or moves the file (from the current filename to `new_filename`)
* if the `action` is `remove`, removes the emoji named `shortcode` and it's associated file * if the `action` is `remove`, removes the emoji named `shortcode` and it's associated file
* Response: JSON, updated "files" section of the pack and 200 status, 409 if the trying to use a shortcode * Response: JSON, emoji shortcode with filename which was added/updated/deleted and 200 status, 409 if the trying to use a shortcode
that is already taken, 400 if there was an error with the shortcode, filename or file (additional info that is already taken, 400 if there was an error with the shortcode, filename or file (additional info
in the "error" part of the response JSON) in the "error" part of the response JSON)

View file

@ -385,23 +385,35 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
json(conn, new_data) json(conn, new_data)
end end
defp get_filename(%{"filename" => filename}), do: filename defp get_filename(%Plug.Upload{filename: filename}), do: filename
defp get_filename(url) when is_binary(url), do: Path.basename(url)
defp get_filename(%{"file" => file}) do
case file do
%Plug.Upload{filename: filename} -> filename
url when is_binary(url) -> Path.basename(url)
end
end
defp empty?(str), do: String.trim(str) == "" defp empty?(str), do: String.trim(str) == ""
defp update_file_and_send(conn, updated_full_pack, pack_file_p) do defp update_pack_file(updated_full_pack, pack_file_p) do
# Write the emoji pack file content = Jason.encode!(updated_full_pack, pretty: true)
File.write!(pack_file_p, Jason.encode!(updated_full_pack, pretty: true))
# Return the modified file list File.write!(pack_file_p, content)
json(conn, updated_full_pack["files"]) end
defp create_subdirs(file_path) do
if String.contains?(file_path, "/") do
file_path
|> Path.dirname()
|> File.mkdir_p!()
end
end
defp pack_info(pack_name) do
dir = Path.join(emoji_dir_path(), pack_name)
json_path = Path.join(dir, "pack.json")
json =
json_path
|> File.read!()
|> Jason.decode!()
{dir, json_path, json}
end end
@doc """ @doc """
@ -422,23 +434,25 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
# Add # Add
def update_file( def update_file(
conn, conn,
%{"pack_name" => pack_name, "action" => "add", "shortcode" => shortcode} = params %{"pack_name" => pack_name, "action" => "add"} = params
) do ) do
pack_dir = Path.join(emoji_dir_path(), pack_name) shortcode =
pack_file_p = Path.join(pack_dir, "pack.json") if params["shortcode"] do
params["shortcode"]
else
filename = get_filename(params["file"])
Path.basename(filename, Path.extname(filename))
end
full_pack = Jason.decode!(File.read!(pack_file_p)) {pack_dir, pack_file_p, full_pack} = pack_info(pack_name)
with {_, false} <- {:has_shortcode, Map.has_key?(full_pack["files"], shortcode)}, with {_, false} <- {:has_shortcode, Map.has_key?(full_pack["files"], shortcode)},
filename <- get_filename(params), filename <- params["filename"] || get_filename(params["file"]),
false <- empty?(shortcode), false <- empty?(shortcode),
false <- empty?(filename) do false <- empty?(filename),
file_path = Path.join(pack_dir, filename) file_path <- Path.join(pack_dir, filename) do
# If the name contains directories, create them # If the name contains directories, create them
if String.contains?(file_path, "/") do create_subdirs(file_path)
File.mkdir_p!(Path.dirname(file_path))
end
case params["file"] do case params["file"] do
%Plug.Upload{path: upload_path} -> %Plug.Upload{path: upload_path} ->
@ -451,8 +465,11 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
File.write!(file_path, file_contents) File.write!(file_path, file_contents)
end end
updated_full_pack = put_in(full_pack, ["files", shortcode], filename) full_pack
update_file_and_send(conn, updated_full_pack, pack_file_p) |> put_in(["files", shortcode], filename)
|> update_pack_file(pack_file_p)
json(conn, %{shortcode => filename})
else else
{:has_shortcode, _} -> {:has_shortcode, _} ->
conn conn
@ -472,10 +489,7 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
"action" => "remove", "action" => "remove",
"shortcode" => shortcode "shortcode" => shortcode
}) do }) do
pack_dir = Path.join(emoji_dir_path(), pack_name) {pack_dir, pack_file_p, full_pack} = pack_info(pack_name)
pack_file_p = Path.join(pack_dir, "pack.json")
full_pack = Jason.decode!(File.read!(pack_file_p))
if Map.has_key?(full_pack["files"], shortcode) do if Map.has_key?(full_pack["files"], shortcode) do
{emoji_file_path, updated_full_pack} = pop_in(full_pack, ["files", shortcode]) {emoji_file_path, updated_full_pack} = pop_in(full_pack, ["files", shortcode])
@ -494,7 +508,8 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
end end
end end
update_file_and_send(conn, updated_full_pack, pack_file_p) update_pack_file(updated_full_pack, pack_file_p)
json(conn, %{shortcode => full_pack["files"][shortcode]})
else else
conn conn
|> put_status(:bad_request) |> put_status(:bad_request)
@ -507,10 +522,7 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
conn, conn,
%{"pack_name" => pack_name, "action" => "update", "shortcode" => shortcode} = params %{"pack_name" => pack_name, "action" => "update", "shortcode" => shortcode} = params
) do ) do
pack_dir = Path.join(emoji_dir_path(), pack_name) {pack_dir, pack_file_p, full_pack} = pack_info(pack_name)
pack_file_p = Path.join(pack_dir, "pack.json")
full_pack = Jason.decode!(File.read!(pack_file_p))
with {_, true} <- {:has_shortcode, Map.has_key?(full_pack["files"], shortcode)}, with {_, true} <- {:has_shortcode, Map.has_key?(full_pack["files"], shortcode)},
%{"new_shortcode" => new_shortcode, "new_filename" => new_filename} <- params, %{"new_shortcode" => new_shortcode, "new_filename" => new_filename} <- params,
@ -522,9 +534,7 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
new_emoji_file_path = Path.join(pack_dir, new_filename) new_emoji_file_path = Path.join(pack_dir, new_filename)
# If the name contains directories, create them # If the name contains directories, create them
if String.contains?(new_emoji_file_path, "/") do create_subdirs(new_emoji_file_path)
File.mkdir_p!(Path.dirname(new_emoji_file_path))
end
# Move/Rename the old filename to a new filename # Move/Rename the old filename to a new filename
# These are probably on the same filesystem, so just rename should work # These are probably on the same filesystem, so just rename should work
@ -540,8 +550,11 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
end end
# Then, put in the new shortcode with the new path # Then, put in the new shortcode with the new path
updated_full_pack = put_in(updated_full_pack, ["files", new_shortcode], new_filename) updated_full_pack
update_file_and_send(conn, updated_full_pack, pack_file_p) |> put_in(["files", new_shortcode], new_filename)
|> update_pack_file(pack_file_p)
json(conn, %{new_shortcode => new_filename})
else else
{:has_shortcode, _} -> {:has_shortcode, _} ->
conn conn

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

View file

@ -295,96 +295,116 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
end end
end end
test "updating pack files" do describe "update_file/2" do
pack_file = "#{@emoji_dir_path}/test_pack/pack.json" setup do
original_content = File.read!(pack_file) pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
original_content = File.read!(pack_file)
on_exit(fn -> on_exit(fn ->
File.write!(pack_file, original_content) File.write!(pack_file, original_content)
end)
File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png") admin = insert(:user, is_admin: true)
File.rm_rf!("#{@emoji_dir_path}/test_pack/dir") %{conn: conn} = oauth_access(["admin:write"], user: admin)
File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2") {:ok, conn: conn}
end) end
admin = insert(:user, is_admin: true) test "update file without shortcode", %{conn: conn} do
%{conn: conn} = oauth_access(["admin:write"], user: admin) on_exit(fn -> File.rm_rf!("#{@emoji_dir_path}/test_pack/shortcode.png") end)
same_name = %{ assert conn
"action" => "add", |> post("/api/pleroma/emoji/packs/test_pack/update_file", %{
"shortcode" => "blank", "action" => "add",
"filename" => "dir/blank.png", "file" => %Plug.Upload{
"file" => %Plug.Upload{ filename: "shortcode.png",
filename: "blank.png", path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png"
path: "#{@emoji_dir_path}/test_pack/blank.png" }
})
|> json_response(200) == %{"shortcode" => "shortcode.png"}
end
test "updating pack files", %{conn: conn} do
on_exit(fn ->
File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png")
File.rm_rf!("#{@emoji_dir_path}/test_pack/dir")
File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
end)
same_name = %{
"action" => "add",
"shortcode" => "blank",
"filename" => "dir/blank.png",
"file" => %Plug.Upload{
filename: "blank.png",
path: "#{@emoji_dir_path}/test_pack/blank.png"
}
} }
}
different_name = %{same_name | "shortcode" => "blank_2"} different_name = %{same_name | "shortcode" => "blank_2"}
assert (conn assert (conn
|> post(emoji_api_path(conn, :update_file, "test_pack"), same_name) |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name)
|> json_response(:conflict))["error"] =~ "already exists" |> json_response(:conflict))["error"] =~ "already exists"
assert conn assert conn
|> post(emoji_api_path(conn, :update_file, "test_pack"), different_name) |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name)
|> json_response(200) == %{"blank" => "blank.png", "blank_2" => "dir/blank.png"} |> json_response(200) == %{"blank_2" => "dir/blank.png"}
assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png") assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png")
assert conn assert conn
|> post(emoji_api_path(conn, :update_file, "test_pack"), %{ |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
"action" => "update", "action" => "update",
"shortcode" => "blank_2", "shortcode" => "blank_2",
"new_shortcode" => "blank_3", "new_shortcode" => "blank_3",
"new_filename" => "dir_2/blank_3.png" "new_filename" => "dir_2/blank_3.png"
}) })
|> json_response(200) == %{"blank" => "blank.png", "blank_3" => "dir_2/blank_3.png"} |> json_response(200) == %{"blank_3" => "dir_2/blank_3.png"}
refute File.exists?("#{@emoji_dir_path}/test_pack/dir/") refute File.exists?("#{@emoji_dir_path}/test_pack/dir/")
assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png") assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png")
assert conn assert conn
|> post(emoji_api_path(conn, :update_file, "test_pack"), %{ |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
"action" => "remove", "action" => "remove",
"shortcode" => "blank_3" "shortcode" => "blank_3"
}) })
|> json_response(200) == %{"blank" => "blank.png"} |> json_response(200) == %{"blank_3" => "dir_2/blank_3.png"}
refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/") refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/")
mock(fn mock(fn
%{ %{
method: :get, method: :get,
url: "https://test-blank/blank_url.png" url: "https://test-blank/blank_url.png"
} -> } ->
text(File.read!("#{@emoji_dir_path}/test_pack/blank.png")) text(File.read!("#{@emoji_dir_path}/test_pack/blank.png"))
end) end)
# The name should be inferred from the URL ending # The name should be inferred from the URL ending
from_url = %{ from_url = %{
"action" => "add", "action" => "add",
"shortcode" => "blank_url", "shortcode" => "blank_url",
"file" => "https://test-blank/blank_url.png" "file" => "https://test-blank/blank_url.png"
} }
assert conn assert conn
|> post(emoji_api_path(conn, :update_file, "test_pack"), from_url) |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url)
|> json_response(200) == %{ |> json_response(200) == %{
"blank" => "blank.png", "blank_url" => "blank_url.png"
"blank_url" => "blank_url.png" }
}
assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png") assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
assert conn assert conn
|> post(emoji_api_path(conn, :update_file, "test_pack"), %{ |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
"action" => "remove", "action" => "remove",
"shortcode" => "blank_url" "shortcode" => "blank_url"
}) })
|> json_response(200) == %{"blank" => "blank.png"} |> json_response(200) == %{"blank_url" => "blank_url.png"}
refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png") refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
end
end end
test "creating and deleting a pack" do test "creating and deleting a pack" do