chat_controller_test.exs 13.3 KB
Newer Older
1
2
3
4
# Pleroma: A lightweight social networking server
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
5
  use Pleroma.Web.ConnCase
6
7

  alias Pleroma.Chat
8
  alias Pleroma.Chat.MessageReference
lain's avatar
lain committed
9
  alias Pleroma.Object
10
  alias Pleroma.User
lain's avatar
lain committed
11
  alias Pleroma.Web.ActivityPub.ActivityPub
lain's avatar
lain committed
12
  alias Pleroma.Web.CommonAPI
13
14
15

  import Pleroma.Factory

16
  describe "POST /api/v1/pleroma/chats/:id/messages/:message_id/read" do
17
    setup do: oauth_access(["write:chats"])
18
19
20
21
22
23
24
25

    test "it marks one message as read", %{conn: conn, user: user} do
      other_user = insert(:user)

      {:ok, create} = CommonAPI.post_chat_message(other_user, user, "sup")
      {:ok, _create} = CommonAPI.post_chat_message(other_user, user, "sup part 2")
      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
      object = Object.normalize(create, false)
26
      cm_ref = MessageReference.for_chat_and_object(chat, object)
27

28
      assert cm_ref.unread == true
29
30
31
32
33
34
35
36

      result =
        conn
        |> post("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}/read")
        |> json_response_and_validate_schema(200)

      assert result["unread"] == false

37
      cm_ref = MessageReference.for_chat_and_object(chat, object)
38

39
      assert cm_ref.unread == false
40
41
42
    end
  end

lain's avatar
lain committed
43
  describe "POST /api/v1/pleroma/chats/:id/read" do
44
    setup do: oauth_access(["write:chats"])
lain's avatar
lain committed
45

46
47
48
49
    test "given a `last_read_id`, it marks everything until then as read", %{
      conn: conn,
      user: user
    } do
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
      other_user = insert(:user)

      {:ok, create} = CommonAPI.post_chat_message(other_user, user, "sup")
      {:ok, _create} = CommonAPI.post_chat_message(other_user, user, "sup part 2")
      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
      object = Object.normalize(create, false)
      cm_ref = MessageReference.for_chat_and_object(chat, object)

      assert cm_ref.unread == true

      result =
        conn
        |> put_req_header("content-type", "application/json")
        |> post("/api/v1/pleroma/chats/#{chat.id}/read", %{"last_read_id" => cm_ref.id})
        |> json_response_and_validate_schema(200)

      assert result["unread"] == 1

      cm_ref = MessageReference.for_chat_and_object(chat, object)

      assert cm_ref.unread == false
    end
lain's avatar
lain committed
72
73
  end

lain's avatar
lain committed
74
  describe "POST /api/v1/pleroma/chats/:id/messages" do
75
    setup do: oauth_access(["write:chats"])
lain's avatar
lain committed
76
77

    test "it posts a message to the chat", %{conn: conn, user: user} do
lain's avatar
lain committed
78
79
80
81
82
83
      other_user = insert(:user)

      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)

      result =
        conn
lain's avatar
lain committed
84
        |> put_req_header("content-type", "application/json")
85
        |> put_req_header("idempotency-key", "123")
lain's avatar
lain committed
86
        |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "Hallo!!"})
87
        |> json_response_and_validate_schema(200)
lain's avatar
lain committed
88
89

      assert result["content"] == "Hallo!!"
lain's avatar
lain committed
90
      assert result["chat_id"] == chat.id |> to_string()
91
      assert result["idempotency_key"] == "123"
lain's avatar
lain committed
92
    end
lain's avatar
lain committed
93

94
95
96
97
98
99
100
101
102
103
104
    test "it fails if there is no content", %{conn: conn, user: user} do
      other_user = insert(:user)

      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)

      result =
        conn
        |> put_req_header("content-type", "application/json")
        |> post("/api/v1/pleroma/chats/#{chat.id}/messages")
        |> json_response_and_validate_schema(400)

Haelwenn's avatar
Haelwenn committed
105
      assert %{"error" => "no_content"} == result
106
107
    end

lain's avatar
lain committed
108
109
    test "it works with an attachment", %{conn: conn, user: user} do
      file = %Plug.Upload{
feld's avatar
feld committed
110
        content_type: "image/jpeg",
lain's avatar
lain committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
        path: Path.absname("test/fixtures/image.jpg"),
        filename: "an_image.jpg"
      }

      {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id)

      other_user = insert(:user)

      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)

      result =
        conn
        |> put_req_header("content-type", "application/json")
        |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{
          "media_id" => to_string(upload.id)
        })
        |> json_response_and_validate_schema(200)

129
      assert result["attachment"]
lain's avatar
lain committed
130
    end
