Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1034 lines
30KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.UserTest do
  5. alias Pleroma.Builders.UserBuilder
  6. alias Pleroma.Activity
  7. alias Pleroma.Repo
  8. alias Pleroma.User
  9. alias Pleroma.Web.CommonAPI
  10. use Pleroma.DataCase
  11. import Pleroma.Factory
  12. setup_all do
  13. Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
  14. :ok
  15. end
  16. describe "when tags are nil" do
  17. test "tagging a user" do
  18. user = insert(:user, %{tags: nil})
  19. user = User.tag(user, ["cool", "dude"])
  20. assert "cool" in user.tags
  21. assert "dude" in user.tags
  22. end
  23. test "untagging a user" do
  24. user = insert(:user, %{tags: nil})
  25. user = User.untag(user, ["cool", "dude"])
  26. assert user.tags == []
  27. end
  28. end
  29. test "ap_id returns the activity pub id for the user" do
  30. user = UserBuilder.build()
  31. expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
  32. assert expected_ap_id == User.ap_id(user)
  33. end
  34. test "ap_followers returns the followers collection for the user" do
  35. user = UserBuilder.build()
  36. expected_followers_collection = "#{User.ap_id(user)}/followers"
  37. assert expected_followers_collection == User.ap_followers(user)
  38. end
  39. test "follow_all follows mutliple users" do
  40. user = insert(:user)
  41. followed_zero = insert(:user)
  42. followed_one = insert(:user)
  43. followed_two = insert(:user)
  44. blocked = insert(:user)
  45. not_followed = insert(:user)
  46. reverse_blocked = insert(:user)
  47. {:ok, user} = User.block(user, blocked)
  48. {:ok, reverse_blocked} = User.block(reverse_blocked, user)
  49. {:ok, user} = User.follow(user, followed_zero)
  50. {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
  51. assert User.following?(user, followed_one)
  52. assert User.following?(user, followed_two)
  53. assert User.following?(user, followed_zero)
  54. refute User.following?(user, not_followed)
  55. refute User.following?(user, blocked)
  56. refute User.following?(user, reverse_blocked)
  57. end
  58. test "follow_all follows mutliple users without duplicating" do
  59. user = insert(:user)
  60. followed_zero = insert(:user)
  61. followed_one = insert(:user)
  62. followed_two = insert(:user)
  63. {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
  64. assert length(user.following) == 3
  65. {:ok, user} = User.follow_all(user, [followed_one, followed_two])
  66. assert length(user.following) == 4
  67. end
  68. test "follow takes a user and another user" do
  69. user = insert(:user)
  70. followed = insert(:user)
  71. {:ok, user} = User.follow(user, followed)
  72. user = Repo.get(User, user.id)
  73. followed = User.get_by_ap_id(followed.ap_id)
  74. assert followed.info.follower_count == 1
  75. assert User.ap_followers(followed) in user.following
  76. end
  77. test "can't follow a deactivated users" do
  78. user = insert(:user)
  79. followed = insert(:user, info: %{deactivated: true})
  80. {:error, _} = User.follow(user, followed)
  81. end
  82. test "can't follow a user who blocked us" do
  83. blocker = insert(:user)
  84. blockee = insert(:user)
  85. {:ok, blocker} = User.block(blocker, blockee)
  86. {:error, _} = User.follow(blockee, blocker)
  87. end
  88. test "local users do not automatically follow local locked accounts" do
  89. follower = insert(:user, info: %{locked: true})
  90. followed = insert(:user, info: %{locked: true})
  91. {:ok, follower} = User.maybe_direct_follow(follower, followed)
  92. refute User.following?(follower, followed)
  93. end
  94. # This is a somewhat useless test.
  95. # test "following a remote user will ensure a websub subscription is present" do
  96. # user = insert(:user)
  97. # {:ok, followed} = OStatus.make_user("shp@social.heldscal.la")
  98. # assert followed.local == false
  99. # {:ok, user} = User.follow(user, followed)
  100. # assert User.ap_followers(followed) in user.following
  101. # query = from w in WebsubClientSubscription,
  102. # where: w.topic == ^followed.info["topic"]
  103. # websub = Repo.one(query)
  104. # assert websub
  105. # end
  106. test "unfollow takes a user and another user" do
  107. followed = insert(:user)
  108. user = insert(:user, %{following: [User.ap_followers(followed)]})
  109. {:ok, user, _activity} = User.unfollow(user, followed)
  110. user = Repo.get(User, user.id)
  111. assert user.following == []
  112. end
  113. test "unfollow doesn't unfollow yourself" do
  114. user = insert(:user)
  115. {:error, _} = User.unfollow(user, user)
  116. user = Repo.get(User, user.id)
  117. assert user.following == [user.ap_id]
  118. end
  119. test "test if a user is following another user" do
  120. followed = insert(:user)
  121. user = insert(:user, %{following: [User.ap_followers(followed)]})
  122. assert User.following?(user, followed)
  123. refute User.following?(followed, user)
  124. end
  125. describe "user registration" do
  126. @full_user_data %{
  127. bio: "A guy",
  128. name: "my name",
  129. nickname: "nick",
  130. password: "test",
  131. password_confirmation: "test",
  132. email: "email@example.com"
  133. }
  134. test "it autofollows accounts that are set for it" do
  135. user = insert(:user)
  136. remote_user = insert(:user, %{local: false})
  137. Pleroma.Config.put([:instance, :autofollowed_nicknames], [
  138. user.nickname,
  139. remote_user.nickname
  140. ])
  141. cng = User.register_changeset(%User{}, @full_user_data)
  142. {:ok, registered_user} = User.register(cng)
  143. assert User.following?(registered_user, user)
  144. refute User.following?(registered_user, remote_user)
  145. Pleroma.Config.put([:instance, :autofollowed_nicknames], [])
  146. end
  147. test "it sends a welcome message if it is set" do
  148. welcome_user = insert(:user)
  149. Pleroma.Config.put([:instance, :welcome_user_nickname], welcome_user.nickname)
  150. Pleroma.Config.put([:instance, :welcome_message], "Hello, this is a cool site")
  151. cng = User.register_changeset(%User{}, @full_user_data)
  152. {:ok, registered_user} = User.register(cng)
  153. activity = Repo.one(Pleroma.Activity)
  154. assert registered_user.ap_id in activity.recipients
  155. assert activity.data["object"]["content"] =~ "cool site"
  156. assert activity.actor == welcome_user.ap_id
  157. Pleroma.Config.put([:instance, :welcome_user_nickname], nil)
  158. Pleroma.Config.put([:instance, :welcome_message], nil)
  159. end
  160. test "it requires an email, name, nickname and password, bio is optional" do
  161. @full_user_data
  162. |> Map.keys()
  163. |> Enum.each(fn key ->
  164. params = Map.delete(@full_user_data, key)
  165. changeset = User.register_changeset(%User{}, params)
  166. assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
  167. end)
  168. end
  169. test "it restricts certain nicknames" do
  170. [restricted_name | _] = Pleroma.Config.get([Pleroma.User, :restricted_nicknames])
  171. assert is_bitstring(restricted_name)
  172. params =
  173. @full_user_data
  174. |> Map.put(:nickname, restricted_name)
  175. changeset = User.register_changeset(%User{}, params)
  176. refute changeset.valid?
  177. end
  178. test "it sets the password_hash, ap_id and following fields" do
  179. changeset = User.register_changeset(%User{}, @full_user_data)
  180. assert changeset.valid?
  181. assert is_binary(changeset.changes[:password_hash])
  182. assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
  183. assert changeset.changes[:following] == [
  184. User.ap_followers(%User{nickname: @full_user_data.nickname})
  185. ]
  186. assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
  187. end
  188. test "it ensures info is not nil" do
  189. changeset = User.register_changeset(%User{}, @full_user_data)
  190. assert changeset.valid?
  191. {:ok, user} =
  192. changeset
  193. |> Repo.insert()
  194. refute is_nil(user.info)
  195. end
  196. end
  197. describe "user registration, with :account_activation_required" do
  198. @full_user_data %{
  199. bio: "A guy",
  200. name: "my name",
  201. nickname: "nick",
  202. password: "test",
  203. password_confirmation: "test",
  204. email: "email@example.com"
  205. }
  206. setup do
  207. setting = Pleroma.Config.get([:instance, :account_activation_required])
  208. unless setting do
  209. Pleroma.Config.put([:instance, :account_activation_required], true)
  210. on_exit(fn -> Pleroma.Config.put([:instance, :account_activation_required], setting) end)
  211. end
  212. :ok
  213. end
  214. test "it creates unconfirmed user" do
  215. changeset = User.register_changeset(%User{}, @full_user_data)
  216. assert changeset.valid?
  217. {:ok, user} = Repo.insert(changeset)
  218. assert user.info.confirmation_pending
  219. assert user.info.confirmation_token
  220. end
  221. test "it creates confirmed user if :confirmed option is given" do
  222. changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
  223. assert changeset.valid?
  224. {:ok, user} = Repo.insert(changeset)
  225. refute user.info.confirmation_pending
  226. refute user.info.confirmation_token
  227. end
  228. end
  229. describe "get_or_fetch/1" do
  230. test "gets an existing user by nickname" do
  231. user = insert(:user)
  232. fetched_user = User.get_or_fetch(user.nickname)
  233. assert user == fetched_user
  234. end
  235. test "gets an existing user by ap_id" do
  236. ap_id = "http://mastodon.example.org/users/admin"
  237. user =
  238. insert(
  239. :user,
  240. local: false,
  241. nickname: "admin@mastodon.example.org",
  242. ap_id: ap_id,
  243. info: %{}
  244. )
  245. fetched_user = User.get_or_fetch(ap_id)
  246. freshed_user = refresh_record(user)
  247. assert freshed_user == fetched_user
  248. end
  249. end
  250. describe "fetching a user from nickname or trying to build one" do
  251. test "gets an existing user" do
  252. user = insert(:user)
  253. fetched_user = User.get_or_fetch_by_nickname(user.nickname)
  254. assert user == fetched_user
  255. end
  256. test "gets an existing user, case insensitive" do
  257. user = insert(:user, nickname: "nick")
  258. fetched_user = User.get_or_fetch_by_nickname("NICK")
  259. assert user == fetched_user
  260. end
  261. test "gets an existing user by fully qualified nickname" do
  262. user = insert(:user)
  263. fetched_user =
  264. User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  265. assert user == fetched_user
  266. end
  267. test "gets an existing user by fully qualified nickname, case insensitive" do
  268. user = insert(:user, nickname: "nick")
  269. casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  270. fetched_user = User.get_or_fetch_by_nickname(casing_altered_fqn)
  271. assert user == fetched_user
  272. end
  273. test "fetches an external user via ostatus if no user exists" do
  274. fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
  275. assert fetched_user.nickname == "shp@social.heldscal.la"
  276. end
  277. test "returns nil if no user could be fetched" do
  278. fetched_user = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
  279. assert fetched_user == nil
  280. end
  281. test "returns nil for nonexistant local user" do
  282. fetched_user = User.get_or_fetch_by_nickname("nonexistant")
  283. assert fetched_user == nil
  284. end
  285. test "updates an existing user, if stale" do
  286. a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
  287. orig_user =
  288. insert(
  289. :user,
  290. local: false,
  291. nickname: "admin@mastodon.example.org",
  292. ap_id: "http://mastodon.example.org/users/admin",
  293. last_refreshed_at: a_week_ago,
  294. info: %{}
  295. )
  296. assert orig_user.last_refreshed_at == a_week_ago
  297. user = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
  298. assert user.info.source_data["endpoints"]
  299. refute user.last_refreshed_at == orig_user.last_refreshed_at
  300. end
  301. end
  302. test "returns an ap_id for a user" do
  303. user = insert(:user)
  304. assert User.ap_id(user) ==
  305. Pleroma.Web.Router.Helpers.o_status_url(
  306. Pleroma.Web.Endpoint,
  307. :feed_redirect,
  308. user.nickname
  309. )
  310. end
  311. test "returns an ap_followers link for a user" do
  312. user = insert(:user)
  313. assert User.ap_followers(user) ==
  314. Pleroma.Web.Router.Helpers.o_status_url(
  315. Pleroma.Web.Endpoint,
  316. :feed_redirect,
  317. user.nickname
  318. ) <> "/followers"
  319. end
  320. describe "remote user creation changeset" do
  321. @valid_remote %{
  322. bio: "hello",
  323. name: "Someone",
  324. nickname: "a@b.de",
  325. ap_id: "http...",
  326. info: %{some: "info"},
  327. avatar: %{some: "avatar"}
  328. }
  329. test "it confirms validity" do
  330. cs = User.remote_user_creation(@valid_remote)
  331. assert cs.valid?
  332. end
  333. test "it sets the follower_adress" do
  334. cs = User.remote_user_creation(@valid_remote)
  335. # remote users get a fake local follower address
  336. assert cs.changes.follower_address ==
  337. User.ap_followers(%User{nickname: @valid_remote[:nickname]})
  338. end
  339. test "it enforces the fqn format for nicknames" do
  340. cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
  341. assert cs.changes.local == false
  342. assert cs.changes.avatar
  343. refute cs.valid?
  344. end
  345. test "it has required fields" do
  346. [:name, :ap_id]
  347. |> Enum.each(fn field ->
  348. cs = User.remote_user_creation(Map.delete(@valid_remote, field))
  349. refute cs.valid?
  350. end)
  351. end
  352. test "it restricts some sizes" do
  353. [bio: 5000, name: 100]
  354. |> Enum.each(fn {field, size} ->
  355. string = String.pad_leading(".", size)
  356. cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
  357. assert cs.valid?
  358. string = String.pad_leading(".", size + 1)
  359. cs = User.remote_user_creation(Map.put(@valid_remote, field, string))
  360. refute cs.valid?
  361. end)
  362. end
  363. end
  364. describe "followers and friends" do
  365. test "gets all followers for a given user" do
  366. user = insert(:user)
  367. follower_one = insert(:user)
  368. follower_two = insert(:user)
  369. not_follower = insert(:user)
  370. {:ok, follower_one} = User.follow(follower_one, user)
  371. {:ok, follower_two} = User.follow(follower_two, user)
  372. {:ok, res} = User.get_followers(user)
  373. assert Enum.member?(res, follower_one)
  374. assert Enum.member?(res, follower_two)
  375. refute Enum.member?(res, not_follower)
  376. end
  377. test "gets all friends (followed users) for a given user" do
  378. user = insert(:user)
  379. followed_one = insert(:user)
  380. followed_two = insert(:user)
  381. not_followed = insert(:user)
  382. {:ok, user} = User.follow(user, followed_one)
  383. {:ok, user} = User.follow(user, followed_two)
  384. {:ok, res} = User.get_friends(user)
  385. followed_one = User.get_by_ap_id(followed_one.ap_id)
  386. followed_two = User.get_by_ap_id(followed_two.ap_id)
  387. assert Enum.member?(res, followed_one)
  388. assert Enum.member?(res, followed_two)
  389. refute Enum.member?(res, not_followed)
  390. end
  391. end
  392. describe "updating note and follower count" do
  393. test "it sets the info->note_count property" do
  394. note = insert(:note)
  395. user = User.get_by_ap_id(note.data["actor"])
  396. assert user.info.note_count == 0
  397. {:ok, user} = User.update_note_count(user)
  398. assert user.info.note_count == 1
  399. end
  400. test "it increases the info->note_count property" do
  401. note = insert(:note)
  402. user = User.get_by_ap_id(note.data["actor"])
  403. assert user.info.note_count == 0
  404. {:ok, user} = User.increase_note_count(user)
  405. assert user.info.note_count == 1
  406. {:ok, user} = User.increase_note_count(user)
  407. assert user.info.note_count == 2
  408. end
  409. test "it decreases the info->note_count property" do
  410. note = insert(:note)
  411. user = User.get_by_ap_id(note.data["actor"])
  412. assert user.info.note_count == 0
  413. {:ok, user} = User.increase_note_count(user)
  414. assert user.info.note_count == 1
  415. {:ok, user} = User.decrease_note_count(user)
  416. assert user.info.note_count == 0
  417. {:ok, user} = User.decrease_note_count(user)
  418. assert user.info.note_count == 0
  419. end
  420. test "it sets the info->follower_count property" do
  421. user = insert(:user)
  422. follower = insert(:user)
  423. User.follow(follower, user)
  424. assert user.info.follower_count == 0
  425. {:ok, user} = User.update_follower_count(user)
  426. assert user.info.follower_count == 1
  427. end
  428. end
  429. describe "follow_import" do
  430. test "it imports user followings from list" do
  431. [user1, user2, user3] = insert_list(3, :user)
  432. identifiers = [
  433. user2.ap_id,
  434. user3.nickname
  435. ]
  436. result = User.follow_import(user1, identifiers)
  437. assert is_list(result)
  438. assert result == [user2, user3]
  439. end
  440. end
  441. describe "blocks" do
  442. test "it blocks people" do
  443. user = insert(:user)
  444. blocked_user = insert(:user)
  445. refute User.blocks?(user, blocked_user)
  446. {:ok, user} = User.block(user, blocked_user)
  447. assert User.blocks?(user, blocked_user)
  448. end
  449. test "it unblocks users" do
  450. user = insert(:user)
  451. blocked_user = insert(:user)
  452. {:ok, user} = User.block(user, blocked_user)
  453. {:ok, user} = User.unblock(user, blocked_user)
  454. refute User.blocks?(user, blocked_user)
  455. end
  456. test "blocks tear down cyclical follow relationships" do
  457. blocker = insert(:user)
  458. blocked = insert(:user)
  459. {:ok, blocker} = User.follow(blocker, blocked)
  460. {:ok, blocked} = User.follow(blocked, blocker)
  461. assert User.following?(blocker, blocked)
  462. assert User.following?(blocked, blocker)
  463. {:ok, blocker} = User.block(blocker, blocked)
  464. blocked = Repo.get(User, blocked.id)
  465. assert User.blocks?(blocker, blocked)
  466. refute User.following?(blocker, blocked)
  467. refute User.following?(blocked, blocker)
  468. end
  469. test "blocks tear down blocker->blocked follow relationships" do
  470. blocker = insert(:user)
  471. blocked = insert(:user)
  472. {:ok, blocker} = User.follow(blocker, blocked)
  473. assert User.following?(blocker, blocked)
  474. refute User.following?(blocked, blocker)
  475. {:ok, blocker} = User.block(blocker, blocked)
  476. blocked = Repo.get(User, blocked.id)
  477. assert User.blocks?(blocker, blocked)
  478. refute User.following?(blocker, blocked)
  479. refute User.following?(blocked, blocker)
  480. end
  481. test "blocks tear down blocked->blocker follow relationships" do
  482. blocker = insert(:user)
  483. blocked = insert(:user)
  484. {:ok, blocked} = User.follow(blocked, blocker)
  485. refute User.following?(blocker, blocked)
  486. assert User.following?(blocked, blocker)
  487. {:ok, blocker} = User.block(blocker, blocked)
  488. blocked = Repo.get(User, blocked.id)
  489. assert User.blocks?(blocker, blocked)
  490. refute User.following?(blocker, blocked)
  491. refute User.following?(blocked, blocker)
  492. end
  493. end
  494. describe "domain blocking" do
  495. test "blocks domains" do
  496. user = insert(:user)
  497. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  498. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  499. assert User.blocks?(user, collateral_user)
  500. end
  501. test "unblocks domains" do
  502. user = insert(:user)
  503. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  504. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  505. {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
  506. refute User.blocks?(user, collateral_user)
  507. end
  508. end
  509. describe "blocks_import" do
  510. test "it imports user blocks from list" do
  511. [user1, user2, user3] = insert_list(3, :user)
  512. identifiers = [
  513. user2.ap_id,
  514. user3.nickname
  515. ]
  516. result = User.blocks_import(user1, identifiers)
  517. assert is_list(result)
  518. assert result == [user2, user3]
  519. end
  520. end
  521. test "get recipients from activity" do
  522. actor = insert(:user)
  523. user = insert(:user, local: true)
  524. user_two = insert(:user, local: false)
  525. addressed = insert(:user, local: true)
  526. addressed_remote = insert(:user, local: false)
  527. {:ok, activity} =
  528. CommonAPI.post(actor, %{
  529. "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
  530. })
  531. assert Enum.map([actor, addressed], & &1.ap_id) --
  532. Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
  533. {:ok, user} = User.follow(user, actor)
  534. {:ok, _user_two} = User.follow(user_two, actor)
  535. recipients = User.get_recipients_from_activity(activity)
  536. assert length(recipients) == 3
  537. assert user in recipients
  538. assert addressed in recipients
  539. end
  540. test ".deactivate can de-activate then re-activate a user" do
  541. user = insert(:user)
  542. assert false == user.info.deactivated
  543. {:ok, user} = User.deactivate(user)
  544. assert true == user.info.deactivated
  545. {:ok, user} = User.deactivate(user, false)
  546. assert false == user.info.deactivated
  547. end
  548. test ".delete deactivates a user, all follow relationships and all create activities" do
  549. user = insert(:user)
  550. followed = insert(:user)
  551. follower = insert(:user)
  552. {:ok, user} = User.follow(user, followed)
  553. {:ok, follower} = User.follow(follower, user)
  554. {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
  555. {:ok, activity_two} = CommonAPI.post(follower, %{"status" => "3hu"})
  556. {:ok, _, _} = CommonAPI.favorite(activity_two.id, user)
  557. {:ok, _, _} = CommonAPI.favorite(activity.id, follower)
  558. {:ok, _, _} = CommonAPI.repeat(activity.id, follower)
  559. {:ok, _} = User.delete(user)
  560. followed = Repo.get(User, followed.id)
  561. follower = Repo.get(User, follower.id)
  562. user = Repo.get(User, user.id)
  563. assert user.info.deactivated
  564. refute User.following?(user, followed)
  565. refute User.following?(followed, follower)
  566. # TODO: Remove favorites, repeats, delete activities.
  567. refute Repo.get(Activity, activity.id)
  568. end
  569. test "get_public_key_for_ap_id fetches a user that's not in the db" do
  570. assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
  571. end
  572. test "insert or update a user from given data" do
  573. user = insert(:user, %{nickname: "nick@name.de"})
  574. data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
  575. assert {:ok, %User{}} = User.insert_or_update_user(data)
  576. end
  577. describe "per-user rich-text filtering" do
  578. test "html_filter_policy returns default policies, when rich-text is enabled" do
  579. user = insert(:user)
  580. assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
  581. end
  582. test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
  583. user = insert(:user, %{info: %{no_rich_text: true}})
  584. assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
  585. end
  586. end
  587. describe "caching" do
  588. test "invalidate_cache works" do
  589. user = insert(:user)
  590. _user_info = User.get_cached_user_info(user)
  591. User.invalidate_cache(user)
  592. {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  593. {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
  594. {:ok, nil} = Cachex.get(:user_cache, "user_info:#{user.id}")
  595. end
  596. test "User.delete() plugs any possible zombie objects" do
  597. user = insert(:user)
  598. {:ok, _} = User.delete(user)
  599. {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  600. assert cached_user != user
  601. {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
  602. assert cached_user != user
  603. end
  604. end
  605. describe "User.search" do
  606. test "finds a user by full or partial nickname" do
  607. user = insert(:user, %{nickname: "john"})
  608. Enum.each(["john", "jo", "j"], fn query ->
  609. assert user == User.search(query) |> List.first() |> Map.put(:search_rank, nil)
  610. end)
  611. end
  612. test "finds a user by full or partial name" do
  613. user = insert(:user, %{name: "John Doe"})
  614. Enum.each(["John Doe", "JOHN", "doe", "j d", "j", "d"], fn query ->
  615. assert user == User.search(query) |> List.first() |> Map.put(:search_rank, nil)
  616. end)
  617. end
  618. test "finds users, preferring nickname matches over name matches" do
  619. u1 = insert(:user, %{name: "lain", nickname: "nick1"})
  620. u2 = insert(:user, %{nickname: "lain", name: "nick1"})
  621. assert [u2.id, u1.id] == Enum.map(User.search("lain"), & &1.id)
  622. end
  623. test "finds users, considering density of matched tokens" do
  624. u1 = insert(:user, %{name: "Bar Bar plus Word Word"})
  625. u2 = insert(:user, %{name: "Word Word Bar Bar Bar"})
  626. assert [u2.id, u1.id] == Enum.map(User.search("bar word"), & &1.id)
  627. end
  628. test "finds users, ranking by similarity" do
  629. u1 = insert(:user, %{name: "lain"})
  630. _u2 = insert(:user, %{name: "ean"})
  631. u3 = insert(:user, %{name: "ebn", nickname: "lain@mastodon.social"})
  632. u4 = insert(:user, %{nickname: "lain@pleroma.soykaf.com"})
  633. assert [u4.id, u3.id, u1.id] == Enum.map(User.search("lain@ple"), & &1.id)
  634. end
  635. test "finds users, handling misspelled requests" do
  636. u1 = insert(:user, %{name: "lain"})
  637. assert [u1.id] == Enum.map(User.search("laiin"), & &1.id)
  638. end
  639. test "finds users, boosting ranks of friends and followers" do
  640. u1 = insert(:user)
  641. u2 = insert(:user, %{name: "Doe"})
  642. follower = insert(:user, %{name: "Doe"})
  643. friend = insert(:user, %{name: "Doe"})
  644. {:ok, follower} = User.follow(follower, u1)
  645. {:ok, u1} = User.follow(u1, friend)
  646. assert [friend.id, follower.id, u2.id] == Enum.map(User.search("doe", false, u1), & &1.id)
  647. end
  648. test "finds a user whose name is nil" do
  649. _user = insert(:user, %{name: "notamatch", nickname: "testuser@pleroma.amplifie.red"})
  650. user_two = insert(:user, %{name: nil, nickname: "lain@pleroma.soykaf.com"})
  651. assert user_two ==
  652. User.search("lain@pleroma.soykaf.com")
  653. |> List.first()
  654. |> Map.put(:search_rank, nil)
  655. end
  656. test "does not yield false-positive matches" do
  657. insert(:user, %{name: "John Doe"})
  658. Enum.each(["mary", "a", ""], fn query ->
  659. assert [] == User.search(query)
  660. end)
  661. end
  662. test "works with URIs" do
  663. results = User.search("http://mastodon.example.org/users/admin", true)
  664. result = results |> List.first()
  665. user = User.get_by_ap_id("http://mastodon.example.org/users/admin")
  666. assert length(results) == 1
  667. assert user == result |> Map.put(:search_rank, nil)
  668. end
  669. end
  670. test "auth_active?/1 works correctly" do
  671. Pleroma.Config.put([:instance, :account_activation_required], true)
  672. local_user = insert(:user, local: true, info: %{confirmation_pending: true})
  673. confirmed_user = insert(:user, local: true, info: %{confirmation_pending: false})
  674. remote_user = insert(:user, local: false)
  675. refute User.auth_active?(local_user)
  676. assert User.auth_active?(confirmed_user)
  677. assert User.auth_active?(remote_user)
  678. Pleroma.Config.put([:instance, :account_activation_required], false)
  679. end
  680. describe "superuser?/1" do
  681. test "returns false for unprivileged users" do
  682. user = insert(:user, local: true)
  683. refute User.superuser?(user)
  684. end
  685. test "returns false for remote users" do
  686. user = insert(:user, local: false)
  687. remote_admin_user = insert(:user, local: false, info: %{is_admin: true})
  688. refute User.superuser?(user)
  689. refute User.superuser?(remote_admin_user)
  690. end
  691. test "returns true for local moderators" do
  692. user = insert(:user, local: true, info: %{is_moderator: true})
  693. assert User.superuser?(user)
  694. end
  695. test "returns true for local admins" do
  696. user = insert(:user, local: true, info: %{is_admin: true})
  697. assert User.superuser?(user)
  698. end
  699. end
  700. describe "visible_for?/2" do
  701. test "returns true when the account is itself" do
  702. user = insert(:user, local: true)
  703. assert User.visible_for?(user, user)
  704. end
  705. test "returns false when the account is unauthenticated and auth is required" do
  706. Pleroma.Config.put([:instance, :account_activation_required], true)
  707. user = insert(:user, local: true, info: %{confirmation_pending: true})
  708. other_user = insert(:user, local: true)
  709. refute User.visible_for?(user, other_user)
  710. Pleroma.Config.put([:instance, :account_activation_required], false)
  711. end
  712. test "returns true when the account is unauthenticated and auth is not required" do
  713. user = insert(:user, local: true, info: %{confirmation_pending: true})
  714. other_user = insert(:user, local: true)
  715. assert User.visible_for?(user, other_user)
  716. end
  717. test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
  718. Pleroma.Config.put([:instance, :account_activation_required], true)
  719. user = insert(:user, local: true, info: %{confirmation_pending: true})
  720. other_user = insert(:user, local: true, info: %{is_admin: true})
  721. assert User.visible_for?(user, other_user)
  722. Pleroma.Config.put([:instance, :account_activation_required], false)
  723. end
  724. end
  725. describe "parse_bio/2" do
  726. test "preserves hosts in user links text" do
  727. remote_user = insert(:user, local: false, nickname: "nick@domain.com")
  728. user = insert(:user)
  729. bio = "A.k.a. @nick@domain.com"
  730. expected_text =
  731. "A.k.a. <span class='h-card'><a data-user='#{remote_user.id}' class='u-url mention' href='#{
  732. remote_user.ap_id
  733. }'>" <> "@<span>nick@domain.com</span></a></span>"
  734. assert expected_text == User.parse_bio(bio, user)
  735. end
  736. end
  737. test "bookmarks" do
  738. user = insert(:user)
  739. {:ok, activity1} =
  740. CommonAPI.post(user, %{
  741. "status" => "heweoo!"
  742. })
  743. id1 = activity1.data["object"]["id"]
  744. {:ok, activity2} =
  745. CommonAPI.post(user, %{
  746. "status" => "heweoo!"
  747. })
  748. id2 = activity2.data["object"]["id"]
  749. assert {:ok, user_state1} = User.bookmark(user, id1)
  750. assert user_state1.bookmarks == [id1]
  751. assert {:ok, user_state2} = User.unbookmark(user, id1)
  752. assert user_state2.bookmarks == []
  753. assert {:ok, user_state3} = User.bookmark(user, id2)
  754. assert user_state3.bookmarks == [id2]
  755. end
  756. end