common_api_test.exs 26.8 KB
Newer Older
kaniini's avatar
kaniini committed
1
# Pleroma: A lightweight social networking server
2
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
kaniini's avatar
kaniini committed
3
4
# SPDX-License-Identifier: AGPL-3.0-only

lain's avatar
lain committed
5
defmodule Pleroma.Web.CommonAPITest do
6
  use Pleroma.DataCase
7
  alias Pleroma.Activity
8
  alias Pleroma.Conversation.Participation
9
  alias Pleroma.Object
rinpatch's avatar
rinpatch committed
10
  alias Pleroma.User
11
  alias Pleroma.Web.ActivityPub.ActivityPub
12
  alias Pleroma.Web.ActivityPub.Transmogrifier
13
  alias Pleroma.Web.ActivityPub.Visibility
14
  alias Pleroma.Web.AdminAPI.AccountView
15
16
17
  alias Pleroma.Web.CommonAPI

  import Pleroma.Factory
18
  import Mock
19

20
21
  require Pleroma.Constants

22
23
24
  setup do: clear_config([:instance, :safe_dm_mentions])
  setup do: clear_config([:instance, :limit])
  setup do: clear_config([:instance, :max_pinned_statuses])
25

26
27
28
29
30
31
32
33
34
35
36
37
  describe "unblocking" do
    test "it works even without an existing block activity" do
      blocked = insert(:user)
      blocker = insert(:user)
      User.block(blocker, blocked)

      assert User.blocks?(blocker, blocked)
      assert {:ok, :no_activity} == CommonAPI.unblock(blocker, blocked)
      refute User.blocks?(blocker, blocked)
    end
  end

38
  describe "deletion" do
39
40
41
    test "it works with pruned objects" do
      user = insert(:user)

