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.

1753 lines
53KB

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