1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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
11 @emoji_path Path.join(
12 Pleroma.Config.get!([:instance, :static_dir]),
15 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
18 admin = insert(:user, is_admin: true)
19 token = insert(:oauth_admin_token, user: admin)
23 |> assign(:user, admin)
24 |> assign(:token, token)
26 Pleroma.Emoji.reload()
27 {:ok, %{admin_conn: admin_conn}}
30 test "GET /api/pleroma/emoji/packs", %{conn: conn} do
31 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
33 shared = resp["test_pack"]
34 assert shared["files"] == %{"blank" => "blank.png"}
35 assert Map.has_key?(shared["pack"], "download-sha256")
36 assert shared["pack"]["can-download"]
37 assert shared["pack"]["share-files"]
39 non_shared = resp["test_pack_nonshared"]
40 assert non_shared["pack"]["share-files"] == false
41 assert non_shared["pack"]["can-download"] == false
44 describe "GET /api/pleroma/emoji/packs/remote" do
45 test "shareable instance", %{admin_conn: admin_conn, conn: conn} do
48 |> get("/api/pleroma/emoji/packs")
49 |> json_response_and_validate_schema(200)
52 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
53 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
55 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
56 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
58 %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
63 |> get("/api/pleroma/emoji/packs/remote?url=https://example.com")
64 |> json_response_and_validate_schema(200) == resp
67 test "non shareable instance", %{admin_conn: admin_conn} do
69 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
70 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
72 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
73 json(%{metadata: %{features: []}})
77 |> get("/api/pleroma/emoji/packs/remote?url=https://example.com")
78 |> json_response_and_validate_schema(500) == %{
79 "error" => "The requested instance does not support sharing emoji packs"
84 describe "GET /api/pleroma/emoji/packs/:name/archive" do
85 test "download shared pack", %{conn: conn} do
88 |> get("/api/pleroma/emoji/packs/test_pack/archive")
91 {:ok, arch} = :zip.unzip(resp, [:memory])
93 assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
94 assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
97 test "non existing pack", %{conn: conn} do
99 |> get("/api/pleroma/emoji/packs/test_pack_for_import/archive")
100 |> json_response_and_validate_schema(:not_found) == %{
101 "error" => "Pack test_pack_for_import does not exist"
105 test "non downloadable pack", %{conn: conn} do
107 |> get("/api/pleroma/emoji/packs/test_pack_nonshared/archive")
108 |> json_response_and_validate_schema(:forbidden) == %{
110 "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"
115 describe "POST /api/pleroma/emoji/packs/download" do
116 test "shared pack from remote and non shared from fallback-src", %{
117 admin_conn: admin_conn,
121 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
122 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
124 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
125 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
129 url: "https://example.com/api/pleroma/emoji/packs/test_pack"
132 |> get("/api/pleroma/emoji/packs/test_pack")
133 |> json_response_and_validate_schema(200)
138 url: "https://example.com/api/pleroma/emoji/packs/test_pack/archive"
141 |> get("/api/pleroma/emoji/packs/test_pack/archive")
147 url: "https://example.com/api/pleroma/emoji/packs/test_pack_nonshared"
150 |> get("/api/pleroma/emoji/packs/test_pack_nonshared")
151 |> json_response_and_validate_schema(200)
156 url: "https://nonshared-pack"
158 text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
162 |> put_req_header("content-type", "multipart/form-data")
163 |> post("/api/pleroma/emoji/packs/download", %{
164 url: "https://example.com",
168 |> json_response_and_validate_schema(200) == "ok"
170 assert File.exists?("#{@emoji_path}/test_pack2/pack.json")
171 assert File.exists?("#{@emoji_path}/test_pack2/blank.png")
174 |> delete("/api/pleroma/emoji/packs/test_pack2")
175 |> json_response_and_validate_schema(200) == "ok"
177 refute File.exists?("#{@emoji_path}/test_pack2")
180 |> put_req_header("content-type", "multipart/form-data")
182 "/api/pleroma/emoji/packs/download",
184 url: "https://example.com",
185 name: "test_pack_nonshared",
186 as: "test_pack_nonshared2"
189 |> json_response_and_validate_schema(200) == "ok"
191 assert File.exists?("#{@emoji_path}/test_pack_nonshared2/pack.json")
192 assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png")
195 |> delete("/api/pleroma/emoji/packs/test_pack_nonshared2")
196 |> json_response_and_validate_schema(200) == "ok"
198 refute File.exists?("#{@emoji_path}/test_pack_nonshared2")
201 test "nonshareable instance", %{admin_conn: admin_conn} do
203 %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
204 json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
206 %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
207 json(%{metadata: %{features: []}})
211 |> put_req_header("content-type", "multipart/form-data")
213 "/api/pleroma/emoji/packs/download",
215 url: "https://old-instance",
220 |> json_response_and_validate_schema(500) == %{
221 "error" => "The requested instance does not support sharing emoji packs"
225 test "checksum fail", %{admin_conn: admin_conn} do
227 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
228 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
230 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
231 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
235 url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha"
237 {:ok, pack} = Pleroma.Emoji.Pack.load_pack("pack_bad_sha")
238 %Tesla.Env{status: 200, body: Jason.encode!(pack)}
242 url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/archive"
246 body: File.read!("test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip")
251 |> put_req_header("content-type", "multipart/form-data")
252 |> post("/api/pleroma/emoji/packs/download", %{
253 url: "https://example.com",
254 name: "pack_bad_sha",
257 |> json_response_and_validate_schema(:internal_server_error) == %{
258 "error" => "SHA256 for the pack doesn't match the one sent by the server"
262 test "other error", %{admin_conn: admin_conn} do
264 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
265 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
267 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
268 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
272 url: "https://example.com/api/pleroma/emoji/packs/test_pack"
274 {:ok, pack} = Pleroma.Emoji.Pack.load_pack("test_pack")
275 %Tesla.Env{status: 200, body: Jason.encode!(pack)}
279 |> put_req_header("content-type", "multipart/form-data")
280 |> post("/api/pleroma/emoji/packs/download", %{
281 url: "https://example.com",
285 |> json_response_and_validate_schema(:internal_server_error) == %{
287 "The pack was not set as shared and there is no fallback src to download from"
292 describe "PATCH /api/pleroma/emoji/packs/:name" do
294 pack_file = "#{@emoji_path}/test_pack/pack.json"
295 original_content = File.read!(pack_file)
298 File.write!(pack_file, original_content)
302 pack_file: pack_file,
304 "license" => "Test license changed",
305 "homepage" => "https://pleroma.social",
306 "description" => "Test description",
307 "share-files" => false
311 test "for a pack without a fallback source", ctx do
312 assert ctx[:admin_conn]
313 |> put_req_header("content-type", "multipart/form-data")
314 |> patch("/api/pleroma/emoji/packs/test_pack", %{"metadata" => ctx[:new_data]})
315 |> json_response_and_validate_schema(200) == ctx[:new_data]
317 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
320 test "for a pack with a fallback source", ctx do
324 url: "https://nonshared-pack"
326 text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
329 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
334 "fallback-src-sha256",
335 "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
338 assert ctx[:admin_conn]
339 |> put_req_header("content-type", "multipart/form-data")
340 |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
341 |> json_response_and_validate_schema(200) == new_data_with_sha
343 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
346 test "when the fallback source doesn't have all the files", ctx do
350 url: "https://nonshared-pack"
352 {:ok, {'empty.zip', empty_arch}} = :zip.zip('empty.zip', [], [:memory])
356 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
358 assert ctx[:admin_conn]
359 |> put_req_header("content-type", "multipart/form-data")
360 |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
361 |> json_response_and_validate_schema(:bad_request) == %{
362 "error" => "The fallback archive does not have all files specified in pack.json"
367 describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/:name/files" do
369 pack_file = "#{@emoji_path}/test_pack/pack.json"
370 original_content = File.read!(pack_file)
373 File.write!(pack_file, original_content)
379 test "create shortcode exists", %{admin_conn: admin_conn} do
381 |> put_req_header("content-type", "multipart/form-data")
382 |> post("/api/pleroma/emoji/packs/test_pack/files", %{
384 filename: "dir/blank.png",
386 filename: "blank.png",
387 path: "#{@emoji_path}/test_pack/blank.png"
390 |> json_response_and_validate_schema(:conflict) == %{
391 "error" => "An emoji with the \"blank\" shortcode already exists"
395 test "don't rewrite old emoji", %{admin_conn: admin_conn} do
396 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end)
399 |> put_req_header("content-type", "multipart/form-data")
400 |> post("/api/pleroma/emoji/packs/test_pack/files", %{
402 filename: "dir/blank.png",
404 filename: "blank.png",
405 path: "#{@emoji_path}/test_pack/blank.png"
408 |> json_response_and_validate_schema(200) == %{
409 "blank" => "blank.png",
410 "blank2" => "dir/blank.png"
413 assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
416 |> put_req_header("content-type", "multipart/form-data")
417 |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
419 new_shortcode: "blank2",
420 new_filename: "dir_2/blank_3.png"
422 |> json_response_and_validate_schema(:conflict) == %{
424 "New shortcode \"blank2\" is already used. If you want to override emoji use 'force' option"
428 test "rewrite old emoji with force option", %{admin_conn: admin_conn} do
429 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end)
432 |> put_req_header("content-type", "multipart/form-data")
433 |> post("/api/pleroma/emoji/packs/test_pack/files", %{
435 filename: "dir/blank.png",
437 filename: "blank.png",
438 path: "#{@emoji_path}/test_pack/blank.png"
441 |> json_response_and_validate_schema(200) == %{
442 "blank" => "blank.png",
443 "blank2" => "dir/blank.png"
446 assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
449 |> put_req_header("content-type", "multipart/form-data")
450 |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
452 new_shortcode: "blank3",
453 new_filename: "dir_2/blank_3.png",
456 |> json_response_and_validate_schema(200) == %{
457 "blank" => "blank.png",
458 "blank3" => "dir_2/blank_3.png"
461 assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
464 test "with empty filename", %{admin_conn: admin_conn} do
466 |> put_req_header("content-type", "multipart/form-data")
467 |> post("/api/pleroma/emoji/packs/test_pack/files", %{
471 filename: "blank.png",
472 path: "#{@emoji_path}/test_pack/blank.png"
475 |> json_response_and_validate_schema(:bad_request) == %{
476 "error" => "pack name, shortcode or filename cannot be empty"
480 test "add file with not loaded pack", %{admin_conn: admin_conn} do
482 |> put_req_header("content-type", "multipart/form-data")
483 |> post("/api/pleroma/emoji/packs/not_loaded/files", %{
485 filename: "dir/blank.png",
487 filename: "blank.png",
488 path: "#{@emoji_path}/test_pack/blank.png"
491 |> json_response_and_validate_schema(:bad_request) == %{
492 "error" => "pack \"not_loaded\" is not found"
496 test "remove file with not loaded pack", %{admin_conn: admin_conn} do
498 |> delete("/api/pleroma/emoji/packs/not_loaded/files?shortcode=blank3")
499 |> json_response_and_validate_schema(:bad_request) == %{
500 "error" => "pack \"not_loaded\" is not found"
504 test "remove file with empty shortcode", %{admin_conn: admin_conn} do
506 |> delete("/api/pleroma/emoji/packs/not_loaded/files?shortcode=")
507 |> json_response_and_validate_schema(:bad_request) == %{
508 "error" => "pack name or shortcode cannot be empty"
512 test "update file with not loaded pack", %{admin_conn: admin_conn} do
514 |> put_req_header("content-type", "multipart/form-data")
515 |> patch("/api/pleroma/emoji/packs/not_loaded/files", %{
517 new_shortcode: "blank3",
518 new_filename: "dir_2/blank_3.png"
520 |> json_response_and_validate_schema(:bad_request) == %{
521 "error" => "pack \"not_loaded\" is not found"
525 test "new with shortcode as file with update", %{admin_conn: admin_conn} do
527 |> put_req_header("content-type", "multipart/form-data")
528 |> post("/api/pleroma/emoji/packs/test_pack/files", %{
530 filename: "dir/blank.png",
532 filename: "blank.png",
533 path: "#{@emoji_path}/test_pack/blank.png"
536 |> json_response_and_validate_schema(200) == %{
537 "blank" => "blank.png",
538 "blank4" => "dir/blank.png"
541 assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
544 |> put_req_header("content-type", "multipart/form-data")
545 |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
547 new_shortcode: "blank3",
548 new_filename: "dir_2/blank_3.png"
550 |> json_response_and_validate_schema(200) == %{
551 "blank3" => "dir_2/blank_3.png",
552 "blank" => "blank.png"
555 refute File.exists?("#{@emoji_path}/test_pack/dir/")
556 assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
559 |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank3")
560 |> json_response_and_validate_schema(200) == %{"blank" => "blank.png"}
562 refute File.exists?("#{@emoji_path}/test_pack/dir_2/")
564 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir") end)
567 test "new with shortcode from url", %{admin_conn: admin_conn} do
571 url: "https://test-blank/blank_url.png"
573 text(File.read!("#{@emoji_path}/test_pack/blank.png"))
577 |> put_req_header("content-type", "multipart/form-data")
578 |> post("/api/pleroma/emoji/packs/test_pack/files", %{
579 shortcode: "blank_url",
580 file: "https://test-blank/blank_url.png"
582 |> json_response_and_validate_schema(200) == %{
583 "blank_url" => "blank_url.png",
584 "blank" => "blank.png"
587 assert File.exists?("#{@emoji_path}/test_pack/blank_url.png")
589 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/blank_url.png") end)
592 test "new without shortcode", %{admin_conn: admin_conn} do
593 on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end)
596 |> put_req_header("content-type", "multipart/form-data")
597 |> post("/api/pleroma/emoji/packs/test_pack/files", %{
599 filename: "shortcode.png",
600 path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png"
603 |> json_response_and_validate_schema(200) == %{
604 "shortcode" => "shortcode.png",
605 "blank" => "blank.png"
609 test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do
611 |> delete("/api/pleroma/emoji/packs/test_pack/files?shortcode=blank2")
612 |> json_response_and_validate_schema(:bad_request) == %{
613 "error" => "Emoji \"blank2\" does not exist"
617 test "update non existing emoji", %{admin_conn: admin_conn} do
619 |> put_req_header("content-type", "multipart/form-data")
620 |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
622 new_shortcode: "blank3",
623 new_filename: "dir_2/blank_3.png"
625 |> json_response_and_validate_schema(:bad_request) == %{
626 "error" => "Emoji \"blank2\" does not exist"
630 test "update with empty shortcode", %{admin_conn: admin_conn} do
632 "error" => "Missing field: new_shortcode."
635 |> put_req_header("content-type", "multipart/form-data")
636 |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
638 new_filename: "dir_2/blank_3.png"
640 |> json_response_and_validate_schema(:bad_request)
644 describe "POST/DELETE /api/pleroma/emoji/packs/:name" do
645 test "creating and deleting a pack", %{admin_conn: admin_conn} do
647 |> post("/api/pleroma/emoji/packs/test_created")
648 |> json_response_and_validate_schema(200) == "ok"
650 assert File.exists?("#{@emoji_path}/test_created/pack.json")
652 assert Jason.decode!(File.read!("#{@emoji_path}/test_created/pack.json")) == %{
658 |> delete("/api/pleroma/emoji/packs/test_created")
659 |> json_response_and_validate_schema(200) == "ok"
661 refute File.exists?("#{@emoji_path}/test_created/pack.json")
664 test "if pack exists", %{admin_conn: admin_conn} do
665 path = Path.join(@emoji_path, "test_created")
667 pack_file = Jason.encode!(%{files: %{}, pack: %{}})
668 File.write!(Path.join(path, "pack.json"), pack_file)
671 |> post("/api/pleroma/emoji/packs/test_created")
672 |> json_response_and_validate_schema(:conflict) == %{
673 "error" => "A pack named \"test_created\" already exists"
676 on_exit(fn -> File.rm_rf(path) end)
679 test "with empty name", %{admin_conn: admin_conn} do
681 |> post("/api/pleroma/emoji/packs/ ")
682 |> json_response_and_validate_schema(:bad_request) == %{
683 "error" => "pack name cannot be empty"
688 test "deleting nonexisting pack", %{admin_conn: admin_conn} do
690 |> delete("/api/pleroma/emoji/packs/non_existing")
691 |> json_response_and_validate_schema(:not_found) == %{
692 "error" => "Pack non_existing does not exist"
696 test "deleting with empty name", %{admin_conn: admin_conn} do
698 |> delete("/api/pleroma/emoji/packs/ ")
699 |> json_response_and_validate_schema(:bad_request) == %{
700 "error" => "pack name cannot be empty"
704 test "filesystem import", %{admin_conn: admin_conn, conn: conn} do
706 File.rm!("#{@emoji_path}/test_pack_for_import/emoji.txt")
707 File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
710 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
712 refute Map.has_key?(resp, "test_pack_for_import")
715 |> get("/api/pleroma/emoji/packs/import")
716 |> json_response_and_validate_schema(200) == ["test_pack_for_import"]
718 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
719 assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
721 File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
722 refute File.exists?("#{@emoji_path}/test_pack_for_import/pack.json")
724 emoji_txt_content = """
725 blank, blank.png, Fun
727 foo, /emoji/test_pack_for_import/blank.png
731 File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
734 |> get("/api/pleroma/emoji/packs/import")
735 |> json_response_and_validate_schema(200) == ["test_pack_for_import"]
737 resp = conn |> get("/api/pleroma/emoji/packs") |> json_response_and_validate_schema(200)
739 assert resp["test_pack_for_import"]["files"] == %{
740 "blank" => "blank.png",
741 "blank2" => "blank.png",
746 describe "GET /api/pleroma/emoji/packs/:name" do
747 test "shows pack.json", %{conn: conn} do
749 "files" => %{"blank" => "blank.png"},
751 "can-download" => true,
752 "description" => "Test description",
753 "download-sha256" => _,
754 "homepage" => "https://pleroma.social",
755 "license" => "Test license",
756 "share-files" => true
760 |> get("/api/pleroma/emoji/packs/test_pack")
761 |> json_response_and_validate_schema(200)
764 test "non existing pack", %{conn: conn} do
766 |> get("/api/pleroma/emoji/packs/non_existing")
767 |> json_response_and_validate_schema(:not_found) == %{
768 "error" => "Pack non_existing does not exist"
772 test "error name", %{conn: conn} do
774 |> get("/api/pleroma/emoji/packs/ ")
775 |> json_response_and_validate_schema(:bad_request) == %{
776 "error" => "pack name cannot be empty"