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.

1789 lines
54KB

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