Merge remote-tracking branch 'remotes/upstream/develop' into 1149-oban-job-queue
[akkoma] / test / web / twitter_api / util_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
6 use Pleroma.Web.ConnCase
7 use Oban.Testing, repo: Pleroma.Repo
8
9 alias Pleroma.Notification
10 alias Pleroma.Repo
11 alias Pleroma.Tests.ObanHelpers
12 alias Pleroma.User
13 alias Pleroma.Web.CommonAPI
14 import Pleroma.Factory
15 import Mock
16
17 setup do
18 Tesla.Mock.mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
19
20 instance_config = Pleroma.Config.get([:instance])
21 pleroma_fe = Pleroma.Config.get([:frontend_configurations, :pleroma_fe])
22 deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
23
24 on_exit(fn ->
25 Pleroma.Config.put([:instance], instance_config)
26 Pleroma.Config.put([:frontend_configurations, :pleroma_fe], pleroma_fe)
27 Pleroma.Config.put([:user, :deny_follow_blocked], deny_follow_blocked)
28 end)
29
30 :ok
31 end
32
33 describe "POST /api/pleroma/follow_import" do
34 test "it returns HTTP 200", %{conn: conn} do
35 user1 = insert(:user)
36 user2 = insert(:user)
37
38 response =
39 conn
40 |> assign(:user, user1)
41 |> post("/api/pleroma/follow_import", %{"list" => "#{user2.ap_id}"})
42 |> json_response(:ok)
43
44 assert response == "job started"
45 end
46
47 test "it imports follow lists from file", %{conn: conn} do
48 user1 = insert(:user)
49 user2 = insert(:user)
50
51 with_mocks([
52 {File, [],
53 read!: fn "follow_list.txt" ->
54 "Account address,Show boosts\n#{user2.ap_id},true"
55 end}
56 ]) do
57 response =
58 conn
59 |> assign(:user, user1)
60 |> post("/api/pleroma/follow_import", %{"list" => %Plug.Upload{path: "follow_list.txt"}})
61 |> json_response(:ok)
62
63 assert response == "job started"
64
65 assert ObanHelpers.member?(
66 %{
67 "op" => "follow_import",
68 "follower_id" => user1.id,
69 "followed_identifiers" => [user2.ap_id]
70 },
71 all_enqueued(worker: Pleroma.Workers.BackgroundWorker)
72 )
73 end
74 end
75
76 test "it imports new-style mastodon follow lists", %{conn: conn} do
77 user1 = insert(:user)
78 user2 = insert(:user)
79
80 response =
81 conn
82 |> assign(:user, user1)
83 |> post("/api/pleroma/follow_import", %{
84 "list" => "Account address,Show boosts\n#{user2.ap_id},true"
85 })
86 |> json_response(:ok)
87
88 assert response == "job started"
89 end
90
91 test "requires 'follow' permission", %{conn: conn} do
92 token1 = insert(:oauth_token, scopes: ["read", "write"])
93 token2 = insert(:oauth_token, scopes: ["follow"])
94 another_user = insert(:user)
95
96 for token <- [token1, token2] do
97 conn =
98 conn
99 |> put_req_header("authorization", "Bearer #{token.token}")
100 |> post("/api/pleroma/follow_import", %{"list" => "#{another_user.ap_id}"})
101
102 if token == token1 do
103 assert %{"error" => "Insufficient permissions: follow."} == json_response(conn, 403)
104 else
105 assert json_response(conn, 200)
106 end
107 end
108 end
109 end
110
111 describe "POST /api/pleroma/blocks_import" do
112 test "it returns HTTP 200", %{conn: conn} do
113 user1 = insert(:user)
114 user2 = insert(:user)
115
116 response =
117 conn
118 |> assign(:user, user1)
119 |> post("/api/pleroma/blocks_import", %{"list" => "#{user2.ap_id}"})
120 |> json_response(:ok)
121
122 assert response == "job started"
123 end
124
125 test "it imports blocks users from file", %{conn: conn} do
126 user1 = insert(:user)
127 user2 = insert(:user)
128 user3 = insert(:user)
129
130 with_mocks([
131 {File, [], read!: fn "blocks_list.txt" -> "#{user2.ap_id} #{user3.ap_id}" end}
132 ]) do
133 response =
134 conn
135 |> assign(:user, user1)
136 |> post("/api/pleroma/blocks_import", %{"list" => %Plug.Upload{path: "blocks_list.txt"}})
137 |> json_response(:ok)
138
139 assert response == "job started"
140
141 assert ObanHelpers.member?(
142 %{
143 "op" => "blocks_import",
144 "blocker_id" => user1.id,
145 "blocked_identifiers" => [user2.ap_id, user3.ap_id]
146 },
147 all_enqueued(worker: Pleroma.Workers.BackgroundWorker)
148 )
149 end
150 end
151 end
152
153 describe "POST /api/pleroma/notifications/read" do
154 test "it marks a single notification as read", %{conn: conn} do
155 user1 = insert(:user)
156 user2 = insert(:user)
157 {:ok, activity1} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
158 {:ok, activity2} = CommonAPI.post(user2, %{"status" => "hi @#{user1.nickname}"})
159 {:ok, [notification1]} = Notification.create_notifications(activity1)
160 {:ok, [notification2]} = Notification.create_notifications(activity2)
161
162 conn
163 |> assign(:user, user1)
164 |> post("/api/pleroma/notifications/read", %{"id" => "#{notification1.id}"})
165 |> json_response(:ok)
166
167 assert Repo.get(Notification, notification1.id).seen
168 refute Repo.get(Notification, notification2.id).seen
169 end
170
171 test "it returns error when notification not found", %{conn: conn} do
172 user1 = insert(:user)
173
174 response =
175 conn
176 |> assign(:user, user1)
177 |> post("/api/pleroma/notifications/read", %{"id" => "22222222222222"})
178 |> json_response(403)
179
180 assert response == %{"error" => "Cannot get notification"}
181 end
182 end
183
184 describe "PUT /api/pleroma/notification_settings" do
185 test "it updates notification settings", %{conn: conn} do
186 user = insert(:user)
187
188 conn
189 |> assign(:user, user)
190 |> put("/api/pleroma/notification_settings", %{
191 "followers" => false,
192 "bar" => 1
193 })
194 |> json_response(:ok)
195
196 user = Repo.get(User, user.id)
197
198 assert %{
199 "followers" => false,
200 "follows" => true,
201 "non_follows" => true,
202 "non_followers" => true
203 } == user.info.notification_settings
204 end
205 end
206
207 describe "GET /api/statusnet/config" do
208 test "it returns config in xml format", %{conn: conn} do
209 instance = Pleroma.Config.get(:instance)
210
211 response =
212 conn
213 |> put_req_header("accept", "application/xml")
214 |> get("/api/statusnet/config")
215 |> response(:ok)
216
217 assert response ==
218 "<config>\n<site>\n<name>#{Keyword.get(instance, :name)}</name>\n<site>#{
219 Pleroma.Web.base_url()
220 }</site>\n<textlimit>#{Keyword.get(instance, :limit)}</textlimit>\n<closed>#{
221 !Keyword.get(instance, :registrations_open)
222 }</closed>\n</site>\n</config>\n"
223 end
224
225 test "it returns config in json format", %{conn: conn} do
226 instance = Pleroma.Config.get(:instance)
227 Pleroma.Config.put([:instance, :managed_config], true)
228 Pleroma.Config.put([:instance, :registrations_open], false)
229 Pleroma.Config.put([:instance, :invites_enabled], true)
230 Pleroma.Config.put([:instance, :public], false)
231 Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
232
233 response =
234 conn
235 |> put_req_header("accept", "application/json")
236 |> get("/api/statusnet/config")
237 |> json_response(:ok)
238
239 expected_data = %{
240 "site" => %{
241 "accountActivationRequired" => "0",
242 "closed" => "1",
243 "description" => Keyword.get(instance, :description),
244 "invitesEnabled" => "1",
245 "name" => Keyword.get(instance, :name),
246 "pleromafe" => %{"theme" => "asuka-hospital"},
247 "private" => "1",
248 "safeDMMentionsEnabled" => "0",
249 "server" => Pleroma.Web.base_url(),
250 "textlimit" => to_string(Keyword.get(instance, :limit)),
251 "uploadlimit" => %{
252 "avatarlimit" => to_string(Keyword.get(instance, :avatar_upload_limit)),
253 "backgroundlimit" => to_string(Keyword.get(instance, :background_upload_limit)),
254 "bannerlimit" => to_string(Keyword.get(instance, :banner_upload_limit)),
255 "uploadlimit" => to_string(Keyword.get(instance, :upload_limit))
256 },
257 "vapidPublicKey" => Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
258 }
259 }
260
261 assert response == expected_data
262 end
263
264 test "returns the state of safe_dm_mentions flag", %{conn: conn} do
265 option = Pleroma.Config.get([:instance, :safe_dm_mentions])
266 Pleroma.Config.put([:instance, :safe_dm_mentions], true)
267
268 response =
269 conn
270 |> get("/api/statusnet/config.json")
271 |> json_response(:ok)
272
273 assert response["site"]["safeDMMentionsEnabled"] == "1"
274
275 Pleroma.Config.put([:instance, :safe_dm_mentions], false)
276
277 response =
278 conn
279 |> get("/api/statusnet/config.json")
280 |> json_response(:ok)
281
282 assert response["site"]["safeDMMentionsEnabled"] == "0"
283
284 Pleroma.Config.put([:instance, :safe_dm_mentions], option)
285 end
286
287 test "it returns the managed config", %{conn: conn} do
288 Pleroma.Config.put([:instance, :managed_config], false)
289 Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
290
291 response =
292 conn
293 |> get("/api/statusnet/config.json")
294 |> json_response(:ok)
295
296 refute response["site"]["pleromafe"]
297
298 Pleroma.Config.put([:instance, :managed_config], true)
299
300 response =
301 conn
302 |> get("/api/statusnet/config.json")
303 |> json_response(:ok)
304
305 assert response["site"]["pleromafe"] == %{"theme" => "asuka-hospital"}
306 end
307 end
308
309 describe "GET /api/pleroma/frontend_configurations" do
310 test "returns everything in :pleroma, :frontend_configurations", %{conn: conn} do
311 config = [
312 frontend_a: %{
313 x: 1,
314 y: 2
315 },
316 frontend_b: %{
317 z: 3
318 }
319 ]
320
321 Pleroma.Config.put(:frontend_configurations, config)
322
323 response =
324 conn
325 |> get("/api/pleroma/frontend_configurations")
326 |> json_response(:ok)
327
328 assert response == Jason.encode!(config |> Enum.into(%{})) |> Jason.decode!()
329 end
330 end
331
332 describe "/api/pleroma/emoji" do
333 test "returns json with custom emoji with tags", %{conn: conn} do
334 emoji =
335 conn
336 |> get("/api/pleroma/emoji")
337 |> json_response(200)
338
339 assert Enum.all?(emoji, fn
340 {_key,
341 %{
342 "image_url" => url,
343 "tags" => tags
344 }} ->
345 is_binary(url) and is_list(tags)
346 end)
347 end
348 end
349
350 describe "GET /ostatus_subscribe - remote_follow/2" do
351 test "adds status to pleroma instance if the `acct` is a status", %{conn: conn} do
352 conn =
353 get(
354 conn,
355 "/ostatus_subscribe?acct=https://mastodon.social/users/emelie/statuses/101849165031453009"
356 )
357
358 assert redirected_to(conn) =~ "/notice/"
359 end
360
361 test "show follow account page if the `acct` is a account link", %{conn: conn} do
362 response =
363 get(
364 conn,
365 "/ostatus_subscribe?acct=https://mastodon.social/users/emelie"
366 )
367
368 assert html_response(response, 200) =~ "Log in to follow"
369 end
370
371 test "show follow page if the `acct` is a account link", %{conn: conn} do
372 user = insert(:user)
373
374 response =
375 conn
376 |> assign(:user, user)
377 |> get("/ostatus_subscribe?acct=https://mastodon.social/users/emelie")
378
379 assert html_response(response, 200) =~ "Remote follow"
380 end
381
382 test "show follow page with error when user cannot fecth by `acct` link", %{conn: conn} do
383 user = insert(:user)
384
385 response =
386 conn
387 |> assign(:user, user)
388 |> get("/ostatus_subscribe?acct=https://mastodon.social/users/not_found")
389
390 assert html_response(response, 200) =~ "Error fetching user"
391 end
392 end
393
394 describe "POST /ostatus_subscribe - do_remote_follow/2 with assigned user " do
395 test "follows user", %{conn: conn} do
396 user = insert(:user)
397 user2 = insert(:user)
398
399 response =
400 conn
401 |> assign(:user, user)
402 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
403 |> response(200)
404
405 assert response =~ "Account followed!"
406 assert user2.follower_address in refresh_record(user).following
407 end
408
409 test "returns error when user is deactivated", %{conn: conn} do
410 user = insert(:user, info: %{deactivated: true})
411 user2 = insert(:user)
412
413 response =
414 conn
415 |> assign(:user, user)
416 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
417 |> response(200)
418
419 assert response =~ "Error following account"
420 end
421
422 test "returns error when user is blocked", %{conn: conn} do
423 Pleroma.Config.put([:user, :deny_follow_blocked], true)
424 user = insert(:user)
425 user2 = insert(:user)
426
427 {:ok, _user} = Pleroma.User.block(user2, user)
428
429 response =
430 conn
431 |> assign(:user, user)
432 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
433 |> response(200)
434
435 assert response =~ "Error following account"
436 end
437
438 test "returns error when followee not found", %{conn: conn} do
439 user = insert(:user)
440
441 response =
442 conn
443 |> assign(:user, user)
444 |> post("/ostatus_subscribe", %{"user" => %{"id" => "jimm"}})
445 |> response(200)
446
447 assert response =~ "Error following account"
448 end
449
450 test "returns success result when user already in followers", %{conn: conn} do
451 user = insert(:user)
452 user2 = insert(:user)
453 {:ok, _, _, _} = CommonAPI.follow(user, user2)
454
455 response =
456 conn
457 |> assign(:user, refresh_record(user))
458 |> post("/ostatus_subscribe", %{"user" => %{"id" => user2.id}})
459 |> response(200)
460
461 assert response =~ "Account followed!"
462 end
463 end
464
465 describe "POST /ostatus_subscribe - do_remote_follow/2 without assigned user " do
466 test "follows", %{conn: conn} do
467 user = insert(:user)
468 user2 = insert(:user)
469
470 response =
471 conn
472 |> post("/ostatus_subscribe", %{
473 "authorization" => %{"name" => user.nickname, "password" => "test", "id" => user2.id}
474 })
475 |> response(200)
476
477 assert response =~ "Account followed!"
478 assert user2.follower_address in refresh_record(user).following
479 end
480
481 test "returns error when followee not found", %{conn: conn} do
482 user = insert(:user)
483
484 response =
485 conn
486 |> post("/ostatus_subscribe", %{
487 "authorization" => %{"name" => user.nickname, "password" => "test", "id" => "jimm"}
488 })
489 |> response(200)
490
491 assert response =~ "Error following account"
492 end
493
494 test "returns error when login invalid", %{conn: conn} do
495 user = insert(:user)
496
497 response =
498 conn
499 |> post("/ostatus_subscribe", %{
500 "authorization" => %{"name" => "jimm", "password" => "test", "id" => user.id}
501 })
502 |> response(200)
503
504 assert response =~ "Wrong username or password"
505 end
506
507 test "returns error when password invalid", %{conn: conn} do
508 user = insert(:user)
509 user2 = insert(:user)
510
511 response =
512 conn
513 |> post("/ostatus_subscribe", %{
514 "authorization" => %{"name" => user.nickname, "password" => "42", "id" => user2.id}
515 })
516 |> response(200)
517
518 assert response =~ "Wrong username or password"
519 end
520
521 test "returns error when user is blocked", %{conn: conn} do
522 Pleroma.Config.put([:user, :deny_follow_blocked], true)
523 user = insert(:user)
524 user2 = insert(:user)
525 {:ok, _user} = Pleroma.User.block(user2, user)
526
527 response =
528 conn
529 |> post("/ostatus_subscribe", %{
530 "authorization" => %{"name" => user.nickname, "password" => "test", "id" => user2.id}
531 })
532 |> response(200)
533
534 assert response =~ "Error following account"
535 end
536 end
537
538 describe "GET /api/pleroma/healthcheck" do
539 setup do
540 config_healthcheck = Pleroma.Config.get([:instance, :healthcheck])
541
542 on_exit(fn ->
543 Pleroma.Config.put([:instance, :healthcheck], config_healthcheck)
544 end)
545
546 :ok
547 end
548
549 test "returns 503 when healthcheck disabled", %{conn: conn} do
550 Pleroma.Config.put([:instance, :healthcheck], false)
551
552 response =
553 conn
554 |> get("/api/pleroma/healthcheck")
555 |> json_response(503)
556
557 assert response == %{}
558 end
559
560 test "returns 200 when healthcheck enabled and all ok", %{conn: conn} do
561 Pleroma.Config.put([:instance, :healthcheck], true)
562
563 with_mock Pleroma.Healthcheck,
564 system_info: fn -> %Pleroma.Healthcheck{healthy: true} end do
565 response =
566 conn
567 |> get("/api/pleroma/healthcheck")
568 |> json_response(200)
569
570 assert %{
571 "active" => _,
572 "healthy" => true,
573 "idle" => _,
574 "memory_used" => _,
575 "pool_size" => _
576 } = response
577 end
578 end
579
580 test "returns 503 when healthcheck enabled and health is false", %{conn: conn} do
581 Pleroma.Config.put([:instance, :healthcheck], true)
582
583 with_mock Pleroma.Healthcheck,
584 system_info: fn -> %Pleroma.Healthcheck{healthy: false} end do
585 response =
586 conn
587 |> get("/api/pleroma/healthcheck")
588 |> json_response(503)
589
590 assert %{
591 "active" => _,
592 "healthy" => false,
593 "idle" => _,
594 "memory_used" => _,
595 "pool_size" => _
596 } = response
597 end
598 end
599 end
600
601 describe "POST /api/pleroma/disable_account" do
602 test "it returns HTTP 200", %{conn: conn} do
603 user = insert(:user)
604
605 response =
606 conn
607 |> assign(:user, user)
608 |> post("/api/pleroma/disable_account", %{"password" => "test"})
609 |> json_response(:ok)
610
611 assert response == %{"status" => "success"}
612 ObanHelpers.perform_all()
613
614 user = User.get_cached_by_id(user.id)
615
616 assert user.info.deactivated == true
617 end
618
619 test "it returns returns when password invalid", %{conn: conn} do
620 user = insert(:user)
621
622 response =
623 conn
624 |> assign(:user, user)
625 |> post("/api/pleroma/disable_account", %{"password" => "test1"})
626 |> json_response(:ok)
627
628 assert response == %{"error" => "Invalid password."}
629 user = User.get_cached_by_id(user.id)
630
631 refute user.info.deactivated
632 end
633 end
634
635 describe "GET /api/statusnet/version" do
636 test "it returns version in xml format", %{conn: conn} do
637 response =
638 conn
639 |> put_req_header("accept", "application/xml")
640 |> get("/api/statusnet/version")
641 |> response(:ok)
642
643 assert response == "<version>#{Pleroma.Application.named_version()}</version>"
644 end
645
646 test "it returns version in json format", %{conn: conn} do
647 response =
648 conn
649 |> put_req_header("accept", "application/json")
650 |> get("/api/statusnet/version")
651 |> json_response(:ok)
652
653 assert response == "#{Pleroma.Application.named_version()}"
654 end
655 end
656
657 describe "POST /main/ostatus - remote_subscribe/2" do
658 test "renders subscribe form", %{conn: conn} do
659 user = insert(:user)
660
661 response =
662 conn
663 |> post("/main/ostatus", %{"nickname" => user.nickname, "profile" => ""})
664 |> response(:ok)
665
666 refute response =~ "Could not find user"
667 assert response =~ "Remotely follow #{user.nickname}"
668 end
669
670 test "renders subscribe form with error when user not found", %{conn: conn} do
671 response =
672 conn
673 |> post("/main/ostatus", %{"nickname" => "nickname", "profile" => ""})
674 |> response(:ok)
675
676 assert response =~ "Could not find user"
677 refute response =~ "Remotely follow"
678 end
679
680 test "it redirect to webfinger url", %{conn: conn} do
681 user = insert(:user)
682 user2 = insert(:user, ap_id: "shp@social.heldscal.la")
683
684 conn =
685 conn
686 |> post("/main/ostatus", %{
687 "user" => %{"nickname" => user.nickname, "profile" => user2.ap_id}
688 })
689
690 assert redirected_to(conn) ==
691 "https://social.heldscal.la/main/ostatussub?profile=#{user.ap_id}"
692 end
693
694 test "it renders form with error when use not found", %{conn: conn} do
695 user2 = insert(:user, ap_id: "shp@social.heldscal.la")
696
697 response =
698 conn
699 |> post("/main/ostatus", %{"user" => %{"nickname" => "jimm", "profile" => user2.ap_id}})
700 |> response(:ok)
701
702 assert response =~ "Something went wrong."
703 end
704 end
705
706 test "it returns new captcha", %{conn: conn} do
707 with_mock Pleroma.Captcha,
708 new: fn -> "test_captcha" end do
709 resp =
710 conn
711 |> get("/api/pleroma/captcha")
712 |> response(200)
713
714 assert resp == "\"test_captcha\""
715 assert called(Pleroma.Captcha.new())
716 end
717 end
718 end