EmojiPackControllerDownloadZipTest: Add test.

This commit is contained in:
Lain Soykaf 2025-08-07 13:47:54 +04:00
commit 897c1ced5f

View file

@ -0,0 +1,311 @@
# Pleroma: A lightweight social networking server
# Copyright © Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerDownloadZipTest do
use Pleroma.Web.ConnCase, async: false
import Tesla.Mock
import Pleroma.Factory
@emoji_path Path.join(
Pleroma.Config.get!([:instance, :static_dir]),
"emoji"
)
setup do
admin = insert(:user, is_admin: true)
token = insert(:oauth_admin_token, user: admin)
admin_conn =
build_conn()
|> assign(:user, admin)
|> assign(:token, token)
Pleroma.Emoji.reload()
# Clean up any test packs from previous runs
on_exit(fn ->
test_packs = [
"test_zip_pack",
"test_zip_pack_url",
"test_zip_pack_malicious",
"test_invalid_pack",
"test_bad_url_pack",
"test_no_source_pack"
]
Enum.each(test_packs, fn pack_name ->
pack_path = Path.join(@emoji_path, pack_name)
if File.exists?(pack_path) do
File.rm_rf!(pack_path)
end
end)
end)
{:ok, %{admin_conn: admin_conn}}
end
describe "POST /api/pleroma/emoji/packs/download_zip" do
setup do
clear_config([:instance, :admin_privileges], [:emoji_manage_emoji])
end
test "creates pack from uploaded ZIP file", %{admin_conn: admin_conn} do
# Create a test ZIP file with emojis
{:ok, zip_path} = create_test_emoji_zip()
upload = %Plug.Upload{
content_type: "application/zip",
path: zip_path,
filename: "test_pack.zip"
}
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: "test_zip_pack",
file: upload
})
|> json_response_and_validate_schema(200) == "ok"
# Verify pack was created
assert File.exists?("#{@emoji_path}/test_zip_pack/pack.json")
assert File.exists?("#{@emoji_path}/test_zip_pack/test_emoji.png")
# Verify pack.json contents
{:ok, pack_json} = File.read("#{@emoji_path}/test_zip_pack/pack.json")
pack_data = Jason.decode!(pack_json)
assert pack_data["files"]["test_emoji"] == "test_emoji.png"
assert pack_data["pack"]["src_sha256"] != nil
# Clean up
File.rm!(zip_path)
end
test "creates pack from URL", %{admin_conn: admin_conn} do
# Mock HTTP request to download ZIP
{:ok, zip_path} = create_test_emoji_zip()
{:ok, zip_data} = File.read(zip_path)
mock(fn
%{method: :get, url: "https://example.com/emoji_pack.zip"} ->
%Tesla.Env{status: 200, body: zip_data}
end)
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: "test_zip_pack_url",
url: "https://example.com/emoji_pack.zip"
})
|> json_response_and_validate_schema(200) == "ok"
# Verify pack was created
assert File.exists?("#{@emoji_path}/test_zip_pack_url/pack.json")
assert File.exists?("#{@emoji_path}/test_zip_pack_url/test_emoji.png")
# Verify pack.json has URL as source
{:ok, pack_json} = File.read("#{@emoji_path}/test_zip_pack_url/pack.json")
pack_data = Jason.decode!(pack_json)
assert pack_data["pack"]["src"] == "https://example.com/emoji_pack.zip"
assert pack_data["pack"]["src_sha256"] != nil
# Clean up
File.rm!(zip_path)
end
test "refuses to overwrite existing pack", %{admin_conn: admin_conn} do
# Create existing pack
pack_path = Path.join(@emoji_path, "test_zip_pack")
File.mkdir_p!(pack_path)
File.write!(Path.join(pack_path, "pack.json"), Jason.encode!(%{files: %{}}))
{:ok, zip_path} = create_test_emoji_zip()
upload = %Plug.Upload{
content_type: "application/zip",
path: zip_path,
filename: "test_pack.zip"
}
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: "test_zip_pack",
file: upload
})
|> json_response_and_validate_schema(400) == %{
"error" => "Pack already exists, refusing to import test_zip_pack"
}
# Clean up
File.rm!(zip_path)
end
test "handles invalid ZIP file", %{admin_conn: admin_conn} do
# Create invalid ZIP file
invalid_zip_path = Path.join(System.tmp_dir!(), "invalid.zip")
File.write!(invalid_zip_path, "not a zip file")
upload = %Plug.Upload{
content_type: "application/zip",
path: invalid_zip_path,
filename: "invalid.zip"
}
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: "test_invalid_pack",
file: upload
})
|> json_response_and_validate_schema(400) == %{
"error" => "Could not unzip pack"
}
# Clean up
File.rm!(invalid_zip_path)
end
test "handles URL download failure", %{admin_conn: admin_conn} do
mock(fn
%{method: :get, url: "https://example.com/bad_pack.zip"} ->
%Tesla.Env{status: 404, body: "Not found"}
end)
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: "test_bad_url_pack",
url: "https://example.com/bad_pack.zip"
})
|> json_response_and_validate_schema(400) == %{
"error" => "Could not download pack"
}
end
test "requires either file or URL parameter", %{admin_conn: admin_conn} do
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: "test_no_source_pack"
})
|> json_response_and_validate_schema(400) == %{
"error" => "Neither file nor URL was present in the request"
}
end
test "preserves existing pack.json if present in ZIP", %{admin_conn: admin_conn} do
# Create ZIP with pack.json
{:ok, zip_path} = create_test_emoji_zip_with_pack_json()
upload = %Plug.Upload{
content_type: "application/zip",
path: zip_path,
filename: "test_pack_with_json.zip"
}
assert admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: "test_zip_pack",
file: upload
})
|> json_response_and_validate_schema(200) == "ok"
# Verify original pack.json was preserved
{:ok, pack_json} = File.read("#{@emoji_path}/test_zip_pack/pack.json")
pack_data = Jason.decode!(pack_json)
assert pack_data["pack"]["description"] == "Test pack from ZIP"
assert pack_data["pack"]["license"] == "Test License"
# Clean up
File.rm!(zip_path)
end
test "rejects malicious pack names", %{admin_conn: admin_conn} do
{:ok, zip_path} = create_test_emoji_zip()
upload = %Plug.Upload{
content_type: "application/zip",
path: zip_path,
filename: "test_pack.zip"
}
# Test path traversal attempts
malicious_names = ["../evil", "../../evil", ".", "..", "evil/../../../etc"]
Enum.each(malicious_names, fn name ->
assert_raise RuntimeError, ~r/Invalid or malicious pack name/, fn ->
admin_conn
|> put_req_header("content-type", "multipart/form-data")
|> post("/api/pleroma/emoji/packs/download_zip", %{
name: name,
file: upload
})
end
end)
# Clean up
File.rm!(zip_path)
end
end
defp create_test_emoji_zip do
tmp_dir = System.tmp_dir!()
zip_path = Path.join(tmp_dir, "test_emoji_pack_#{:rand.uniform(10000)}.zip")
# 1x1 pixel PNG
png_data =
Base.decode64!(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
)
files = [
{~c"test_emoji.png", png_data},
# Will be treated as GIF based on extension
{~c"another_emoji.gif", png_data}
]
{:ok, {_name, zip_binary}} = :zip.zip(~c"test_pack.zip", files, [:memory])
File.write!(zip_path, zip_binary)
{:ok, zip_path}
end
defp create_test_emoji_zip_with_pack_json do
tmp_dir = System.tmp_dir!()
zip_path = Path.join(tmp_dir, "test_emoji_pack_json_#{:rand.uniform(10000)}.zip")
png_data =
Base.decode64!(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
)
pack_json =
Jason.encode!(%{
pack: %{
description: "Test pack from ZIP",
license: "Test License"
},
files: %{
"test_emoji" => "test_emoji.png"
}
})
files = [
{~c"test_emoji.png", png_data},
{~c"pack.json", pack_json}
]
{:ok, {_name, zip_binary}} = :zip.zip(~c"test_pack.zip", files, [:memory])
File.write!(zip_path, zip_binary)
{:ok, zip_path}
end
end