logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://anongit.hacktivis.me/git/pleroma.git/

side_effects_test.exs (33383B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
  5. use Oban.Testing, repo: Pleroma.Repo
  6. use Pleroma.DataCase
  7. alias Pleroma.Activity
  8. alias Pleroma.Chat
  9. alias Pleroma.Chat.MessageReference
  10. alias Pleroma.Notification
  11. alias Pleroma.Object
  12. alias Pleroma.Repo
  13. alias Pleroma.Tests.ObanHelpers
  14. alias Pleroma.User
  15. alias Pleroma.Web.ActivityPub.ActivityPub
  16. alias Pleroma.Web.ActivityPub.Builder
  17. alias Pleroma.Web.ActivityPub.SideEffects
  18. alias Pleroma.Web.ActivityPub.Utils
  19. alias Pleroma.Web.CommonAPI
  20. alias Pleroma.Web.CommonAPI.ActivityDraft
  21. import Mock
  22. import Pleroma.Factory
  23. defp get_announces_of_object(%{data: %{"id" => id}} = _object) do
  24. Pleroma.Activity.Queries.by_type("Announce")
  25. |> Pleroma.Activity.Queries.by_object_id(id)
  26. |> Pleroma.Repo.all()
  27. end
  28. describe "handle_after_transaction" do
  29. test "it streams out notifications and streams" do
  30. author = insert(:user, local: true)
  31. recipient = insert(:user, local: true)
  32. {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
  33. {:ok, create_activity_data, _meta} =
  34. Builder.create(author, chat_message_data["id"], [recipient.ap_id])
  35. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  36. {:ok, _create_activity, meta} =
  37. SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
  38. assert [notification] = meta[:notifications]
  39. with_mocks([
  40. {
  41. Pleroma.Web.Streamer,
  42. [],
  43. [
  44. stream: fn _, _ -> nil end
  45. ]
  46. }
  47. ]) do
  48. SideEffects.handle_after_transaction(meta)
  49. assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
  50. assert called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
  51. assert_enqueued(
  52. worker: "Pleroma.Workers.WebPusherWorker",
  53. args: %{"notification_id" => notification.id, "op" => "web_push"}
  54. )
  55. end
  56. end
  57. end
  58. describe "blocking users" do
  59. setup do
  60. user = insert(:user)
  61. blocked = insert(:user)
  62. User.follow(blocked, user)
  63. User.follow(user, blocked)
  64. {:ok, block_data, []} = Builder.block(user, blocked)
  65. {:ok, block, _meta} = ActivityPub.persist(block_data, local: true)
  66. %{user: user, blocked: blocked, block: block}
  67. end
  68. test "it unfollows and blocks", %{user: user, blocked: blocked, block: block} do
  69. assert User.following?(user, blocked)
  70. assert User.following?(blocked, user)
  71. {:ok, _, _} = SideEffects.handle(block)
  72. refute User.following?(user, blocked)
  73. refute User.following?(blocked, user)
  74. assert User.blocks?(user, blocked)
  75. end
  76. test "it updates following relationship", %{user: user, blocked: blocked, block: block} do
  77. {:ok, _, _} = SideEffects.handle(block)
  78. refute Pleroma.FollowingRelationship.get(user, blocked)
  79. assert User.get_follow_state(user, blocked) == nil
  80. assert User.get_follow_state(blocked, user) == nil
  81. assert User.get_follow_state(user, blocked, nil) == nil
  82. assert User.get_follow_state(blocked, user, nil) == nil
  83. end
  84. test "it blocks but does not unfollow if the relevant setting is set", %{
  85. user: user,
  86. blocked: blocked,
  87. block: block
  88. } do
  89. clear_config([:activitypub, :unfollow_blocked], false)
  90. assert User.following?(user, blocked)
  91. assert User.following?(blocked, user)
  92. {:ok, _, _} = SideEffects.handle(block)
  93. refute User.following?(user, blocked)
  94. assert User.following?(blocked, user)
  95. assert User.blocks?(user, blocked)
  96. end
  97. end
  98. describe "update users" do
  99. setup do
  100. user = insert(:user, local: false)
  101. {:ok, update_data, []} =
  102. Builder.update(user, %{"id" => user.ap_id, "type" => "Person", "name" => "new name!"})
  103. {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
  104. %{user: user, update_data: update_data, update: update}
  105. end
  106. test "it updates the user", %{user: user, update: update} do
  107. {:ok, _, _} = SideEffects.handle(update)
  108. user = User.get_by_id(user.id)
  109. assert user.name == "new name!"
  110. end
  111. test "it uses a given changeset to update", %{user: user, update: update} do
  112. changeset = Ecto.Changeset.change(user, %{default_scope: "direct"})
  113. assert user.default_scope == "public"
  114. {:ok, _, _} = SideEffects.handle(update, user_update_changeset: changeset)
  115. user = User.get_by_id(user.id)
  116. assert user.default_scope == "direct"
  117. end
  118. end
  119. describe "update notes" do
  120. setup do
  121. make_time = fn ->
  122. Pleroma.Web.ActivityPub.Utils.make_date()
  123. end
  124. user = insert(:user)
  125. note = insert(:note, user: user, data: %{"published" => make_time.()})
  126. _note_activity = insert(:note_activity, note: note)
  127. updated_note =
  128. note.data
  129. |> Map.put("summary", "edited summary")
  130. |> Map.put("content", "edited content")
  131. |> Map.put("updated", make_time.())
  132. {:ok, update_data, []} = Builder.update(user, updated_note)
  133. {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
  134. %{
  135. user: user,
  136. note: note,
  137. object_id: note.id,
  138. update_data: update_data,
  139. update: update,
  140. updated_note: updated_note
  141. }
  142. end
  143. test "it updates the note", %{
  144. object_id: object_id,
  145. update: update,
  146. updated_note: updated_note
  147. } do
  148. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  149. updated_time = updated_note["updated"]
  150. new_note = Pleroma.Object.get_by_id(object_id)
  151. assert %{
  152. "summary" => "edited summary",
  153. "content" => "edited content",
  154. "updated" => ^updated_time
  155. } = new_note.data
  156. end
  157. test "it rejects updates with no updated attribute in object", %{
  158. object_id: object_id,
  159. update: update,
  160. updated_note: updated_note
  161. } do
  162. old_note = Pleroma.Object.get_by_id(object_id)
  163. updated_note = Map.drop(updated_note, ["updated"])
  164. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  165. new_note = Pleroma.Object.get_by_id(object_id)
  166. assert old_note.data == new_note.data
  167. end
  168. test "it rejects updates with updated attribute older than what we have in the original object",
  169. %{
  170. object_id: object_id,
  171. update: update,
  172. updated_note: updated_note
  173. } do
  174. old_note = Pleroma.Object.get_by_id(object_id)
  175. {:ok, creation_time, _} = DateTime.from_iso8601(old_note.data["published"])
  176. updated_note =
  177. Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(creation_time, -10)))
  178. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  179. new_note = Pleroma.Object.get_by_id(object_id)
  180. assert old_note.data == new_note.data
  181. end
  182. test "it rejects updates with updated attribute older than the last Update", %{
  183. object_id: object_id,
  184. update: update,
  185. updated_note: updated_note
  186. } do
  187. old_note = Pleroma.Object.get_by_id(object_id)
  188. {:ok, creation_time, _} = DateTime.from_iso8601(old_note.data["published"])
  189. updated_note =
  190. Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(creation_time, +10)))
  191. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  192. old_note = Pleroma.Object.get_by_id(object_id)
  193. {:ok, update_time, _} = DateTime.from_iso8601(old_note.data["updated"])
  194. updated_note =
  195. Map.put(updated_note, "updated", DateTime.to_iso8601(DateTime.add(update_time, -5)))
  196. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  197. new_note = Pleroma.Object.get_by_id(object_id)
  198. assert old_note.data == new_note.data
  199. end
  200. test "it updates using object_data", %{
  201. object_id: object_id,
  202. update: update,
  203. updated_note: updated_note
  204. } do
  205. updated_note = Map.put(updated_note, "summary", "mew mew")
  206. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  207. new_note = Pleroma.Object.get_by_id(object_id)
  208. assert %{"summary" => "mew mew", "content" => "edited content"} = new_note.data
  209. end
  210. test "it records the original note in formerRepresentations", %{
  211. note: note,
  212. object_id: object_id,
  213. update: update,
  214. updated_note: updated_note
  215. } do
  216. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  217. %{data: new_note} = Pleroma.Object.get_by_id(object_id)
  218. assert %{"summary" => "edited summary", "content" => "edited content"} = new_note
  219. assert [Map.drop(note.data, ["id", "formerRepresentations"])] ==
  220. new_note["formerRepresentations"]["orderedItems"]
  221. assert new_note["formerRepresentations"]["totalItems"] == 1
  222. end
  223. test "it puts the original note at the front of formerRepresentations", %{
  224. user: user,
  225. note: note,
  226. object_id: object_id,
  227. update: update,
  228. updated_note: updated_note
  229. } do
  230. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  231. %{data: first_edit} = Pleroma.Object.get_by_id(object_id)
  232. second_updated_note =
  233. note.data
  234. |> Map.put("summary", "edited summary 2")
  235. |> Map.put("content", "edited content 2")
  236. |> Map.put(
  237. "updated",
  238. first_edit["updated"]
  239. |> DateTime.from_iso8601()
  240. |> elem(1)
  241. |> DateTime.add(10)
  242. |> DateTime.to_iso8601()
  243. )
  244. {:ok, second_update_data, []} = Builder.update(user, second_updated_note)
  245. {:ok, update, _meta} = ActivityPub.persist(second_update_data, local: true)
  246. {:ok, _, _} = SideEffects.handle(update, object_data: second_updated_note)
  247. %{data: new_note} = Pleroma.Object.get_by_id(object_id)
  248. assert %{"summary" => "edited summary 2", "content" => "edited content 2"} = new_note
  249. original_version = Map.drop(note.data, ["id", "formerRepresentations"])
  250. first_edit = Map.drop(first_edit, ["id", "formerRepresentations"])
  251. assert [first_edit, original_version] ==
  252. new_note["formerRepresentations"]["orderedItems"]
  253. assert new_note["formerRepresentations"]["totalItems"] == 2
  254. end
  255. test "it does not prepend to formerRepresentations if no actual changes are made", %{
  256. note: note,
  257. object_id: object_id,
  258. update: update,
  259. updated_note: updated_note
  260. } do
  261. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  262. %{data: first_edit} = Pleroma.Object.get_by_id(object_id)
  263. updated_note =
  264. updated_note
  265. |> Map.put(
  266. "updated",
  267. first_edit["updated"]
  268. |> DateTime.from_iso8601()
  269. |> elem(1)
  270. |> DateTime.add(10)
  271. |> DateTime.to_iso8601()
  272. )
  273. {:ok, _, _} = SideEffects.handle(update, object_data: updated_note)
  274. %{data: new_note} = Pleroma.Object.get_by_id(object_id)
  275. assert %{"summary" => "edited summary", "content" => "edited content"} = new_note
  276. original_version = Map.drop(note.data, ["id", "formerRepresentations"])
  277. assert [original_version] ==
  278. new_note["formerRepresentations"]["orderedItems"]
  279. assert new_note["formerRepresentations"]["totalItems"] == 1
  280. end
  281. end
  282. describe "update questions" do
  283. setup do
  284. user = insert(:user)
  285. question =
  286. insert(:question,
  287. user: user,
  288. data: %{"published" => Pleroma.Web.ActivityPub.Utils.make_date()}
  289. )
  290. %{user: user, data: question.data, id: question.id}
  291. end
  292. test "allows updating choice count without generating edit history", %{
  293. user: user,
  294. data: data,
  295. id: id
  296. } do
  297. new_choices =
  298. data["oneOf"]
  299. |> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
  300. updated_question =
  301. data
  302. |> Map.put("oneOf", new_choices)
  303. |> Map.put("updated", Pleroma.Web.ActivityPub.Utils.make_date())
  304. {:ok, update_data, []} = Builder.update(user, updated_question)
  305. {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
  306. {:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
  307. %{data: new_question} = Pleroma.Object.get_by_id(id)
  308. assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
  309. new_question["oneOf"]
  310. refute Map.has_key?(new_question, "formerRepresentations")
  311. end
  312. test "allows updating choice count without updated field", %{
  313. user: user,
  314. data: data,
  315. id: id
  316. } do
  317. new_choices =
  318. data["oneOf"]
  319. |> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
  320. updated_question =
  321. data
  322. |> Map.put("oneOf", new_choices)
  323. {:ok, update_data, []} = Builder.update(user, updated_question)
  324. {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
  325. {:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
  326. %{data: new_question} = Pleroma.Object.get_by_id(id)
  327. assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
  328. new_question["oneOf"]
  329. refute Map.has_key?(new_question, "formerRepresentations")
  330. end
  331. test "allows updating choice count with updated field same as the creation date", %{
  332. user: user,
  333. data: data,
  334. id: id
  335. } do
  336. new_choices =
  337. data["oneOf"]
  338. |> Enum.map(fn choice -> put_in(choice, ["replies", "totalItems"], 5) end)
  339. updated_question =
  340. data
  341. |> Map.put("oneOf", new_choices)
  342. |> Map.put("updated", data["published"])
  343. {:ok, update_data, []} = Builder.update(user, updated_question)
  344. {:ok, update, _meta} = ActivityPub.persist(update_data, local: true)
  345. {:ok, _, _} = SideEffects.handle(update, object_data: updated_question)
  346. %{data: new_question} = Pleroma.Object.get_by_id(id)
  347. assert [%{"replies" => %{"totalItems" => 5}}, %{"replies" => %{"totalItems" => 5}}] =
  348. new_question["oneOf"]
  349. refute Map.has_key?(new_question, "formerRepresentations")
  350. end
  351. end
  352. describe "EmojiReact objects" do
  353. setup do
  354. poster = insert(:user)
  355. user = insert(:user)
  356. {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
  357. {:ok, emoji_react_data, []} = Builder.emoji_react(user, post.object, "👌")
  358. {:ok, emoji_react, _meta} = ActivityPub.persist(emoji_react_data, local: true)
  359. %{emoji_react: emoji_react, user: user, poster: poster}
  360. end
  361. test "adds the reaction to the object", %{emoji_react: emoji_react, user: user} do
  362. {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
  363. object = Object.get_by_ap_id(emoji_react.data["object"])
  364. assert object.data["reaction_count"] == 1
  365. assert ["👌", [user.ap_id], nil] in object.data["reactions"]
  366. end
  367. test "creates a notification", %{emoji_react: emoji_react, poster: poster} do
  368. {:ok, emoji_react, _} = SideEffects.handle(emoji_react)
  369. assert Repo.get_by(Notification, user_id: poster.id, activity_id: emoji_react.id)
  370. end
  371. end
  372. describe "Question objects" do
  373. setup do
  374. user = insert(:user)
  375. question = build(:question, user: user)
  376. question_activity = build(:question_activity, question: question)
  377. activity_data = Map.put(question_activity.data, "object", question.data["id"])
  378. meta = [object_data: question.data, local: false]
  379. {:ok, activity, meta} = ActivityPub.persist(activity_data, meta)
  380. %{activity: activity, meta: meta}
  381. end
  382. test "enqueues the poll end", %{activity: activity, meta: meta} do
  383. {:ok, activity, meta} = SideEffects.handle(activity, meta)
  384. assert_enqueued(
  385. worker: Pleroma.Workers.PollWorker,
  386. args: %{op: "poll_end", activity_id: activity.id},
  387. scheduled_at: NaiveDateTime.from_iso8601!(meta[:object_data]["closed"])
  388. )
  389. end
  390. end
  391. describe "delete users with confirmation pending" do
  392. setup do
  393. user = insert(:user, is_confirmed: false)
  394. {:ok, delete_user_data, _meta} = Builder.delete(user, user.ap_id)
  395. {:ok, delete_user, _meta} = ActivityPub.persist(delete_user_data, local: true)
  396. {:ok, delete: delete_user, user: user}
  397. end
  398. test "when activation is required", %{delete: delete, user: user} do
  399. clear_config([:instance, :account_activation_required], true)
  400. {:ok, _, _} = SideEffects.handle(delete)
  401. ObanHelpers.perform_all()
  402. refute User.get_cached_by_id(user.id)
  403. end
  404. end
  405. describe "Undo objects" do
  406. setup do
  407. poster = insert(:user)
  408. user = insert(:user)
  409. {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
  410. {:ok, like} = CommonAPI.favorite(post.id, user)
  411. {:ok, reaction} = CommonAPI.react_with_emoji(post.id, user, "👍")
  412. {:ok, announce} = CommonAPI.repeat(post.id, user)
  413. {:ok, block} = CommonAPI.block(poster, user)
  414. {:ok, undo_data, _meta} = Builder.undo(user, like)
  415. {:ok, like_undo, _meta} = ActivityPub.persist(undo_data, local: true)
  416. {:ok, undo_data, _meta} = Builder.undo(user, reaction)
  417. {:ok, reaction_undo, _meta} = ActivityPub.persist(undo_data, local: true)
  418. {:ok, undo_data, _meta} = Builder.undo(user, announce)
  419. {:ok, announce_undo, _meta} = ActivityPub.persist(undo_data, local: true)
  420. {:ok, undo_data, _meta} = Builder.undo(user, block)
  421. {:ok, block_undo, _meta} = ActivityPub.persist(undo_data, local: true)
  422. %{
  423. like_undo: like_undo,
  424. post: post,
  425. like: like,
  426. reaction_undo: reaction_undo,
  427. reaction: reaction,
  428. announce_undo: announce_undo,
  429. announce: announce,
  430. block_undo: block_undo,
  431. block: block,
  432. poster: poster,
  433. user: user
  434. }
  435. end
  436. test "deletes the original block", %{
  437. block_undo: block_undo,
  438. block: block
  439. } do
  440. {:ok, _block_undo, _meta} = SideEffects.handle(block_undo)
  441. refute Activity.get_by_id(block.id)
  442. end
  443. test "unblocks the blocked user", %{block_undo: block_undo, block: block} do
  444. blocker = User.get_by_ap_id(block.data["actor"])
  445. blocked = User.get_by_ap_id(block.data["object"])
  446. {:ok, _block_undo, _} = SideEffects.handle(block_undo)
  447. refute User.blocks?(blocker, blocked)
  448. end
  449. test "an announce undo removes the announce from the object", %{
  450. announce_undo: announce_undo,
  451. post: post
  452. } do
  453. {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
  454. object = Object.get_by_ap_id(post.data["object"])
  455. assert object.data["announcement_count"] == 0
  456. assert object.data["announcements"] == []
  457. end
  458. test "deletes the original announce", %{announce_undo: announce_undo, announce: announce} do
  459. {:ok, _announce_undo, _} = SideEffects.handle(announce_undo)
  460. refute Activity.get_by_id(announce.id)
  461. end
  462. test "a reaction undo removes the reaction from the object", %{
  463. reaction_undo: reaction_undo,
  464. post: post
  465. } do
  466. {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
  467. object = Object.get_by_ap_id(post.data["object"])
  468. assert object.data["reaction_count"] == 0
  469. assert object.data["reactions"] == []
  470. end
  471. test "deletes the original reaction", %{reaction_undo: reaction_undo, reaction: reaction} do
  472. {:ok, _reaction_undo, _} = SideEffects.handle(reaction_undo)
  473. refute Activity.get_by_id(reaction.id)
  474. end
  475. test "a like undo removes the like from the object", %{like_undo: like_undo, post: post} do
  476. {:ok, _like_undo, _} = SideEffects.handle(like_undo)
  477. object = Object.get_by_ap_id(post.data["object"])
  478. assert object.data["like_count"] == 0
  479. assert object.data["likes"] == []
  480. end
  481. test "deletes the original like", %{like_undo: like_undo, like: like} do
  482. {:ok, _like_undo, _} = SideEffects.handle(like_undo)
  483. refute Activity.get_by_id(like.id)
  484. end
  485. end
  486. describe "like objects" do
  487. setup do
  488. poster = insert(:user)
  489. user = insert(:user)
  490. {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
  491. {:ok, like_data, _meta} = Builder.like(user, post.object)
  492. {:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
  493. %{like: like, user: user, poster: poster}
  494. end
  495. test "add the like to the original object", %{like: like, user: user} do
  496. {:ok, like, _} = SideEffects.handle(like)
  497. object = Object.get_by_ap_id(like.data["object"])
  498. assert object.data["like_count"] == 1
  499. assert user.ap_id in object.data["likes"]
  500. end
  501. test "creates a notification", %{like: like, poster: poster} do
  502. {:ok, like, _} = SideEffects.handle(like)
  503. assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
  504. end
  505. end
  506. describe "creation of ChatMessages" do
  507. test "notifies the recipient" do
  508. author = insert(:user, local: false)
  509. recipient = insert(:user, local: true)
  510. {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
  511. {:ok, create_activity_data, _meta} =
  512. Builder.create(author, chat_message_data["id"], [recipient.ap_id])
  513. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  514. {:ok, _create_activity, _meta} =
  515. SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
  516. assert Repo.get_by(Notification, user_id: recipient.id, activity_id: create_activity.id)
  517. end
  518. test "it streams the created ChatMessage" do
  519. author = insert(:user, local: true)
  520. recipient = insert(:user, local: true)
  521. {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
  522. {:ok, create_activity_data, _meta} =
  523. Builder.create(author, chat_message_data["id"], [recipient.ap_id])
  524. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  525. {:ok, _create_activity, meta} =
  526. SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
  527. assert [_, _] = meta[:streamables]
  528. end
  529. test "it creates a Chat and MessageReferences for the local users and bumps the unread count, except for the author" do
  530. author = insert(:user, local: true)
  531. recipient = insert(:user, local: true)
  532. {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
  533. {:ok, create_activity_data, _meta} =
  534. Builder.create(author, chat_message_data["id"], [recipient.ap_id])
  535. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  536. with_mocks([
  537. {
  538. Pleroma.Web.Streamer,
  539. [],
  540. [
  541. stream: fn _, _ -> nil end
  542. ]
  543. },
  544. {
  545. Pleroma.Web.Push,
  546. [],
  547. [
  548. send: fn _ -> nil end
  549. ]
  550. }
  551. ]) do
  552. {:ok, _create_activity, meta} =
  553. SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
  554. # The notification gets created
  555. assert [notification] = meta[:notifications]
  556. assert notification.activity_id == create_activity.id
  557. # But it is not sent out
  558. refute called(Pleroma.Web.Streamer.stream(["user", "user:notification"], notification))
  559. refute called(Pleroma.Web.Push.send(notification))
  560. # Same for the user chat stream
  561. assert [{topics, _}, _] = meta[:streamables]
  562. assert topics == ["user", "user:pleroma_chat"]
  563. refute called(Pleroma.Web.Streamer.stream(["user", "user:pleroma_chat"], :_))
  564. chat = Chat.get(author.id, recipient.ap_id)
  565. [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
  566. assert cm_ref.object.data["content"] == "hey"
  567. assert cm_ref.unread == false
  568. chat = Chat.get(recipient.id, author.ap_id)
  569. [cm_ref] = MessageReference.for_chat_query(chat) |> Repo.all()
  570. assert cm_ref.object.data["content"] == "hey"
  571. assert cm_ref.unread == true
  572. end
  573. end
  574. test "it creates a Chat for the local users and bumps the unread count" do
  575. author = insert(:user, local: false)
  576. recipient = insert(:user, local: true)
  577. {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
  578. {:ok, create_activity_data, _meta} =
  579. Builder.create(author, chat_message_data["id"], [recipient.ap_id])
  580. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  581. {:ok, _create_activity, _meta} =
  582. SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
  583. # An object is created
  584. assert Object.get_by_ap_id(chat_message_data["id"])
  585. # The remote user won't get a chat
  586. chat = Chat.get(author.id, recipient.ap_id)
  587. refute chat
  588. # The local user will get a chat
  589. chat = Chat.get(recipient.id, author.ap_id)
  590. assert chat
  591. author = insert(:user, local: true)
  592. recipient = insert(:user, local: true)
  593. {:ok, chat_message_data, _meta} = Builder.chat_message(author, recipient.ap_id, "hey")
  594. {:ok, create_activity_data, _meta} =
  595. Builder.create(author, chat_message_data["id"], [recipient.ap_id])
  596. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  597. {:ok, _create_activity, _meta} =
  598. SideEffects.handle(create_activity, local: false, object_data: chat_message_data)
  599. # Both users are local and get the chat
  600. chat = Chat.get(author.id, recipient.ap_id)
  601. assert chat
  602. chat = Chat.get(recipient.id, author.ap_id)
  603. assert chat
  604. end
  605. end
  606. describe "announce objects" do
  607. setup do
  608. poster = insert(:user)
  609. user = insert(:user)
  610. {:ok, post} = CommonAPI.post(poster, %{status: "hey"})
  611. {:ok, private_post} = CommonAPI.post(poster, %{status: "hey", visibility: "private"})
  612. {:ok, announce_data, _meta} = Builder.announce(user, post.object, public: true)
  613. {:ok, private_announce_data, _meta} =
  614. Builder.announce(user, private_post.object, public: false)
  615. {:ok, relay_announce_data, _meta} =
  616. Builder.announce(Pleroma.Web.ActivityPub.Relay.get_actor(), post.object, public: true)
  617. {:ok, announce, _meta} = ActivityPub.persist(announce_data, local: true)
  618. {:ok, private_announce, _meta} = ActivityPub.persist(private_announce_data, local: true)
  619. {:ok, relay_announce, _meta} = ActivityPub.persist(relay_announce_data, local: true)
  620. %{
  621. announce: announce,
  622. user: user,
  623. poster: poster,
  624. private_announce: private_announce,
  625. relay_announce: relay_announce
  626. }
  627. end
  628. test "adds the announce to the original object", %{announce: announce, user: user} do
  629. {:ok, announce, _} = SideEffects.handle(announce)
  630. object = Object.get_by_ap_id(announce.data["object"])
  631. assert object.data["announcement_count"] == 1
  632. assert user.ap_id in object.data["announcements"]
  633. end
  634. test "does not add the announce to the original object if the actor is a service actor", %{
  635. relay_announce: announce
  636. } do
  637. {:ok, announce, _} = SideEffects.handle(announce)
  638. object = Object.get_by_ap_id(announce.data["object"])
  639. assert object.data["announcement_count"] == nil
  640. end
  641. test "creates a notification", %{announce: announce, poster: poster} do
  642. {:ok, announce, _} = SideEffects.handle(announce)
  643. assert Repo.get_by(Notification, user_id: poster.id, activity_id: announce.id)
  644. end
  645. end
  646. describe "removing a follower" do
  647. setup do
  648. user = insert(:user)
  649. followed = insert(:user)
  650. {:ok, _, _, follow_activity} = CommonAPI.follow(followed, user)
  651. {:ok, reject_data, []} = Builder.reject(followed, follow_activity)
  652. {:ok, reject, _meta} = ActivityPub.persist(reject_data, local: true)
  653. %{user: user, followed: followed, reject: reject}
  654. end
  655. test "", %{user: user, followed: followed, reject: reject} do
  656. assert User.following?(user, followed)
  657. assert Pleroma.FollowingRelationship.get(user, followed)
  658. {:ok, _, _} = SideEffects.handle(reject)
  659. refute User.following?(user, followed)
  660. refute Pleroma.FollowingRelationship.get(user, followed)
  661. assert User.get_follow_state(user, followed) == nil
  662. assert User.get_follow_state(user, followed, nil) == nil
  663. end
  664. end
  665. describe "removing a follower from remote" do
  666. setup do
  667. user = insert(:user)
  668. followed = insert(:user, local: false)
  669. # Mock a local-to-remote follow
  670. {:ok, follow_data, []} = Builder.follow(user, followed)
  671. follow_data =
  672. follow_data
  673. |> Map.put("state", "accept")
  674. {:ok, follow, _meta} = ActivityPub.persist(follow_data, local: true)
  675. {:ok, _, _} = SideEffects.handle(follow)
  676. # Mock a remote-to-local accept
  677. {:ok, accept_data, _} = Builder.accept(followed, follow)
  678. {:ok, accept, _} = ActivityPub.persist(accept_data, local: false)
  679. {:ok, _, _} = SideEffects.handle(accept)
  680. # Mock a remote-to-local reject
  681. {:ok, reject_data, []} = Builder.reject(followed, follow)
  682. {:ok, reject, _meta} = ActivityPub.persist(reject_data, local: false)
  683. %{user: user, followed: followed, reject: reject}
  684. end
  685. test "", %{user: user, followed: followed, reject: reject} do
  686. assert User.following?(user, followed)
  687. assert Pleroma.FollowingRelationship.get(user, followed)
  688. {:ok, _, _} = SideEffects.handle(reject)
  689. refute User.following?(user, followed)
  690. refute Pleroma.FollowingRelationship.get(user, followed)
  691. assert Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(user, followed).data["state"] ==
  692. "reject"
  693. assert User.get_follow_state(user, followed) == nil
  694. assert User.get_follow_state(user, followed, nil) == nil
  695. end
  696. end
  697. describe "Group actors" do
  698. setup do
  699. poster =
  700. insert(:user,
  701. local: false,
  702. nickname: "poster@example.com",
  703. ap_id: "https://example.com/users/poster"
  704. )
  705. group = insert(:user, actor_type: "Group")
  706. make_create = fn mentioned_users ->
  707. mentions = mentioned_users |> Enum.map(fn u -> "@#{u.nickname}" end) |> Enum.join(" ")
  708. {:ok, draft} = ActivityDraft.create(poster, %{status: "#{mentions} hey"})
  709. create_activity_data =
  710. Utils.make_create_data(draft.changes |> Map.put(:published, nil), %{})
  711. |> put_in(["object", "id"], "https://example.com/object")
  712. |> put_in(["id"], "https://example.com/activity")
  713. assert Enum.all?(mentioned_users, fn u -> u.ap_id in create_activity_data["to"] end)
  714. create_activity_data
  715. end
  716. %{poster: poster, group: group, make_create: make_create}
  717. end
  718. test "group should boost it", %{make_create: make_create, group: group} do
  719. create_activity_data = make_create.([group])
  720. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  721. {:ok, _create_activity, _meta} =
  722. SideEffects.handle(create_activity,
  723. local: false,
  724. object_data: create_activity_data["object"]
  725. )
  726. object = Object.normalize(create_activity, fetch: false)
  727. assert [announce] = get_announces_of_object(object)
  728. assert announce.actor == group.ap_id
  729. end
  730. test "remote group should not boost it", %{make_create: make_create, group: group} do
  731. remote_group =
  732. insert(:user, actor_type: "Group", local: false, nickname: "remotegroup@example.com")
  733. create_activity_data = make_create.([group, remote_group])
  734. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  735. {:ok, _create_activity, _meta} =
  736. SideEffects.handle(create_activity,
  737. local: false,
  738. object_data: create_activity_data["object"]
  739. )
  740. object = Object.normalize(create_activity, fetch: false)
  741. assert [announce] = get_announces_of_object(object)
  742. assert announce.actor == group.ap_id
  743. end
  744. test "group should not boost it if group is blocking poster", %{
  745. make_create: make_create,
  746. group: group,
  747. poster: poster
  748. } do
  749. {:ok, _} = CommonAPI.block(poster, group)
  750. create_activity_data = make_create.([group])
  751. {:ok, create_activity, _meta} = ActivityPub.persist(create_activity_data, local: false)
  752. {:ok, _create_activity, _meta} =
  753. SideEffects.handle(create_activity,
  754. local: false,
  755. object_data: create_activity_data["object"]
  756. )
  757. object = Object.normalize(create_activity, fetch: false)
  758. assert [] = get_announces_of_object(object)
  759. end
  760. end
  761. end