42
      {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
43
44
45
46
47
48
49
50
51
52
53
54
55
56

      Object.normalize(post, false)
      |> Object.prune()

      with_mock Pleroma.Web.Federator,
        publish: fn _ -> nil end do
        assert {:ok, delete} = CommonAPI.delete(post.id, user)
        assert delete.local
        assert called(Pleroma.Web.Federator.publish(delete))
      end

      refute Activity.get_by_id(post.id)
    end

57
58
59
    test "it allows users to delete their posts" do
      user = insert(:user)

60
      {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

      with_mock Pleroma.Web.Federator,
        publish: fn _ -> nil end do
        assert {:ok, delete} = CommonAPI.delete(post.id, user)
        assert delete.local
        assert called(Pleroma.Web.Federator.publish(delete))
      end

      refute Activity.get_by_id(post.id)
    end

    test "it does not allow a user to delete their posts" do
      user = insert(:user)
      other_user = insert(:user)

76
      {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
77
78
79
80
81
82
83
84
85

      assert {:error, "Could not delete"} = CommonAPI.delete(post.id, other_user)
      assert Activity.get_by_id(post.id)
    end

    test "it allows moderators to delete other user's posts" do
      user = insert(:user)
      moderator = insert(:user, is_moderator: true)

86
      {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
87
88
89
90
91
92
93
94
95
96
97

      assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
      assert delete.local

      refute Activity.get_by_id(post.id)
    end

    test "it allows admins to delete other user's posts" do
      user = insert(:user)
      moderator = insert(:user, is_admin: true)

98
      {:ok, post} = CommonAPI.post(user, %{status: "namu amida butsu"})
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

      assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
      assert delete.local

      refute Activity.get_by_id(post.id)
    end

    test "superusers deleting non-local posts won't federate the delete" do
      # This is the user of the ingested activity
      _user =
        insert(:user,
          local: false,
          ap_id: "http://mastodon.example.org/users/admin",
          last_refreshed_at: NaiveDateTime.utc_now()
        )

      moderator = insert(:user, is_admin: true)

      data =
        File.read!("test/fixtures/mastodon-post-activity.json")
        |> Jason.decode!()

      {:ok, post} = Transmogrifier.handle_incoming(data)

      with_mock Pleroma.Web.Federator,
        publish: fn _ -> nil end do
        assert {:ok, delete} = CommonAPI.delete(post.id, moderator)
        assert delete.local
        refute called(Pleroma.Web.Federator.publish(:_))
      end

      refute Activity.get_by_id(post.id)
    end
  end

lain's avatar
lain committed
134
135
136
137
138
  test "favoriting race condition" do
    user = insert(:user)
    users_serial = insert_list(10, :user)
    users = insert_list(10, :user)

139
    {:ok, activity} = CommonAPI.post(user, %{status: "."})
lain's avatar
lain committed
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

    users_serial
    |> Enum.map(fn user ->
      CommonAPI.favorite(user, activity.id)
    end)

    object = Object.get_by_ap_id(activity.data["object"])
    assert object.data["like_count"] == 10

    users
    |> Enum.map(fn user ->
      Task.async(fn ->
        CommonAPI.favorite(user, activity.id)
      end)
    end)
    |> Enum.map(&Task.await/1)

    object = Object.get_by_ap_id(activity.data["object"])
    assert object.data["like_count"] == 20
  end

lain's avatar
lain committed
161
162
163
164
165
  test "repeating race condition" do
    user = insert(:user)
    users_serial = insert_list(10, :user)
    users = insert_list(10, :user)

166
    {:ok, activity} = CommonAPI.post(user, %{status: "."})
lain's avatar
lain committed
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187

    users_serial
    |> Enum.map(fn user ->
      CommonAPI.repeat(activity.id, user)
    end)

    object = Object.get_by_ap_id(activity.data["object"])
    assert object.data["announcement_count"] == 10

    users
    |> Enum.map(fn user ->
      Task.async(fn ->
        CommonAPI.repeat(activity.id, user)
      end)
    end)
    |> Enum.map(&Task.await/1)

    object = Object.get_by_ap_id(activity.data["object"])
    assert object.data["announcement_count"] == 20
  end

188
189
  test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do
    user = insert(:user)
190
    {:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
191
192
193
194

    [participation] = Participation.for_user(user)

    {:ok, convo_reply} =
195
      CommonAPI.post(user, %{status: ".", in_reply_to_conversation_id: participation.id})
196
197
198
199
200
201

    assert Visibility.is_direct?(convo_reply)

    assert activity.data["context"] == convo_reply.data["context"]
  end

202
203
204
205
206
207
208
  test "when replying to a conversation / participation, it only mentions the recipients explicitly declared in the participation" do
    har = insert(:user)
    jafnhar = insert(:user)
    tridi = insert(:user)

    {:ok, activity} =
      CommonAPI.post(har, %{
209
210
        status: "@#{jafnhar.nickname} hey",
        visibility: "direct"
211
212
213
214
215
216
217
218
219
      })

    assert har.ap_id in activity.recipients
    assert jafnhar.ap_id in activity.recipients

    [participation] = Participation.for_user(har)

    {:ok, activity} =
      CommonAPI.post(har, %{
220
221
222
223
        status: "I don't really like @#{tridi.nickname}",
        visibility: "direct",
        in_reply_to_status_id: activity.id,
        in_reply_to_conversation_id: participation.id
224
225
226
227
228
229
230
      })

    assert har.ap_id in activity.recipients
    assert jafnhar.ap_id in activity.recipients
    refute tridi.ap_id in activity.recipients
  end

lain's avatar
lain committed
231
232
233
234
  test "with the safe_dm_mention option set, it does not mention people beyond the initial tags" do
    har = insert(:user)
    jafnhar = insert(:user)
    tridi = insert(:user)
235

lain's avatar
lain committed
236
237
238
239
    Pleroma.Config.put([:instance, :safe_dm_mentions], true)

    {:ok, activity} =
      CommonAPI.post(har, %{
240
241
        status: "@#{jafnhar.nickname} hey, i never want to see @#{tridi.nickname} again",
        visibility: "direct"
lain's avatar
lain committed
242
243
244
245
246
247
      })

    refute tridi.ap_id in activity.recipients
    assert jafnhar.ap_id in activity.recipients
  end

248
249
  test "it de-duplicates tags" do
    user = insert(:user)
250
    {:ok, activity} = CommonAPI.post(user, %{status: "#2hu #2HU"})
251

252
    object = Object.normalize(activity)
kaniini's avatar
kaniini committed
253
254

    assert object.data["tag"] == ["2hu"]
255
  end
256

lain's avatar
lain committed
257
258
  test "it adds emoji in the object" do
    user = insert(:user)
259
    {:ok, activity} = CommonAPI.post(user, %{status: ":firefox:"})
lain's avatar
lain committed
260

vaartis's avatar
vaartis committed
261
    assert Object.normalize(activity).data["emoji"]["firefox"]
lain's avatar
lain committed
262
263
  end

264
  describe "posting" do
lain's avatar
lain committed
265
266
267
268
269
270
271
272
    test "it supports explicit addressing" do
      user = insert(:user)
      user_two = insert(:user)
      user_three = insert(:user)
      user_four = insert(:user)

      {:ok, activity} =
        CommonAPI.post(user, %{
273
          status:
lain's avatar
lain committed
274
            "Hey, I think @#{user_three.nickname} is ugly. @#{user_four.nickname} is alright though.",
275
          to: [user_two.nickname, user_four.nickname, "nonexistent"]
lain's avatar
lain committed
276
277
278
279
280
281
282
283
        })

      assert user.ap_id in activity.recipients
      assert user_two.ap_id in activity.recipients
      assert user_four.ap_id in activity.recipients
      refute user_three.ap_id in activity.recipients
    end

284
285
286
    test "it filters out obviously bad tags when accepting a post as HTML" do
      user = insert(:user)

287
      post = "<p><b>2hu</b></p><script>alert('xss')</script>"
288
289
290

      {:ok, activity} =
        CommonAPI.post(user, %{
291
292
          status: post,
          content_type: "text/html"
293
294
        })

295
      object = Object.normalize(activity)
kaniini's avatar
kaniini committed
296

297
      assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
298
299
300
301
302
    end

    test "it filters out obviously bad tags when accepting a post as Markdown" do
      user = insert(:user)

303
      post = "<p><b>2hu</b></p><script>alert('xss')</script>"
304
305
306

      {:ok, activity} =
        CommonAPI.post(user, %{
307
308
          status: post,
          content_type: "text/markdown"
309
310
        })

311
      object = Object.normalize(activity)
kaniini's avatar
kaniini committed
312

313
      assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
314
    end
minibikini's avatar
minibikini committed
315

316
317
318
    test "it does not allow replies to direct messages that are not direct messages themselves" do
      user = insert(:user)

319
      {:ok, activity} = CommonAPI.post(user, %{status: "suya..", visibility: "direct"})
320
321
322

      assert {:ok, _} =
               CommonAPI.post(user, %{
323
324
325
                 status: "suya..",
                 visibility: "direct",
                 in_reply_to_status_id: activity.id
326
327
328
               })

      Enum.each(["public", "private", "unlisted"], fn visibility ->
329
        assert {:error, "The message visibility must be direct"} =
330
                 CommonAPI.post(user, %{
331
332
333
                   status: "suya..",
                   visibility: visibility,
                   in_reply_to_status_id: activity.id
334
335
336
                 })
      end)
    end
337

minibikini's avatar
minibikini committed
338
339
340
341
    test "it allows to address a list" do
      user = insert(:user)
      {:ok, list} = Pleroma.List.create("foo", user)

342
      {:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
minibikini's avatar
minibikini committed
343

minibikini's avatar
minibikini committed
344
345
      assert activity.data["bcc"] == [list.ap_id]
      assert activity.recipients == [list.ap_id, user.ap_id]
minibikini's avatar
minibikini committed
346
      assert activity.data["listMessage"] == list.ap_id
minibikini's avatar
minibikini committed
347
    end
348
349
350
351
352

    test "it returns error when status is empty and no attachments" do
      user = insert(:user)

      assert {:error, "Cannot post an empty status without attachments"} =
353
               CommonAPI.post(user, %{status: ""})
354
355
    end

feld's avatar
feld committed
356
    test "it validates character limits are correctly enforced" do
357
358
359
360
361
      Pleroma.Config.put([:instance, :limit], 5)

      user = insert(:user)

      assert {:error, "The status is over the character limit"} =
362
               CommonAPI.post(user, %{status: "foobar"})
feld's avatar
feld committed
363

364
      assert {:ok, activity} = CommonAPI.post(user, %{status: "12345"})
365
    end
366
367
368
369
370
371
372
373
374

    test "it can handle activities that expire" do
      user = insert(:user)

      expires_at =
        NaiveDateTime.utc_now()
        |> NaiveDateTime.truncate(:second)
        |> NaiveDateTime.add(1_000_000, :second)

375
      assert {:ok, activity} = CommonAPI.post(user, %{status: "chai", expires_in: 1_000_000})
376
377
378
379

      assert expiration = Pleroma.ActivityExpiration.get_by_activity_id(activity.id)
      assert expiration.scheduled_at == expires_at
    end
380
  end
381
382

  describe "reactions" do
lain's avatar
lain committed
383
384
385
386
    test "reacting to a status with an emoji" do
      user = insert(:user)
      other_user = insert(:user)

387
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
lain's avatar
lain committed
388

lain's avatar
lain committed
389
      {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍")
lain's avatar
lain committed
390
391
392
393

      assert reaction.data["actor"] == user.ap_id
      assert reaction.data["content"] == "👍"

394
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
395
396

      {:error, _} = CommonAPI.react_with_emoji(activity.id, user, ".")
lain's avatar
lain committed
397
398
    end

lain's avatar
.    
lain committed
399
400
401
402
    test "unreacting to a status with an emoji" do
      user = insert(:user)
      other_user = insert(:user)

403
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
lain's avatar
lain committed
404
      {:ok, reaction} = CommonAPI.react_with_emoji(activity.id, user, "👍")
lain's avatar
.    
lain committed
405

406
      {:ok, unreaction} = CommonAPI.unreact_with_emoji(activity.id, user, "👍")
lain's avatar
lain committed
407
408
409

      assert unreaction.data["type"] == "Undo"
      assert unreaction.data["object"] == reaction.data["id"]
410
      assert unreaction.local
lain's avatar
.    
lain committed
411
412
    end

413
414
415
416
    test "repeating a status" do
      user = insert(:user)
      other_user = insert(:user)

417
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
418

419
420
      {:ok, %Activity{} = announce_activity} = CommonAPI.repeat(activity.id, user)
      assert Visibility.is_public?(announce_activity)
421
422
    end

423
424
425
    test "can't repeat a repeat" do
      user = insert(:user)
      other_user = insert(:user)
426
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
427

428
      {:ok, %Activity{} = announce} = CommonAPI.repeat(activity.id, other_user)
429

430
      refute match?({:ok, %Activity{}}, CommonAPI.repeat(announce.id, user))
431
432
    end

433
434
435
436
    test "repeating a status privately" do
      user = insert(:user)
      other_user = insert(:user)

437
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
438

439
      {:ok, %Activity{} = announce_activity} =
440
        CommonAPI.repeat(activity.id, user, %{visibility: "private"})
441
442
443
444

      assert Visibility.is_private?(announce_activity)
    end

445
446
447
448
    test "favoriting a status" do
      user = insert(:user)
      other_user = insert(:user)

449
      {:ok, post_activity} = CommonAPI.post(other_user, %{status: "cofe"})
450

451
452
453
454
      {:ok, %Activity{data: data}} = CommonAPI.favorite(user, post_activity.id)
      assert data["type"] == "Like"
      assert data["actor"] == user.ap_id
      assert data["object"] == post_activity.data["object"]
455
456
    end

457
    test "retweeting a status twice returns the status" do
458
459
460
      user = insert(:user)
      other_user = insert(:user)

461
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
462
463
      {:ok, %Activity{} = announce} = CommonAPI.repeat(activity.id, user)
      {:ok, ^announce} = CommonAPI.repeat(activity.id, user)
464
465
    end

466
    test "favoriting a status twice returns ok, but without the like activity" do
467
468
469
      user = insert(:user)
      other_user = insert(:user)

470
      {:ok, activity} = CommonAPI.post(other_user, %{status: "cofe"})
471
      {:ok, %Activity{}} = CommonAPI.favorite(user, activity.id)
472
      assert {:ok, :already_liked} = CommonAPI.favorite(user, activity.id)
473
474
    end
  end
minibikini's avatar
minibikini committed
475

minibikini's avatar
minibikini committed
476
  describe "pinned statuses" do
minibikini's avatar
minibikini committed
477
    setup do
minibikini's avatar
minibikini committed
478
      Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
minibikini's avatar
minibikini committed
479

minibikini's avatar
minibikini committed
480
      user = insert(:user)
481
      {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!"})
minibikini's avatar
minibikini committed
482

minibikini's avatar
minibikini committed
483
      [user: user, activity: activity]
minibikini's avatar
minibikini committed
484
485
    end

minibikini's avatar
minibikini committed
486
487
    test "pin status", %{user: user, activity: activity} do
      assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
minibikini's avatar
minibikini committed
488
489
490
491

      id = activity.id
      user = refresh_record(user)

492
      assert %User{pinned_activities: [^id]} = user
493
494
    end

rinpatch's avatar
rinpatch committed
495
496
497
    test "pin poll", %{user: user} do
      {:ok, activity} =
        CommonAPI.post(user, %{
498
499
          status: "How is fediverse today?",
          poll: %{options: ["Absolutely outstanding", "Not good"], expires_in: 20}
rinpatch's avatar
rinpatch committed
500
501
502
503
504
505
506
507
508
509
        })

      assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)

      id = activity.id
      user = refresh_record(user)

      assert %User{pinned_activities: [^id]} = user
    end

510
    test "unlisted statuses can be pinned", %{user: user} do
511
      {:ok, activity} = CommonAPI.post(user, %{status: "HI!!!", visibility: "unlisted"})
512
513
514
      assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
    end

minibikini's avatar
minibikini committed
515
    test "only self-authored can be pinned", %{activity: activity} do
minibikini's avatar
minibikini committed
516
517
      user = insert(:user)

minibikini's avatar
minibikini committed
518
519
520
521
      assert {:error, "Could not pin"} = CommonAPI.pin(activity.id, user)
    end

    test "max pinned statuses", %{user: user, activity: activity_one} do
522
      {:ok, activity_two} = CommonAPI.post(user, %{status: "HI!!!"})
minibikini's avatar
minibikini committed
523
524
525

      assert {:ok, ^activity_one} = CommonAPI.pin(activity_one.id, user)

minibikini's avatar
minibikini committed
526
      user = refresh_record(user)
minibikini's avatar
minibikini committed
527

minibikini's avatar
minibikini committed
528
      assert {:error, "You have already pinned the maximum number of statuses"} =
minibikini's avatar
minibikini committed
529
530
531
               CommonAPI.pin(activity_two.id, user)
    end

minibikini's avatar
minibikini committed
532
    test "unpin status", %{user: user, activity: activity} do
minibikini's avatar
minibikini committed
533
534
      {:ok, activity} = CommonAPI.pin(activity.id, user)

minibikini's avatar
minibikini committed
535
536
      user = refresh_record(user)

537
538
539
      id = activity.id

      assert match?({:ok, %{id: ^id}}, CommonAPI.unpin(activity.id, user))
minibikini's avatar
minibikini committed
540
541
542

      user = refresh_record(user)

543
      assert %User{pinned_activities: []} = user
minibikini's avatar
minibikini committed
544
545
    end

minibikini's avatar
typo    
minibikini committed
546
    test "should unpin when deleting a status", %{user: user, activity: activity} do
minibikini's avatar
minibikini committed
547
548
549
550
551
552
553
554
      {:ok, activity} = CommonAPI.pin(activity.id, user)

      user = refresh_record(user)

      assert {:ok, _} = CommonAPI.delete(activity.id, user)

      user = refresh_record(user)

555
      assert %User{pinned_activities: []} = user
minibikini's avatar
minibikini committed
556
557
    end
  end
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583

  describe "mute tests" do
    setup do
      user = insert(:user)

      activity = insert(:note_activity)

      [user: user, activity: activity]
    end

    test "add mute", %{user: user, activity: activity} do
      {:ok, _} = CommonAPI.add_mute(user, activity)
      assert CommonAPI.thread_muted?(user, activity)
    end

    test "remove mute", %{user: user, activity: activity} do
      CommonAPI.add_mute(user, activity)
      {:ok, _} = CommonAPI.remove_mute(user, activity)
      refute CommonAPI.thread_muted?(user, activity)
    end

    test "check that mutes can't be duplicate", %{user: user, activity: activity} do
      CommonAPI.add_mute(user, activity)
      {:error, _} = CommonAPI.add_mute(user, activity)
    end
  end
minibikini's avatar
Reports    
minibikini committed
584
585
586
587
588
589

  describe "reports" do
    test "creates a report" do
      reporter = insert(:user)
      target_user = insert(:user)

590
      {:ok, activity} = CommonAPI.post(target_user, %{status: "foobar"})
minibikini's avatar
Reports    
minibikini committed
591
592
593
594
595
596
597

      reporter_ap_id = reporter.ap_id
      target_ap_id = target_user.ap_id
      activity_ap_id = activity.data["id"]
      comment = "foobar"

      report_data = %{
598
599
600
        account_id: target_user.id,
        comment: comment,
        status_ids: [activity.id]
minibikini's avatar
Reports    
minibikini committed
601
602
      }

603
604
605
606
607
608
609
610
      note_obj = %{
        "type" => "Note",
        "id" => activity_ap_id,
        "content" => "foobar",
        "published" => activity.object.data["published"],
        "actor" => AccountView.render("show.json", %{user: target_user})
      }

minibikini's avatar
Reports    
minibikini committed
611
612
613
614
615
616
617
      assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)

      assert %Activity{
               actor: ^reporter_ap_id,
               data: %{
                 "type" => "Flag",
                 "content" => ^comment,
618
                 "object" => [^target_ap_id, ^note_obj],
Sergey Suprunenko's avatar
Sergey Suprunenko committed
619
                 "state" => "open"
minibikini's avatar
Reports    
minibikini committed
620
621
622
               }
             } = flag_activity
    end
Sergey Suprunenko's avatar
Sergey Suprunenko committed
623
624
625
626
627
628
629

    test "updates report state" do
      [reporter, target_user] = insert_pair(:user)
      activity = insert(:note_activity, user: target_user)

      {:ok, %Activity{id: report_id}} =
        CommonAPI.report(reporter, %{
630
631
632
          account_id: target_user.id,
          comment: "I feel offended",
          status_ids: [activity.id]
Sergey Suprunenko's avatar
Sergey Suprunenko committed
633
634
635
636
637
        })

      {:ok, report} = CommonAPI.update_report_state(report_id, "resolved")

      assert report.data["state"] == "resolved"
638
639
640
641
642

      [reported_user, activity_id] = report.data["object"]

      assert reported_user == target_user.ap_id
      assert activity_id == activity.data["id"]
Sergey Suprunenko's avatar
Sergey Suprunenko committed
643
644
645
646
647
648
649
650
    end

    test "does not update report state when state is unsupported" do
      [reporter, target_user] = insert_pair(:user)
      activity = insert(:note_activity, user: target_user)

      {:ok, %Activity{id: report_id}} =
        CommonAPI.report(reporter, %{
651
652
653
          account_id: target_user.id,
          comment: "I feel offended",
          status_ids: [activity.id]
Sergey Suprunenko's avatar
Sergey Suprunenko committed
654
655
656
657
        })

      assert CommonAPI.update_report_state(report_id, "test") == {:error, "Unsupported state"}
    end
658
659
660
661
662
663
664

    test "updates state of multiple reports" do
      [reporter, target_user] = insert_pair(:user)
      activity = insert(:note_activity, user: target_user)

      {:ok, %Activity{id: first_report_id}} =
        CommonAPI.report(reporter, %{
665
666
667
          account_id: target_user.id,
          comment: "I feel offended",
          status_ids: [activity.id]
668
669
670
671
        })

      {:ok, %Activity{id: second_report_id}} =
        CommonAPI.report(reporter, %{
672
673
674
          account_id: target_user.id,
          comment: "I feel very offended!",
          status_ids: [activity.id]
675
676
677
678
679
680
681
682
683
684
685
686
        })

      {:ok, report_ids} =
        CommonAPI.update_report_state([first_report_id, second_report_id], "resolved")

      first_report = Activity.get_by_id(first_report_id)
      second_report = Activity.get_by_id(second_report_id)

      assert report_ids -- [first_report_id, second_report_id] == []
      assert first_report.data["state"] == "resolved"
      assert second_report.data["state"] == "resolved"
    end
minibikini's avatar
Reports    
minibikini committed
687
  end
688
689
690
691
692
693
694
695
696
697
698

  describe "reblog muting" do
    setup do
      muter = insert(:user)

      muted = insert(:user)

      [muter: muter, muted: muted]
    end

    test "add a reblog mute", %{muter: muter, muted: muted} do
699
      {:ok, _reblog_mute} = CommonAPI.hide_reblogs(muter, muted)
700

Alexander Strizhakov's avatar
Alexander Strizhakov committed
701
      assert User.showing_reblogs?(muter, muted) == false
702
703
704
    end

    test "remove a reblog mute", %{muter: muter, muted: muted} do
705
706
      {:ok, _reblog_mute} = CommonAPI.hide_reblogs(muter, muted)
      {:ok, _reblog_mute} = CommonAPI.show_reblogs(muter, muted)
707

Alexander Strizhakov's avatar
Alexander Strizhakov committed
708
      assert User.showing_reblogs?(muter, muted) == true
709
710
    end
  end
711

712
713
714
715
  describe "unfollow/2" do
    test "also unsubscribes a user" do
      [follower, followed] = insert_pair(:user)
      {:ok, follower, followed, _} = CommonAPI.follow(follower, followed)
716
      {:ok, _subscription} = User.subscribe(follower, followed)
717
718
719
720
721
722
723

      assert User.subscribed_to?(follower, followed)

      {:ok, follower} = CommonAPI.unfollow(follower, followed)

      refute User.subscribed_to?(follower, followed)
    end
724

725
    test "cancels a pending follow for a local user" do
726
727
728
      follower = insert(:user)
      followed = insert(:user, locked: true)

729
730
731
      assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
               CommonAPI.follow(follower, followed)

732
      assert User.get_follow_state(follower, followed) == :follow_pending
733
      assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
minibikini's avatar
minibikini committed
734
      assert User.get_follow_state(follower, followed) == nil
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750

      assert %{id: ^activity_id, data: %{"state" => "cancelled"}} =
               Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)

      assert %{
               data: %{
                 "type" => "Undo",
                 "object" => %{"type" => "Follow", "state" => "cancelled"}
               }
             } = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower)
    end

    test "cancels a pending follow for a remote user" do
      follower = insert(:user)
      followed = insert(:user, locked: true, local: false, ap_enabled: true)

751
752
753
      assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} =
               CommonAPI.follow(follower, followed)

754
      assert User.get_follow_state(follower, followed) == :follow_pending
755
      assert {:ok, follower} = CommonAPI.unfollow(follower, followed)
minibikini's avatar
minibikini committed
756
      assert User.get_follow_state(follower, followed) == nil
757
758
759
760
761
762
763
764
765
766
767

      assert %{id: ^activity_id, data: %{"state" => "cancelled"}} =
               Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed)

      assert %{
               data: %{
                 "type" => "Undo",
                 "object" => %{"type" => "Follow", "state" => "cancelled"}
               }
             } = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower)
    end
768
769
  end

770
771
  describe "accept_follow_request/2" do
    test "after acceptance, it sets all existing pending follow request states to 'accept'" do
772
      user = insert(:user, locked: true)
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
      follower = insert(:user)
      follower_two = insert(:user)

      {:ok, follow_activity} = ActivityPub.follow(follower, user)
      {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
      {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user)

      assert follow_activity.data["state"] == "pending"
      assert follow_activity_two.data["state"] == "pending"
      assert follow_activity_three.data["state"] == "pending"

      {:ok, _follower} = CommonAPI.accept_follow_request(follower, user)

      assert Repo.get(Activity, follow_activity.id).data["state"] == "accept"
      assert Repo.get(Activity, follow_activity_two.id).data["state"] == "accept"
      assert Repo.get(Activity, follow_activity_three.id).data["state"] == "pending"
    end

    test "after rejection, it sets all existing pending follow request states to 'reject'" do
792
      user = insert(:user, locked: true)
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
      follower = insert(:user)
      follower_two = insert(:user)

      {:ok, follow_activity} = ActivityPub.follow(follower, user)
      {:ok, follow_activity_two} = ActivityPub.follow(follower, user)
      {:ok, follow_activity_three} = ActivityPub.follow(follower_two, user)

      assert follow_activity.data["state"] == "pending"
      assert follow_activity_two.data["state"] == "pending"
      assert follow_activity_three.data["state"] == "pending"

      {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)

      assert Repo.get(Activity, follow_activity.id).data["state"] == "reject"
      assert Repo.get(Activity, follow_activity_two.id).data["state"] == "reject"
      assert Repo.get(Activity, follow_activity_three.id).data["state"] == "pending"
    end
810
811
812
813
814
815
816
817

    test "doesn't create a following relationship if the corresponding follow request doesn't exist" do
      user = insert(:user, locked: true)
      not_follower = insert(:user)
      CommonAPI.accept_follow_request(not_follower, user)

      assert Pleroma.FollowingRelationship.following?(not_follower, user) == false
    end
818
  end
819
820
821
822
823
824
825
826

  describe "vote/3" do
    test "does not allow to vote twice" do
      user = insert(:user)
      other_user = insert(:user)

      {:ok, activity} =
        CommonAPI.post(user, %{
827
828
          status: "Am I cute?",
          poll: %{options: ["Yes", "No"], expires_in: 20}
829
830
831
832
833
834
835
836
837
        })

      object = Object.normalize(activity)

      {:ok, _, object} = CommonAPI.vote(other_user, object, [0])

      assert {:error, "Already voted"} == CommonAPI.vote(other_user, object, [1])
    end
  end
kaniini's avatar
kaniini committed
838
839
840
841
842
843
844

  describe "listen/2" do
    test "returns a valid activity" do
      user = insert(:user)

      {:ok, activity} =
        CommonAPI.listen(user, %{
845
846
847
848
          title: "lain radio episode 1",
          album: "lain radio",
          artist: "lain",
          length: 180_000
kaniini's avatar
kaniini committed
849
850
851
852
853
854
855
856
857
858
859
860
861
862
        })

      object = Object.normalize(activity)

      assert object.data["title"] == "lain radio episode 1"

      assert Visibility.get_visibility(activity) == "public"
    end

    test "respects visibility=private" do
      user = insert(:user)

      {:ok, activity} =
        CommonAPI.listen(user, %{
863
864
865
866
867
          title: "lain radio episode 1",
          album: "lain radio",
          artist: "lain",
          length: 180_000,
          visibility: "private"
kaniini's avatar
kaniini committed
868
869
870
871
872
873
874
875
876
        })

      object = Object.normalize(activity)

      assert object.data["title"] == "lain radio episode 1"

      assert Visibility.get_visibility(activity) == "private"
    end
  end
877
end