Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

1270 wiersze
38KB

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