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.

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