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.

1779 lines
53KB

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