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.

1862 lines
56KB

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