Merge branch 'support/issue_442' into 'develop'
[akkoma] / test / web / twitter_api / twitter_api_controller_test.exs
1 defmodule Pleroma.Web.TwitterAPI.ControllerTest do
2 use Pleroma.Web.ConnCase
3 alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
4 alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
5 alias Pleroma.{Repo, Activity, User, Object, Notification}
6 alias Pleroma.Web.ActivityPub.ActivityPub
7 alias Pleroma.Web.TwitterAPI.UserView
8 alias Pleroma.Web.TwitterAPI.NotificationView
9 alias Pleroma.Web.CommonAPI
10 alias Pleroma.Web.TwitterAPI.TwitterAPI
11 alias Comeonin.Pbkdf2
12
13 import Pleroma.Factory
14
15 @banner "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
16
17 describe "POST /api/account/update_profile_banner" do
18 test "it updates the banner", %{conn: conn} do
19 user = insert(:user)
20
21 conn
22 |> assign(:user, user)
23 |> post(authenticated_twitter_api__path(conn, :update_banner), %{"banner" => @banner})
24 |> json_response(200)
25
26 user = refresh_record(user)
27 assert user.info.banner["type"] == "Image"
28 end
29 end
30
31 describe "POST /api/qvitter/update_background_image" do
32 test "it updates the background", %{conn: conn} do
33 user = insert(:user)
34
35 conn
36 |> assign(:user, user)
37 |> post(authenticated_twitter_api__path(conn, :update_background), %{"img" => @banner})
38 |> json_response(200)
39
40 user = refresh_record(user)
41 assert user.info.background["type"] == "Image"
42 end
43 end
44
45 describe "POST /api/account/verify_credentials" do
46 setup [:valid_user]
47
48 test "without valid credentials", %{conn: conn} do
49 conn = post(conn, "/api/account/verify_credentials.json")
50 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
51 end
52
53 test "with credentials", %{conn: conn, user: user} do
54 response =
55 conn
56 |> with_credentials(user.nickname, "test")
57 |> post("/api/account/verify_credentials.json")
58 |> json_response(200)
59
60 assert response == UserView.render("show.json", %{user: user, token: response["token"]})
61 end
62 end
63
64 describe "POST /statuses/update.json" do
65 setup [:valid_user]
66
67 test "without valid credentials", %{conn: conn} do
68 conn = post(conn, "/api/statuses/update.json")
69 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
70 end
71
72 test "with credentials", %{conn: conn, user: user} do
73 conn_with_creds = conn |> with_credentials(user.nickname, "test")
74 request_path = "/api/statuses/update.json"
75
76 error_response = %{
77 "request" => request_path,
78 "error" => "Client must provide a 'status' parameter with a value."
79 }
80
81 conn =
82 conn_with_creds
83 |> post(request_path)
84
85 assert json_response(conn, 400) == error_response
86
87 conn =
88 conn_with_creds
89 |> post(request_path, %{status: ""})
90
91 assert json_response(conn, 400) == error_response
92
93 conn =
94 conn_with_creds
95 |> post(request_path, %{status: " "})
96
97 assert json_response(conn, 400) == error_response
98
99 # we post with visibility private in order to avoid triggering relay
100 conn =
101 conn_with_creds
102 |> post(request_path, %{status: "Nice meme.", visibility: "private"})
103
104 assert json_response(conn, 200) ==
105 ActivityRepresenter.to_map(Repo.one(Activity), %{user: user})
106 end
107 end
108
109 describe "GET /statuses/public_timeline.json" do
110 test "returns statuses", %{conn: conn} do
111 user = insert(:user)
112 activities = ActivityBuilder.insert_list(30, %{}, %{user: user})
113 ActivityBuilder.insert_list(10, %{}, %{user: user})
114 since_id = List.last(activities).id
115
116 conn =
117 conn
118 |> get("/api/statuses/public_timeline.json", %{since_id: since_id})
119
120 response = json_response(conn, 200)
121
122 assert length(response) == 10
123 end
124
125 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
126 instance =
127 Application.get_env(:pleroma, :instance)
128 |> Keyword.put(:public, false)
129
130 Application.put_env(:pleroma, :instance, instance)
131
132 conn
133 |> get("/api/statuses/public_timeline.json")
134 |> json_response(403)
135
136 instance =
137 Application.get_env(:pleroma, :instance)
138 |> Keyword.put(:public, true)
139
140 Application.put_env(:pleroma, :instance, instance)
141 end
142
143 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
144 conn
145 |> get("/api/statuses/public_timeline.json")
146 |> json_response(200)
147 end
148 end
149
150 describe "GET /statuses/public_and_external_timeline.json" do
151 test "returns 403 to unauthenticated request when the instance is not public", %{conn: conn} do
152 instance =
153 Application.get_env(:pleroma, :instance)
154 |> Keyword.put(:public, false)
155
156 Application.put_env(:pleroma, :instance, instance)
157
158 conn
159 |> get("/api/statuses/public_and_external_timeline.json")
160 |> json_response(403)
161
162 instance =
163 Application.get_env(:pleroma, :instance)
164 |> Keyword.put(:public, true)
165
166 Application.put_env(:pleroma, :instance, instance)
167 end
168
169 test "returns 200 to unauthenticated request when the instance is public", %{conn: conn} do
170 conn
171 |> get("/api/statuses/public_and_external_timeline.json")
172 |> json_response(200)
173 end
174 end
175
176 describe "GET /statuses/show/:id.json" do
177 test "returns one status", %{conn: conn} do
178 user = insert(:user)
179 {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey!"})
180 actor = Repo.get_by!(User, ap_id: activity.data["actor"])
181
182 conn =
183 conn
184 |> get("/api/statuses/show/#{activity.id}.json")
185
186 response = json_response(conn, 200)
187
188 assert response == ActivityRepresenter.to_map(activity, %{user: actor})
189 end
190 end
191
192 describe "GET /users/show.json" do
193 test "gets user with screen_name", %{conn: conn} do
194 user = insert(:user)
195
196 conn =
197 conn
198 |> get("/api/users/show.json", %{"screen_name" => user.nickname})
199
200 response = json_response(conn, 200)
201
202 assert response["id"] == user.id
203 end
204
205 test "gets user with user_id", %{conn: conn} do
206 user = insert(:user)
207
208 conn =
209 conn
210 |> get("/api/users/show.json", %{"user_id" => user.id})
211
212 response = json_response(conn, 200)
213
214 assert response["id"] == user.id
215 end
216
217 test "gets a user for a logged in user", %{conn: conn} do
218 user = insert(:user)
219 logged_in = insert(:user)
220
221 {:ok, logged_in, user, _activity} = TwitterAPI.follow(logged_in, %{"user_id" => user.id})
222
223 conn =
224 conn
225 |> with_credentials(logged_in.nickname, "test")
226 |> get("/api/users/show.json", %{"user_id" => user.id})
227
228 response = json_response(conn, 200)
229
230 assert response["following"] == true
231 end
232 end
233
234 describe "GET /statusnet/conversation/:id.json" do
235 test "returns the statuses in the conversation", %{conn: conn} do
236 {:ok, _user} = UserBuilder.insert()
237 {:ok, activity} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
238 {:ok, _activity_two} = ActivityBuilder.insert(%{"type" => "Create", "context" => "2hu"})
239 {:ok, _activity_three} = ActivityBuilder.insert(%{"type" => "Create", "context" => "3hu"})
240
241 conn =
242 conn
243 |> get("/api/statusnet/conversation/#{activity.data["context_id"]}.json")
244
245 response = json_response(conn, 200)
246
247 assert length(response) == 2
248 end
249 end
250
251 describe "GET /statuses/friends_timeline.json" do
252 setup [:valid_user]
253
254 test "without valid credentials", %{conn: conn} do
255 conn = get(conn, "/api/statuses/friends_timeline.json")
256 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
257 end
258
259 test "with credentials", %{conn: conn, user: current_user} do
260 user = insert(:user)
261
262 activities =
263 ActivityBuilder.insert_list(30, %{"to" => [User.ap_followers(user)]}, %{user: user})
264
265 returned_activities =
266 ActivityBuilder.insert_list(10, %{"to" => [User.ap_followers(user)]}, %{user: user})
267
268 other_user = insert(:user)
269 ActivityBuilder.insert_list(10, %{}, %{user: other_user})
270 since_id = List.last(activities).id
271
272 current_user =
273 Ecto.Changeset.change(current_user, following: [User.ap_followers(user)])
274 |> Repo.update!()
275
276 conn =
277 conn
278 |> with_credentials(current_user.nickname, "test")
279 |> get("/api/statuses/friends_timeline.json", %{since_id: since_id})
280
281 response = json_response(conn, 200)
282
283 assert length(response) == 10
284
285 assert response ==
286 Enum.map(returned_activities, fn activity ->
287 ActivityRepresenter.to_map(activity, %{
288 user: User.get_cached_by_ap_id(activity.data["actor"]),
289 for: current_user
290 })
291 end)
292 end
293 end
294
295 describe "GET /statuses/dm_timeline.json" do
296 test "it show direct messages", %{conn: conn} do
297 user_one = insert(:user)
298 user_two = insert(:user)
299
300 {:ok, user_two} = User.follow(user_two, user_one)
301
302 {:ok, direct} =
303 CommonAPI.post(user_one, %{
304 "status" => "Hi @#{user_two.nickname}!",
305 "visibility" => "direct"
306 })
307
308 {:ok, direct_two} =
309 CommonAPI.post(user_two, %{
310 "status" => "Hi @#{user_one.nickname}!",
311 "visibility" => "direct"
312 })
313
314 {:ok, _follower_only} =
315 CommonAPI.post(user_one, %{
316 "status" => "Hi @#{user_two.nickname}!",
317 "visibility" => "private"
318 })
319
320 # Only direct should be visible here
321 res_conn =
322 conn
323 |> assign(:user, user_two)
324 |> get("/api/statuses/dm_timeline.json")
325
326 [status, status_two] = json_response(res_conn, 200)
327 assert status["id"] == direct_two.id
328 assert status_two["id"] == direct.id
329 end
330 end
331
332 describe "GET /statuses/mentions.json" do
333 setup [:valid_user]
334
335 test "without valid credentials", %{conn: conn} do
336 conn = get(conn, "/api/statuses/mentions.json")
337 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
338 end
339
340 test "with credentials", %{conn: conn, user: current_user} do
341 {:ok, activity} =
342 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user})
343
344 conn =
345 conn
346 |> with_credentials(current_user.nickname, "test")
347 |> get("/api/statuses/mentions.json")
348
349 response = json_response(conn, 200)
350
351 assert length(response) == 1
352
353 assert Enum.at(response, 0) ==
354 ActivityRepresenter.to_map(activity, %{
355 user: current_user,
356 mentioned: [current_user]
357 })
358 end
359 end
360
361 describe "GET /api/qvitter/statuses/notifications.json" do
362 setup [:valid_user]
363
364 test "without valid credentials", %{conn: conn} do
365 conn = get(conn, "/api/qvitter/statuses/notifications.json")
366 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
367 end
368
369 test "with credentials", %{conn: conn, user: current_user} do
370 other_user = insert(:user)
371
372 {:ok, _activity} =
373 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
374
375 conn =
376 conn
377 |> with_credentials(current_user.nickname, "test")
378 |> get("/api/qvitter/statuses/notifications.json")
379
380 response = json_response(conn, 200)
381
382 assert length(response) == 1
383
384 assert response ==
385 NotificationView.render("notification.json", %{
386 notifications: Notification.for_user(current_user),
387 for: current_user
388 })
389 end
390 end
391
392 describe "POST /api/qvitter/statuses/notifications/read" do
393 setup [:valid_user]
394
395 test "without valid credentials", %{conn: conn} do
396 conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567})
397 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
398 end
399
400 test "with credentials, without any params", %{conn: conn, user: current_user} do
401 conn =
402 conn
403 |> with_credentials(current_user.nickname, "test")
404 |> post("/api/qvitter/statuses/notifications/read")
405
406 assert json_response(conn, 400) == %{
407 "error" => "You need to specify latest_id",
408 "request" => "/api/qvitter/statuses/notifications/read"
409 }
410 end
411
412 test "with credentials, with params", %{conn: conn, user: current_user} do
413 other_user = insert(:user)
414
415 {:ok, _activity} =
416 ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user})
417
418 response_conn =
419 conn
420 |> with_credentials(current_user.nickname, "test")
421 |> get("/api/qvitter/statuses/notifications.json")
422
423 [notification] = response = json_response(response_conn, 200)
424
425 assert length(response) == 1
426
427 assert notification["is_seen"] == 0
428
429 response_conn =
430 conn
431 |> with_credentials(current_user.nickname, "test")
432 |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]})
433
434 [notification] = response = json_response(response_conn, 200)
435
436 assert length(response) == 1
437
438 assert notification["is_seen"] == 1
439 end
440 end
441
442 describe "GET /statuses/user_timeline.json" do
443 setup [:valid_user]
444
445 test "without any params", %{conn: conn} do
446 conn = get(conn, "/api/statuses/user_timeline.json")
447
448 assert json_response(conn, 400) == %{
449 "error" => "You need to specify screen_name or user_id",
450 "request" => "/api/statuses/user_timeline.json"
451 }
452 end
453
454 test "with user_id", %{conn: conn} do
455 user = insert(:user)
456 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
457
458 conn = get(conn, "/api/statuses/user_timeline.json", %{"user_id" => user.id})
459 response = json_response(conn, 200)
460 assert length(response) == 1
461 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
462 end
463
464 test "with screen_name", %{conn: conn} do
465 user = insert(:user)
466 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
467
468 conn = get(conn, "/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
469 response = json_response(conn, 200)
470 assert length(response) == 1
471 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
472 end
473
474 test "with credentials", %{conn: conn, user: current_user} do
475 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: current_user})
476
477 conn =
478 conn
479 |> with_credentials(current_user.nickname, "test")
480 |> get("/api/statuses/user_timeline.json")
481
482 response = json_response(conn, 200)
483
484 assert length(response) == 1
485 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: current_user})
486 end
487
488 test "with credentials with user_id", %{conn: conn, user: current_user} do
489 user = insert(:user)
490 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
491
492 conn =
493 conn
494 |> with_credentials(current_user.nickname, "test")
495 |> get("/api/statuses/user_timeline.json", %{"user_id" => user.id})
496
497 response = json_response(conn, 200)
498
499 assert length(response) == 1
500 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
501 end
502
503 test "with credentials screen_name", %{conn: conn, user: current_user} do
504 user = insert(:user)
505 {:ok, activity} = ActivityBuilder.insert(%{"id" => 1}, %{user: user})
506
507 conn =
508 conn
509 |> with_credentials(current_user.nickname, "test")
510 |> get("/api/statuses/user_timeline.json", %{"screen_name" => user.nickname})
511
512 response = json_response(conn, 200)
513
514 assert length(response) == 1
515 assert Enum.at(response, 0) == ActivityRepresenter.to_map(activity, %{user: user})
516 end
517 end
518
519 describe "POST /friendships/create.json" do
520 setup [:valid_user]
521
522 test "without valid credentials", %{conn: conn} do
523 conn = post(conn, "/api/friendships/create.json")
524 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
525 end
526
527 test "with credentials", %{conn: conn, user: current_user} do
528 followed = insert(:user)
529
530 conn =
531 conn
532 |> with_credentials(current_user.nickname, "test")
533 |> post("/api/friendships/create.json", %{user_id: followed.id})
534
535 current_user = Repo.get(User, current_user.id)
536 assert User.ap_followers(followed) in current_user.following
537
538 assert json_response(conn, 200) ==
539 UserView.render("show.json", %{user: followed, for: current_user})
540 end
541 end
542
543 describe "POST /friendships/destroy.json" do
544 setup [:valid_user]
545
546 test "without valid credentials", %{conn: conn} do
547 conn = post(conn, "/api/friendships/destroy.json")
548 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
549 end
550
551 test "with credentials", %{conn: conn, user: current_user} do
552 followed = insert(:user)
553
554 {:ok, current_user} = User.follow(current_user, followed)
555 assert User.ap_followers(followed) in current_user.following
556 ActivityPub.follow(current_user, followed)
557
558 conn =
559 conn
560 |> with_credentials(current_user.nickname, "test")
561 |> post("/api/friendships/destroy.json", %{user_id: followed.id})
562
563 current_user = Repo.get(User, current_user.id)
564 assert current_user.following == [current_user.ap_id]
565
566 assert json_response(conn, 200) ==
567 UserView.render("show.json", %{user: followed, for: current_user})
568 end
569 end
570
571 describe "POST /blocks/create.json" do
572 setup [:valid_user]
573
574 test "without valid credentials", %{conn: conn} do
575 conn = post(conn, "/api/blocks/create.json")
576 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
577 end
578
579 test "with credentials", %{conn: conn, user: current_user} do
580 blocked = insert(:user)
581
582 conn =
583 conn
584 |> with_credentials(current_user.nickname, "test")
585 |> post("/api/blocks/create.json", %{user_id: blocked.id})
586
587 current_user = Repo.get(User, current_user.id)
588 assert User.blocks?(current_user, blocked)
589
590 assert json_response(conn, 200) ==
591 UserView.render("show.json", %{user: blocked, for: current_user})
592 end
593 end
594
595 describe "POST /blocks/destroy.json" do
596 setup [:valid_user]
597
598 test "without valid credentials", %{conn: conn} do
599 conn = post(conn, "/api/blocks/destroy.json")
600 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
601 end
602
603 test "with credentials", %{conn: conn, user: current_user} do
604 blocked = insert(:user)
605
606 {:ok, current_user, blocked} = TwitterAPI.block(current_user, %{"user_id" => blocked.id})
607 assert User.blocks?(current_user, blocked)
608
609 conn =
610 conn
611 |> with_credentials(current_user.nickname, "test")
612 |> post("/api/blocks/destroy.json", %{user_id: blocked.id})
613
614 current_user = Repo.get(User, current_user.id)
615 assert current_user.info.blocks == []
616
617 assert json_response(conn, 200) ==
618 UserView.render("show.json", %{user: blocked, for: current_user})
619 end
620 end
621
622 describe "GET /help/test.json" do
623 test "returns \"ok\"", %{conn: conn} do
624 conn = get(conn, "/api/help/test.json")
625 assert json_response(conn, 200) == "ok"
626 end
627 end
628
629 describe "POST /api/qvitter/update_avatar.json" do
630 setup [:valid_user]
631
632 test "without valid credentials", %{conn: conn} do
633 conn = post(conn, "/api/qvitter/update_avatar.json")
634 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
635 end
636
637 test "with credentials", %{conn: conn, user: current_user} do
638 avatar_image = File.read!("test/fixtures/avatar_data_uri")
639
640 conn =
641 conn
642 |> with_credentials(current_user.nickname, "test")
643 |> post("/api/qvitter/update_avatar.json", %{img: avatar_image})
644
645 current_user = Repo.get(User, current_user.id)
646 assert is_map(current_user.avatar)
647
648 assert json_response(conn, 200) ==
649 UserView.render("show.json", %{user: current_user, for: current_user})
650 end
651 end
652
653 describe "GET /api/qvitter/mutes.json" do
654 setup [:valid_user]
655
656 test "unimplemented mutes without valid credentials", %{conn: conn} do
657 conn = get(conn, "/api/qvitter/mutes.json")
658 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
659 end
660
661 test "unimplemented mutes with credentials", %{conn: conn, user: current_user} do
662 response =
663 conn
664 |> with_credentials(current_user.nickname, "test")
665 |> get("/api/qvitter/mutes.json")
666 |> json_response(200)
667
668 assert [] = response
669 end
670 end
671
672 describe "POST /api/favorites/create/:id" do
673 setup [:valid_user]
674
675 test "without valid credentials", %{conn: conn} do
676 note_activity = insert(:note_activity)
677 conn = post(conn, "/api/favorites/create/#{note_activity.id}.json")
678 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
679 end
680
681 test "with credentials", %{conn: conn, user: current_user} do
682 note_activity = insert(:note_activity)
683
684 conn =
685 conn
686 |> with_credentials(current_user.nickname, "test")
687 |> post("/api/favorites/create/#{note_activity.id}.json")
688
689 assert json_response(conn, 200)
690 end
691
692 test "with credentials, invalid param", %{conn: conn, user: current_user} do
693 conn =
694 conn
695 |> with_credentials(current_user.nickname, "test")
696 |> post("/api/favorites/create/wrong.json")
697
698 assert json_response(conn, 400)
699 end
700
701 test "with credentials, invalid activity", %{conn: conn, user: current_user} do
702 conn =
703 conn
704 |> with_credentials(current_user.nickname, "test")
705 |> post("/api/favorites/create/1.json")
706
707 assert json_response(conn, 500)
708 end
709 end
710
711 describe "POST /api/favorites/destroy/:id" do
712 setup [:valid_user]
713
714 test "without valid credentials", %{conn: conn} do
715 note_activity = insert(:note_activity)
716 conn = post(conn, "/api/favorites/destroy/#{note_activity.id}.json")
717 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
718 end
719
720 test "with credentials", %{conn: conn, user: current_user} do
721 note_activity = insert(:note_activity)
722 object = Object.get_by_ap_id(note_activity.data["object"]["id"])
723 ActivityPub.like(current_user, object)
724
725 conn =
726 conn
727 |> with_credentials(current_user.nickname, "test")
728 |> post("/api/favorites/destroy/#{note_activity.id}.json")
729
730 assert json_response(conn, 200)
731 end
732 end
733
734 describe "POST /api/statuses/retweet/:id" do
735 setup [:valid_user]
736
737 test "without valid credentials", %{conn: conn} do
738 note_activity = insert(:note_activity)
739 conn = post(conn, "/api/statuses/retweet/#{note_activity.id}.json")
740 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
741 end
742
743 test "with credentials", %{conn: conn, user: current_user} do
744 note_activity = insert(:note_activity)
745
746 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
747
748 response =
749 conn
750 |> with_credentials(current_user.nickname, "test")
751 |> post(request_path)
752
753 activity = Repo.get(Activity, note_activity.id)
754 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
755
756 assert json_response(response, 200) ==
757 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
758 end
759 end
760
761 describe "POST /api/statuses/unretweet/:id" do
762 setup [:valid_user]
763
764 test "without valid credentials", %{conn: conn} do
765 note_activity = insert(:note_activity)
766 conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json")
767 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
768 end
769
770 test "with credentials", %{conn: conn, user: current_user} do
771 note_activity = insert(:note_activity)
772
773 request_path = "/api/statuses/retweet/#{note_activity.id}.json"
774
775 _response =
776 conn
777 |> with_credentials(current_user.nickname, "test")
778 |> post(request_path)
779
780 request_path = String.replace(request_path, "retweet", "unretweet")
781
782 response =
783 conn
784 |> with_credentials(current_user.nickname, "test")
785 |> post(request_path)
786
787 activity = Repo.get(Activity, note_activity.id)
788 activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"])
789
790 assert json_response(response, 200) ==
791 ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user})
792 end
793 end
794
795 describe "POST /api/account/register" do
796 test "it creates a new user", %{conn: conn} do
797 data = %{
798 "nickname" => "lain",
799 "email" => "lain@wired.jp",
800 "fullname" => "lain iwakura",
801 "bio" => "close the world.",
802 "password" => "bear",
803 "confirm" => "bear"
804 }
805
806 conn =
807 conn
808 |> post("/api/account/register", data)
809
810 user = json_response(conn, 200)
811
812 fetched_user = Repo.get_by(User, nickname: "lain")
813 assert user == UserView.render("show.json", %{user: fetched_user})
814 end
815
816 test "it returns errors on a problem", %{conn: conn} do
817 data = %{
818 "email" => "lain@wired.jp",
819 "fullname" => "lain iwakura",
820 "bio" => "close the world.",
821 "password" => "bear",
822 "confirm" => "bear"
823 }
824
825 conn =
826 conn
827 |> post("/api/account/register", data)
828
829 errors = json_response(conn, 400)
830
831 assert is_binary(errors["error"])
832 end
833 end
834
835 describe "GET /api/externalprofile/show" do
836 test "it returns the user", %{conn: conn} do
837 user = insert(:user)
838 other_user = insert(:user)
839
840 conn =
841 conn
842 |> assign(:user, user)
843 |> get("/api/externalprofile/show", %{profileurl: other_user.ap_id})
844
845 assert json_response(conn, 200) == UserView.render("show.json", %{user: other_user})
846 end
847 end
848
849 describe "GET /api/statuses/followers" do
850 test "it returns a user's followers", %{conn: conn} do
851 user = insert(:user)
852 follower_one = insert(:user)
853 follower_two = insert(:user)
854 _not_follower = insert(:user)
855
856 {:ok, follower_one} = User.follow(follower_one, user)
857 {:ok, follower_two} = User.follow(follower_two, user)
858
859 conn =
860 conn
861 |> assign(:user, user)
862 |> get("/api/statuses/followers")
863
864 expected = UserView.render("index.json", %{users: [follower_one, follower_two], for: user})
865 result = json_response(conn, 200)
866 assert Enum.sort(expected) == Enum.sort(result)
867 end
868
869 test "it returns a given user's followers with user_id", %{conn: conn} do
870 user = insert(:user)
871 follower_one = insert(:user)
872 follower_two = insert(:user)
873 not_follower = insert(:user)
874
875 {:ok, follower_one} = User.follow(follower_one, user)
876 {:ok, follower_two} = User.follow(follower_two, user)
877
878 conn =
879 conn
880 |> assign(:user, not_follower)
881 |> get("/api/statuses/followers", %{"user_id" => user.id})
882
883 assert MapSet.equal?(
884 MapSet.new(json_response(conn, 200)),
885 MapSet.new(
886 UserView.render("index.json", %{
887 users: [follower_one, follower_two],
888 for: not_follower
889 })
890 )
891 )
892 end
893
894 test "it returns empty for a hidden network", %{conn: conn} do
895 user = insert(:user, %{info: %{hide_network: true}})
896 follower_one = insert(:user)
897 follower_two = insert(:user)
898 not_follower = insert(:user)
899
900 {:ok, _follower_one} = User.follow(follower_one, user)
901 {:ok, _follower_two} = User.follow(follower_two, user)
902
903 response =
904 conn
905 |> assign(:user, not_follower)
906 |> get("/api/statuses/followers", %{"user_id" => user.id})
907 |> json_response(200)
908
909 assert [] == response
910 end
911
912 test "it returns the followers for a hidden network if requested by the user themselves", %{
913 conn: conn
914 } do
915 user = insert(:user, %{info: %{hide_network: true}})
916 follower_one = insert(:user)
917 follower_two = insert(:user)
918 _not_follower = insert(:user)
919
920 {:ok, _follower_one} = User.follow(follower_one, user)
921 {:ok, _follower_two} = User.follow(follower_two, user)
922
923 conn =
924 conn
925 |> assign(:user, user)
926 |> get("/api/statuses/followers", %{"user_id" => user.id})
927
928 refute [] == json_response(conn, 200)
929 end
930 end
931
932 describe "GET /api/statuses/friends" do
933 test "it returns the logged in user's friends", %{conn: conn} do
934 user = insert(:user)
935 followed_one = insert(:user)
936 followed_two = insert(:user)
937 _not_followed = insert(:user)
938
939 {:ok, user} = User.follow(user, followed_one)
940 {:ok, user} = User.follow(user, followed_two)
941
942 conn =
943 conn
944 |> assign(:user, user)
945 |> get("/api/statuses/friends")
946
947 expected = UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
948 result = json_response(conn, 200)
949 assert Enum.sort(expected) == Enum.sort(result)
950 end
951
952 test "it returns a given user's friends with user_id", %{conn: conn} do
953 user = insert(:user)
954 followed_one = insert(:user)
955 followed_two = insert(:user)
956 _not_followed = insert(:user)
957
958 {:ok, user} = User.follow(user, followed_one)
959 {:ok, user} = User.follow(user, followed_two)
960
961 conn =
962 conn
963 |> assign(:user, user)
964 |> get("/api/statuses/friends", %{"user_id" => user.id})
965
966 assert MapSet.equal?(
967 MapSet.new(json_response(conn, 200)),
968 MapSet.new(
969 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
970 )
971 )
972 end
973
974 test "it returns empty for a hidden network", %{conn: conn} do
975 user = insert(:user, %{info: %{hide_network: true}})
976 followed_one = insert(:user)
977 followed_two = insert(:user)
978 not_followed = insert(:user)
979
980 {:ok, user} = User.follow(user, followed_one)
981 {:ok, user} = User.follow(user, followed_two)
982
983 conn =
984 conn
985 |> assign(:user, not_followed)
986 |> get("/api/statuses/friends", %{"user_id" => user.id})
987
988 assert [] == json_response(conn, 200)
989 end
990
991 test "it returns friends for a hidden network if the user themselves request it", %{
992 conn: conn
993 } do
994 user = insert(:user, %{info: %{hide_network: true}})
995 followed_one = insert(:user)
996 followed_two = insert(:user)
997 _not_followed = insert(:user)
998
999 {:ok, _user} = User.follow(user, followed_one)
1000 {:ok, _user} = User.follow(user, followed_two)
1001
1002 response =
1003 conn
1004 |> assign(:user, user)
1005 |> get("/api/statuses/friends", %{"user_id" => user.id})
1006 |> json_response(200)
1007
1008 refute [] == response
1009 end
1010
1011 test "it returns a given user's friends with screen_name", %{conn: conn} do
1012 user = insert(:user)
1013 followed_one = insert(:user)
1014 followed_two = insert(:user)
1015 _not_followed = insert(:user)
1016
1017 {:ok, user} = User.follow(user, followed_one)
1018 {:ok, user} = User.follow(user, followed_two)
1019
1020 conn =
1021 conn
1022 |> assign(:user, user)
1023 |> get("/api/statuses/friends", %{"screen_name" => user.nickname})
1024
1025 assert MapSet.equal?(
1026 MapSet.new(json_response(conn, 200)),
1027 MapSet.new(
1028 UserView.render("index.json", %{users: [followed_one, followed_two], for: user})
1029 )
1030 )
1031 end
1032 end
1033
1034 describe "GET /friends/ids" do
1035 test "it returns a user's friends", %{conn: conn} do
1036 user = insert(:user)
1037 followed_one = insert(:user)
1038 followed_two = insert(:user)
1039 _not_followed = insert(:user)
1040
1041 {:ok, user} = User.follow(user, followed_one)
1042 {:ok, user} = User.follow(user, followed_two)
1043
1044 conn =
1045 conn
1046 |> assign(:user, user)
1047 |> get("/api/friends/ids")
1048
1049 expected = [followed_one.id, followed_two.id]
1050
1051 assert MapSet.equal?(
1052 MapSet.new(Poison.decode!(json_response(conn, 200))),
1053 MapSet.new(expected)
1054 )
1055 end
1056 end
1057
1058 describe "POST /api/account/update_profile.json" do
1059 test "it updates a user's profile", %{conn: conn} do
1060 user = insert(:user)
1061 user2 = insert(:user)
1062
1063 conn =
1064 conn
1065 |> assign(:user, user)
1066 |> post("/api/account/update_profile.json", %{
1067 "name" => "new name",
1068 "description" => "hi @#{user2.nickname}"
1069 })
1070
1071 user = Repo.get!(User, user.id)
1072 assert user.name == "new name"
1073
1074 assert user.bio ==
1075 "hi <span><a data-user='#{user2.id}' class='mention' href='#{user2.ap_id}'>@<span>#{
1076 user2.nickname
1077 }</span></a></span>"
1078
1079 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1080 end
1081
1082 test "it sets and un-sets hide_network", %{conn: conn} do
1083 user = insert(:user)
1084
1085 conn
1086 |> assign(:user, user)
1087 |> post("/api/account/update_profile.json", %{
1088 "hide_network" => "true"
1089 })
1090
1091 user = Repo.get!(User, user.id)
1092 assert user.info.hide_network == true
1093
1094 conn =
1095 conn
1096 |> assign(:user, user)
1097 |> post("/api/account/update_profile.json", %{
1098 "hide_network" => "false"
1099 })
1100
1101 user = Repo.get!(User, user.id)
1102 assert user.info.hide_network == false
1103 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1104 end
1105
1106 test "it locks an account", %{conn: conn} do
1107 user = insert(:user)
1108
1109 conn =
1110 conn
1111 |> assign(:user, user)
1112 |> post("/api/account/update_profile.json", %{
1113 "locked" => "true"
1114 })
1115
1116 user = Repo.get!(User, user.id)
1117 assert user.info.locked == true
1118
1119 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1120 end
1121
1122 test "it unlocks an account", %{conn: conn} do
1123 user = insert(:user)
1124
1125 conn =
1126 conn
1127 |> assign(:user, user)
1128 |> post("/api/account/update_profile.json", %{
1129 "locked" => "false"
1130 })
1131
1132 user = Repo.get!(User, user.id)
1133 assert user.info.locked == false
1134
1135 assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
1136 end
1137 end
1138
1139 defp valid_user(_context) do
1140 user = insert(:user)
1141 [user: user]
1142 end
1143
1144 defp with_credentials(conn, username, password) do
1145 header_content = "Basic " <> Base.encode64("#{username}:#{password}")
1146 put_req_header(conn, "authorization", header_content)
1147 end
1148
1149 describe "GET /api/search.json" do
1150 test "it returns search results", %{conn: conn} do
1151 user = insert(:user)
1152 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1153
1154 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"})
1155 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1156
1157 conn =
1158 conn
1159 |> get("/api/search.json", %{"q" => "2hu", "page" => "1", "rpp" => "1"})
1160
1161 assert [status] = json_response(conn, 200)
1162 assert status["id"] == activity.id
1163 end
1164 end
1165
1166 describe "GET /api/statusnet/tags/timeline/:tag.json" do
1167 test "it returns the tags timeline", %{conn: conn} do
1168 user = insert(:user)
1169 user_two = insert(:user, %{nickname: "shp@shitposter.club"})
1170
1171 {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about #2hu"})
1172 {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"})
1173
1174 conn =
1175 conn
1176 |> get("/api/statusnet/tags/timeline/2hu.json")
1177
1178 assert [status] = json_response(conn, 200)
1179 assert status["id"] == activity.id
1180 end
1181 end
1182
1183 test "Convert newlines to <br> in bio", %{conn: conn} do
1184 user = insert(:user)
1185
1186 _conn =
1187 conn
1188 |> assign(:user, user)
1189 |> post("/api/account/update_profile.json", %{
1190 "description" => "Hello,\r\nWorld! I\n am a test."
1191 })
1192
1193 user = Repo.get!(User, user.id)
1194 assert user.bio == "Hello,<br>World! I<br> am a test."
1195 end
1196
1197 describe "POST /api/pleroma/change_password" do
1198 setup [:valid_user]
1199
1200 test "without credentials", %{conn: conn} do
1201 conn = post(conn, "/api/pleroma/change_password")
1202 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1203 end
1204
1205 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1206 conn =
1207 conn
1208 |> with_credentials(current_user.nickname, "test")
1209 |> post("/api/pleroma/change_password", %{
1210 "password" => "hi",
1211 "new_password" => "newpass",
1212 "new_password_confirmation" => "newpass"
1213 })
1214
1215 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1216 end
1217
1218 test "with credentials, valid password and new password and confirmation not matching", %{
1219 conn: conn,
1220 user: current_user
1221 } do
1222 conn =
1223 conn
1224 |> with_credentials(current_user.nickname, "test")
1225 |> post("/api/pleroma/change_password", %{
1226 "password" => "test",
1227 "new_password" => "newpass",
1228 "new_password_confirmation" => "notnewpass"
1229 })
1230
1231 assert json_response(conn, 200) == %{
1232 "error" => "New password does not match confirmation."
1233 }
1234 end
1235
1236 test "with credentials, valid password and invalid new password", %{
1237 conn: conn,
1238 user: current_user
1239 } do
1240 conn =
1241 conn
1242 |> with_credentials(current_user.nickname, "test")
1243 |> post("/api/pleroma/change_password", %{
1244 "password" => "test",
1245 "new_password" => "",
1246 "new_password_confirmation" => ""
1247 })
1248
1249 assert json_response(conn, 200) == %{
1250 "error" => "New password can't be blank."
1251 }
1252 end
1253
1254 test "with credentials, valid password and matching new password and confirmation", %{
1255 conn: conn,
1256 user: current_user
1257 } do
1258 conn =
1259 conn
1260 |> with_credentials(current_user.nickname, "test")
1261 |> post("/api/pleroma/change_password", %{
1262 "password" => "test",
1263 "new_password" => "newpass",
1264 "new_password_confirmation" => "newpass"
1265 })
1266
1267 assert json_response(conn, 200) == %{"status" => "success"}
1268 fetched_user = Repo.get(User, current_user.id)
1269 assert Pbkdf2.checkpw("newpass", fetched_user.password_hash) == true
1270 end
1271 end
1272
1273 describe "POST /api/pleroma/delete_account" do
1274 setup [:valid_user]
1275
1276 test "without credentials", %{conn: conn} do
1277 conn = post(conn, "/api/pleroma/delete_account")
1278 assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
1279 end
1280
1281 test "with credentials and invalid password", %{conn: conn, user: current_user} do
1282 conn =
1283 conn
1284 |> with_credentials(current_user.nickname, "test")
1285 |> post("/api/pleroma/delete_account", %{"password" => "hi"})
1286
1287 assert json_response(conn, 200) == %{"error" => "Invalid password."}
1288 end
1289
1290 test "with credentials and valid password", %{conn: conn, user: current_user} do
1291 conn =
1292 conn
1293 |> with_credentials(current_user.nickname, "test")
1294 |> post("/api/pleroma/delete_account", %{"password" => "test"})
1295
1296 assert json_response(conn, 200) == %{"status" => "success"}
1297 # Wait a second for the started task to end
1298 :timer.sleep(1000)
1299 end
1300 end
1301
1302 describe "GET /api/pleroma/friend_requests" do
1303 test "it lists friend requests" do
1304 user = insert(:user)
1305 other_user = insert(:user)
1306
1307 {:ok, _activity} = ActivityPub.follow(other_user, user)
1308
1309 user = Repo.get(User, user.id)
1310 other_user = Repo.get(User, other_user.id)
1311
1312 assert User.following?(other_user, user) == false
1313
1314 conn =
1315 build_conn()
1316 |> assign(:user, user)
1317 |> get("/api/pleroma/friend_requests")
1318
1319 assert [relationship] = json_response(conn, 200)
1320 assert other_user.id == relationship["id"]
1321 end
1322 end
1323
1324 describe "POST /api/pleroma/friendships/approve" do
1325 test "it approves a friend request" do
1326 user = insert(:user)
1327 other_user = insert(:user)
1328
1329 {:ok, _activity} = ActivityPub.follow(other_user, user)
1330
1331 user = Repo.get(User, user.id)
1332 other_user = Repo.get(User, other_user.id)
1333
1334 assert User.following?(other_user, user) == false
1335
1336 conn =
1337 build_conn()
1338 |> assign(:user, user)
1339 |> post("/api/pleroma/friendships/approve", %{"user_id" => to_string(other_user.id)})
1340
1341 assert relationship = json_response(conn, 200)
1342 assert other_user.id == relationship["id"]
1343 assert relationship["follows_you"] == true
1344 end
1345 end
1346
1347 describe "POST /api/pleroma/friendships/deny" do
1348 test "it denies a friend request" do
1349 user = insert(:user)
1350 other_user = insert(:user)
1351
1352 {:ok, _activity} = ActivityPub.follow(other_user, user)
1353
1354 user = Repo.get(User, user.id)
1355 other_user = Repo.get(User, other_user.id)
1356
1357 assert User.following?(other_user, user) == false
1358
1359 conn =
1360 build_conn()
1361 |> assign(:user, user)
1362 |> post("/api/pleroma/friendships/deny", %{"user_id" => to_string(other_user.id)})
1363
1364 assert relationship = json_response(conn, 200)
1365 assert other_user.id == relationship["id"]
1366 assert relationship["follows_you"] == false
1367 end
1368 end
1369
1370 describe "GET /api/pleroma/search_user" do
1371 test "it returns users, ordered by similarity", %{conn: conn} do
1372 user = insert(:user, %{name: "eal"})
1373 user_two = insert(:user, %{name: "ean"})
1374 user_three = insert(:user, %{name: "ebn"})
1375
1376 resp =
1377 conn
1378 |> get(twitter_api_search__path(conn, :search_user), query: "eal")
1379 |> json_response(200)
1380
1381 assert length(resp) == 3
1382 assert [user.id, user_two.id, user_three.id] == Enum.map(resp, fn %{"id" => id} -> id end)
1383 end
1384 end
1385
1386 describe "POST /api/media/upload" do
1387 setup context do
1388 Pleroma.DataCase.ensure_local_uploader(context)
1389 end
1390
1391 test "it performs the upload and sets `data[actor]` with AP id of uploader user", %{
1392 conn: conn
1393 } do
1394 user = insert(:user)
1395
1396 upload_filename = "test/fixtures/image_tmp.jpg"
1397 File.cp!("test/fixtures/image.jpg", upload_filename)
1398
1399 file = %Plug.Upload{
1400 content_type: "image/jpg",
1401 path: Path.absname(upload_filename),
1402 filename: "image.jpg"
1403 }
1404
1405 response =
1406 conn
1407 |> assign(:user, user)
1408 |> put_req_header("content-type", "application/octet-stream")
1409 |> post("/api/media/upload", %{
1410 "media" => file
1411 })
1412 |> json_response(:ok)
1413
1414 assert response["media_id"]
1415 object = Repo.get(Object, response["media_id"])
1416 assert object
1417 assert object.data["actor"] == User.ap_id(user)
1418 end
1419 end
1420
1421 describe "POST /api/media/metadata/create" do
1422 setup do
1423 object = insert(:note)
1424 user = User.get_by_ap_id(object.data["actor"])
1425 %{object: object, user: user}
1426 end
1427
1428 test "it returns :forbidden status on attempt to modify someone else's upload", %{
1429 conn: conn,
1430 object: object
1431 } do
1432 initial_description = object.data["name"]
1433 another_user = insert(:user)
1434
1435 conn
1436 |> assign(:user, another_user)
1437 |> post("/api/media/metadata/create", %{"media_id" => object.id})
1438 |> json_response(:forbidden)
1439
1440 object = Repo.get(Object, object.id)
1441 assert object.data["name"] == initial_description
1442 end
1443
1444 test "it updates `data[name]` of referenced Object with provided value", %{
1445 conn: conn,
1446 object: object,
1447 user: user
1448 } do
1449 description = "Informative description of the image. Initial value: #{object.data["name"]}}"
1450
1451 conn
1452 |> assign(:user, user)
1453 |> post("/api/media/metadata/create", %{
1454 "media_id" => object.id,
1455 "alt_text" => %{"text" => description}
1456 })
1457 |> json_response(:no_content)
1458
1459 object = Repo.get(Object, object.id)
1460 assert object.data["name"] == description
1461 end
1462 end
1463 end