131
132
133
134
135
136
137
138
139
140
141
142
143

    test "gets MRF reason when rejected", %{conn: conn, user: user} do
      clear_config([:mrf_keyword, :reject], ["GNO"])
      clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])

      other_user = insert(:user)

      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)

      result =
        conn
        |> put_req_header("content-type", "application/json")
        |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "GNO/Linux"})
Haelwenn's avatar
Haelwenn committed
144
        |> json_response_and_validate_schema(422)
145

Haelwenn's avatar
Haelwenn committed
146
      assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} == result
147
    end
lain's avatar
lain committed
148
149
  end

150
  describe "DELETE /api/v1/pleroma/chats/:id/messages/:message_id" do
151
    setup do: oauth_access(["write:chats"])
152

153
    test "it deletes a message from the chat", %{conn: conn, user: user} do
154
155
156
157
158
      recipient = insert(:user)

      {:ok, message} =
        CommonAPI.post_chat_message(user, recipient, "Hello darkness my old friend")

159
160
      {:ok, other_message} = CommonAPI.post_chat_message(recipient, user, "nico nico ni")

161
162
163
164
      object = Object.normalize(message, false)

      chat = Chat.get(user.id, recipient.ap_id)

165
      cm_ref = MessageReference.for_chat_and_object(chat, object)
166
167

      # Deleting your own message removes the message and the reference
168
169
170
      result =
        conn
        |> put_req_header("content-type", "application/json")
171
        |> delete("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}")
172
173
        |> json_response_and_validate_schema(200)

174
      assert result["id"] == cm_ref.id
175
      refute MessageReference.get_by_id(cm_ref.id)
176
      assert %{data: %{"type" => "Tombstone"}} = Object.get_by_id(object.id)
177

178
      # Deleting other people's messages just removes the reference
179
      object = Object.normalize(other_message, false)
180
      cm_ref = MessageReference.for_chat_and_object(chat, object)
181
182
183
184

      result =
        conn
        |> put_req_header("content-type", "application/json")
185
186
        |> delete("/api/v1/pleroma/chats/#{chat.id}/messages/#{cm_ref.id}")
        |> json_response_and_validate_schema(200)
187

188
      assert result["id"] == cm_ref.id
189
      refute MessageReference.get_by_id(cm_ref.id)
190
      assert Object.get_by_id(object.id)
191
192
193
    end
  end

194
  describe "GET /api/v1/pleroma/chats/:id/messages" do
195
    setup do: oauth_access(["read:chats"])
lain's avatar
lain committed
196
197

    test "it paginates", %{conn: conn, user: user} do
