logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

common_api_utils_test.exs (18244B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.CommonAPI.UtilsTest do
  5. alias Pleroma.Builders.UserBuilder
  6. alias Pleroma.Object
  7. alias Pleroma.Web.CommonAPI
  8. alias Pleroma.Web.CommonAPI.Utils
  9. use Pleroma.DataCase
  10. import ExUnit.CaptureLog
  11. import Pleroma.Factory
  12. @public_address "https://www.w3.org/ns/activitystreams#Public"
  13. describe "add_attachments/2" do
  14. setup do
  15. name =
  16. "Sakura Mana – Turned on by a Senior OL with a Temptating Tight Skirt-s Full Hipline and Panty Shot- Beautiful Thick Thighs- and Erotic Ass- -2015- -- Oppaitime 8-28-2017 6-50-33 PM.png"
  17. attachment = %{
  18. "url" => [%{"href" => URI.encode(name)}]
  19. }
  20. %{name: name, attachment: attachment}
  21. end
  22. test "it adds attachment links to a given text and attachment set", %{
  23. name: name,
  24. attachment: attachment
  25. } do
  26. len = 10
  27. clear_config([Pleroma.Upload, :filename_display_max_length], len)
  28. expected =
  29. "<br><a href=\"#{URI.encode(name)}\" class='attachment'>#{String.slice(name, 0..len)}…</a>"
  30. assert Utils.add_attachments("", [attachment]) == expected
  31. end
  32. test "doesn't truncate file name if config for truncate is set to 0", %{
  33. name: name,
  34. attachment: attachment
  35. } do
  36. clear_config([Pleroma.Upload, :filename_display_max_length], 0)
  37. expected = "<br><a href=\"#{URI.encode(name)}\" class='attachment'>#{name}</a>"
  38. assert Utils.add_attachments("", [attachment]) == expected
  39. end
  40. end
  41. describe "it confirms the password given is the current users password" do
  42. test "incorrect password given" do
  43. {:ok, user} = UserBuilder.insert()
  44. assert Utils.confirm_current_password(user, "") == {:error, "Invalid password."}
  45. end
  46. test "correct password given" do
  47. {:ok, user} = UserBuilder.insert()
  48. assert Utils.confirm_current_password(user, "test") == {:ok, user}
  49. end
  50. end
  51. describe "format_input/3" do
  52. test "works for bare text/plain" do
  53. text = "hello world!"
  54. expected = "hello world!"
  55. {output, [], []} = Utils.format_input(text, "text/plain")
  56. assert output == expected
  57. text = "hello world!\n\nsecond paragraph!"
  58. expected = "hello world!<br><br>second paragraph!"
  59. {output, [], []} = Utils.format_input(text, "text/plain")
  60. assert output == expected
  61. end
  62. test "works for bare text/html" do
  63. text = "<p>hello world!</p>"
  64. expected = "<p>hello world!</p>"
  65. {output, [], []} = Utils.format_input(text, "text/html")
  66. assert output == expected
  67. text = "<p>hello world!</p><br/>\n<p>second paragraph</p>"
  68. expected = "<p>hello world!</p><br/>\n<p>second paragraph</p>"
  69. {output, [], []} = Utils.format_input(text, "text/html")
  70. assert output == expected
  71. end
  72. test "works for bare text/markdown" do
  73. text = "**hello world**"
  74. expected = "<p><strong>hello world</strong></p>"
  75. {output, [], []} = Utils.format_input(text, "text/markdown")
  76. assert output == expected
  77. text = "**hello world**\n\n*another paragraph*"
  78. expected = "<p><strong>hello world</strong></p><p><em>another paragraph</em></p>"
  79. {output, [], []} = Utils.format_input(text, "text/markdown")
  80. assert output == expected
  81. text = """
  82. > cool quote
  83. by someone
  84. """
  85. expected = "<blockquote><p>cool quote</p></blockquote><p>by someone</p>"
  86. {output, [], []} = Utils.format_input(text, "text/markdown")
  87. assert output == expected
  88. end
  89. test "works for bare text/bbcode" do
  90. text = "[b]hello world[/b]"
  91. expected = "<strong>hello world</strong>"
  92. {output, [], []} = Utils.format_input(text, "text/bbcode")
  93. assert output == expected
  94. text = "[b]hello world![/b]\n\nsecond paragraph!"
  95. expected = "<strong>hello world!</strong><br><br>second paragraph!"
  96. {output, [], []} = Utils.format_input(text, "text/bbcode")
  97. assert output == expected
  98. text = "[b]hello world![/b]\n\n<strong>second paragraph!</strong>"
  99. expected =
  100. "<strong>hello world!</strong><br><br>&lt;strong&gt;second paragraph!&lt;/strong&gt;"
  101. {output, [], []} = Utils.format_input(text, "text/bbcode")
  102. assert output == expected
  103. end
  104. test "works for text/markdown with mentions" do
  105. {:ok, user} =
  106. UserBuilder.insert(%{nickname: "user__test", ap_id: "http://foo.com/user__test"})
  107. text =
  108. "**hello world**\n\n*another @user__test and @user__test http://google.com paragraph*"
  109. {output, _, _} = Utils.format_input(text, "text/markdown")
  110. assert output ==
  111. ~s(<p><strong>hello world</strong></p><p><em>another <span class="h-card"><a class="u-url mention" data-user="#{
  112. user.id
  113. }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> and <span class="h-card"><a class="u-url mention" data-user="#{
  114. user.id
  115. }" href="http://foo.com/user__test" rel="ugc">@<span>user__test</span></a></span> <a href="http://google.com" rel="ugc">http://google.com</a> paragraph</em></p>)
  116. end
  117. end
  118. describe "context_to_conversation_id" do
  119. test "creates a mapping object" do
  120. conversation_id = Utils.context_to_conversation_id("random context")
  121. object = Object.get_by_ap_id("random context")
  122. assert conversation_id == object.id
  123. end
  124. test "returns an existing mapping for an existing object" do
  125. {:ok, object} = Object.context_mapping("random context") |> Repo.insert()
  126. conversation_id = Utils.context_to_conversation_id("random context")
  127. assert conversation_id == object.id
  128. end
  129. end
  130. describe "formats date to asctime" do
  131. test "when date is in ISO 8601 format" do
  132. date = DateTime.utc_now() |> DateTime.to_iso8601()
  133. expected =
  134. date
  135. |> DateTime.from_iso8601()
  136. |> elem(1)
  137. |> Calendar.Strftime.strftime!("%a %b %d %H:%M:%S %z %Y")
  138. assert Utils.date_to_asctime(date) == expected
  139. end
  140. test "when date is a binary in wrong format" do
  141. date = DateTime.utc_now()
  142. expected = ""
  143. assert capture_log(fn ->
  144. assert Utils.date_to_asctime(date) == expected
  145. end) =~ "[warn] Date #{date} in wrong format, must be ISO 8601"
  146. end
  147. test "when date is a Unix timestamp" do
  148. date = DateTime.utc_now() |> DateTime.to_unix()
  149. expected = ""
  150. assert capture_log(fn ->
  151. assert Utils.date_to_asctime(date) == expected
  152. end) =~ "[warn] Date #{date} in wrong format, must be ISO 8601"
  153. end
  154. test "when date is nil" do
  155. expected = ""
  156. assert capture_log(fn ->
  157. assert Utils.date_to_asctime(nil) == expected
  158. end) =~ "[warn] Date in wrong format, must be ISO 8601"
  159. end
  160. test "when date is a random string" do
  161. assert capture_log(fn ->
  162. assert Utils.date_to_asctime("foo") == ""
  163. end) =~ "[warn] Date foo in wrong format, must be ISO 8601"
  164. end
  165. end
  166. describe "get_to_and_cc" do
  167. test "for public posts, not a reply" do
  168. user = insert(:user)
  169. mentioned_user = insert(:user)
  170. mentions = [mentioned_user.ap_id]
  171. {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "public", nil)
  172. assert length(to) == 2
  173. assert length(cc) == 1
  174. assert @public_address in to
  175. assert mentioned_user.ap_id in to
  176. assert user.follower_address in cc
  177. end
  178. test "for public posts, a reply" do
  179. user = insert(:user)
  180. mentioned_user = insert(:user)
  181. third_user = insert(:user)
  182. {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
  183. mentions = [mentioned_user.ap_id]
  184. {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "public", nil)
  185. assert length(to) == 3
  186. assert length(cc) == 1
  187. assert @public_address in to
  188. assert mentioned_user.ap_id in to
  189. assert third_user.ap_id in to
  190. assert user.follower_address in cc
  191. end
  192. test "for unlisted posts, not a reply" do
  193. user = insert(:user)
  194. mentioned_user = insert(:user)
  195. mentions = [mentioned_user.ap_id]
  196. {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "unlisted", nil)
  197. assert length(to) == 2
  198. assert length(cc) == 1
  199. assert @public_address in cc
  200. assert mentioned_user.ap_id in to
  201. assert user.follower_address in to
  202. end
  203. test "for unlisted posts, a reply" do
  204. user = insert(:user)
  205. mentioned_user = insert(:user)
  206. third_user = insert(:user)
  207. {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
  208. mentions = [mentioned_user.ap_id]
  209. {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "unlisted", nil)
  210. assert length(to) == 3
  211. assert length(cc) == 1
  212. assert @public_address in cc
  213. assert mentioned_user.ap_id in to
  214. assert third_user.ap_id in to
  215. assert user.follower_address in to
  216. end
  217. test "for private posts, not a reply" do
  218. user = insert(:user)
  219. mentioned_user = insert(:user)
  220. mentions = [mentioned_user.ap_id]
  221. {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "private", nil)
  222. assert length(to) == 2
  223. assert Enum.empty?(cc)
  224. assert mentioned_user.ap_id in to
  225. assert user.follower_address in to
  226. end
  227. test "for private posts, a reply" do
  228. user = insert(:user)
  229. mentioned_user = insert(:user)
  230. third_user = insert(:user)
  231. {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
  232. mentions = [mentioned_user.ap_id]
  233. {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "private", nil)
  234. assert length(to) == 2
  235. assert Enum.empty?(cc)
  236. assert mentioned_user.ap_id in to
  237. assert user.follower_address in to
  238. end
  239. test "for direct posts, not a reply" do
  240. user = insert(:user)
  241. mentioned_user = insert(:user)
  242. mentions = [mentioned_user.ap_id]
  243. {to, cc} = Utils.get_to_and_cc(user, mentions, nil, "direct", nil)
  244. assert length(to) == 1
  245. assert Enum.empty?(cc)
  246. assert mentioned_user.ap_id in to
  247. end
  248. test "for direct posts, a reply" do
  249. user = insert(:user)
  250. mentioned_user = insert(:user)
  251. third_user = insert(:user)
  252. {:ok, activity} = CommonAPI.post(third_user, %{status: "uguu"})
  253. mentions = [mentioned_user.ap_id]
  254. {to, cc} = Utils.get_to_and_cc(user, mentions, activity, "direct", nil)
  255. assert length(to) == 1
  256. assert Enum.empty?(cc)
  257. assert mentioned_user.ap_id in to
  258. {:ok, direct_activity} = CommonAPI.post(third_user, %{status: "uguu", visibility: "direct"})
  259. {to, cc} = Utils.get_to_and_cc(user, mentions, direct_activity, "direct", nil)
  260. assert length(to) == 2
  261. assert Enum.empty?(cc)
  262. assert mentioned_user.ap_id in to
  263. assert third_user.ap_id in to
  264. end
  265. end
  266. describe "to_master_date/1" do
  267. test "removes microseconds from date (NaiveDateTime)" do
  268. assert Utils.to_masto_date(~N[2015-01-23 23:50:07.123]) == "2015-01-23T23:50:07.000Z"
  269. end
  270. test "removes microseconds from date (String)" do
  271. assert Utils.to_masto_date("2015-01-23T23:50:07.123Z") == "2015-01-23T23:50:07.000Z"
  272. end
  273. test "returns empty string when date invalid" do
  274. assert Utils.to_masto_date("2015-01?23T23:50:07.123Z") == ""
  275. end
  276. end
  277. describe "conversation_id_to_context/1" do
  278. test "returns id" do
  279. object = insert(:note)
  280. assert Utils.conversation_id_to_context(object.id) == object.data["id"]
  281. end
  282. test "returns error if object not found" do
  283. assert Utils.conversation_id_to_context("123") == {:error, "No such conversation"}
  284. end
  285. end
  286. describe "maybe_notify_mentioned_recipients/2" do
  287. test "returns recipients when activity is not `Create`" do
  288. activity = insert(:like_activity)
  289. assert Utils.maybe_notify_mentioned_recipients(["test"], activity) == ["test"]
  290. end
  291. test "returns recipients from tag" do
  292. user = insert(:user)
  293. object =
  294. insert(:note,
  295. user: user,
  296. data: %{
  297. "tag" => [
  298. %{"type" => "Hashtag"},
  299. "",
  300. %{"type" => "Mention", "href" => "https://testing.pleroma.lol/users/lain"},
  301. %{"type" => "Mention", "href" => "https://shitposter.club/user/5381"},
  302. %{"type" => "Mention", "href" => "https://shitposter.club/user/5381"}
  303. ]
  304. }
  305. )
  306. activity = insert(:note_activity, user: user, note: object)
  307. assert Utils.maybe_notify_mentioned_recipients(["test"], activity) == [
  308. "test",
  309. "https://testing.pleroma.lol/users/lain",
  310. "https://shitposter.club/user/5381"
  311. ]
  312. end
  313. test "returns recipients when object is map" do
  314. user = insert(:user)
  315. object = insert(:note, user: user)
  316. activity =
  317. insert(:note_activity,
  318. user: user,
  319. note: object,
  320. data_attrs: %{
  321. "object" => %{
  322. "tag" => [
  323. %{"type" => "Hashtag"},
  324. "",
  325. %{"type" => "Mention", "href" => "https://testing.pleroma.lol/users/lain"},
  326. %{"type" => "Mention", "href" => "https://shitposter.club/user/5381"},
  327. %{"type" => "Mention", "href" => "https://shitposter.club/user/5381"}
  328. ]
  329. }
  330. }
  331. )
  332. Pleroma.Repo.delete(object)
  333. assert Utils.maybe_notify_mentioned_recipients(["test"], activity) == [
  334. "test",
  335. "https://testing.pleroma.lol/users/lain",
  336. "https://shitposter.club/user/5381"
  337. ]
  338. end
  339. test "returns recipients when object not found" do
  340. user = insert(:user)
  341. object = insert(:note, user: user)
  342. activity = insert(:note_activity, user: user, note: object)
  343. Pleroma.Repo.delete(object)
  344. obj_url = activity.data["object"]
  345. Tesla.Mock.mock(fn
  346. %{method: :get, url: ^obj_url} ->
  347. %Tesla.Env{status: 404, body: ""}
  348. end)
  349. assert Utils.maybe_notify_mentioned_recipients(["test-test"], activity) == [
  350. "test-test"
  351. ]
  352. end
  353. end
  354. describe "attachments_from_ids_descs/2" do
  355. test "returns [] when attachment ids is empty" do
  356. assert Utils.attachments_from_ids_descs([], "{}") == []
  357. end
  358. test "returns list attachments with desc" do
  359. object = insert(:note)
  360. desc = Jason.encode!(%{object.id => "test-desc"})
  361. assert Utils.attachments_from_ids_descs(["#{object.id}", "34"], desc) == [
  362. Map.merge(object.data, %{"name" => "test-desc"})
  363. ]
  364. end
  365. end
  366. describe "attachments_from_ids/1" do
  367. test "returns attachments with descs" do
  368. object = insert(:note)
  369. desc = Jason.encode!(%{object.id => "test-desc"})
  370. assert Utils.attachments_from_ids(%{
  371. media_ids: ["#{object.id}"],
  372. descriptions: desc
  373. }) == [
  374. Map.merge(object.data, %{"name" => "test-desc"})
  375. ]
  376. end
  377. test "returns attachments without descs" do
  378. object = insert(:note)
  379. assert Utils.attachments_from_ids(%{media_ids: ["#{object.id}"]}) == [object.data]
  380. end
  381. test "returns [] when not pass media_ids" do
  382. assert Utils.attachments_from_ids(%{}) == []
  383. end
  384. end
  385. describe "maybe_add_list_data/3" do
  386. test "adds list params when found user list" do
  387. user = insert(:user)
  388. {:ok, %Pleroma.List{} = list} = Pleroma.List.create("title", user)
  389. assert Utils.maybe_add_list_data(%{additional: %{}, object: %{}}, user, {:list, list.id}) ==
  390. %{
  391. additional: %{"bcc" => [list.ap_id], "listMessage" => list.ap_id},
  392. object: %{"listMessage" => list.ap_id}
  393. }
  394. end
  395. test "returns original params when list not found" do
  396. user = insert(:user)
  397. {:ok, %Pleroma.List{} = list} = Pleroma.List.create("title", insert(:user))
  398. assert Utils.maybe_add_list_data(%{additional: %{}, object: %{}}, user, {:list, list.id}) ==
  399. %{additional: %{}, object: %{}}
  400. end
  401. end
  402. describe "make_note_data/11" do
  403. test "returns note data" do
  404. user = insert(:user)
  405. note = insert(:note)
  406. user2 = insert(:user)
  407. user3 = insert(:user)
  408. assert Utils.make_note_data(
  409. user.ap_id,
  410. [user2.ap_id],
  411. "2hu",
  412. "<h1>This is :moominmamma: note</h1>",
  413. [],
  414. note.id,
  415. [name: "jimm"],
  416. "test summary",
  417. [user3.ap_id],
  418. false,
  419. %{"custom_tag" => "test"}
  420. ) == %{
  421. "actor" => user.ap_id,
  422. "attachment" => [],
  423. "cc" => [user3.ap_id],
  424. "content" => "<h1>This is :moominmamma: note</h1>",
  425. "context" => "2hu",
  426. "sensitive" => false,
  427. "summary" => "test summary",
  428. "hashtags" => ["jimm"],
  429. "tag" => [],
  430. "to" => [user2.ap_id],
  431. "type" => "Note",
  432. "custom_tag" => "test"
  433. }
  434. end
  435. end
  436. describe "maybe_add_attachments/3" do
  437. test "returns parsed results when attachment_links is false" do
  438. assert Utils.maybe_add_attachments(
  439. {"test", [], ["tags"]},
  440. [],
  441. false
  442. ) == {"test", [], ["tags"]}
  443. end
  444. test "adds attachments to parsed results" do
  445. attachment = %{"url" => [%{"href" => "SakuraPM.png"}]}
  446. assert Utils.maybe_add_attachments(
  447. {"test", [], ["tags"]},
  448. [attachment],
  449. true
  450. ) == {
  451. "test<br><a href=\"SakuraPM.png\" class='attachment'>SakuraPM.png</a>",
  452. [],
  453. ["tags"]
  454. }
  455. end
  456. end
  457. end