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