1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.PleromaAPI.EmojiPackControllerTest do
6 use Pleroma.Web.ConnCase, async: false
10 import Pleroma.Factory
12 @emoji_path Path.join(
13 Pleroma.Config.get!([:instance, :static_dir]),
17 setup do: clear_config([:instance, :public], true)
20 admin = insert(:user, is_admin: true)
21 token = insert(:oauth_admin_token, user: admin)
25 |> assign(:user, admin)
26 |> assign(:token, token)
28 Pleroma.Emoji.reload()
29 {:ok, %{admin_conn: admin_conn}}
32 test "GET /api/v1/pleroma/emoji/packs when :public: false", %{conn: conn} do
33 clear_config([:instance, :public], false)
34 conn |> get("/api/v1/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
37 test "GET /api/v1/pleroma/emoji/packs", %{conn: conn} do
40 |> get("/api/v1/pleroma/emoji/packs")
41 |> json_response_and_validate_schema(200)
43 assert resp["count"] == 4
49 shared = resp["packs"]["test_pack"]
50 assert shared["files"] == %{"blank" => "blank.png", "blank2" => "blank2.png"}
51 assert Map.has_key?(shared["pack"], "download-sha256")
52 assert shared["pack"]["can-download"]
53 assert shared["pack"]["share-files"]
55 non_shared = resp["packs"]["test_pack_nonshared"]
56 assert non_shared["pack"]["share-files"] == false
57 assert non_shared["pack"]["can-download"] == false
61 |> get("/api/v1/pleroma/emoji/packs?page_size=1")
62 |> json_response_and_validate_schema(200)
64 assert resp["count"] == 4
66 packs = Map.keys(resp["packs"])
68 assert length(packs) == 1
74 |> get("/api/v1/pleroma/emoji/packs?page_size=1&page=2")
75 |> json_response_and_validate_schema(200)
77 assert resp["count"] == 4
78 packs = Map.keys(resp["packs"])
79 assert length(packs) == 1
84 |> get("/api/v1/pleroma/emoji/packs?page_size=1&page=3")
85 |> json_response_and_validate_schema(200)
87 assert resp["count"] == 4
88 packs = Map.keys(resp["packs"])
89 assert length(packs) == 1
94 |> get("/api/v1/pleroma/emoji/packs?page_size=1&page=4")
95 |> json_response_and_validate_schema(200)
97 assert resp["count"] == 4
98 packs = Map.keys(resp["packs"])
99 assert length(packs) == 1
101 assert [pack1, pack2, pack3, pack4] |> Enum.uniq() |> length() == 4
104 describe "GET /api/v1/pleroma/emoji/packs/remote" do
105 test "shareable instance", %{admin_conn: admin_conn, conn: conn} do
108 |> get("/api/v1/pleroma/emoji/packs?page=2&page_size=1")
109 |> json_response_and_validate_schema(200)
112 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
113 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
115 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
116 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
120 url: "https://example.com/api/v1/pleroma/emoji/packs?page=2&page_size=1"
127 "/api/v1/pleroma/emoji/packs/remote?url=https://example.com&page=2&page_size=1"
129 |> json_response_and_validate_schema(200) == resp
132 test "non shareable instance", %{admin_conn: admin_conn} do
134 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
135 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
137 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
138 json(%{metadata: %{features: []}})
142 |> get("/api/v1/pleroma/emoji/packs/remote?url=https://example.com")
143 |> json_response_and_validate_schema(500) == %{
144 "error" => "The requested instance does not support sharing emoji packs"
149 describe "GET /api/v1/pleroma/emoji/packs/archive?name=:name" do
150 test "download shared pack", %{conn: conn} do
153 |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack")
156 {:ok, arch} = :zip.unzip(resp, [:memory])
158 assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
159 assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
162 test "non existing pack", %{conn: conn} do
164 |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack_for_import")
165 |> json_response_and_validate_schema(:not_found) == %{
166 "error" => "Pack test_pack_for_import does not exist"
170 test "non downloadable pack", %{conn: conn} do
172 |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack_nonshared")
173 |> json_response_and_validate_schema(:forbidden) == %{
175 "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"
180 describe "POST /api/v1/pleroma/emoji/packs/download" do
181 test "shared pack from remote and non shared from fallback-src", %{
182 admin_conn: admin_conn,
186 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
187 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
189 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
190 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
194 url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack"
197 |> get("/api/v1/pleroma/emoji/pack?name=test_pack")
198 |> json_response_and_validate_schema(200)
203 url: "https://example.com/api/v1/pleroma/emoji/packs/archive?name=test_pack"
206 |> get("/api/v1/pleroma/emoji/packs/archive?name=test_pack")
212 url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack_nonshared"
215 |> get("/api/v1/pleroma/emoji/pack?name=test_pack_nonshared")
216 |> json_response_and_validate_schema(200)
221 url: "https://nonshared-pack"
223 text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
227 |> put_req_header("content-type", "multipart/form-data")
228 |> post("/api/v1/pleroma/emoji/packs/download", %{
229 url: "https://example.com",
233 |> json_response_and_validate_schema(200) == "ok"
235 assert File.exists?("#{@emoji_path}/test_pack2/pack.json")
236 assert File.exists?("#{@emoji_path}/test_pack2/blank.png")
239 |> delete("/api/v1/pleroma/emoji/pack?name=test_pack2")
240 |> json_response_and_validate_schema(200) == "ok"
242 refute File.exists?("#{@emoji_path}/test_pack2")
245 |> put_req_header("content-type", "multipart/form-data")
247 "/api/v1/pleroma/emoji/packs/download",
249 url: "https://example.com",
250 name: "test_pack_nonshared",
251 as: "test_pack_nonshared2"
254 |> json_response_and_validate_schema(200) == "ok"
256 assert File.exists?("#{@emoji_path}/test_pack_nonshared2/pack.json")
257 assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png")
260 |> delete("/api/v1/pleroma/emoji/pack?name=test_pack_nonshared2")
261 |> json_response_and_validate_schema(200) == "ok"
263 refute File.exists?("#{@emoji_path}/test_pack_nonshared2")
266 test "nonshareable instance", %{admin_conn: admin_conn} do
268 %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
269 json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
271 %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
272 json(%{metadata: %{features: []}})
276 |> put_req_header("content-type", "multipart/form-data")
278 "/api/v1/pleroma/emoji/packs/download",
280 url: "https://old-instance",
285 |> json_response_and_validate_schema(500) == %{
286 "error" => "The requested instance does not support sharing emoji packs"
290 test "checksum fail", %{admin_conn: admin_conn} do
292 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
293 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
295 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
296 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
300 url: "https://example.com/api/v1/pleroma/emoji/pack?name=pack_bad_sha"
302 {:ok, pack} = Pleroma.Emoji.Pack.load_pack("pack_bad_sha")
303 %Tesla.Env{status: 200, body: Jason.encode!(pack)}
307 url: "https://example.com/api/v1/pleroma/emoji/packs/archive?name=pack_bad_sha"
311 body: File.read!("test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip")
316 |> put_req_header("content-type", "multipart/form-data")
317 |> post("/api/v1/pleroma/emoji/packs/download", %{
318 url: "https://example.com",
319 name: "pack_bad_sha",
322 |> json_response_and_validate_schema(:internal_server_error) == %{
323 "error" => "SHA256 for the pack doesn't match the one sent by the server"
327 test "other error", %{admin_conn: admin_conn} do
329 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
330 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
332 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
333 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
337 url: "https://example.com/api/v1/pleroma/emoji/pack?name=test_pack"
339 {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack")
340 %Tesla.Env{status: 200, body: Jason.encode!(pack)}
344 |> put_req_header("content-type", "multipart/form-data")
345 |> post("/api/v1/pleroma/emoji/packs/download", %{
346 url: "https://example.com",
350 |> json_response_and_validate_schema(:internal_server_error) == %{
352 "The pack was not set as shared and there is no fallback src to download from"
357 describe "PATCH/update /api/v1/pleroma/emoji/pack?name=:name" do
359 pack_file = "#{@emoji_path}/test_pack/pack.json"
360 original_content = File.read!(pack_file)
363 File.write!(pack_file, original_content)
367 pack_file: pack_file,
369 "license" => "Test license changed",
370 "homepage" => "https://pleroma.social",
371 "description" => "Test description",
372 "share-files" => false
376 test "returns error when file system not writable", %{admin_conn: conn} = ctx do
378 {File, [:passthrough], [stat: fn _ -> {:error, :eacces} end]}
381 |> put_req_header("content-type", "multipart/form-data")
383 "/api/v1/pleroma/emoji/pack?name=test_pack",
384 %{"metadata" => ctx[:new_data]}
386 |> json_response_and_validate_schema(500)
390 test "for a pack without a fallback source", ctx do
391 assert ctx[:admin_conn]
392 |> put_req_header("content-type", "multipart/form-data")
393 |> patch("/api/v1/pleroma/emoji/pack?name=test_pack", %{
394 "metadata" => ctx[:new_data]
396 |> json_response_and_validate_schema(200) == ctx[:new_data]
398 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
401 test "for a pack with a fallback source", ctx do
405 url: "https://nonshared-pack"
407 text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
410 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
415 "fallback-src-sha256",
416 "1967BB4E42BCC34BCC12D57BE7811D3B7BE52F965BCE45C87BD377B9499CE11D"
419 assert ctx[:admin_conn]
420 |> put_req_header("content-type", "multipart/form-data")
421 |> patch("/api/v1/pleroma/emoji/pack?name=test_pack", %{metadata: new_data})
422 |> json_response_and_validate_schema(200) == new_data_with_sha
424 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
427 test "when the fallback source doesn't have all the files", ctx do
431 url: "https://nonshared-pack"
433 {:ok, {'empty.zip', empty_arch}} = :zip.zip('empty.zip', [], [:memory])
437 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
439 assert ctx[:admin_conn]
440 |> put_req_header("content-type", "multipart/form-data")
441 |> patch("/api/v1/pleroma/emoji/pack?name=test_pack", %{metadata: new_data})
442 |> json_response_and_validate_schema(:bad_request) == %{
443 "error" => "The fallback archive does not have all files specified in pack.json"
448 describe "POST/DELETE /api/v1/pleroma/emoji/pack?name=:name" do
449 test "returns an error on creates pack when file system not writable", %{
450 admin_conn: admin_conn
452 path_pack = Path.join(@emoji_path, "test_pack")
455 {File, [:passthrough], [mkdir: fn ^path_pack -> {:error, :eacces} end]}
458 |> post("/api/v1/pleroma/emoji/pack?name=test_pack")
459 |> json_response_and_validate_schema(500) == %{
461 "Unexpected error occurred while creating pack. (POSIX error: Permission denied)"
466 test "returns an error on deletes pack when the file system is not writable", %{
467 admin_conn: admin_conn
469 path_pack = Path.join(@emoji_path, "test_emoji_pack")
472 {:ok, _pack} = Pleroma.Emoji.Pack.create("test_emoji_pack")
475 {File, [:passthrough], [rm_rf: fn ^path_pack -> {:error, :eacces, path_pack} end]}
478 |> delete("/api/v1/pleroma/emoji/pack?name=test_emoji_pack")
479 |> json_response_and_validate_schema(500) == %{
481 "Couldn't delete the `test_emoji_pack` pack (POSIX error: Permission denied)"
485 File.rm_rf(path_pack)
489 test "creating and deleting a pack", %{admin_conn: admin_conn} do
491 |> post("/api/v1/pleroma/emoji/pack?name=test_created")
492 |> json_response_and_validate_schema(200) == "ok"
494 assert File.exists?("#{@emoji_path}/test_created/pack.json")
496 assert Jason.decode!(File.read!("#{@emoji_path}/test_created/pack.json")) == %{
503 |> delete("/api/v1/pleroma/emoji/pack?name=test_created")
504 |> json_response_and_validate_schema(200) == "ok"
506 refute File.exists?("#{@emoji_path}/test_created/pack.json")
509 test "if pack exists", %{admin_conn: admin_conn} do
510 path = Path.join(@emoji_path, "test_created")
512 pack_file = Jason.encode!(%{files: %{}, pack: %{}})
513 File.write!(Path.join(path, "pack.json"), pack_file)
516 |> post("/api/v1/pleroma/emoji/pack?name=test_created")
517 |> json_response_and_validate_schema(:conflict) == %{
518 "error" => "A pack named \"test_created\" already exists"
521 on_exit(fn -> File.rm_rf(path) end)
524 test "with empty name", %{admin_conn: admin_conn} do
526 |> post("/api/v1/pleroma/emoji/pack?name= ")
527 |> json_response_and_validate_schema(:bad_request) == %{
528 "error" => "pack name cannot be empty"
533 test "deleting nonexisting pack", %{admin_conn: admin_conn} do
535 |> delete("/api/v1/pleroma/emoji/pack?name=non_existing")
536 |> json_response_and_validate_schema(:not_found) == %{
537 "error" => "Pack non_existing does not exist"
541 test "deleting with empty name", %{admin_conn: admin_conn} do
543 |> delete("/api/v1/pleroma/emoji/pack?name= ")
544 |> json_response_and_validate_schema(:bad_request) == %{
545 "error" => "pack name cannot be empty"
549 test "filesystem import", %{admin_conn: admin_conn, conn: conn} do
551 File.rm!("#{@emoji_path}/test_pack_for_import/emoji.txt")
552 File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
557 |> get("/api/v1/pleroma/emoji/packs")
558 |> json_response_and_validate_schema(200)
560 refute Map.has_key?(resp["packs"], "test_pack_for_import")
563 |> get("/api/v1/pleroma/emoji/packs/import")
564 |> json_response_and_validate_schema(200) == ["test_pack_for_import"]
568 |> get("/api/v1/pleroma/emoji/packs")
569 |> json_response_and_validate_schema(200)
571 assert resp["packs"]["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
573 File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
574 refute File.exists?("#{@emoji_path}/test_pack_for_import/pack.json")
576 emoji_txt_content = """
577 blank, blank.png, Fun
579 foo, /emoji/test_pack_for_import/blank.png
583 File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
586 |> get("/api/v1/pleroma/emoji/packs/import")
587 |> json_response_and_validate_schema(200) == ["test_pack_for_import"]
591 |> get("/api/v1/pleroma/emoji/packs")
592 |> json_response_and_validate_schema(200)
594 assert resp["packs"]["test_pack_for_import"]["files"] == %{
595 "blank" => "blank.png",
596 "blank2" => "blank.png",
601 describe "GET /api/v1/pleroma/emoji/pack?name=:name" do
602 test "shows pack.json", %{conn: conn} do
607 "can-download" => true,
608 "description" => "Test description",
609 "download-sha256" => _,
610 "homepage" => "https://pleroma.social",
611 "license" => "Test license",
612 "share-files" => true
616 |> get("/api/v1/pleroma/emoji/pack?name=test_pack")
617 |> json_response_and_validate_schema(200)
619 assert files == %{"blank" => "blank.png", "blank2" => "blank2.png"}
626 |> get("/api/v1/pleroma/emoji/pack?name=test_pack&page_size=1")
627 |> json_response_and_validate_schema(200)
629 assert files |> Map.keys() |> length() == 1
636 |> get("/api/v1/pleroma/emoji/pack?name=test_pack&page_size=1&page=2")
637 |> json_response_and_validate_schema(200)
639 assert files |> Map.keys() |> length() == 1
642 test "for pack name with special chars", %{conn: conn} do
647 "can-download" => true,
648 "description" => "Test description",
649 "download-sha256" => _,
650 "homepage" => "https://pleroma.social",
651 "license" => "Test license",
652 "share-files" => true
656 |> get("/api/v1/pleroma/emoji/pack?name=blobs.gg")
657 |> json_response_and_validate_schema(200)
660 test "non existing pack", %{conn: conn} do
662 |> get("/api/v1/pleroma/emoji/pack?name=non_existing")
663 |> json_response_and_validate_schema(:not_found) == %{
664 "error" => "Pack non_existing does not exist"
668 test "error name", %{conn: conn} do
670 |> get("/api/v1/pleroma/emoji/pack?name= ")
671 |> json_response_and_validate_schema(:bad_request) == %{
672 "error" => "pack name cannot be empty"