lain's avatar
lain committed
198
199
200
201
202
203
204
205
      recipient = insert(:user)

      Enum.each(1..30, fn _ ->
        {:ok, _} = CommonAPI.post_chat_message(user, recipient, "hey")
      end)

      chat = Chat.get(user.id, recipient.ap_id)

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
      response = get(conn, "/api/v1/pleroma/chats/#{chat.id}/messages")
      result = json_response_and_validate_schema(response, 200)

      [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ")
      api_endpoint = "/api/v1/pleroma/chats/"

      assert String.match?(
               next,
               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&max_id=.*; rel=\"next\"$)
             )

      assert String.match?(
               prev,
               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&min_id=.*; rel=\"prev\"$)
             )
lain's avatar
lain committed
221
222
223

      assert length(result) == 20

224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
      response =
        get(conn, "/api/v1/pleroma/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}")

      result = json_response_and_validate_schema(response, 200)
      [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ")

      assert String.match?(
               next,
               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&max_id=.*; rel=\"next\"$)
             )

      assert String.match?(
               prev,
               ~r(#{api_endpoint}.*/messages\?id=.*&limit=\d+&max_id=.*&min_id=.*; rel=\"prev\"$)
             )
lain's avatar
lain committed
239
240
241
242

      assert length(result) == 10
    end

lain's avatar
lain committed
243
    test "it returns the messages for a given chat", %{conn: conn, user: user} do
244
245
246
247
248
249
250
251
252
253
254
255
256
      other_user = insert(:user)
      third_user = insert(:user)

      {:ok, _} = CommonAPI.post_chat_message(user, other_user, "hey")
      {:ok, _} = CommonAPI.post_chat_message(user, third_user, "hey")
      {:ok, _} = CommonAPI.post_chat_message(user, other_user, "how are you?")
      {:ok, _} = CommonAPI.post_chat_message(other_user, user, "fine, how about you?")

      chat = Chat.get(user.id, other_user.ap_id)

      result =
        conn
        |> get("/api/v1/pleroma/chats/#{chat.id}/messages")
257
        |> json_response_and_validate_schema(200)
258

259
260
      result
      |> Enum.each(fn message ->
lain's avatar
lain committed
261
        assert message["chat_id"] == chat.id |> to_string()
262
263
      end)

264
      assert length(result) == 3
lain's avatar
lain committed
265
266

      # Trying to get the chat of a different user
267
268
269
270
      conn
      |> assign(:user, other_user)
      |> get("/api/v1/pleroma/chats/#{chat.id}/messages")
      |> json_response_and_validate_schema(404)
271
272
273
    end
  end

274
  describe "POST /api/v1/pleroma/chats/by-account-id/:id" do
275
    setup do: oauth_access(["write:chats"])
lain's avatar
lain committed
276

277
278
279
280
281
    test "it creates or returns a chat", %{conn: conn} do
      other_user = insert(:user)

      result =
        conn
282
        |> post("/api/v1/pleroma/chats/by-account-id/#{other_user.id}")
283
        |> json_response_and_validate_schema(200)
284
285
286
287
288

      assert result["id"]
    end
  end

lain's avatar
lain committed
289
  describe "GET /api/v1/pleroma/chats/:id" do
290
    setup do: oauth_access(["read:chats"])
lain's avatar
lain committed
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305

    test "it returns a chat", %{conn: conn, user: user} do
      other_user = insert(:user)

      {:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)

      result =
        conn
        |> get("/api/v1/pleroma/chats/#{chat.id}")
        |> json_response_and_validate_schema(200)

      assert result["id"] == to_string(chat.id)
    end
  end

306
  describe "GET /api/v1/pleroma/chats" do
307
    setup do: oauth_access(["read:chats"])
lain's avatar
lain committed
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
    test "it does not return chats with deleted users", %{conn: conn, user: user} do
      recipient = insert(:user)
      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)

      Pleroma.Repo.delete(recipient)
      User.invalidate_cache(recipient)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
        |> json_response_and_validate_schema(200)

      assert length(result) == 0
    end

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
    test "it does not return chats with users you blocked", %{conn: conn, user: user} do
      recipient = insert(:user)

      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
        |> json_response_and_validate_schema(200)

      assert length(result) == 1

      User.block(user, recipient)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
        |> json_response_and_validate_schema(200)

      assert length(result) == 0
    end
minibikini's avatar
minibikini committed
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

    test "it does not return chats with users you muted", %{conn: conn, user: user} do
      recipient = insert(:user)

      {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
        |> json_response_and_validate_schema(200)

      assert length(result) == 1

      User.mute(user, recipient)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
        |> json_response_and_validate_schema(200)

      assert length(result) == 0
366
367
368
369
370
371
372

      result =
        conn
        |> get("/api/v1/pleroma/chats?with_muted=true")
        |> json_response_and_validate_schema(200)

      assert length(result) == 1
minibikini's avatar
minibikini committed
373
    end
374

375
    test "it returns all chats", %{conn: conn, user: user} do
lain's avatar
lain committed
376
377
378
379
380
381
382
383
      Enum.each(1..30, fn _ ->
        recipient = insert(:user)
        {:ok, _} = Chat.get_or_create(user.id, recipient.ap_id)
      end)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
384
        |> json_response_and_validate_schema(200)
lain's avatar
lain committed
385

386
      assert length(result) == 30
lain's avatar
lain committed
387
388
    end

389
    test "it return a list of chats the current user is participating in, in descending order of updates",
lain's avatar
lain committed
390
         %{conn: conn, user: user} do
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
      har = insert(:user)
      jafnhar = insert(:user)
      tridi = insert(:user)

      {:ok, chat_1} = Chat.get_or_create(user.id, har.ap_id)
      :timer.sleep(1000)
      {:ok, _chat_2} = Chat.get_or_create(user.id, jafnhar.ap_id)
      :timer.sleep(1000)
      {:ok, chat_3} = Chat.get_or_create(user.id, tridi.ap_id)
      :timer.sleep(1000)

      # bump the second one
      {:ok, chat_2} = Chat.bump_or_create(user.id, jafnhar.ap_id)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
408
        |> json_response_and_validate_schema(200)
409
410
411

      ids = Enum.map(result, & &1["id"])

lain's avatar
lain committed
412
413
414
415
416
      assert ids == [
               chat_2.id |> to_string(),
               chat_3.id |> to_string(),
               chat_1.id |> to_string()
             ]
417
    end
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

    test "it is not affected by :restrict_unauthenticated setting (issue #1973)", %{
      conn: conn,
      user: user
    } do
      clear_config([:restrict_unauthenticated, :profiles, :local], true)
      clear_config([:restrict_unauthenticated, :profiles, :remote], true)

      user2 = insert(:user)
      user3 = insert(:user, local: false)

      {:ok, _chat_12} = Chat.get_or_create(user.id, user2.ap_id)
      {:ok, _chat_13} = Chat.get_or_create(user.id, user3.ap_id)

      result =
        conn
        |> get("/api/v1/pleroma/chats")
        |> json_response_and_validate_schema(200)

      account_ids = Enum.map(result, &get_in(&1, ["account", "id"]))
      assert Enum.sort(account_ids) == Enum.sort([user2.id, user3.id])
    end
440
441
  end
end