Fix delete activities not federating
[akkoma] / test / web / twitter_api / twitter_api_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.ControllerTest do
6 use Pleroma.Web.ConnCase
7 alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
8 alias Pleroma.Builders.ActivityBuilder
9 alias Pleroma.Builders.UserBuilder
10 alias Pleroma.Repo
11 alias Pleroma.Activity
12 alias Pleroma.User
13 alias Pleroma.Object
14 alias Pleroma.Notification
15 alias Pleroma.Web.ActivityPub.ActivityPub
16 alias Pleroma.Web.OAuth.Token
17 alias Pleroma.Web.TwitterAPI.Controller
18 alias Pleroma.Web.TwitterAPI.UserView
19 alias Pleroma.Web.TwitterAPI.NotificationView
20 alias Pleroma.Web.CommonAPI
21 alias Pleroma.Web.TwitterAPI.TwitterAPI
22 alias Comeonin.Pbkdf2
23 alias Ecto.Changeset
24
25 import Pleroma.Factory
26 import Mock
27
28 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
29
30 describe "POST /api/account/update_profile_banner" do
31 test "it updates the banner", %{conn: conn} do
32 user = insert(:user)
33
34 conn
35 |> assign(:user, user)
36 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
37 |> json_response(200)
38
39 user = refresh_record(user)
40 assert user.info.banner["type"] == "Image"
41 end
42 end
43
44 describe "POST /api/qvitter/update_background_image" do
45 test "it updates the background", %{conn: conn} do
46 user = insert(:user)
47
48 conn
49 |> assign(:user, user)
50 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
51 |> json_response(200)
52
53 user = refresh_record(user)
54 assert user.info.background["type"] == "Image"
55 end
56 end
57
58 describe "POST /api/account/verify_credentials" do
59 setup [:valid_user]
60
61 test "without valid credentials", %{conn: conn} do
62 conn = post(conn, "/api/account/verify_credentials.json")
63 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
64 end
65
66 test "with credentials", %{conn: conn, user: user} do
67 response =
68 conn
69 |> with_credentials(user.nickname, "test")
70 |> post("/api/account/verify_credentials.json")
71 |> json_response(200)
72
73 assert response ==
74 UserView.render("show.json", %{user: user, token: response["token"], for: user})
75 end
76 end
77
78 describe "POST /statuses/update.json" do
79 setup [:valid_user]
80
81 test "without valid credentials", %{conn: conn} do
82 conn = post(conn, "/api/statuses/update.json")
83 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
84 end
85
86 test "with credentials", %{conn: conn, user: user} do
87 conn_with_creds = conn |> with_credentials(user.nickname, "test")
88 request_path = "/api/statuses/update.json"
89
90 error_response = %{
91 "request" => request_path,
92 "error" => "Client must provide a 'status' parameter with a value."
93 }
94
95 conn =
96 conn_with_creds
97 |> post(request_path)
98
99 assert json_response(conn, 400) == error_response
100
101 conn =
102 conn_with_creds
103 |> post(request_path, %{status: ""})
104
105 assert json_response(conn, 400) == error_response
106
107 conn =
108 conn_with_creds
109 |> post(request_path, %{status: " "})
110
111 assert json_response(conn, 400) == error_response
112
113 # we post with visibility private in order to avoid triggering relay
114 conn =
115 conn_with_creds
116 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
117
118 assert json_response(conn, 200) ==
119 ActivityRepresenter.to_map(Repo.one(Activity), %{user: user, for: user})
120 end
121 end
122
123 describe "GET /statuses/public_timeline.json" do
124 setup [:valid_user]
125
126 test "returns statuses", %{conn: conn} do
127 user = insert(:user)
128 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
129 ActivityBuilder.insert_list(10, %{}, %{user: user})
130 since_id = List.last(activities).id
131
132 conn =
133 conn
134 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
135
136 response = json_response(conn, 200)
137
138 assert length(response) == 10
139 end
140
141 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
142 instance =
143 Application.get_env(:pleroma, :instance)
144 |> Keyword.put(:public, false)
145
146 Application.put_env(:pleroma, :instance, instance)
147
148 conn
149 |> get("/api/statuses/public_timeline.json")
150 |> json_response(403)
151
152 instance =
153 Application.get_env(:pleroma, :instance)
154 |> Keyword.put(:public, true)
155
156 Application.put_env(:pleroma, :instance, instance)
157 end
158
159 test "returns 200 to authenticated request when the instance is not public",
160 %{conn: conn, user: user} do
161 instance =
162 Application.get_env(:pleroma, :instance)
163 |> Keyword.put(:public, false)
164
165 Application.put_env(:pleroma, :instance, instance)
166
167 conn
168 |> with_credentials(user.nickname, "test")
169 |> get("/api/statuses/public_timeline.json")
170 |> json_response(200)
171
172 instance =
173 Application.get_env(:pleroma, :instance)
174 |> Keyword.put(:public, true)
175
176 Application.put_env(:pleroma, :instance, instance)
177 end
178
179 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
180 conn
181 |> get("/api/statuses/public_timeline.json")
182 |> json_response(200)
183 end
184
185 test "returns 200 to authenticated request when the instance is public",
186 %{conn: conn, user: user} do
187 conn
188 |> with_credentials(user.nickname, "test")
189 |> get("/api/statuses/public_timeline.json")
190 |> json_response(200)
191 end
192
193 test_with_mock "treats user as unauthenticated if `assigns[:token]` is present but lacks `read` permission",
194 Controller,
195 [:passthrough],
196 [] do
197 token = insert(:oauth_token, scopes: ["write"])
198
199 build_conn()
200 |> put_req_header("authorization", "Bearer #{token.token}")
201 |> get("/api/statuses/public_timeline.json")
202 |> json_response(200)
203
204 assert called(Controller.public_timeline(%{assigns: %{user: nil}}, :_))
205 end
206 end
207
208 describe "GET /statuses/public_and_external_timeline.json" do
209 setup [:valid_user]
210
211 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
212 instance =
213 Application.get_env(:pleroma, :instance)
214 |> Keyword.put(:public, false)
215
216 Application.put_env(:pleroma, :instance, instance)
217
218 conn
219 |> get("/api/statuses/public_and_external_timeline.json")
220 |> json_response(403)
221
222 instance =
223 Application.get_env(:pleroma, :instance)
224 |> Keyword.put(:public, true)
225
226 Application.put_env(:pleroma, :instance, instance)
227 end
228
229 test "returns 200 to authenticated request when the instance is not public",
230 %{conn: conn, user: user} do
231 instance =
232 Application.get_env(:pleroma, :instance)
233 |> Keyword.put(:public, false)
234
235 Application.put_env(:pleroma, :instance, instance)
236
237 conn
238 |> with_credentials(user.nickname, "test")
239 |> get("/api/statuses/public_and_external_timeline.json")
240 |> json_response(200)
241
242 instance =
243 Application.get_env(:pleroma, :instance)
244 |> Keyword.put(:public, true)
245
246 Application.put_env(:pleroma, :instance, instance)
247 end
248
249 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
250 conn
251 |> get("/api/statuses/public_and_external_timeline.json")
252 |> json_response(200)
253 end
254
255 test "returns 200 to authenticated request when the instance is public",
256 %{conn: conn, user: user} do
257 conn
258 |> with_credentials(user.nickname, "test")
259 |> get("/api/statuses/public_and_external_timeline.json")
260 |> json_response(200)
261 end
262 end
263
264 describe "GET /statuses/show/:id.json" do
265 test "returns one status", %{conn: conn} do
266 user = insert(:user)
267 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
268 actor = Repo.get_by!(User, ap_id: activity.data["actor"])
269
270 conn =
271 conn
272 |> get("/api/statuses/show/#{activity.id}.json")
273
274 response = json_response(conn, 200)
275
276 assert response == ActivityRepresenter.to_map(activity, %{user: actor})
277 end
278 end
279
280 describe "GET /users/show.json" do
281 test "gets user with screen_name", %{conn: conn} do
282 user = insert(:user)
283
284 conn =
285 conn
286 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
287
288 response = json_response(conn, 200)
289
290 assert response["id"] == user.id
291 end
292
293 test "gets user with user_id", %{conn: conn} do
294 user = insert(:user)
295
296 conn =
297 conn
298 |> get("/api/users/show.json", %{"user_id" => user.id})
299
300 response = json_response(conn, 200)
301
302 assert response["id"] == user.id
303 end
304
305 test "gets a user for a logged in user", %{conn: conn} do
306 user = insert(:user)
307 logged_in = insert(:user)
308
309 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
310
311 conn =
312 conn
313 |> with_credentials(logged_in.nickname, "test")
314 |> get("/api/users/show.json", %{"user_id" => user.id})
315
316 response = json_response(conn, 200)
317
318 assert response["following"] == true
319 end
320 end
321
322 describe "GET /statusnet/conversation/:id.json" do
323 test "returns the statuses in the conversation", %{conn: conn} do
324 {:ok, _user} = UserBuilder.insert()
325 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
326 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
327 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
328
329 conn =
330 conn
331 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
332
333 response = json_response(conn, 200)
334
335 assert length(response) == 2
336 end
337 end
338
339 describe "GET /statuses/friends_timeline.json" do
340 setup [:valid_user]
341
342 test "without valid credentials", %{conn: conn} do
343 conn = get(conn, "/api/statuses/friends_timeline.json")
344 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
345 end
346
347 test "with credentials", %{conn: conn, user: current_user} do
348 user = insert(:user)
349
350 activities =
351 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
352
353 returned_activities =
354 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
355
356 other_user = insert(:user)
357 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
358 since_id = List.last(activities).id
359
360 current_user =
361 Changeset.change(current_user, following: [User.ap_followers(user)])
362 |> Repo.update!()
363
364 conn =
365 conn
366 |> with_credentials(current_user.nickname, "test")
367 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
368
369 response = json_response(conn, 200)
370
371 assert length(response) == 10
372
373 assert response ==
374 Enum.map(returned_activities, fn activity ->
375 ActivityRepresenter.to_map(activity, %{
376 user: User.get_cached_by_ap_id(activity.data["actor"]),
377 for: current_user
378 })
379 end)
380 end
381 end
382
383 describe "GET /statuses/dm_timeline.json" do
384 test "it show direct messages", %{conn: conn} do
385 user_one = insert(:user)
386 user_two = insert(:user)
387
388 {:ok, user_two} = User.follow(user_two, user_one)
389
390 {:ok, direct} =
391 CommonAPI.post(user_one, %{
392 "status" => "Hi @#{user_two.nickname}!",
393 "visibility" => "direct"
394 })
395
396 {:ok, direct_two} =
397 CommonAPI.post(user_two, %{
398 "status" => "Hi @#{user_one.nickname}!",
399 "visibility" => "direct"
400 })
401
402 {:ok, _follower_only} =
403 CommonAPI.post(user_one, %{
404 "status" => "Hi @#{user_two.nickname}!",
405 "visibility" => "private"
406 })
407
408 # Only direct should be visible here
409 res_conn =
410 conn
411 |> assign(:user, user_two)
412 |> get("/api/statuses/dm_timeline.json")
413
414 [status, status_two] = json_response(res_conn, 200)
415 assert status["id"] == direct_two.id
416 assert status_two["id"] == direct.id
417 end
418
419 test "doesn't include DMs from blocked users", %{conn: conn} do
420 blocker = insert(:user)
421 blocked = insert(:user)
422 user = insert(:user)
423 {:ok, blocker} = User.block(blocker, blocked)
424
425 {:ok, _blocked_direct} =
426 CommonAPI.post(blocked, %{
427 "status" => "Hi @#{blocker.nickname}!",
428 "visibility" => "direct"
429 })
430
431 {:ok, direct} =
432 CommonAPI.post(user, %{
433 "status" => "Hi @#{blocker.nickname}!",
434 "visibility" => "direct"
435 })
436
437 res_conn =
438 conn
439 |> assign(:user, blocker)
440 |> get("/api/statuses/dm_timeline.json")
441
442 [status] = json_response(res_conn, 200)
443 assert status["id"] == direct.id
444 end
445 end
446
447 describe "GET /statuses/mentions.json" do
448 setup [:valid_user]
449
450 test "without valid credentials", %{conn: conn} do
451 conn = get(conn, "/api/statuses/mentions.json")
452 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
453 end
454
455 test "with credentials", %{conn: conn, user: current_user} do
456 {:ok, activity} =
457 CommonAPI.post(current_user, %{
458 "status" => "why is tenshi eating a corndog so cute?",
459 "visibility" => "public"
460 })
461
462 conn =
463 conn
464 |> with_credentials(current_user.nickname, "test")
465 |> get("/api/statuses/mentions.json")
466
467 response = json_response(conn, 200)
468
469 assert length(response) == 1
470
471 assert Enum.at(response, 0) ==
472 ActivityRepresenter.to_map(activity, %{
473 user: current_user,
474 for: current_user,
475 mentioned: [current_user]
476 })
477 end
478
479 test "does not show DMs in mentions timeline", %{conn: conn, user: current_user} do
480 {:ok, _activity} =
481 CommonAPI.post(current_user, %{
482 "status" => "Have you guys ever seen how cute tenshi eating a corndog is?",
483 "visibility" => "direct"
484 })
485
486 conn =
487 conn
488 |> with_credentials(current_user.nickname, "test")
489 |> get("/api/statuses/mentions.json")
490
491 response = json_response(conn, 200)
492
493 assert length(response) == 0
494 end
495 end
496
497 describe "GET /api/qvitter/statuses/notifications.json" do
498 setup [:valid_user]
499
500 test "without valid credentials", %{conn: conn} do
501 conn = get(conn, "/api/qvitter/statuses/notifications.json")
502 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
503 end
504
505 test "with credentials", %{conn: conn, user: current_user} do
506 other_user = insert(:user)
507
508 {:ok, _activity} =
509 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
510
511 conn =
512 conn
513 |> with_credentials(current_user.nickname, "test")
514 |> get("/api/qvitter/statuses/notifications.json")
515
516 response = json_response(conn, 200)
517
518 assert length(response) == 1
519
520 assert response ==
521 NotificationView.render("notification.json", %{
522 notifications: Notification.for_user(current_user),
523 for: current_user
524 })
525 end
526 end
527
528 describe "POST /api/qvitter/statuses/notifications/read" do
529 setup [:valid_user]
530
531 test "without valid credentials", %{conn: conn} do
532 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
533 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
534 end
535
536 test "with credentials, without any params", %{conn: conn, user: current_user} do
537 conn =
538 conn
539 |> with_credentials(current_user.nickname, "test")
540 |> post("/api/qvitter/statuses/notifications/read")
541
542 assert json_response(conn, 400) == %{
543 "error" => "You need to specify latest_id",
544 "request" => "/api/qvitter/statuses/notifications/read"
545 }
546 end
547
548 test "with credentials, with params", %{conn: conn, user: current_user} do
549 other_user = insert(:user)
550
551 {:ok, _activity} =
552 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
553
554 response_conn =
555 conn
556 |> with_credentials(current_user.nickname, "test")
557 |> get("/api/qvitter/statuses/notifications.json")
558
559 [notification] = response = json_response(response_conn, 200)
560
561 assert length(response) == 1
562
563 assert notification["is_seen"] == 0
564
565 response_conn =
566 conn
567 |> with_credentials(current_user.nickname, "test")
568 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
569
570 [notification] = response = json_response(response_conn, 200)
571
572 assert length(response) == 1
573
574 assert notification["is_seen"] == 1
575 end
576 end
577
578 describe "GET /statuses/user_timeline.json" do
579 setup [:valid_user]
580
581 test "without any params", %{conn: conn} do
582 conn = get(conn, "/api/statuses/user_timeline.json")
583
584 assert json_response(conn, 400) == %{
585 "error" => "You need to specify screen_name or user_id",
586 "request" => "/api/statuses/user_timeline.json"
587 }
588 end
589
590 test "with user_id", %{conn: conn} do
591 user = insert(:user)
592 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
593
594 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
595 response = json_response(conn, 200)
596 assert length(response) == 1
597 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
598 end
599
600 test "with screen_name", %{conn: conn} do
601 user = insert(:user)
602 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
603
604 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
605 response = json_response(conn, 200)
606 assert length(response) == 1
607 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
608 end
609
610 test "with credentials", %{conn: conn, user: current_user} do
611 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
612
613 conn =
614 conn
615 |> with_credentials(current_user.nickname, "test")
616 |> get("/api/statuses/user_timeline.json")
617
618 response = json_response(conn, 200)
619
620 assert length(response) == 1
621
622 assert Enum.at(response, 0) ==
623 ActivityRepresenter.to_map(activity, %{user: current_user, for: current_user})
624 end
625
626 test "with credentials with user_id", %{conn: conn, user: current_user} do
627 user = insert(:user)
628 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
629
630 conn =
631 conn
632 |> with_credentials(current_user.nickname, "test")
633 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
634
635 response = json_response(conn, 200)
636
637 assert length(response) == 1
638 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
639 end
640
641 test "with credentials screen_name", %{conn: conn, user: current_user} do
642 user = insert(:user)
643 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
644
645 conn =
646 conn
647 |> with_credentials(current_user.nickname, "test")
648 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
649
650 response = json_response(conn, 200)
651
652 assert length(response) == 1
653 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
654 end
655
656 test "with credentials with user_id, excluding RTs", %{conn: conn, user: current_user} do
657 user = insert(:user)
658 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1, "type" => "Create"}, %{user: user})
659 {:ok, _} = ActivityBuilder.insert(%{"id" => 2, "type" => "Announce"}, %{user: user})
660
661 conn =
662 conn
663 |> with_credentials(current_user.nickname, "test")
664 |> get("/api/statuses/user_timeline.json", %{
665 "user_id" => user.id,
666 "include_rts" => "false"
667 })
668
669 response = json_response(conn, 200)
670
671 assert length(response) == 1
672 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
673
674 conn =
675 conn
676 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id, "include_rts" => "0"})
677
678 response = json_response(conn, 200)
679
680 assert length(response) == 1
681 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
682 end
683 end
684
685 describe "POST /friendships/create.json" do
686 setup [:valid_user]
687
688 test "without valid credentials", %{conn: conn} do
689 conn = post(conn, "/api/friendships/create.json")
690 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
691 end
692
693 test "with credentials", %{conn: conn, user: current_user} do
694 followed = insert(:user)
695
696 conn =
697 conn
698 |> with_credentials(current_user.nickname, "test")
699 |> post("/api/friendships/create.json", %{user_id: followed.id})
700
701 current_user = Repo.get(User, current_user.id)
702 assert User.ap_followers(followed) in current_user.following
703
704 assert json_response(conn, 200) ==
705 UserView.render("show.json", %{user: followed, for: current_user})
706 end
707
708 test "for restricted account", %{conn: conn, user: current_user} do
709 followed = insert(:user, info: %User.Info{locked: true})
710
711 conn =
712 conn
713 |> with_credentials(current_user.nickname, "test")
714 |> post("/api/friendships/create.json", %{user_id: followed.id})
715
716 current_user = Repo.get(User, current_user.id)
717 followed = Repo.get(User, followed.id)
718
719 refute User.ap_followers(followed) in current_user.following
720
721 assert json_response(conn, 200) ==
722 UserView.render("show.json", %{user: followed, for: current_user})
723 end
724 end
725
726 describe "POST /friendships/destroy.json" do
727 setup [:valid_user]
728
729 test "without valid credentials", %{conn: conn} do
730 conn = post(conn, "/api/friendships/destroy.json")
731 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
732 end
733
734 test "with credentials", %{conn: conn, user: current_user} do
735 followed = insert(:user)
736
737 {:ok, current_user} = User.follow(current_user, followed)
738 assert User.ap_followers(followed) in current_user.following
739 ActivityPub.follow(current_user, followed)
740
741 conn =
742 conn
743 |> with_credentials(current_user.nickname, "test")
744 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
745
746 current_user = Repo.get(User, current_user.id)
747 assert current_user.following == [current_user.ap_id]
748
749 assert json_response(conn, 200) ==
750 UserView.render("show.json", %{user: followed, for: current_user})
751 end
752 end
753
754 describe "POST /blocks/create.json" do
755 setup [:valid_user]
756
757 test "without valid credentials", %{conn: conn} do
758 conn = post(conn, "/api/blocks/create.json")
759 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
760 end
761
762 test "with credentials", %{conn: conn, user: current_user} do
763 blocked = insert(:user)
764
765 conn =
766 conn
767 |> with_credentials(current_user.nickname, "test")
768 |> post("/api/blocks/create.json", %{user_id: blocked.id})
769
770 current_user = Repo.get(User, current_user.id)
771 assert User.blocks?(current_user, blocked)
772
773 assert json_response(conn, 200) ==
774 UserView.render("show.json", %{user: blocked, for: current_user})
775 end
776 end
777
778 describe "POST /blocks/destroy.json" do
779 setup [:valid_user]
780
781 test "without valid credentials", %{conn: conn} do
782 conn = post(conn, "/api/blocks/destroy.json")
783 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
784 end
785
786 test "with credentials", %{conn: conn, user: current_user} do
787 blocked = insert(:user)
788
789 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
790 assert User.blocks?(current_user, blocked)
791
792 conn =
793 conn
794 |> with_credentials(current_user.nickname, "test")
795 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
796
797 current_user = Repo.get(User, current_user.id)
798 assert current_user.info.blocks == []
799
800 assert json_response(conn, 200) ==
801 UserView.render("show.json", %{user: blocked, for: current_user})
802 end
803 end
804
805 describe "GET /help/test.json" do
806 test "returns \"ok\"", %{conn: conn} do
807 conn = get(conn, "/api/help/test.json")
808 assert json_response(conn, 200) == "ok"
809 end
810 end
811
812 describe "POST /api/qvitter/update_avatar.json" do
813 setup [:valid_user]
814
815 test "without valid credentials", %{conn: conn} do
816 conn = post(conn, "/api/qvitter/update_avatar.json")
817 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
818 end
819
820 test "with credentials", %{conn: conn, user: current_user} do
821 avatar_image = File.read!("test/fixtures/avatar_data_uri")
822
823 conn =
824 conn
825 |> with_credentials(current_user.nickname, "test")
826 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
827
828 current_user = Repo.get(User, current_user.id)
829 assert is_map(current_user.avatar)
830
831 assert json_response(conn, 200) ==
832 UserView.render("show.json", %{user: current_user, for: current_user})
833 end
834 end
835
836 describe "GET /api/qvitter/mutes.json" do
837 setup [:valid_user]
838
839 test "unimplemented mutes without valid credentials", %{conn: conn} do
840 conn = get(conn, "/api/qvitter/mutes.json")
841 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
842 end
843
844 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
845 response =
846 conn
847 |> with_credentials(current_user.nickname, "test")
848 |> get("/api/qvitter/mutes.json")
849 |> json_response(200)
850
851 assert [] = response
852 end
853 end
854
855 describe "POST /api/favorites/create/:id" do
856 setup [:valid_user]
857
858 test "without valid credentials", %{conn: conn} do
859 note_activity = insert(:note_activity)
860 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
861 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
862 end
863
864 test "with credentials", %{conn: conn, user: current_user} do
865 note_activity = insert(:note_activity)
866
867 conn =
868 conn
869 |> with_credentials(current_user.nickname, "test")
870 |> post("/api/favorites/create/#{note_activity.id}.json")
871
872 assert json_response(conn, 200)
873 end
874
875 test "with credentials, invalid param", %{conn: conn, user: current_user} do
876 conn =
877 conn
878 |> with_credentials(current_user.nickname, "test")
879 |> post("/api/favorites/create/wrong.json")
880
881 assert json_response(conn, 400)
882 end
883
884 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
885 conn =
886 conn
887 |> with_credentials(current_user.nickname, "test")
888 |> post("/api/favorites/create/1.json")
889
890 assert json_response(conn, 400)
891 end
892 end
893
894 describe "POST /api/favorites/destroy/:id" do
895 setup [:valid_user]
896
897 test "without valid credentials", %{conn: conn} do
898 note_activity = insert(:note_activity)
899 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
900 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
901 end
902
903 test "with credentials", %{conn: conn, user: current_user} do
904 note_activity = insert(:note_activity)
905 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
906 ActivityPub.like(current_user, object)
907
908 conn =
909 conn
910 |> with_credentials(current_user.nickname, "test")
911 |> post("/api/favorites/destroy/#{note_activity.id}.json")
912
913 assert json_response(conn, 200)
914 end
915 end
916
917 describe "POST /api/statuses/retweet/:id" do
918 setup [:valid_user]
919
920 test "without valid credentials", %{conn: conn} do
921 note_activity = insert(:note_activity)
922 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
923 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
924 end
925
926 test "with credentials", %{conn: conn, user: current_user} do
927 note_activity = insert(:note_activity)
928
929 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
930
931 response =
932 conn
933 |> with_credentials(current_user.nickname, "test")
934 |> post(request_path)
935
936 activity = Repo.get(Activity, note_activity.id)
937 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
938
939 assert json_response(response, 200) ==
940 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
941 end
942 end
943
944 describe "POST /api/statuses/unretweet/:id" do
945 setup [:valid_user]
946
947 test "without valid credentials", %{conn: conn} do
948 note_activity = insert(:note_activity)
949 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
950 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
951 end
952
953 test "with credentials", %{conn: conn, user: current_user} do
954 note_activity = insert(:note_activity)
955
956 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
957
958 _response =
959 conn
960 |> with_credentials(current_user.nickname, "test")
961 |> post(request_path)
962
963 request_path = String.replace(request_path, "retweet", "unretweet")
964
965 response =
966 conn
967 |> with_credentials(current_user.nickname, "test")
968 |> post(request_path)
969
970 activity = Repo.get(Activity, note_activity.id)
971 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
972
973 assert json_response(response, 200) ==
974 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
975 end
976 end
977
978 describe "POST /api/account/register" do
979 test "it creates a new user", %{conn: conn} do
980 data = %{
981 "nickname" => "lain",
982 "email" => "lain@wired.jp",
983 "fullname" => "lain iwakura",
984 "bio" => "close the world.",
985 "password" => "bear",
986 "confirm" => "bear"
987 }
988
989 conn =
990 conn
991 |> post("/api/account/register", data)
992
993 user = json_response(conn, 200)
994
995 fetched_user = Repo.get_by(User, nickname: "lain")
996 assert user == UserView.render("show.json", %{user: fetched_user})
997 end
998
999 test "it returns errors on a problem", %{conn: conn} do
1000 data = %{
1001 "email" => "lain@wired.jp",
1002 "fullname" => "lain iwakura",
1003 "bio" => "close the world.",
1004 "password" => "bear",
1005 "confirm" => "bear"
1006 }
1007
1008 conn =
1009 conn
1010 |> post("/api/account/register", data)
1011
1012 errors = json_response(conn, 400)
1013
1014 assert is_binary(errors["error"])
1015 end
1016 end
1017
1018 describe "POST /api/account/password_reset, with valid parameters" do
1019 setup %{conn: conn} do
1020 user = insert(:user)
1021 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1022 %{conn: conn, user: user}
1023 end
1024
1025 test "it returns 204", %{conn: conn} do
1026 assert json_response(conn, :no_content)
1027 end
1028
1029 test "it creates a PasswordResetToken record for user", %{user: user} do
1030 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1031 assert token_record
1032 end
1033
1034 test "it sends an email to user", %{user: user} do
1035 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
1036
1037 Swoosh.TestAssertions.assert_email_sent(
1038 Pleroma.UserEmail.password_reset_email(user, token_record.token)
1039 )
1040 end
1041 end
1042
1043 describe "POST /api/account/password_reset, with invalid parameters" do
1044 setup [:valid_user]
1045
1046 test "it returns 500 when user is not found", %{conn: conn, user: user} do
1047 conn = post(conn, "/api/account/password_reset?email=nonexisting_#{user.email}")
1048 assert json_response(conn, :internal_server_error)
1049 end
1050
1051 test "it returns 500 when user is not local", %{conn: conn, user: user} do
1052 {:ok, user} = Repo.update(Changeset.change(user, local: false))
1053 conn = post(conn, "/api/account/password_reset?email=#{user.email}")
1054 assert json_response(conn, :internal_server_error)
1055 end
1056 end
1057
1058 describe "GET /api/account/confirm_email/:id/:token" do
1059 setup do
1060 user = insert(:user)
1061 info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
1062
1063 {:ok, user} =
1064 user
1065 |> Changeset.change()
1066 |> Changeset.put_embed(:info, info_change)
1067 |> Repo.update()
1068
1069 assert user.info.confirmation_pending
1070
1071 [user: user]
1072 end
1073
1074 test "it redirects to root url", %{conn: conn, user: user} do
1075 conn = get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1076
1077 assert 302 == conn.status
1078 end
1079
1080 test "it confirms the user account", %{conn: conn, user: user} do
1081 get(conn, "/api/account/confirm_email/#{user.id}/#{user.info.confirmation_token}")
1082
1083 user = Repo.get(User, user.id)
1084
1085 refute user.info.confirmation_pending
1086 refute user.info.confirmation_token
1087 end
1088
1089 test "it returns 500 if user cannot be found by id", %{conn: conn, user: user} do
1090 conn = get(conn, "/api/account/confirm_email/0/#{user.info.confirmation_token}")
1091
1092 assert 500 == conn.status
1093 end
1094
1095 test "it returns 500 if token is invalid", %{conn: conn, user: user} do
1096 conn = get(conn, "/api/account/confirm_email/#{user.id}/wrong_token")
1097
1098 assert 500 == conn.status
1099 end
1100 end
1101
1102 describe "POST /api/account/resend_confirmation_email" do
1103 setup do
1104 setting = Pleroma.Config.get([:instance, :account_activation_required])
1105
1106 unless setting do
1107 Pleroma.Config.put([:instance, :account_activation_required], true)
1108 on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
1109 end
1110
1111 user = insert(:user)
1112 info_change = User.Info.confirmation_changeset(user.info, :unconfirmed)
1113
1114 {:ok, user} =
1115 user
1116 |> Changeset.change()
1117 |> Changeset.put_embed(:info, info_change)
1118 |> Repo.update()
1119
1120 assert user.info.confirmation_pending
1121
1122 [user: user]
1123 end
1124
1125 test "it returns 204 No Content", %{conn: conn, user: user} do
1126 conn
1127 |> assign(:user, user)
1128 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1129 |> json_response(:no_content)
1130 end
1131
1132 test "it sends confirmation email", %{conn: conn, user: user} do
1133 conn
1134 |> assign(:user, user)
1135 |> post("/api/account/resend_confirmation_email?email=#{user.email}")
1136
1137 Swoosh.TestAssertions.assert_email_sent(Pleroma.UserEmail.account_confirmation_email(user))
1138 end
1139 end
1140
1141 describe "GET /api/externalprofile/show" do
1142 test "it returns the user", %{conn: conn} do
1143 user = insert(:user)
1144 other_user = insert(:user)
1145
1146 conn =
1147 conn
1148 |> assign(:user, user)
1149 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
1150
1151 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
1152 end
1153 end
1154
1155 describe "GET /api/statuses/followers" do
1156 test "it returns a user's followers", %{conn: conn} do
1157 user = insert(:user)
1158 follower_one = insert(:user)
1159 follower_two = insert(:user)
1160 _not_follower = insert(:user)
1161
1162 {:ok, follower_one} = User.follow(follower_one, user)
1163 {:ok, follower_two} = User.follow(follower_two, user)
1164
1165 conn =
1166 conn
1167 |> assign(:user, user)
1168 |> get("/api/statuses/followers")
1169
1170 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
1171 result = json_response(conn, 200)
1172 assert Enum.sort(expected) == Enum.sort(result)
1173 end
1174
1175 test "it returns 20 followers per page", %{conn: conn} do
1176 user = insert(:user)
1177 followers = insert_list(21, :user)
1178
1179 Enum.each(followers, fn follower ->
1180 User.follow(follower, user)
1181 end)
1182
1183 res_conn =
1184 conn
1185 |> assign(:user, user)
1186 |> get("/api/statuses/followers")
1187
1188 result = json_response(res_conn, 200)
1189 assert length(result) == 20
1190
1191 res_conn =
1192 conn
1193 |> assign(:user, user)
1194 |> get("/api/statuses/followers?page=2")
1195
1196 result = json_response(res_conn, 200)
1197 assert length(result) == 1
1198 end
1199
1200 test "it returns a given user's followers with user_id", %{conn: conn} do
1201 user = insert(:user)
1202 follower_one = insert(:user)
1203 follower_two = insert(:user)
1204 not_follower = insert(:user)
1205
1206 {:ok, follower_one} = User.follow(follower_one, user)
1207 {:ok, follower_two} = User.follow(follower_two, user)
1208
1209 conn =
1210 conn
1211 |> assign(:user, not_follower)
1212 |> get("/api/statuses/followers", %{"user_id" => user.id})
1213
1214 assert MapSet.equal?(
1215 MapSet.new(json_response(conn, 200)),
1216 MapSet.new(
1217 UserView.render("index.json", %{
1218 users: [follower_one, follower_two],
1219 for: not_follower
1220 })
1221 )
1222 )
1223 end
1224
1225 test "it returns empty when hide_followers is set to true", %{conn: conn} do
1226 user = insert(:user, %{info: %{hide_followers: true}})
1227 follower_one = insert(:user)
1228 follower_two = insert(:user)
1229 not_follower = insert(:user)
1230
1231 {:ok, _follower_one} = User.follow(follower_one, user)
1232 {:ok, _follower_two} = User.follow(follower_two, user)
1233
1234 response =
1235 conn
1236 |> assign(:user, not_follower)
1237 |> get("/api/statuses/followers", %{"user_id" => user.id})
1238 |> json_response(200)
1239
1240 assert [] == response
1241 end
1242
1243 test "it returns the followers when hide_followers is set to true if requested by the user themselves",
1244 %{
1245 conn: conn
1246 } do
1247 user = insert(:user, %{info: %{hide_followers: true}})
1248 follower_one = insert(:user)
1249 follower_two = insert(:user)
1250 _not_follower = insert(:user)
1251
1252 {:ok, _follower_one} = User.follow(follower_one, user)
1253 {:ok, _follower_two} = User.follow(follower_two, user)
1254
1255 conn =
1256 conn
1257 |> assign(:user, user)
1258 |> get("/api/statuses/followers", %{"user_id" => user.id})
1259
1260 refute [] == json_response(conn, 200)
1261 end
1262 end
1263
1264 describe "GET /api/statuses/blocks" do
1265 test "it returns the list of users blocked by requester", %{conn: conn} do
1266 user = insert(:user)
1267 other_user = insert(:user)
1268
1269 {:ok, user} = User.block(user, other_user)
1270
1271 conn =
1272 conn
1273 |> assign(:user, user)
1274 |> get("/api/statuses/blocks")
1275
1276 expected = UserView.render("index.json", %{users: [other_user], for: user})
1277 result = json_response(conn, 200)
1278 assert Enum.sort(expected) == Enum.sort(result)
1279 end
1280 end
1281
1282 describe "GET /api/statuses/friends" do
1283 test "it returns the logged in user's friends", %{conn: conn} do
1284 user = insert(:user)
1285 followed_one = insert(:user)
1286 followed_two = insert(:user)
1287 _not_followed = insert(:user)
1288
1289 {:ok, user} = User.follow(user, followed_one)
1290 {:ok, user} = User.follow(user, followed_two)
1291
1292 conn =
1293 conn
1294 |> assign(:user, user)
1295 |> get("/api/statuses/friends")
1296
1297 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1298 result = json_response(conn, 200)
1299 assert Enum.sort(expected) == Enum.sort(result)
1300 end
1301
1302 test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
1303 user = insert(:user)
1304 followeds = insert_list(21, :user)
1305
1306 {:ok, user} =
1307 Enum.reduce(followeds, {:ok, user}, fn followed, {:ok, user} ->
1308 User.follow(user, followed)
1309 end)
1310
1311 res_conn =
1312 conn
1313 |> assign(:user, user)
1314 |> get("/api/statuses/friends")
1315
1316 result = json_response(res_conn, 200)
1317 assert length(result) == 20
1318
1319 res_conn =
1320 conn
1321 |> assign(:user, user)
1322 |> get("/api/statuses/friends", %{page: 2})
1323
1324 result = json_response(res_conn, 200)
1325 assert length(result) == 1
1326
1327 res_conn =
1328 conn
1329 |> assign(:user, user)
1330 |> get("/api/statuses/friends", %{all: true})
1331
1332 result = json_response(res_conn, 200)
1333 assert length(result) == 21
1334 end
1335
1336 test "it returns a given user's friends with user_id", %{conn: conn} do
1337 user = insert(:user)
1338 followed_one = insert(:user)
1339 followed_two = insert(:user)
1340 _not_followed = insert(:user)
1341
1342 {:ok, user} = User.follow(user, followed_one)
1343 {:ok, user} = User.follow(user, followed_two)
1344
1345 conn =
1346 conn
1347 |> assign(:user, user)
1348 |> get("/api/statuses/friends", %{"user_id" => user.id})
1349
1350 assert MapSet.equal?(
1351 MapSet.new(json_response(conn, 200)),
1352 MapSet.new(
1353 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1354 )
1355 )
1356 end
1357
1358 test "it returns empty when hide_follows is set to true", %{conn: conn} do
1359 user = insert(:user, %{info: %{hide_follows: true}})
1360 followed_one = insert(:user)
1361 followed_two = insert(:user)
1362 not_followed = insert(:user)
1363
1364 {:ok, user} = User.follow(user, followed_one)
1365 {:ok, user} = User.follow(user, followed_two)
1366
1367 conn =
1368 conn
1369 |> assign(:user, not_followed)
1370 |> get("/api/statuses/friends", %{"user_id" => user.id})
1371
1372 assert [] == json_response(conn, 200)
1373 end
1374
1375 test "it returns friends when hide_follows is set to true if the user themselves request it",
1376 %{
1377 conn: conn
1378 } do
1379 user = insert(:user, %{info: %{hide_follows: true}})
1380 followed_one = insert(:user)
1381 followed_two = insert(:user)
1382 _not_followed = insert(:user)
1383
1384 {:ok, _user} = User.follow(user, followed_one)
1385 {:ok, _user} = User.follow(user, followed_two)
1386
1387 response =
1388 conn
1389 |> assign(:user, user)
1390 |> get("/api/statuses/friends", %{"user_id" => user.id})
1391 |> json_response(200)
1392
1393 refute [] == response
1394 end
1395
1396 test "it returns a given user's friends with screen_name", %{conn: conn} do
1397 user = insert(:user)
1398 followed_one = insert(:user)
1399 followed_two = insert(:user)
1400 _not_followed = insert(:user)
1401
1402 {:ok, user} = User.follow(user, followed_one)
1403 {:ok, user} = User.follow(user, followed_two)
1404
1405 conn =
1406 conn
1407 |> assign(:user, user)
1408 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1409
1410 assert MapSet.equal?(
1411 MapSet.new(json_response(conn, 200)),
1412 MapSet.new(
1413 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1414 )
1415 )
1416 end
1417 end
1418
1419 describe "GET /friends/ids" do
1420 test "it returns a user's friends", %{conn: conn} do
1421 user = insert(:user)
1422 followed_one = insert(:user)
1423 followed_two = insert(:user)
1424 _not_followed = insert(:user)
1425
1426 {:ok, user} = User.follow(user, followed_one)
1427 {:ok, user} = User.follow(user, followed_two)
1428
1429 conn =
1430 conn
1431 |> assign(:user, user)
1432 |> get("/api/friends/ids")
1433
1434 expected = [followed_one.id, followed_two.id]
1435
1436 assert MapSet.equal?(
1437 MapSet.new(Poison.decode!(json_response(conn, 200))),
1438 MapSet.new(expected)
1439 )
1440 end
1441 end
1442
1443 describe "POST /api/account/update_profile.json" do
1444 test "it updates a user's profile", %{conn: conn} do
1445 user = insert(:user)
1446 user2 = insert(:user)
1447
1448 conn =
1449 conn
1450 |> assign(:user, user)
1451 |> post("/api/account/update_profile.json", %{
1452 "name" => "new name",
1453 "description" => "hi @#{user2.nickname}"
1454 })
1455
1456 user = Repo.get!(User, user.id)
1457 assert user.name == "new name"
1458
1459 assert user.bio ==
1460 "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
1461 user2.ap_id
1462 }'>@<span>#{user2.nickname}</span></a></span>"
1463
1464 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1465 end
1466
1467 test "it sets and un-sets hide_follows", %{conn: conn} do
1468 user = insert(:user)
1469
1470 conn
1471 |> assign(:user, user)
1472 |> post("/api/account/update_profile.json", %{
1473 "hide_follows" => "true"
1474 })
1475
1476 user = Repo.get!(User, user.id)
1477 assert user.info.hide_follows == true
1478
1479 conn =
1480 conn
1481 |> assign(:user, user)
1482 |> post("/api/account/update_profile.json", %{
1483 "hide_follows" => "false"
1484 })
1485
1486 user = Repo.get!(User, user.id)
1487 assert user.info.hide_follows == false
1488 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1489 end
1490
1491 test "it sets and un-sets hide_followers", %{conn: conn} do
1492 user = insert(:user)
1493
1494 conn
1495 |> assign(:user, user)
1496 |> post("/api/account/update_profile.json", %{
1497 "hide_followers" => "true"
1498 })
1499
1500 user = Repo.get!(User, user.id)
1501 assert user.info.hide_followers == true
1502
1503 conn =
1504 conn
1505 |> assign(:user, user)
1506 |> post("/api/account/update_profile.json", %{
1507 "hide_followers" => "false"
1508 })
1509
1510 user = Repo.get!(User, user.id)
1511 assert user.info.hide_followers == false
1512 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1513 end
1514
1515 test "it sets and un-sets show_role", %{conn: conn} do
1516 user = insert(:user)
1517
1518 conn
1519 |> assign(:user, user)
1520 |> post("/api/account/update_profile.json", %{
1521 "show_role" => "true"
1522 })
1523
1524 user = Repo.get!(User, user.id)
1525 assert user.info.show_role == true
1526
1527 conn =
1528 conn
1529 |> assign(:user, user)
1530 |> post("/api/account/update_profile.json", %{
1531 "show_role" => "false"
1532 })
1533
1534 user = Repo.get!(User, user.id)
1535 assert user.info.show_role == false
1536 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1537 end
1538
1539 test "it locks an account", %{conn: conn} do
1540 user = insert(:user)
1541
1542 conn =
1543 conn
1544 |> assign(:user, user)
1545 |> post("/api/account/update_profile.json", %{
1546 "locked" => "true"
1547 })
1548
1549 user = Repo.get!(User, user.id)
1550 assert user.info.locked == true
1551
1552 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1553 end
1554
1555 test "it unlocks an account", %{conn: conn} do
1556 user = insert(:user)
1557
1558 conn =
1559 conn
1560 |> assign(:user, user)
1561 |> post("/api/account/update_profile.json", %{
1562 "locked" => "false"
1563 })
1564
1565 user = Repo.get!(User, user.id)
1566 assert user.info.locked == false
1567
1568 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1569 end
1570 end
1571
1572 defp valid_user(_context) do
1573 user = insert(:user)
1574 [user: user]
1575 end
1576
1577 defp with_credentials(conn, username, password) do
1578 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1579 put_req_header(conn, "authorization", header_content)
1580 end
1581
1582 describe "GET /api/search.json" do
1583 test "it returns search results", %{conn: conn} do
1584 user = insert(:user)
1585 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1586
1587 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1588 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1589
1590 conn =
1591 conn
1592 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1593
1594 assert [status] = json_response(conn, 200)
1595 assert status["id"] == activity.id
1596 end
1597 end
1598
1599 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1600 test "it returns the tags timeline", %{conn: conn} do
1601 user = insert(:user)
1602 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1603
1604 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1605 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1606
1607 conn =
1608 conn
1609 |> get("/api/statusnet/tags/timeline/2hu.json")
1610
1611 assert [status] = json_response(conn, 200)
1612 assert status["id"] == activity.id
1613 end
1614 end
1615
1616 test "Convert newlines to <br> in bio", %{conn: conn} do
1617 user = insert(:user)
1618
1619 _conn =
1620 conn
1621 |> assign(:user, user)
1622 |> post("/api/account/update_profile.json", %{
1623 "description" => "Hello,\r\nWorld! I\n am a test."
1624 })
1625
1626 user = Repo.get!(User, user.id)
1627 assert user.bio == "Hello,<br>World! I<br> am a test."
1628 end
1629
1630 describe "POST /api/pleroma/change_password" do
1631 setup [:valid_user]
1632
1633 test "without credentials", %{conn: conn} do
1634 conn = post(conn, "/api/pleroma/change_password")
1635 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1636 end
1637
1638 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1639 conn =
1640 conn
1641 |> with_credentials(current_user.nickname, "test")
1642 |> post("/api/pleroma/change_password", %{
1643 "password" => "hi",
1644 "new_password" => "newpass",
1645 "new_password_confirmation" => "newpass"
1646 })
1647
1648 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1649 end
1650
1651 test "with credentials, valid password and new password and confirmation not matching", %{
1652 conn: conn,
1653 user: current_user
1654 } do
1655 conn =
1656 conn
1657 |> with_credentials(current_user.nickname, "test")
1658 |> post("/api/pleroma/change_password", %{
1659 "password" => "test",
1660 "new_password" => "newpass",
1661 "new_password_confirmation" => "notnewpass"
1662 })
1663
1664 assert json_response(conn, 200) == %{
1665 "error" => "New password does not match confirmation."
1666 }
1667 end
1668
1669 test "with credentials, valid password and invalid new password", %{
1670 conn: conn,
1671 user: current_user
1672 } do
1673 conn =
1674 conn
1675 |> with_credentials(current_user.nickname, "test")
1676 |> post("/api/pleroma/change_password", %{
1677 "password" => "test",
1678 "new_password" => "",
1679 "new_password_confirmation" => ""
1680 })
1681
1682 assert json_response(conn, 200) == %{
1683 "error" => "New password can't be blank."
1684 }
1685 end
1686
1687 test "with credentials, valid password and matching new password and confirmation", %{
1688 conn: conn,
1689 user: current_user
1690 } do
1691 conn =
1692 conn
1693 |> with_credentials(current_user.nickname, "test")
1694 |> post("/api/pleroma/change_password", %{
1695 "password" => "test",
1696 "new_password" => "newpass",
1697 "new_password_confirmation" => "newpass"
1698 })
1699
1700 assert json_response(conn, 200) == %{"status" => "success"}
1701 fetched_user = Repo.get(User, current_user.id)
1702 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1703 end
1704 end
1705
1706 describe "POST /api/pleroma/delete_account" do
1707 setup [:valid_user]
1708
1709 test "without credentials", %{conn: conn} do
1710 conn = post(conn, "/api/pleroma/delete_account")
1711 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1712 end
1713
1714 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1715 conn =
1716 conn
1717 |> with_credentials(current_user.nickname, "test")
1718 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1719
1720 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1721 end
1722
1723 test "with credentials and valid password", %{conn: conn, user: current_user} do
1724 conn =
1725 conn
1726 |> with_credentials(current_user.nickname, "test")
1727 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1728
1729 assert json_response(conn, 200) == %{"status" => "success"}
1730 # Wait a second for the started task to end
1731 :timer.sleep(1000)
1732 end
1733 end
1734
1735 describe "GET /api/pleroma/friend_requests" do
1736 test "it lists friend requests" do
1737 user = insert(:user)
1738 other_user = insert(:user)
1739
1740 {:ok, _activity} = ActivityPub.follow(other_user, user)
1741
1742 user = Repo.get(User, user.id)
1743 other_user = Repo.get(User, other_user.id)
1744
1745 assert User.following?(other_user, user) == false
1746
1747 conn =
1748 build_conn()
1749 |> assign(:user, user)
1750 |> get("/api/pleroma/friend_requests")
1751
1752 assert [relationship] = json_response(conn, 200)
1753 assert other_user.id == relationship["id"]
1754 end
1755
1756 test "requires 'read' permission", %{conn: conn} do
1757 token1 = insert(:oauth_token, scopes: ["write"])
1758 token2 = insert(:oauth_token, scopes: ["read"])
1759
1760 for token <- [token1, token2] do
1761 conn =
1762 conn
1763 |> put_req_header("authorization", "Bearer #{token.token}")
1764 |> get("/api/pleroma/friend_requests")
1765
1766 if token == token1 do
1767 assert %{"error" => "Insufficient permissions: read."} == json_response(conn, 403)
1768 else
1769 assert json_response(conn, 200)
1770 end
1771 end
1772 end
1773 end
1774
1775 describe "POST /api/pleroma/friendships/approve" do
1776 test "it approves a friend request" do
1777 user = insert(:user)
1778 other_user = insert(:user)
1779
1780 {:ok, _activity} = ActivityPub.follow(other_user, user)
1781
1782 user = Repo.get(User, user.id)
1783 other_user = Repo.get(User, other_user.id)
1784
1785 assert User.following?(other_user, user) == false
1786
1787 conn =
1788 build_conn()
1789 |> assign(:user, user)
1790 |> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
1791
1792 assert relationship = json_response(conn, 200)
1793 assert other_user.id == relationship["id"]
1794 assert relationship["follows_you"] == true
1795 end
1796 end
1797
1798 describe "POST /api/pleroma/friendships/deny" do
1799 test "it denies a friend request" do
1800 user = insert(:user)
1801 other_user = insert(:user)
1802
1803 {:ok, _activity} = ActivityPub.follow(other_user, user)
1804
1805 user = Repo.get(User, user.id)
1806 other_user = Repo.get(User, other_user.id)
1807
1808 assert User.following?(other_user, user) == false
1809
1810 conn =
1811 build_conn()
1812 |> assign(:user, user)
1813 |> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
1814
1815 assert relationship = json_response(conn, 200)
1816 assert other_user.id == relationship["id"]
1817 assert relationship["follows_you"] == false
1818 end
1819 end
1820
1821 describe "GET /api/pleroma/search_user" do
1822 test "it returns users, ordered by similarity", %{conn: conn} do
1823 user = insert(:user, %{name: "eal"})
1824 user_two = insert(:user, %{name: "eal me"})
1825 _user_three = insert(:user, %{name: "zzz"})
1826
1827 resp =
1828 conn
1829 |> get(twitter_api_search__path(conn, :search_user), query: "eal me")
1830 |> json_response(200)
1831
1832 assert length(resp) == 2
1833 assert [user_two.id, user.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1834 end
1835 end
1836
1837 describe "POST /api/media/upload" do
1838 setup context do
1839 Pleroma.DataCase.ensure_local_uploader(context)
1840 end
1841
1842 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1843 conn: conn
1844 } do
1845 user = insert(:user)
1846
1847 upload_filename = "test/fixtures/image_tmp.jpg"
1848 File.cp!("test/fixtures/image.jpg", upload_filename)
1849
1850 file = %Plug.Upload{
1851 content_type: "image/jpg",
1852 path: Path.absname(upload_filename),
1853 filename: "image.jpg"
1854 }
1855
1856 response =
1857 conn
1858 |> assign(:user, user)
1859 |> put_req_header("content-type", "application/octet-stream")
1860 |> post("/api/media/upload", %{
1861 "media" => file
1862 })
1863 |> json_response(:ok)
1864
1865 assert response["media_id"]
1866 object = Repo.get(Object, response["media_id"])
1867 assert object
1868 assert object.data["actor"] == User.ap_id(user)
1869 end
1870 end
1871
1872 describe "POST /api/media/metadata/create" do
1873 setup do
1874 object = insert(:note)
1875 user = User.get_by_ap_id(object.data["actor"])
1876 %{object: object, user: user}
1877 end
1878
1879 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1880 conn: conn,
1881 object: object
1882 } do
1883 initial_description = object.data["name"]
1884 another_user = insert(:user)
1885
1886 conn
1887 |> assign(:user, another_user)
1888 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1889 |> json_response(:forbidden)
1890
1891 object = Repo.get(Object, object.id)
1892 assert object.data["name"] == initial_description
1893 end
1894
1895 test "it updates `data[name]` of referenced Object with provided value", %{
1896 conn: conn,
1897 object: object,
1898 user: user
1899 } do
1900 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
1901
1902 conn
1903 |> assign(:user, user)
1904 |> post("/api/media/metadata/create", %{
1905 "media_id" => object.id,
1906 "alt_text" => %{"text" => description}
1907 })
1908 |> json_response(:no_content)
1909
1910 object = Repo.get(Object, object.id)
1911 assert object.data["name"] == description
1912 end
1913 end
1914
1915 describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
1916 test "it returns a list of pinned statuses", %{conn: conn} do
1917 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1918
1919 user = insert(:user, %{name: "egor"})
1920 {:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
1921 {:ok, _} = CommonAPI.pin(activity_id, user)
1922
1923 resp =
1924 conn
1925 |> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
1926 |> json_response(200)
1927
1928 assert length(resp) == 1
1929 assert [%{"id" => ^activity_id, "pinned" => true}] = resp
1930 end
1931 end
1932
1933 describe "POST /api/statuses/pin/:id" do
1934 setup do
1935 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1936 [user: insert(:user)]
1937 end
1938
1939 test "without valid credentials", %{conn: conn} do
1940 note_activity = insert(:note_activity)
1941 conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
1942 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1943 end
1944
1945 test "with credentials", %{conn: conn, user: user} do
1946 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
1947
1948 request_path = "/api/statuses/pin/#{activity.id}.json"
1949
1950 response =
1951 conn
1952 |> with_credentials(user.nickname, "test")
1953 |> post(request_path)
1954
1955 user = refresh_record(user)
1956
1957 assert json_response(response, 200) ==
1958 ActivityRepresenter.to_map(activity, %{user: user, for: user})
1959 end
1960 end
1961
1962 describe "POST /api/statuses/unpin/:id" do
1963 setup do
1964 Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
1965 [user: insert(:user)]
1966 end
1967
1968 test "without valid credentials", %{conn: conn} do
1969 note_activity = insert(:note_activity)
1970 conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
1971 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1972 end
1973
1974 test "with credentials", %{conn: conn, user: user} do
1975 {:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
1976 {:ok, activity} = CommonAPI.pin(activity.id, user)
1977
1978 request_path = "/api/statuses/unpin/#{activity.id}.json"
1979
1980 response =
1981 conn
1982 |> with_credentials(user.nickname, "test")
1983 |> post(request_path)
1984
1985 user = refresh_record(user)
1986
1987 assert json_response(response, 200) ==
1988 ActivityRepresenter.to_map(activity, %{user: user, for: user})
1989 end
1990 end
1991
1992 describe "GET /api/oauth_tokens" do
1993 setup do
1994 token = insert(:oauth_token) |> Repo.preload(:user)
1995
1996 %{token: token}
1997 end
1998
1999 test "renders list", %{token: token} do
2000 response =
2001 build_conn()
2002 |> assign(:user, token.user)
2003 |> get("/api/oauth_tokens")
2004
2005 keys =
2006 json_response(response, 200)
2007 |> hd()
2008 |> Map.keys()
2009
2010 assert keys -- ["id", "app_name", "valid_until"] == []
2011 end
2012
2013 test "revoke token", %{token: token} do
2014 response =
2015 build_conn()
2016 |> assign(:user, token.user)
2017 |> delete("/api/oauth_tokens/#{token.id}")
2018
2019 tokens = Token.get_user_tokens(token.user)
2020
2021 assert tokens == []
2022 assert response.status == 201
2023 end
2024 end
2025 end