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.

1756 lines
52KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2019 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.Tests.ObanHelpers
  10. alias Pleroma.User
  11. alias Pleroma.Web.ActivityPub.ActivityPub
  12. alias Pleroma.Web.CommonAPI
  13. use Pleroma.DataCase
  14. use Oban.Testing, repo: Pleroma.Repo
  15. import Mock
  16. import Pleroma.Factory
  17. setup_all do
  18. Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
  19. :ok
  20. end
  21. clear_config([:instance, :account_activation_required])
  22. describe "when tags are nil" do
  23. test "tagging a user" do
  24. user = insert(:user, %{tags: nil})
  25. user = User.tag(user, ["cool", "dude"])
  26. assert "cool" in user.tags
  27. assert "dude" in user.tags
  28. end
  29. test "untagging a user" do
  30. user = insert(:user, %{tags: nil})
  31. user = User.untag(user, ["cool", "dude"])
  32. assert user.tags == []
  33. end
  34. end
  35. test "ap_id returns the activity pub id for the user" do
  36. user = UserBuilder.build()
  37. expected_ap_id = "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
  38. assert expected_ap_id == User.ap_id(user)
  39. end
  40. test "ap_followers returns the followers collection for the user" do
  41. user = UserBuilder.build()
  42. expected_followers_collection = "#{User.ap_id(user)}/followers"
  43. assert expected_followers_collection == User.ap_followers(user)
  44. end
  45. test "ap_following returns the following collection for the user" do
  46. user = UserBuilder.build()
  47. expected_followers_collection = "#{User.ap_id(user)}/following"
  48. assert expected_followers_collection == User.ap_following(user)
  49. end
  50. test "returns all pending follow requests" do
  51. unlocked = insert(:user)
  52. locked = insert(:user, locked: true)
  53. follower = insert(:user)
  54. CommonAPI.follow(follower, unlocked)
  55. CommonAPI.follow(follower, locked)
  56. assert [] = User.get_follow_requests(unlocked)
  57. assert [activity] = User.get_follow_requests(locked)
  58. assert activity
  59. end
  60. test "doesn't return already accepted or duplicate follow requests" do
  61. locked = insert(:user, locked: true)
  62. pending_follower = insert(:user)
  63. accepted_follower = insert(:user)
  64. CommonAPI.follow(pending_follower, locked)
  65. CommonAPI.follow(pending_follower, locked)
  66. CommonAPI.follow(accepted_follower, locked)
  67. User.follow(accepted_follower, locked)
  68. assert [activity] = User.get_follow_requests(locked)
  69. assert activity
  70. end
  71. test "clears follow requests when requester is blocked" do
  72. followed = insert(:user, locked: true)
  73. follower = insert(:user)
  74. CommonAPI.follow(follower, followed)
  75. assert [_activity] = User.get_follow_requests(followed)
  76. {:ok, _follower} = User.block(followed, follower)
  77. assert [] = User.get_follow_requests(followed)
  78. end
  79. test "follow_all follows mutliple users" do
  80. user = insert(:user)
  81. followed_zero = insert(:user)
  82. followed_one = insert(:user)
  83. followed_two = insert(:user)
  84. blocked = insert(:user)
  85. not_followed = insert(:user)
  86. reverse_blocked = insert(:user)
  87. {:ok, user} = User.block(user, blocked)
  88. {:ok, reverse_blocked} = User.block(reverse_blocked, user)
  89. {:ok, user} = User.follow(user, followed_zero)
  90. {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
  91. assert User.following?(user, followed_one)
  92. assert User.following?(user, followed_two)
  93. assert User.following?(user, followed_zero)
  94. refute User.following?(user, not_followed)
  95. refute User.following?(user, blocked)
  96. refute User.following?(user, reverse_blocked)
  97. end
  98. test "follow_all follows mutliple users without duplicating" do
  99. user = insert(:user)
  100. followed_zero = insert(:user)
  101. followed_one = insert(:user)
  102. followed_two = insert(:user)
  103. {:ok, user} = User.follow_all(user, [followed_zero, followed_one])
  104. assert length(user.following) == 3
  105. {:ok, user} = User.follow_all(user, [followed_one, followed_two])
  106. assert length(user.following) == 4
  107. end
  108. test "follow takes a user and another user" do
  109. user = insert(:user)
  110. followed = insert(:user)
  111. {:ok, user} = User.follow(user, followed)
  112. user = User.get_cached_by_id(user.id)
  113. followed = User.get_cached_by_ap_id(followed.ap_id)
  114. assert followed.follower_count == 1
  115. assert User.ap_followers(followed) in user.following
  116. end
  117. test "can't follow a deactivated users" do
  118. user = insert(:user)
  119. followed = insert(:user, %{deactivated: true})
  120. {:error, _} = User.follow(user, followed)
  121. end
  122. test "can't follow a user who blocked us" do
  123. blocker = insert(:user)
  124. blockee = insert(:user)
  125. {:ok, blocker} = User.block(blocker, blockee)
  126. {:error, _} = User.follow(blockee, blocker)
  127. end
  128. test "can't subscribe to a user who blocked us" do
  129. blocker = insert(:user)
  130. blocked = insert(:user)
  131. {:ok, blocker} = User.block(blocker, blocked)
  132. {:error, _} = User.subscribe(blocked, blocker)
  133. end
  134. test "local users do not automatically follow local locked accounts" do
  135. follower = insert(:user, locked: true)
  136. followed = insert(:user, locked: true)
  137. {:ok, follower} = User.maybe_direct_follow(follower, followed)
  138. refute User.following?(follower, followed)
  139. end
  140. describe "unfollow/2" do
  141. setup do
  142. setting = Pleroma.Config.get([:instance, :external_user_synchronization])
  143. on_exit(fn ->
  144. Pleroma.Config.put([:instance, :external_user_synchronization], setting)
  145. end)
  146. :ok
  147. end
  148. test "unfollow with syncronizes external user" do
  149. Pleroma.Config.put([:instance, :external_user_synchronization], true)
  150. followed =
  151. insert(:user,
  152. nickname: "fuser1",
  153. follower_address: "http://localhost:4001/users/fuser1/followers",
  154. following_address: "http://localhost:4001/users/fuser1/following",
  155. ap_id: "http://localhost:4001/users/fuser1"
  156. )
  157. user =
  158. insert(:user, %{
  159. local: false,
  160. nickname: "fuser2",
  161. ap_id: "http://localhost:4001/users/fuser2",
  162. follower_address: "http://localhost:4001/users/fuser2/followers",
  163. following_address: "http://localhost:4001/users/fuser2/following",
  164. following: [User.ap_followers(followed)]
  165. })
  166. {:ok, user, _activity} = User.unfollow(user, followed)
  167. user = User.get_cached_by_id(user.id)
  168. assert user.following == []
  169. end
  170. test "unfollow takes a user and another user" do
  171. followed = insert(:user)
  172. user = insert(:user, %{following: [User.ap_followers(followed)]})
  173. {:ok, user, _activity} = User.unfollow(user, followed)
  174. user = User.get_cached_by_id(user.id)
  175. assert user.following == []
  176. end
  177. test "unfollow doesn't unfollow yourself" do
  178. user = insert(:user)
  179. {:error, _} = User.unfollow(user, user)
  180. user = User.get_cached_by_id(user.id)
  181. assert user.following == [user.ap_id]
  182. end
  183. end
  184. test "test if a user is following another user" do
  185. followed = insert(:user)
  186. user = insert(:user, %{following: [User.ap_followers(followed)]})
  187. assert User.following?(user, followed)
  188. refute User.following?(followed, user)
  189. end
  190. test "fetches correct profile for nickname beginning with number" do
  191. # Use old-style integer ID to try to reproduce the problem
  192. user = insert(:user, %{id: 1080})
  193. user_with_numbers = insert(:user, %{nickname: "#{user.id}garbage"})
  194. assert user_with_numbers == User.get_cached_by_nickname_or_id(user_with_numbers.nickname)
  195. end
  196. describe "user registration" do
  197. @full_user_data %{
  198. bio: "A guy",
  199. name: "my name",
  200. nickname: "nick",
  201. password: "test",
  202. password_confirmation: "test",
  203. email: "email@example.com"
  204. }
  205. clear_config([:instance, :autofollowed_nicknames])
  206. clear_config([:instance, :welcome_message])
  207. clear_config([:instance, :welcome_user_nickname])
  208. test "it autofollows accounts that are set for it" do
  209. user = insert(:user)
  210. remote_user = insert(:user, %{local: false})
  211. Pleroma.Config.put([:instance, :autofollowed_nicknames], [
  212. user.nickname,
  213. remote_user.nickname
  214. ])
  215. cng = User.register_changeset(%User{}, @full_user_data)
  216. {:ok, registered_user} = User.register(cng)
  217. assert User.following?(registered_user, user)
  218. refute User.following?(registered_user, remote_user)
  219. end
  220. test "it sends a welcome message if it is set" do
  221. welcome_user = insert(:user)
  222. Pleroma.Config.put([:instance, :welcome_user_nickname], welcome_user.nickname)
  223. Pleroma.Config.put([:instance, :welcome_message], "Hello, this is a cool site")
  224. cng = User.register_changeset(%User{}, @full_user_data)
  225. {:ok, registered_user} = User.register(cng)
  226. activity = Repo.one(Pleroma.Activity)
  227. assert registered_user.ap_id in activity.recipients
  228. assert Object.normalize(activity).data["content"] =~ "cool site"
  229. assert activity.actor == welcome_user.ap_id
  230. end
  231. test "it requires an email, name, nickname and password, bio is optional" do
  232. @full_user_data
  233. |> Map.keys()
  234. |> Enum.each(fn key ->
  235. params = Map.delete(@full_user_data, key)
  236. changeset = User.register_changeset(%User{}, params)
  237. assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
  238. end)
  239. end
  240. test "it restricts certain nicknames" do
  241. [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
  242. assert is_bitstring(restricted_name)
  243. params =
  244. @full_user_data
  245. |> Map.put(:nickname, restricted_name)
  246. changeset = User.register_changeset(%User{}, params)
  247. refute changeset.valid?
  248. end
  249. test "it sets the password_hash, ap_id and following fields" do
  250. changeset = User.register_changeset(%User{}, @full_user_data)
  251. assert changeset.valid?
  252. assert is_binary(changeset.changes[:password_hash])
  253. assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
  254. assert changeset.changes[:following] == [
  255. User.ap_followers(%User{nickname: @full_user_data.nickname})
  256. ]
  257. assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
  258. end
  259. test "it ensures info is not nil" do
  260. changeset = User.register_changeset(%User{}, @full_user_data)
  261. assert changeset.valid?
  262. {:ok, user} =
  263. changeset
  264. |> Repo.insert()
  265. refute is_nil(user.info)
  266. end
  267. end
  268. describe "user registration, with :account_activation_required" do
  269. @full_user_data %{
  270. bio: "A guy",
  271. name: "my name",
  272. nickname: "nick",
  273. password: "test",
  274. password_confirmation: "test",
  275. email: "email@example.com"
  276. }
  277. clear_config([:instance, :account_activation_required]) do
  278. Pleroma.Config.put([:instance, :account_activation_required], true)
  279. end
  280. test "it creates unconfirmed user" do
  281. changeset = User.register_changeset(%User{}, @full_user_data)
  282. assert changeset.valid?
  283. {:ok, user} = Repo.insert(changeset)
  284. assert user.confirmation_pending
  285. assert user.confirmation_token
  286. end
  287. test "it creates confirmed user if :confirmed option is given" do
  288. changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
  289. assert changeset.valid?
  290. {:ok, user} = Repo.insert(changeset)
  291. refute user.confirmation_pending
  292. refute user.confirmation_token
  293. end
  294. end
  295. describe "get_or_fetch/1" do
  296. test "gets an existing user by nickname" do
  297. user = insert(:user)
  298. {:ok, fetched_user} = User.get_or_fetch(user.nickname)
  299. assert user == fetched_user
  300. end
  301. test "gets an existing user by ap_id" do
  302. ap_id = "http://mastodon.example.org/users/admin"
  303. user =
  304. insert(
  305. :user,
  306. local: false,
  307. nickname: "admin@mastodon.example.org",
  308. ap_id: ap_id,
  309. info: %{}
  310. )
  311. {:ok, fetched_user} = User.get_or_fetch(ap_id)
  312. freshed_user = refresh_record(user)
  313. assert freshed_user == fetched_user
  314. end
  315. end
  316. describe "fetching a user from nickname or trying to build one" do
  317. test "gets an existing user" do
  318. user = insert(:user)
  319. {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
  320. assert user == fetched_user
  321. end
  322. test "gets an existing user, case insensitive" do
  323. user = insert(:user, nickname: "nick")
  324. {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
  325. assert user == fetched_user
  326. end
  327. test "gets an existing user by fully qualified nickname" do
  328. user = insert(:user)
  329. {:ok, fetched_user} =
  330. User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  331. assert user == fetched_user
  332. end
  333. test "gets an existing user by fully qualified nickname, case insensitive" do
  334. user = insert(:user, nickname: "nick")
  335. casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  336. {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
  337. assert user == fetched_user
  338. end
  339. test "returns nil if no user could be fetched" do
  340. {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
  341. assert fetched_user == "not found nonexistant@social.heldscal.la"
  342. end
  343. test "returns nil for nonexistant local user" do
  344. {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
  345. assert fetched_user == "not found nonexistant"
  346. end
  347. test "updates an existing user, if stale" do
  348. a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
  349. orig_user =
  350. insert(
  351. :user,
  352. local: false,
  353. nickname: "admin@mastodon.example.org",
  354. ap_id: "http://mastodon.example.org/users/admin",
  355. last_refreshed_at: a_week_ago,
  356. info: %{}
  357. )
  358. assert orig_user.last_refreshed_at == a_week_ago
  359. {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
  360. assert user.source_data["endpoints"]
  361. refute user.last_refreshed_at == orig_user.last_refreshed_at
  362. end
  363. end
  364. test "returns an ap_id for a user" do
  365. user = insert(:user)
  366. assert User.ap_id(user) ==
  367. Pleroma.Web.Router.Helpers.feed_url(
  368. Pleroma.Web.Endpoint,
  369. :feed_redirect,
  370. user.nickname
  371. )
  372. end
  373. test "returns an ap_followers link for a user" do
  374. user = insert(:user)
  375. assert User.ap_followers(user) ==
  376. Pleroma.Web.Router.Helpers.feed_url(
  377. Pleroma.Web.Endpoint,
  378. :feed_redirect,
  379. user.nickname
  380. ) <> "/followers"
  381. end
  382. describe "remote user creation changeset" do
  383. @valid_remote %{
  384. bio: "hello",
  385. name: "Someone",
  386. nickname: "a@b.de",
  387. ap_id: "http...",
  388. info: %{some: "info"},
  389. avatar: %{some: "avatar"}
  390. }
  391. clear_config([:instance, :user_bio_length])
  392. clear_config([:instance, :user_name_length])
  393. test "it confirms validity" do
  394. cs = User.remote_user_creation(@valid_remote)
  395. assert cs.valid?
  396. end
  397. test "it sets the follower_adress" do
  398. cs = User.remote_user_creation(@valid_remote)
  399. # remote users get a fake local follower address
  400. assert cs.changes.follower_address ==
  401. User.ap_followers(%User{nickname: @valid_remote[:nickname]})
  402. end
  403. test "it enforces the fqn format for nicknames" do
  404. cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
  405. assert Ecto.Changeset.get_field(cs, :local) == false
  406. assert cs.changes.avatar
  407. refute cs.valid?
  408. end
  409. test "it has required fields" do
  410. [:name, :ap_id]
  411. |> Enum.each(fn field ->
  412. cs = User.remote_user_creation(Map.delete(@valid_remote, field))
  413. refute cs.valid?
  414. end)
  415. end
  416. end
  417. describe "followers and friends" do
  418. test "gets all followers for a given user" do
  419. user = insert(:user)
  420. follower_one = insert(:user)
  421. follower_two = insert(:user)
  422. not_follower = insert(:user)
  423. {:ok, follower_one} = User.follow(follower_one, user)
  424. {:ok, follower_two} = User.follow(follower_two, user)
  425. res = User.get_followers(user)
  426. assert Enum.member?(res, follower_one)
  427. assert Enum.member?(res, follower_two)
  428. refute Enum.member?(res, not_follower)
  429. end
  430. test "gets all friends (followed users) for a given user" do
  431. user = insert(:user)
  432. followed_one = insert(:user)
  433. followed_two = insert(:user)
  434. not_followed = insert(:user)
  435. {:ok, user} = User.follow(user, followed_one)
  436. {:ok, user} = User.follow(user, followed_two)
  437. res = User.get_friends(user)
  438. followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
  439. followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
  440. assert Enum.member?(res, followed_one)
  441. assert Enum.member?(res, followed_two)
  442. refute Enum.member?(res, not_followed)
  443. end
  444. end
  445. describe "updating note and follower count" do
  446. test "it sets the note_count property" do
  447. note = insert(:note)
  448. user = User.get_cached_by_ap_id(note.data["actor"])
  449. assert user.note_count == 0
  450. {:ok, user} = User.update_note_count(user)
  451. assert user.note_count == 1
  452. end
  453. test "it increases the note_count property" do
  454. note = insert(:note)
  455. user = User.get_cached_by_ap_id(note.data["actor"])
  456. assert user.note_count == 0
  457. {:ok, user} = User.increase_note_count(user)
  458. assert user.note_count == 1
  459. {:ok, user} = User.increase_note_count(user)
  460. assert user.note_count == 2
  461. end
  462. test "it decreases the note_count property" do
  463. note = insert(:note)
  464. user = User.get_cached_by_ap_id(note.data["actor"])
  465. assert user.note_count == 0
  466. {:ok, user} = User.increase_note_count(user)
  467. assert user.note_count == 1
  468. {:ok, user} = User.decrease_note_count(user)
  469. assert user.note_count == 0
  470. {:ok, user} = User.decrease_note_count(user)
  471. assert user.note_count == 0
  472. end
  473. test "it sets the follower_count property" do
  474. user = insert(:user)
  475. follower = insert(:user)
  476. User.follow(follower, user)
  477. assert user.follower_count == 0
  478. {:ok, user} = User.update_follower_count(user)
  479. assert user.follower_count == 1
  480. end
  481. end
  482. describe "remove duplicates from following list" do
  483. test "it removes duplicates" do
  484. user = insert(:user)
  485. follower = insert(:user)
  486. {:ok, %User{following: following} = follower} = User.follow(follower, user)
  487. assert length(following) == 2
  488. {:ok, follower} =
  489. follower
  490. |> User.update_changeset(%{following: following ++ following})
  491. |> Repo.update()
  492. assert length(follower.following) == 4
  493. {:ok, follower} = User.remove_duplicated_following(follower)
  494. assert length(follower.following) == 2
  495. end
  496. test "it does nothing when following is uniq" do
  497. user = insert(:user)
  498. follower = insert(:user)
  499. {:ok, follower} = User.follow(follower, user)
  500. assert length(follower.following) == 2
  501. {:ok, follower} = User.remove_duplicated_following(follower)
  502. assert length(follower.following) == 2
  503. end
  504. end
  505. describe "follow_import" do
  506. test "it imports user followings from list" do
  507. [user1, user2, user3] = insert_list(3, :user)
  508. identifiers = [
  509. user2.ap_id,
  510. user3.nickname
  511. ]
  512. {:ok, job} = User.follow_import(user1, identifiers)
  513. result = ObanHelpers.perform(job)
  514. assert is_list(result)
  515. assert result == [user2, user3]
  516. end
  517. end
  518. describe "mutes" do
  519. test "it mutes people" do
  520. user = insert(:user)
  521. muted_user = insert(:user)
  522. refute User.mutes?(user, muted_user)
  523. refute User.muted_notifications?(user, muted_user)
  524. {:ok, user} = User.mute(user, muted_user)
  525. assert User.mutes?(user, muted_user)
  526. assert User.muted_notifications?(user, muted_user)
  527. end
  528. test "it unmutes users" do
  529. user = insert(:user)
  530. muted_user = insert(:user)
  531. {:ok, user} = User.mute(user, muted_user)
  532. {:ok, user} = User.unmute(user, muted_user)
  533. refute User.mutes?(user, muted_user)
  534. refute User.muted_notifications?(user, muted_user)
  535. end
  536. test "it mutes user without notifications" do
  537. user = insert(:user)
  538. muted_user = insert(:user)
  539. refute User.mutes?(user, muted_user)
  540. refute User.muted_notifications?(user, muted_user)
  541. {:ok, user} = User.mute(user, muted_user, false)
  542. assert User.mutes?(user, muted_user)
  543. refute User.muted_notifications?(user, muted_user)
  544. end
  545. end
  546. describe "blocks" do
  547. test "it blocks people" do
  548. user = insert(:user)
  549. blocked_user = insert(:user)
  550. refute User.blocks?(user, blocked_user)
  551. {:ok, user} = User.block(user, blocked_user)
  552. assert User.blocks?(user, blocked_user)
  553. end
  554. test "it unblocks users" do
  555. user = insert(:user)
  556. blocked_user = insert(:user)
  557. {:ok, user} = User.block(user, blocked_user)
  558. {:ok, user} = User.unblock(user, blocked_user)
  559. refute User.blocks?(user, blocked_user)
  560. end
  561. test "blocks tear down cyclical follow relationships" do
  562. blocker = insert(:user)
  563. blocked = insert(:user)
  564. {:ok, blocker} = User.follow(blocker, blocked)
  565. {:ok, blocked} = User.follow(blocked, blocker)
  566. assert User.following?(blocker, blocked)
  567. assert User.following?(blocked, blocker)
  568. {:ok, blocker} = User.block(blocker, blocked)
  569. blocked = User.get_cached_by_id(blocked.id)
  570. assert User.blocks?(blocker, blocked)
  571. refute User.following?(blocker, blocked)
  572. refute User.following?(blocked, blocker)
  573. end
  574. test "blocks tear down blocker->blocked follow relationships" do
  575. blocker = insert(:user)
  576. blocked = insert(:user)
  577. {:ok, blocker} = User.follow(blocker, blocked)
  578. assert User.following?(blocker, blocked)
  579. refute User.following?(blocked, blocker)
  580. {:ok, blocker} = User.block(blocker, blocked)
  581. blocked = User.get_cached_by_id(blocked.id)
  582. assert User.blocks?(blocker, blocked)
  583. refute User.following?(blocker, blocked)
  584. refute User.following?(blocked, blocker)
  585. end
  586. test "blocks tear down blocked->blocker follow relationships" do
  587. blocker = insert(:user)
  588. blocked = insert(:user)
  589. {:ok, blocked} = User.follow(blocked, blocker)
  590. refute User.following?(blocker, blocked)
  591. assert User.following?(blocked, blocker)
  592. {:ok, blocker} = User.block(blocker, blocked)
  593. blocked = User.get_cached_by_id(blocked.id)
  594. assert User.blocks?(blocker, blocked)
  595. refute User.following?(blocker, blocked)
  596. refute User.following?(blocked, blocker)
  597. end
  598. test "blocks tear down blocked->blocker subscription relationships" do
  599. blocker = insert(:user)
  600. blocked = insert(:user)
  601. {:ok, blocker} = User.subscribe(blocked, blocker)
  602. assert User.subscribed_to?(blocked, blocker)
  603. refute User.subscribed_to?(blocker, blocked)
  604. {:ok, blocker} = User.block(blocker, blocked)
  605. assert User.blocks?(blocker, blocked)
  606. refute User.subscribed_to?(blocker, blocked)
  607. refute User.subscribed_to?(blocked, blocker)
  608. end
  609. end
  610. describe "domain blocking" do
  611. test "blocks domains" do
  612. user = insert(:user)
  613. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  614. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  615. assert User.blocks?(user, collateral_user)
  616. end
  617. test "does not block domain with same end" do
  618. user = insert(:user)
  619. collateral_user =
  620. insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
  621. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  622. refute User.blocks?(user, collateral_user)
  623. end
  624. test "does not block domain with same end if wildcard added" do
  625. user = insert(:user)
  626. collateral_user =
  627. insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
  628. {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
  629. refute User.blocks?(user, collateral_user)
  630. end
  631. test "blocks domain with wildcard for subdomain" do
  632. user = insert(:user)
  633. user_from_subdomain =
  634. insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
  635. user_with_two_subdomains =
  636. insert(:user, %{
  637. ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
  638. })
  639. user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  640. {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
  641. assert User.blocks?(user, user_from_subdomain)
  642. assert User.blocks?(user, user_with_two_subdomains)
  643. assert User.blocks?(user, user_domain)
  644. end
  645. test "unblocks domains" do
  646. user = insert(:user)
  647. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  648. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  649. {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
  650. refute User.blocks?(user, collateral_user)
  651. end
  652. end
  653. describe "blocks_import" do
  654. test "it imports user blocks from list" do
  655. [user1, user2, user3] = insert_list(3, :user)
  656. identifiers = [
  657. user2.ap_id,
  658. user3.nickname
  659. ]
  660. {:ok, job} = User.blocks_import(user1, identifiers)
  661. result = ObanHelpers.perform(job)
  662. assert is_list(result)
  663. assert result == [user2, user3]
  664. end
  665. end
  666. test "get recipients from activity" do
  667. actor = insert(:user)
  668. user = insert(:user, local: true)
  669. user_two = insert(:user, local: false)
  670. addressed = insert(:user, local: true)
  671. addressed_remote = insert(:user, local: false)
  672. {:ok, activity} =
  673. CommonAPI.post(actor, %{
  674. "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
  675. })
  676. assert Enum.map([actor, addressed], & &1.ap_id) --
  677. Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
  678. {:ok, user} = User.follow(user, actor)
  679. {:ok, _user_two} = User.follow(user_two, actor)
  680. recipients = User.get_recipients_from_activity(activity)
  681. assert length(recipients) == 3
  682. assert user in recipients
  683. assert addressed in recipients
  684. end
  685. describe ".deactivate" do
  686. test "can de-activate then re-activate a user" do
  687. user = insert(:user)
  688. assert false == user.deactivated
  689. {:ok, user} = User.deactivate(user)
  690. assert true == user.deactivated
  691. {:ok, user} = User.deactivate(user, false)
  692. assert false == user.deactivated
  693. end
  694. test "hide a user from followers" do
  695. user = insert(:user)
  696. user2 = insert(:user)
  697. {:ok, user} = User.follow(user, user2)
  698. {:ok, _user} = User.deactivate(user)
  699. info = User.get_cached_user_info(user2)
  700. assert info.follower_count == 0
  701. assert [] = User.get_followers(user2)
  702. end
  703. test "hide a user from friends" do
  704. user = insert(:user)
  705. user2 = insert(:user)
  706. {:ok, user2} = User.follow(user2, user)
  707. assert User.following_count(user2) == 1
  708. {:ok, _user} = User.deactivate(user)
  709. info = User.get_cached_user_info(user2)
  710. assert info.following_count == 0
  711. assert User.following_count(user2) == 0
  712. assert [] = User.get_friends(user2)
  713. end
  714. test "hide a user's statuses from timelines and notifications" do
  715. user = insert(:user)
  716. user2 = insert(:user)
  717. {:ok, user2} = User.follow(user2, user)
  718. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}"})
  719. activity = Repo.preload(activity, :bookmark)
  720. [notification] = Pleroma.Notification.for_user(user2)
  721. assert notification.activity.id == activity.id
  722. assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
  723. assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
  724. ActivityPub.fetch_activities([user2.ap_id | user2.following], %{"user" => user2})
  725. {:ok, _user} = User.deactivate(user)
  726. assert [] == ActivityPub.fetch_public_activities(%{})
  727. assert [] == Pleroma.Notification.for_user(user2)
  728. assert [] ==
  729. ActivityPub.fetch_activities([user2.ap_id | user2.following], %{"user" => user2})
  730. end
  731. end
  732. describe "delete" do
  733. setup do
  734. {:ok, user} = insert(:user) |> User.set_cache()
  735. [user: user]
  736. end
  737. clear_config([:instance, :federating])
  738. test ".delete_user_activities deletes all create activities", %{user: user} do
  739. {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
  740. User.delete_user_activities(user)
  741. # TODO: Remove favorites, repeats, delete activities.
  742. refute Activity.get_by_id(activity.id)
  743. end
  744. test "it deletes deactivated user" do
  745. {:ok, user} = insert(:user, deactivated: true) |> User.set_cache()
  746. {:ok, job} = User.delete(user)
  747. {:ok, _user} = ObanHelpers.perform(job)
  748. refute User.get_by_id(user.id)
  749. end
  750. test "it deletes a user, all follow relationships and all activities", %{user: user} do
  751. follower = insert(:user)
  752. {:ok, follower} = User.follow(follower, user)
  753. object = insert(:note, user: user)
  754. activity = insert(:note_activity, user: user, note: object)
  755. object_two = insert(:note, user: follower)
  756. activity_two = insert(:note_activity, user: follower, note: object_two)
  757. {:ok, like, _} = CommonAPI.favorite(activity_two.id, user)
  758. {:ok, like_two, _} = CommonAPI.favorite(activity.id, follower)
  759. {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
  760. {:ok, job} = User.delete(user)
  761. {:ok, _user} = ObanHelpers.perform(job)
  762. follower = User.get_cached_by_id(follower.id)
  763. refute User.following?(follower, user)
  764. refute User.get_by_id(user.id)
  765. assert {:ok, nil} == Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  766. user_activities =
  767. user.ap_id
  768. |> Activity.Queries.by_actor()
  769. |> Repo.all()
  770. |> Enum.map(fn act -> act.data["type"] end)
  771. assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
  772. refute Activity.get_by_id(activity.id)
  773. refute Activity.get_by_id(like.id)
  774. refute Activity.get_by_id(like_two.id)
  775. refute Activity.get_by_id(repeat.id)
  776. end
  777. test_with_mock "it sends out User Delete activity",
  778. %{user: user},
  779. Pleroma.Web.ActivityPub.Publisher,
  780. [:passthrough],
  781. [] do
  782. Pleroma.Config.put([:instance, :federating], true)
  783. {:ok, follower} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
  784. {:ok, _} = User.follow(follower, user)
  785. {:ok, job} = User.delete(user)
  786. {:ok, _user} = ObanHelpers.perform(job)
  787. assert ObanHelpers.member?(
  788. %{
  789. "op" => "publish_one",
  790. "params" => %{
  791. "inbox" => "http://mastodon.example.org/inbox",
  792. "id" => "pleroma:fakeid"
  793. }
  794. },
  795. all_enqueued(worker: Pleroma.Workers.PublisherWorker)
  796. )
  797. end
  798. end
  799. test "get_public_key_for_ap_id fetches a user that's not in the db" do
  800. assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
  801. end
  802. describe "insert or update a user from given data" do
  803. test "with normal data" do
  804. user = insert(:user, %{nickname: "nick@name.de"})
  805. data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
  806. assert {:ok, %User{}} = User.insert_or_update_user(data)
  807. end
  808. test "with overly long fields" do
  809. current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255)
  810. user = insert(:user, nickname: "nickname@supergood.domain")
  811. data = %{
  812. ap_id: user.ap_id,
  813. name: user.name,
  814. nickname: user.nickname,
  815. fields: [
  816. %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}
  817. ]
  818. }
  819. assert {:ok, %User{}} = User.insert_or_update_user(data)
  820. end
  821. test "with an overly long bio" do
  822. current_max_length = Pleroma.Config.get([:instance, :user_bio_length], 5000)
  823. user = insert(:user, nickname: "nickname@supergood.domain")
  824. data = %{
  825. ap_id: user.ap_id,
  826. name: user.name,
  827. nickname: user.nickname,
  828. bio: String.duplicate("h", current_max_length + 1),
  829. info: %{}
  830. }
  831. assert {:ok, %User{}} = User.insert_or_update_user(data)
  832. end
  833. test "with an overly long display name" do
  834. current_max_length = Pleroma.Config.get([:instance, :user_name_length], 100)
  835. user = insert(:user, nickname: "nickname@supergood.domain")
  836. data = %{
  837. ap_id: user.ap_id,
  838. name: String.duplicate("h", current_max_length + 1),
  839. nickname: user.nickname,
  840. info: %{}
  841. }
  842. assert {:ok, %User{}} = User.insert_or_update_user(data)
  843. end
  844. end
  845. describe "per-user rich-text filtering" do
  846. test "html_filter_policy returns default policies, when rich-text is enabled" do
  847. user = insert(:user)
  848. assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
  849. end
  850. test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
  851. user = insert(:user, no_rich_text: true)
  852. assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
  853. end
  854. end
  855. describe "caching" do
  856. test "invalidate_cache works" do
  857. user = insert(:user)
  858. _user_info = User.get_cached_user_info(user)
  859. User.invalidate_cache(user)
  860. {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  861. {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
  862. {:ok, nil} = Cachex.get(:user_cache, "user_info:#{user.id}")
  863. end
  864. test "User.delete() plugs any possible zombie objects" do
  865. user = insert(:user)
  866. {:ok, job} = User.delete(user)
  867. {:ok, _} = ObanHelpers.perform(job)
  868. {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  869. assert cached_user != user
  870. {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
  871. assert cached_user != user
  872. end
  873. end
  874. test "auth_active?/1 works correctly" do
  875. Pleroma.Config.put([:instance, :account_activation_required], true)
  876. local_user = insert(:user, local: true, confirmation_pending: true)
  877. confirmed_user = insert(:user, local: true, confirmation_pending: false)
  878. remote_user = insert(:user, local: false)
  879. refute User.auth_active?(local_user)
  880. assert User.auth_active?(confirmed_user)
  881. assert User.auth_active?(remote_user)
  882. end
  883. describe "superuser?/1" do
  884. test "returns false for unprivileged users" do
  885. user = insert(:user, local: true)
  886. refute User.superuser?(user)
  887. end
  888. test "returns false for remote users" do
  889. user = insert(:user, local: false)
  890. remote_admin_user = insert(:user, local: false, is_admin: true)
  891. refute User.superuser?(user)
  892. refute User.superuser?(remote_admin_user)
  893. end
  894. test "returns true for local moderators" do
  895. user = insert(:user, local: true, is_moderator: true)
  896. assert User.superuser?(user)
  897. end
  898. test "returns true for local admins" do
  899. user = insert(:user, local: true, is_admin: true)
  900. assert User.superuser?(user)
  901. end
  902. end
  903. describe "invisible?/1" do
  904. test "returns true for an invisible user" do
  905. user = insert(:user, local: true, invisible: true)
  906. assert User.invisible?(user)
  907. end
  908. test "returns false for a non-invisible user" do
  909. user = insert(:user, local: true)
  910. refute User.invisible?(user)
  911. end
  912. end
  913. describe "visible_for?/2" do
  914. test "returns true when the account is itself" do
  915. user = insert(:user, local: true)
  916. assert User.visible_for?(user, user)
  917. end
  918. test "returns false when the account is unauthenticated and auth is required" do
  919. Pleroma.Config.put([:instance, :account_activation_required], true)
  920. user = insert(:user, local: true, confirmation_pending: true)
  921. other_user = insert(:user, local: true)
  922. refute User.visible_for?(user, other_user)
  923. end
  924. test "returns true when the account is unauthenticated and auth is not required" do
  925. user = insert(:user, local: true, confirmation_pending: true)
  926. other_user = insert(:user, local: true)
  927. assert User.visible_for?(user, other_user)
  928. end
  929. test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
  930. Pleroma.Config.put([:instance, :account_activation_required], true)
  931. user = insert(:user, local: true, confirmation_pending: true)
  932. other_user = insert(:user, local: true, is_admin: true)
  933. assert User.visible_for?(user, other_user)
  934. end
  935. end
  936. describe "parse_bio/2" do
  937. test "preserves hosts in user links text" do
  938. remote_user = insert(:user, local: false, nickname: "nick@domain.com")
  939. user = insert(:user)
  940. bio = "A.k.a. @nick@domain.com"
  941. expected_text =
  942. ~s(A.k.a. <span class="h-card"><a data-user="#{remote_user.id}" class="u-url mention" href="#{
  943. remote_user.ap_id
  944. }" rel="ugc">@<span>nick@domain.com</span></a></span>)
  945. assert expected_text == User.parse_bio(bio, user)
  946. end
  947. test "Adds rel=me on linkbacked urls" do
  948. user = insert(:user, ap_id: "https://social.example.org/users/lain")
  949. bio = "http://example.com/rel_me/null"
  950. expected_text = "<a href=\"#{bio}\">#{bio}</a>"
  951. assert expected_text == User.parse_bio(bio, user)
  952. bio = "http://example.com/rel_me/link"
  953. expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
  954. assert expected_text == User.parse_bio(bio, user)
  955. bio = "http://example.com/rel_me/anchor"
  956. expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
  957. assert expected_text == User.parse_bio(bio, user)
  958. end
  959. end
  960. test "follower count is updated when a follower is blocked" do
  961. user = insert(:user)
  962. follower = insert(:user)
  963. follower2 = insert(:user)
  964. follower3 = insert(:user)
  965. {:ok, follower} = User.follow(follower, user)
  966. {:ok, _follower2} = User.follow(follower2, user)
  967. {:ok, _follower3} = User.follow(follower3, user)
  968. {:ok, user} = User.block(user, follower)
  969. assert User.user_info(user).follower_count == 2
  970. end
  971. describe "list_inactive_users_query/1" do
  972. defp days_ago(days) do
  973. NaiveDateTime.add(
  974. NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
  975. -days * 60 * 60 * 24,
  976. :second
  977. )
  978. end
  979. test "Users are inactive by default" do
  980. total = 10
  981. users =
  982. Enum.map(1..total, fn _ ->
  983. insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
  984. end)
  985. inactive_users_ids =
  986. Pleroma.User.list_inactive_users_query()
  987. |> Pleroma.Repo.all()
  988. |> Enum.map(& &1.id)
  989. Enum.each(users, fn user ->
  990. assert user.id in inactive_users_ids
  991. end)
  992. end
  993. test "Only includes users who has no recent activity" do
  994. total = 10
  995. users =
  996. Enum.map(1..total, fn _ ->
  997. insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
  998. end)
  999. {inactive, active} = Enum.split(users, trunc(total / 2))
  1000. Enum.map(active, fn user ->
  1001. to = Enum.random(users -- [user])
  1002. {:ok, _} =
  1003. CommonAPI.post(user, %{
  1004. "status" => "hey @#{to.nickname}"
  1005. })
  1006. end)
  1007. inactive_users_ids =
  1008. Pleroma.User.list_inactive_users_query()
  1009. |> Pleroma.Repo.all()
  1010. |> Enum.map(& &1.id)
  1011. Enum.each(active, fn user ->
  1012. refute user.id in inactive_users_ids
  1013. end)
  1014. Enum.each(inactive, fn user ->
  1015. assert user.id in inactive_users_ids
  1016. end)
  1017. end
  1018. test "Only includes users with no read notifications" do
  1019. total = 10
  1020. users =
  1021. Enum.map(1..total, fn _ ->
  1022. insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
  1023. end)
  1024. [sender | recipients] = users
  1025. {inactive, active} = Enum.split(recipients, trunc(total / 2))
  1026. Enum.each(recipients, fn to ->
  1027. {:ok, _} =
  1028. CommonAPI.post(sender, %{
  1029. "status" => "hey @#{to.nickname}"
  1030. })
  1031. {:ok, _} =
  1032. CommonAPI.post(sender, %{
  1033. "status" => "hey again @#{to.nickname}"
  1034. })
  1035. end)
  1036. Enum.each(active, fn user ->
  1037. [n1, _n2] = Pleroma.Notification.for_user(user)
  1038. {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
  1039. end)
  1040. inactive_users_ids =
  1041. Pleroma.User.list_inactive_users_query()
  1042. |> Pleroma.Repo.all()
  1043. |> Enum.map(& &1.id)
  1044. Enum.each(active, fn user ->
  1045. refute user.id in inactive_users_ids
  1046. end)
  1047. Enum.each(inactive, fn user ->
  1048. assert user.id in inactive_users_ids
  1049. end)
  1050. end
  1051. end
  1052. describe "toggle_confirmation/1" do
  1053. test "if user is confirmed" do
  1054. user = insert(:user, confirmation_pending: false)
  1055. {:ok, user} = User.toggle_confirmation(user)
  1056. assert user.confirmation_pending
  1057. assert user.confirmation_token
  1058. end
  1059. test "if user is unconfirmed" do
  1060. user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
  1061. {:ok, user} = User.toggle_confirmation(user)
  1062. refute user.confirmation_pending
  1063. refute user.confirmation_token
  1064. end
  1065. end
  1066. describe "ensure_keys_present" do
  1067. test "it creates keys for a user and stores them in info" do
  1068. user = insert(:user)
  1069. refute is_binary(user.keys)
  1070. {:ok, user} = User.ensure_keys_present(user)
  1071. assert is_binary(user.keys)
  1072. end
  1073. test "it doesn't create keys if there already are some" do
  1074. user = insert(:user, keys: "xxx")
  1075. {:ok, user} = User.ensure_keys_present(user)
  1076. assert user.keys == "xxx"
  1077. end
  1078. end
  1079. describe "get_ap_ids_by_nicknames" do
  1080. test "it returns a list of AP ids for a given set of nicknames" do
  1081. user = insert(:user)
  1082. user_two = insert(:user)
  1083. ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
  1084. assert length(ap_ids) == 2
  1085. assert user.ap_id in ap_ids
  1086. assert user_two.ap_id in ap_ids
  1087. end
  1088. end
  1089. describe "sync followers count" do
  1090. setup do
  1091. user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
  1092. user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
  1093. insert(:user, local: true)
  1094. insert(:user, local: false, deactivated: true)
  1095. {:ok, user1: user1, user2: user2}
  1096. end
  1097. test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
  1098. [fdb_user1] = User.external_users(limit: 1)
  1099. assert fdb_user1.ap_id
  1100. assert fdb_user1.ap_id == user1.ap_id
  1101. assert fdb_user1.id == user1.id
  1102. [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
  1103. assert fdb_user2.ap_id
  1104. assert fdb_user2.ap_id == user2.ap_id
  1105. assert fdb_user2.id == user2.id
  1106. assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
  1107. end
  1108. end
  1109. describe "set_info_cache/2" do
  1110. setup do
  1111. user = insert(:user)
  1112. {:ok, user: user}
  1113. end
  1114. test "update from args", %{user: user} do
  1115. User.set_info_cache(user, %{following_count: 15, follower_count: 18})
  1116. %{follower_count: followers, following_count: following} = User.get_cached_user_info(user)
  1117. assert followers == 18
  1118. assert following == 15
  1119. end
  1120. test "without args", %{user: user} do
  1121. User.set_info_cache(user, %{})
  1122. %{follower_count: followers, following_count: following} = User.get_cached_user_info(user)
  1123. assert followers == 0
  1124. assert following == 0
  1125. end
  1126. end
  1127. describe "user_info/2" do
  1128. setup do
  1129. user = insert(:user)
  1130. {:ok, user: user}
  1131. end
  1132. test "update from args", %{user: user} do
  1133. %{follower_count: followers, following_count: following} =
  1134. User.user_info(user, %{following_count: 15, follower_count: 18})
  1135. assert followers == 18
  1136. assert following == 15
  1137. end
  1138. test "without args", %{user: user} do
  1139. %{follower_count: followers, following_count: following} = User.user_info(user)
  1140. assert followers == 0
  1141. assert following == 0
  1142. end
  1143. end
  1144. describe "is_internal_user?/1" do
  1145. test "non-internal user returns false" do
  1146. user = insert(:user)
  1147. refute User.is_internal_user?(user)
  1148. end
  1149. test "user with no nickname returns true" do
  1150. user = insert(:user, %{nickname: nil})
  1151. assert User.is_internal_user?(user)
  1152. end
  1153. test "user with internal-prefixed nickname returns true" do
  1154. user = insert(:user, %{nickname: "internal.test"})
  1155. assert User.is_internal_user?(user)
  1156. end
  1157. end
  1158. describe "update_and_set_cache/1" do
  1159. test "returns error when user is stale instead Ecto.StaleEntryError" do
  1160. user = insert(:user)
  1161. changeset = Ecto.Changeset.change(user, bio: "test")
  1162. Repo.delete(user)
  1163. assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
  1164. User.update_and_set_cache(changeset)
  1165. end
  1166. test "performs update cache if user updated" do
  1167. user = insert(:user)
  1168. assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1169. changeset = Ecto.Changeset.change(user, bio: "test-bio")
  1170. assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
  1171. assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1172. assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
  1173. end
  1174. end
  1175. describe "following/followers synchronization" do
  1176. clear_config([:instance, :external_user_synchronization])
  1177. test "updates the counters normally on following/getting a follow when disabled" do
  1178. Pleroma.Config.put([:instance, :external_user_synchronization], false)
  1179. user = insert(:user)
  1180. other_user =
  1181. insert(:user,
  1182. local: false,
  1183. follower_address: "http://localhost:4001/users/masto_closed/followers",
  1184. following_address: "http://localhost:4001/users/masto_closed/following",
  1185. ap_enabled: true
  1186. )
  1187. assert User.user_info(other_user).following_count == 0
  1188. assert User.user_info(other_user).follower_count == 0
  1189. {:ok, user} = Pleroma.User.follow(user, other_user)
  1190. other_user = Pleroma.User.get_by_id(other_user.id)
  1191. assert User.user_info(user).following_count == 1
  1192. assert User.user_info(other_user).follower_count == 1
  1193. end
  1194. test "syncronizes the counters with the remote instance for the followed when enabled" do
  1195. Pleroma.Config.put([:instance, :external_user_synchronization], false)
  1196. user = insert(:user)
  1197. other_user =
  1198. insert(:user,
  1199. local: false,
  1200. follower_address: "http://localhost:4001/users/masto_closed/followers",
  1201. following_address: "http://localhost:4001/users/masto_closed/following",
  1202. ap_enabled: true
  1203. )
  1204. assert User.user_info(other_user).following_count == 0
  1205. assert User.user_info(other_user).follower_count == 0
  1206. Pleroma.Config.put([:instance, :external_user_synchronization], true)
  1207. {:ok, _user} = User.follow(user, other_user)
  1208. other_user = User.get_by_id(other_user.id)
  1209. assert User.user_info(other_user).follower_count == 437
  1210. end
  1211. test "syncronizes the counters with the remote instance for the follower when enabled" do
  1212. Pleroma.Config.put([:instance, :external_user_synchronization], false)
  1213. user = insert(:user)
  1214. other_user =
  1215. insert(:user,
  1216. local: false,
  1217. follower_address: "http://localhost:4001/users/masto_closed/followers",
  1218. following_address: "http://localhost:4001/users/masto_closed/following",
  1219. ap_enabled: true
  1220. )
  1221. assert User.user_info(other_user).following_count == 0
  1222. assert User.user_info(other_user).follower_count == 0
  1223. Pleroma.Config.put([:instance, :external_user_synchronization], true)
  1224. {:ok, other_user} = User.follow(other_user, user)
  1225. assert User.user_info(other_user).following_count == 152
  1226. end
  1227. end
  1228. describe "change_email/2" do
  1229. setup do
  1230. [user: insert(:user)]
  1231. end
  1232. test "blank email returns error", %{user: user} do
  1233. assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
  1234. assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
  1235. end
  1236. test "non unique email returns error", %{user: user} do
  1237. %{email: email} = insert(:user)
  1238. assert {:error, %{errors: [email: {"has already been taken", _}]}} =
  1239. User.change_email(user, email)
  1240. end
  1241. test "invalid email returns error", %{user: user} do
  1242. assert {:error, %{errors: [email: {"has invalid format", _}]}} =
  1243. User.change_email(user, "cofe")
  1244. end
  1245. test "changes email", %{user: user} do
  1246. assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
  1247. end
  1248. end
  1249. describe "get_cached_by_nickname_or_id" do
  1250. setup do
  1251. limit_to_local_content = Pleroma.Config.get([:instance, :limit_to_local_content])
  1252. local_user = insert(:user)
  1253. remote_user = insert(:user, nickname: "nickname@example.com", local: false)
  1254. on_exit(fn ->
  1255. Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local_content)
  1256. end)
  1257. [local_user: local_user, remote_user: remote_user]
  1258. end
  1259. test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
  1260. remote_user: remote_user
  1261. } do
  1262. Pleroma.Config.put([:instance, :limit_to_local_content], false)
  1263. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1264. Pleroma.Config.put([:instance, :limit_to_local_content], true)
  1265. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1266. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1267. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1268. end
  1269. test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
  1270. %{remote_user: remote_user} do
  1271. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1272. assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
  1273. end
  1274. test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
  1275. %{remote_user: remote_user, local_user: local_user} do
  1276. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1277. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
  1278. end
  1279. test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
  1280. %{remote_user: remote_user} do
  1281. Pleroma.Config.put([:instance, :limit_to_local_content], true)
  1282. assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
  1283. end
  1284. test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
  1285. %{local_user: local_user} do
  1286. Pleroma.Config.put([:instance, :limit_to_local_content], false)
  1287. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1288. Pleroma.Config.put([:instance, :limit_to_local_content], true)
  1289. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1290. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1291. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1292. end
  1293. end
  1294. describe "update_email_notifications/2" do
  1295. setup do
  1296. user = insert(:user, email_notifications: %{"digest" => true})
  1297. {:ok, user: user}
  1298. end
  1299. test "Notifications are updated", %{user: user} do
  1300. true = user.email_notifications["digest"]
  1301. assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
  1302. assert result.email_notifications["digest"] == false
  1303. end
  1304. end
  1305. end