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.

1171 lines
34KB

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