Remove vapidPublicKey from Nodeinfo
[akkoma] / test / web / pleroma_api / controllers / emoji_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
6 use Pleroma.Web.ConnCase
7
8 import Tesla.Mock
9 import Pleroma.Factory
10
11 @emoji_dir_path Path.join(
12 Pleroma.Config.get!([:instance, :static_dir]),
13 "emoji"
14 )
15 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
16
17 test "shared & non-shared pack information in list_packs is ok" do
18 conn = build_conn()
19 resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
20
21 assert Map.has_key?(resp, "test_pack")
22
23 pack = resp["test_pack"]
24
25 assert Map.has_key?(pack["pack"], "download-sha256")
26 assert pack["pack"]["can-download"]
27
28 assert pack["files"] == %{"blank" => "blank.png"}
29
30 # Non-shared pack
31
32 assert Map.has_key?(resp, "test_pack_nonshared")
33
34 pack = resp["test_pack_nonshared"]
35
36 refute pack["pack"]["shared"]
37 refute pack["pack"]["can-download"]
38 end
39
40 test "listing remote packs" do
41 admin = insert(:user, is_admin: true)
42 %{conn: conn} = oauth_access(["admin:write"], user: admin)
43
44 resp =
45 build_conn()
46 |> get(emoji_api_path(conn, :list_packs))
47 |> json_response(200)
48
49 mock(fn
50 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
51 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
52
53 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
54 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
55
56 %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
57 json(resp)
58 end)
59
60 assert conn
61 |> post(emoji_api_path(conn, :list_from), %{instance_address: "https://example.com"})
62 |> json_response(200) == resp
63 end
64
65 test "downloading a shared pack from download_shared" do
66 conn = build_conn()
67
68 resp =
69 conn
70 |> get(emoji_api_path(conn, :download_shared, "test_pack"))
71 |> response(200)
72
73 {:ok, arch} = :zip.unzip(resp, [:memory])
74
75 assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
76 assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
77 end
78
79 test "downloading shared & unshared packs from another instance via download_from, deleting them" do
80 on_exit(fn ->
81 File.rm_rf!("#{@emoji_dir_path}/test_pack2")
82 File.rm_rf!("#{@emoji_dir_path}/test_pack_nonshared2")
83 end)
84
85 mock(fn
86 %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
87 json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
88
89 %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
90 json(%{metadata: %{features: []}})
91
92 %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
93 json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
94
95 %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
96 json(%{metadata: %{features: ["shareable_emoji_packs"]}})
97
98 %{
99 method: :get,
100 url: "https://example.com/api/pleroma/emoji/packs/list"
101 } ->
102 conn = build_conn()
103
104 conn
105 |> get(emoji_api_path(conn, :list_packs))
106 |> json_response(200)
107 |> json()
108
109 %{
110 method: :get,
111 url: "https://example.com/api/pleroma/emoji/packs/download_shared/test_pack"
112 } ->
113 conn = build_conn()
114
115 conn
116 |> get(emoji_api_path(conn, :download_shared, "test_pack"))
117 |> response(200)
118 |> text()
119
120 %{
121 method: :get,
122 url: "https://nonshared-pack"
123 } ->
124 text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
125 end)
126
127 admin = insert(:user, is_admin: true)
128
129 conn =
130 build_conn()
131 |> assign(:user, admin)
132 |> assign(:token, insert(:oauth_admin_token, user: admin, scopes: ["admin:write"]))
133
134 assert (conn
135 |> put_req_header("content-type", "application/json")
136 |> post(
137 emoji_api_path(
138 conn,
139 :download_from
140 ),
141 %{
142 instance_address: "https://old-instance",
143 pack_name: "test_pack",
144 as: "test_pack2"
145 }
146 |> Jason.encode!()
147 )
148 |> json_response(500))["error"] =~ "does not support"
149
150 assert conn
151 |> put_req_header("content-type", "application/json")
152 |> post(
153 emoji_api_path(
154 conn,
155 :download_from
156 ),
157 %{
158 instance_address: "https://example.com",
159 pack_name: "test_pack",
160 as: "test_pack2"
161 }
162 |> Jason.encode!()
163 )
164 |> json_response(200) == "ok"
165
166 assert File.exists?("#{@emoji_dir_path}/test_pack2/pack.json")
167 assert File.exists?("#{@emoji_dir_path}/test_pack2/blank.png")
168
169 assert conn
170 |> delete(emoji_api_path(conn, :delete, "test_pack2"))
171 |> json_response(200) == "ok"
172
173 refute File.exists?("#{@emoji_dir_path}/test_pack2")
174
175 # non-shared, downloaded from the fallback URL
176
177 assert conn
178 |> put_req_header("content-type", "application/json")
179 |> post(
180 emoji_api_path(
181 conn,
182 :download_from
183 ),
184 %{
185 instance_address: "https://example.com",
186 pack_name: "test_pack_nonshared",
187 as: "test_pack_nonshared2"
188 }
189 |> Jason.encode!()
190 )
191 |> json_response(200) == "ok"
192
193 assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/pack.json")
194 assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/blank.png")
195
196 assert conn
197 |> delete(emoji_api_path(conn, :delete, "test_pack_nonshared2"))
198 |> json_response(200) == "ok"
199
200 refute File.exists?("#{@emoji_dir_path}/test_pack_nonshared2")
201 end
202
203 describe "updating pack metadata" do
204 setup do
205 pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
206 original_content = File.read!(pack_file)
207
208 on_exit(fn ->
209 File.write!(pack_file, original_content)
210 end)
211
212 admin = insert(:user, is_admin: true)
213 %{conn: conn} = oauth_access(["admin:write"], user: admin)
214
215 {:ok,
216 admin: admin,
217 conn: conn,
218 pack_file: pack_file,
219 new_data: %{
220 "license" => "Test license changed",
221 "homepage" => "https://pleroma.social",
222 "description" => "Test description",
223 "share-files" => false
224 }}
225 end
226
227 test "for a pack without a fallback source", ctx do
228 conn = ctx[:conn]
229
230 assert conn
231 |> post(
232 emoji_api_path(conn, :update_metadata, "test_pack"),
233 %{
234 "new_data" => ctx[:new_data]
235 }
236 )
237 |> json_response(200) == ctx[:new_data]
238
239 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
240 end
241
242 test "for a pack with a fallback source", ctx do
243 mock(fn
244 %{
245 method: :get,
246 url: "https://nonshared-pack"
247 } ->
248 text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
249 end)
250
251 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
252
253 new_data_with_sha =
254 Map.put(
255 new_data,
256 "fallback-src-sha256",
257 "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
258 )
259
260 conn = ctx[:conn]
261
262 assert conn
263 |> post(
264 emoji_api_path(conn, :update_metadata, "test_pack"),
265 %{
266 "new_data" => new_data
267 }
268 )
269 |> json_response(200) == new_data_with_sha
270
271 assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
272 end
273
274 test "when the fallback source doesn't have all the files", ctx do
275 mock(fn
276 %{
277 method: :get,
278 url: "https://nonshared-pack"
279 } ->
280 {:ok, {'empty.zip', empty_arch}} = :zip.zip('empty.zip', [], [:memory])
281 text(empty_arch)
282 end)
283
284 new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
285
286 conn = ctx[:conn]
287
288 assert (conn
289 |> post(
290 emoji_api_path(conn, :update_metadata, "test_pack"),
291 %{
292 "new_data" => new_data
293 }
294 )
295 |> json_response(:bad_request))["error"] =~ "does not have all"
296 end
297 end
298
299 test "updating pack files" do
300 pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
301 original_content = File.read!(pack_file)
302
303 on_exit(fn ->
304 File.write!(pack_file, original_content)
305
306 File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png")
307 File.rm_rf!("#{@emoji_dir_path}/test_pack/dir")
308 File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
309 end)
310
311 admin = insert(:user, is_admin: true)
312 %{conn: conn} = oauth_access(["admin:write"], user: admin)
313
314 same_name = %{
315 "action" => "add",
316 "shortcode" => "blank",
317 "filename" => "dir/blank.png",
318 "file" => %Plug.Upload{
319 filename: "blank.png",
320 path: "#{@emoji_dir_path}/test_pack/blank.png"
321 }
322 }
323
324 different_name = %{same_name | "shortcode" => "blank_2"}
325
326 assert (conn
327 |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name)
328 |> json_response(:conflict))["error"] =~ "already exists"
329
330 assert conn
331 |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name)
332 |> json_response(200) == %{"blank" => "blank.png", "blank_2" => "dir/blank.png"}
333
334 assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png")
335
336 assert conn
337 |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
338 "action" => "update",
339 "shortcode" => "blank_2",
340 "new_shortcode" => "blank_3",
341 "new_filename" => "dir_2/blank_3.png"
342 })
343 |> json_response(200) == %{"blank" => "blank.png", "blank_3" => "dir_2/blank_3.png"}
344
345 refute File.exists?("#{@emoji_dir_path}/test_pack/dir/")
346 assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png")
347
348 assert conn
349 |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
350 "action" => "remove",
351 "shortcode" => "blank_3"
352 })
353 |> json_response(200) == %{"blank" => "blank.png"}
354
355 refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/")
356
357 mock(fn
358 %{
359 method: :get,
360 url: "https://test-blank/blank_url.png"
361 } ->
362 text(File.read!("#{@emoji_dir_path}/test_pack/blank.png"))
363 end)
364
365 # The name should be inferred from the URL ending
366 from_url = %{
367 "action" => "add",
368 "shortcode" => "blank_url",
369 "file" => "https://test-blank/blank_url.png"
370 }
371
372 assert conn
373 |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url)
374 |> json_response(200) == %{
375 "blank" => "blank.png",
376 "blank_url" => "blank_url.png"
377 }
378
379 assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
380
381 assert conn
382 |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
383 "action" => "remove",
384 "shortcode" => "blank_url"
385 })
386 |> json_response(200) == %{"blank" => "blank.png"}
387
388 refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
389 end
390
391 test "creating and deleting a pack" do
392 on_exit(fn ->
393 File.rm_rf!("#{@emoji_dir_path}/test_created")
394 end)
395
396 admin = insert(:user, is_admin: true)
397 %{conn: conn} = oauth_access(["admin:write"], user: admin)
398
399 assert conn
400 |> put_req_header("content-type", "application/json")
401 |> put(
402 emoji_api_path(
403 conn,
404 :create,
405 "test_created"
406 )
407 )
408 |> json_response(200) == "ok"
409
410 assert File.exists?("#{@emoji_dir_path}/test_created/pack.json")
411
412 assert Jason.decode!(File.read!("#{@emoji_dir_path}/test_created/pack.json")) == %{
413 "pack" => %{},
414 "files" => %{}
415 }
416
417 assert conn
418 |> delete(emoji_api_path(conn, :delete, "test_created"))
419 |> json_response(200) == "ok"
420
421 refute File.exists?("#{@emoji_dir_path}/test_created/pack.json")
422 end
423
424 test "filesystem import" do
425 on_exit(fn ->
426 File.rm!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt")
427 File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
428 end)
429
430 conn = build_conn()
431 resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
432
433 refute Map.has_key?(resp, "test_pack_for_import")
434
435 admin = insert(:user, is_admin: true)
436 %{conn: conn} = oauth_access(["admin:write"], user: admin)
437
438 assert conn
439 |> post(emoji_api_path(conn, :import_from_fs))
440 |> json_response(200) == ["test_pack_for_import"]
441
442 resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
443 assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
444
445 File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
446 refute File.exists?("#{@emoji_dir_path}/test_pack_for_import/pack.json")
447
448 emoji_txt_content = "blank, blank.png, Fun\n\nblank2, blank.png"
449
450 File.write!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
451
452 assert conn
453 |> post(emoji_api_path(conn, :import_from_fs))
454 |> json_response(200) == ["test_pack_for_import"]
455
456 resp = build_conn() |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
457
458 assert resp["test_pack_for_import"]["files"] == %{
459 "blank" => "blank.png",
460 "blank2" => "blank.png"
461 }
462 end
463 end