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.

1814 lines
55KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.UserTest do
  5. alias Pleroma.Activity
  6. alias Pleroma.Builders.UserBuilder
  7. alias Pleroma.Object
  8. alias Pleroma.Repo
  9. alias Pleroma.Tests.ObanHelpers
  10. alias Pleroma.User
  11. alias Pleroma.Web.ActivityPub.ActivityPub
  12. alias Pleroma.Web.CommonAPI
  13. use Pleroma.DataCase
  14. use Oban.Testing, repo: Pleroma.Repo
  15. import Mock
  16. import Pleroma.Factory
  17. import ExUnit.CaptureLog
  18. setup_all do
  19. Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
  20. :ok
  21. end
  22. 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_relations_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_relations_ap_ids = User.outgoing_relations_ap_ids(user, rel_types)
  101. assert ap_ids_by_rel ==
  102. Enum.into(outgoing_relations_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, "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
  225. setting = Pleroma.Config.get([:instance, :external_user_synchronization])
  226. on_exit(fn ->
  227. Pleroma.Config.put([:instance, :external_user_synchronization], setting)
  228. end)
  229. :ok
  230. end
  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, "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, "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, "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. clear_config([:instance, :autofollowed_nicknames])
  290. clear_config([:instance, :welcome_message])
  291. 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. test "it requires an email, name, nickname and password, bio is optional" do
  316. @full_user_data
  317. |> Map.keys()
  318. |> Enum.each(fn key ->
  319. params = Map.delete(@full_user_data, key)
  320. changeset = User.register_changeset(%User{}, params)
  321. assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
  322. end)
  323. end
  324. test "it restricts certain nicknames" do
  325. [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
  326. assert is_bitstring(restricted_name)
  327. params =
  328. @full_user_data
  329. |> Map.put(:nickname, restricted_name)
  330. changeset = User.register_changeset(%User{}, params)
  331. refute changeset.valid?
  332. end
  333. test "it sets the password_hash and ap_id" do
  334. changeset = User.register_changeset(%User{}, @full_user_data)
  335. assert changeset.valid?
  336. assert is_binary(changeset.changes[:password_hash])
  337. assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
  338. assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
  339. end
  340. end
  341. describe "user registration, with :account_activation_required" do
  342. @full_user_data %{
  343. bio: "A guy",
  344. name: "my name",
  345. nickname: "nick",
  346. password: "test",
  347. password_confirmation: "test",
  348. email: "email@example.com"
  349. }
  350. clear_config([:instance, :account_activation_required]) do
  351. Pleroma.Config.put([:instance, :account_activation_required], true)
  352. end
  353. test "it creates unconfirmed user" do
  354. changeset = User.register_changeset(%User{}, @full_user_data)
  355. assert changeset.valid?
  356. {:ok, user} = Repo.insert(changeset)
  357. assert user.confirmation_pending
  358. assert user.confirmation_token
  359. end
  360. test "it creates confirmed user if :confirmed option is given" do
  361. changeset = User.register_changeset(%User{}, @full_user_data, need_confirmation: false)
  362. assert changeset.valid?
  363. {:ok, user} = Repo.insert(changeset)
  364. refute user.confirmation_pending
  365. refute user.confirmation_token
  366. end
  367. end
  368. describe "get_or_fetch/1" do
  369. test "gets an existing user by nickname" do
  370. user = insert(:user)
  371. {:ok, fetched_user} = User.get_or_fetch(user.nickname)
  372. assert user == fetched_user
  373. end
  374. test "gets an existing user by ap_id" do
  375. ap_id = "http://mastodon.example.org/users/admin"
  376. user =
  377. insert(
  378. :user,
  379. local: false,
  380. nickname: "admin@mastodon.example.org",
  381. ap_id: ap_id
  382. )
  383. {:ok, fetched_user} = User.get_or_fetch(ap_id)
  384. freshed_user = refresh_record(user)
  385. assert freshed_user == fetched_user
  386. end
  387. end
  388. describe "fetching a user from nickname or trying to build one" do
  389. test "gets an existing user" do
  390. user = insert(:user)
  391. {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
  392. assert user == fetched_user
  393. end
  394. test "gets an existing user, case insensitive" do
  395. user = insert(:user, nickname: "nick")
  396. {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
  397. assert user == fetched_user
  398. end
  399. test "gets an existing user by fully qualified nickname" do
  400. user = insert(:user)
  401. {:ok, fetched_user} =
  402. User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  403. assert user == fetched_user
  404. end
  405. test "gets an existing user by fully qualified nickname, case insensitive" do
  406. user = insert(:user, nickname: "nick")
  407. casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  408. {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
  409. assert user == fetched_user
  410. end
  411. test "returns nil if no user could be fetched" do
  412. {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
  413. assert fetched_user == "not found nonexistant@social.heldscal.la"
  414. end
  415. test "returns nil for nonexistant local user" do
  416. {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
  417. assert fetched_user == "not found nonexistant"
  418. end
  419. test "updates an existing user, if stale" do
  420. a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
  421. orig_user =
  422. insert(
  423. :user,
  424. local: false,
  425. nickname: "admin@mastodon.example.org",
  426. ap_id: "http://mastodon.example.org/users/admin",
  427. last_refreshed_at: a_week_ago
  428. )
  429. assert orig_user.last_refreshed_at == a_week_ago
  430. {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
  431. assert user.source_data["endpoints"]
  432. refute user.last_refreshed_at == orig_user.last_refreshed_at
  433. end
  434. end
  435. test "returns an ap_id for a user" do
  436. user = insert(:user)
  437. assert User.ap_id(user) ==
  438. Pleroma.Web.Router.Helpers.feed_url(
  439. Pleroma.Web.Endpoint,
  440. :feed_redirect,
  441. user.nickname
  442. )
  443. end
  444. test "returns an ap_followers link for a user" do
  445. user = insert(:user)
  446. assert User.ap_followers(user) ==
  447. Pleroma.Web.Router.Helpers.feed_url(
  448. Pleroma.Web.Endpoint,
  449. :feed_redirect,
  450. user.nickname
  451. ) <> "/followers"
  452. end
  453. describe "remote user creation changeset" do
  454. @valid_remote %{
  455. bio: "hello",
  456. name: "Someone",
  457. nickname: "a@b.de",
  458. ap_id: "http...",
  459. avatar: %{some: "avatar"}
  460. }
  461. clear_config([:instance, :user_bio_length])
  462. clear_config([:instance, :user_name_length])
  463. test "it confirms validity" do
  464. cs = User.remote_user_creation(@valid_remote)
  465. assert cs.valid?
  466. end
  467. test "it sets the follower_adress" do
  468. cs = User.remote_user_creation(@valid_remote)
  469. # remote users get a fake local follower address
  470. assert cs.changes.follower_address ==
  471. User.ap_followers(%User{nickname: @valid_remote[:nickname]})
  472. end
  473. test "it enforces the fqn format for nicknames" do
  474. cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
  475. assert Ecto.Changeset.get_field(cs, :local) == false
  476. assert cs.changes.avatar
  477. refute cs.valid?
  478. end
  479. test "it has required fields" do
  480. [:name, :ap_id]
  481. |> Enum.each(fn field ->
  482. cs = User.remote_user_creation(Map.delete(@valid_remote, field))
  483. refute cs.valid?
  484. end)
  485. end
  486. end
  487. describe "followers and friends" do
  488. test "gets all followers for a given user" do
  489. user = insert(:user)
  490. follower_one = insert(:user)
  491. follower_two = insert(:user)
  492. not_follower = insert(:user)
  493. {:ok, follower_one} = User.follow(follower_one, user)
  494. {:ok, follower_two} = User.follow(follower_two, user)
  495. res = User.get_followers(user)
  496. assert Enum.member?(res, follower_one)
  497. assert Enum.member?(res, follower_two)
  498. refute Enum.member?(res, not_follower)
  499. end
  500. test "gets all friends (followed users) for a given user" do
  501. user = insert(:user)
  502. followed_one = insert(:user)
  503. followed_two = insert(:user)
  504. not_followed = insert(:user)
  505. {:ok, user} = User.follow(user, followed_one)
  506. {:ok, user} = User.follow(user, followed_two)
  507. res = User.get_friends(user)
  508. followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
  509. followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
  510. assert Enum.member?(res, followed_one)
  511. assert Enum.member?(res, followed_two)
  512. refute Enum.member?(res, not_followed)
  513. end
  514. end
  515. describe "updating note and follower count" do
  516. test "it sets the note_count property" do
  517. note = insert(:note)
  518. user = User.get_cached_by_ap_id(note.data["actor"])
  519. assert user.note_count == 0
  520. {:ok, user} = User.update_note_count(user)
  521. assert user.note_count == 1
  522. end
  523. test "it increases the note_count property" do
  524. note = insert(:note)
  525. user = User.get_cached_by_ap_id(note.data["actor"])
  526. assert user.note_count == 0
  527. {:ok, user} = User.increase_note_count(user)
  528. assert user.note_count == 1
  529. {:ok, user} = User.increase_note_count(user)
  530. assert user.note_count == 2
  531. end
  532. test "it decreases the note_count property" do
  533. note = insert(:note)
  534. user = User.get_cached_by_ap_id(note.data["actor"])
  535. assert user.note_count == 0
  536. {:ok, user} = User.increase_note_count(user)
  537. assert user.note_count == 1
  538. {:ok, user} = User.decrease_note_count(user)
  539. assert user.note_count == 0
  540. {:ok, user} = User.decrease_note_count(user)
  541. assert user.note_count == 0
  542. end
  543. test "it sets the follower_count property" do
  544. user = insert(:user)
  545. follower = insert(:user)
  546. User.follow(follower, user)
  547. assert user.follower_count == 0
  548. {:ok, user} = User.update_follower_count(user)
  549. assert user.follower_count == 1
  550. end
  551. end
  552. describe "follow_import" do
  553. test "it imports user followings from list" do
  554. [user1, user2, user3] = insert_list(3, :user)
  555. identifiers = [
  556. user2.ap_id,
  557. user3.nickname
  558. ]
  559. {:ok, job} = User.follow_import(user1, identifiers)
  560. result = ObanHelpers.perform(job)
  561. assert is_list(result)
  562. assert result == [user2, user3]
  563. end
  564. end
  565. describe "mutes" do
  566. test "it mutes people" do
  567. user = insert(:user)
  568. muted_user = insert(:user)
  569. refute User.mutes?(user, muted_user)
  570. refute User.muted_notifications?(user, muted_user)
  571. {:ok, _user_relationships} = User.mute(user, muted_user)
  572. assert User.mutes?(user, muted_user)
  573. assert User.muted_notifications?(user, muted_user)
  574. end
  575. test "it unmutes users" do
  576. user = insert(:user)
  577. muted_user = insert(:user)
  578. {:ok, _user_relationships} = User.mute(user, muted_user)
  579. {:ok, _user_mute} = User.unmute(user, muted_user)
  580. refute User.mutes?(user, muted_user)
  581. refute User.muted_notifications?(user, muted_user)
  582. end
  583. test "it mutes user without notifications" do
  584. user = insert(:user)
  585. muted_user = insert(:user)
  586. refute User.mutes?(user, muted_user)
  587. refute User.muted_notifications?(user, muted_user)
  588. {:ok, _user_relationships} = User.mute(user, muted_user, false)
  589. assert User.mutes?(user, muted_user)
  590. refute User.muted_notifications?(user, muted_user)
  591. end
  592. end
  593. describe "blocks" do
  594. test "it blocks people" do
  595. user = insert(:user)
  596. blocked_user = insert(:user)
  597. refute User.blocks?(user, blocked_user)
  598. {:ok, _user_relationship} = User.block(user, blocked_user)
  599. assert User.blocks?(user, blocked_user)
  600. end
  601. test "it unblocks users" do
  602. user = insert(:user)
  603. blocked_user = insert(:user)
  604. {:ok, _user_relationship} = User.block(user, blocked_user)
  605. {:ok, _user_block} = User.unblock(user, blocked_user)
  606. refute User.blocks?(user, blocked_user)
  607. end
  608. test "blocks tear down cyclical follow relationships" do
  609. blocker = insert(:user)
  610. blocked = insert(:user)
  611. {:ok, blocker} = User.follow(blocker, blocked)
  612. {:ok, blocked} = User.follow(blocked, blocker)
  613. assert User.following?(blocker, blocked)
  614. assert User.following?(blocked, blocker)
  615. {:ok, _user_relationship} = User.block(blocker, blocked)
  616. blocked = User.get_cached_by_id(blocked.id)
  617. assert User.blocks?(blocker, blocked)
  618. refute User.following?(blocker, blocked)
  619. refute User.following?(blocked, blocker)
  620. end
  621. test "blocks tear down blocker->blocked follow relationships" do
  622. blocker = insert(:user)
  623. blocked = insert(:user)
  624. {:ok, blocker} = User.follow(blocker, blocked)
  625. assert User.following?(blocker, blocked)
  626. refute User.following?(blocked, blocker)
  627. {:ok, _user_relationship} = User.block(blocker, blocked)
  628. blocked = User.get_cached_by_id(blocked.id)
  629. assert User.blocks?(blocker, blocked)
  630. refute User.following?(blocker, blocked)
  631. refute User.following?(blocked, blocker)
  632. end
  633. test "blocks tear down blocked->blocker follow relationships" do
  634. blocker = insert(:user)
  635. blocked = insert(:user)
  636. {:ok, blocked} = User.follow(blocked, blocker)
  637. refute User.following?(blocker, blocked)
  638. assert User.following?(blocked, blocker)
  639. {:ok, _user_relationship} = User.block(blocker, blocked)
  640. blocked = User.get_cached_by_id(blocked.id)
  641. assert User.blocks?(blocker, blocked)
  642. refute User.following?(blocker, blocked)
  643. refute User.following?(blocked, blocker)
  644. end
  645. test "blocks tear down blocked->blocker subscription relationships" do
  646. blocker = insert(:user)
  647. blocked = insert(:user)
  648. {:ok, _subscription} = User.subscribe(blocked, blocker)
  649. assert User.subscribed_to?(blocked, blocker)
  650. refute User.subscribed_to?(blocker, blocked)
  651. {:ok, _user_relationship} = User.block(blocker, blocked)
  652. assert User.blocks?(blocker, blocked)
  653. refute User.subscribed_to?(blocker, blocked)
  654. refute User.subscribed_to?(blocked, blocker)
  655. end
  656. end
  657. describe "domain blocking" do
  658. test "blocks domains" do
  659. user = insert(:user)
  660. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  661. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  662. assert User.blocks?(user, collateral_user)
  663. end
  664. test "does not block domain with same end" do
  665. user = insert(:user)
  666. collateral_user =
  667. insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
  668. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  669. refute User.blocks?(user, collateral_user)
  670. end
  671. test "does not block domain with same end if wildcard added" do
  672. user = insert(:user)
  673. collateral_user =
  674. insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
  675. {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
  676. refute User.blocks?(user, collateral_user)
  677. end
  678. test "blocks domain with wildcard for subdomain" do
  679. user = insert(:user)
  680. user_from_subdomain =
  681. insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
  682. user_with_two_subdomains =
  683. insert(:user, %{
  684. ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
  685. })
  686. user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  687. {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
  688. assert User.blocks?(user, user_from_subdomain)
  689. assert User.blocks?(user, user_with_two_subdomains)
  690. assert User.blocks?(user, user_domain)
  691. end
  692. test "unblocks domains" do
  693. user = insert(:user)
  694. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  695. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  696. {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
  697. refute User.blocks?(user, collateral_user)
  698. end
  699. test "follows take precedence over domain blocks" do
  700. user = insert(:user)
  701. good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
  702. {:ok, user} = User.block_domain(user, "meanies.social")
  703. {:ok, user} = User.follow(user, good_eggo)
  704. refute User.blocks?(user, good_eggo)
  705. end
  706. end
  707. describe "blocks_import" do
  708. test "it imports user blocks from list" do
  709. [user1, user2, user3] = insert_list(3, :user)
  710. identifiers = [
  711. user2.ap_id,
  712. user3.nickname
  713. ]
  714. {:ok, job} = User.blocks_import(user1, identifiers)
  715. result = ObanHelpers.perform(job)
  716. assert is_list(result)
  717. assert result == [user2, user3]
  718. end
  719. end
  720. describe "get_recipients_from_activity" do
  721. test "get recipients" do
  722. actor = insert(:user)
  723. user = insert(:user, local: true)
  724. user_two = insert(:user, local: false)
  725. addressed = insert(:user, local: true)
  726. addressed_remote = insert(:user, local: false)
  727. {:ok, activity} =
  728. CommonAPI.post(actor, %{
  729. "status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
  730. })
  731. assert Enum.map([actor, addressed], & &1.ap_id) --
  732. Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
  733. {:ok, user} = User.follow(user, actor)
  734. {:ok, _user_two} = User.follow(user_two, actor)
  735. recipients = User.get_recipients_from_activity(activity)
  736. assert length(recipients) == 3
  737. assert user in recipients
  738. assert addressed in recipients
  739. end
  740. test "has following" do
  741. actor = insert(:user)
  742. user = insert(:user)
  743. user_two = insert(:user)
  744. addressed = insert(:user, local: true)
  745. {:ok, activity} =
  746. CommonAPI.post(actor, %{
  747. "status" => "hey @#{addressed.nickname}"
  748. })
  749. assert Enum.map([actor, addressed], & &1.ap_id) --
  750. Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
  751. {:ok, _actor} = User.follow(actor, user)
  752. {:ok, _actor} = User.follow(actor, user_two)
  753. recipients = User.get_recipients_from_activity(activity)
  754. assert length(recipients) == 2
  755. assert addressed in recipients
  756. end
  757. end
  758. describe ".deactivate" do
  759. test "can de-activate then re-activate a user" do
  760. user = insert(:user)
  761. assert false == user.deactivated
  762. {:ok, user} = User.deactivate(user)
  763. assert true == user.deactivated
  764. {:ok, user} = User.deactivate(user, false)
  765. assert false == user.deactivated
  766. end
  767. test "hide a user from followers" do
  768. user = insert(:user)
  769. user2 = insert(:user)
  770. {:ok, user} = User.follow(user, user2)
  771. {:ok, _user} = User.deactivate(user)
  772. user2 = User.get_cached_by_id(user2.id)
  773. assert user2.follower_count == 0
  774. assert [] = User.get_followers(user2)
  775. end
  776. test "hide a user from friends" do
  777. user = insert(:user)
  778. user2 = insert(:user)
  779. {:ok, user2} = User.follow(user2, user)
  780. assert user2.following_count == 1
  781. assert User.following_count(user2) == 1
  782. {:ok, _user} = User.deactivate(user)
  783. user2 = User.get_cached_by_id(user2.id)
  784. assert refresh_record(user2).following_count == 0
  785. assert user2.following_count == 0
  786. assert User.following_count(user2) == 0
  787. assert [] = User.get_friends(user2)
  788. end
  789. test "hide a user's statuses from timelines and notifications" do
  790. user = insert(:user)
  791. user2 = insert(:user)
  792. {:ok, user2} = User.follow(user2, user)
  793. {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}"})
  794. activity = Repo.preload(activity, :bookmark)
  795. [notification] = Pleroma.Notification.for_user(user2)
  796. assert notification.activity.id == activity.id
  797. assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
  798. assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
  799. ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
  800. "user" => user2
  801. })
  802. {:ok, _user} = User.deactivate(user)
  803. assert [] == ActivityPub.fetch_public_activities(%{})
  804. assert [] == Pleroma.Notification.for_user(user2)
  805. assert [] ==
  806. ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
  807. "user" => user2
  808. })
  809. end
  810. end
  811. describe "delete" do
  812. setup do
  813. {:ok, user} = insert(:user) |> User.set_cache()
  814. [user: user]
  815. end
  816. clear_config([:instance, :federating])
  817. test ".delete_user_activities deletes all create activities", %{user: user} do
  818. {:ok, activity} = CommonAPI.post(user, %{"status" => "2hu"})
  819. User.delete_user_activities(user)
  820. # TODO: Remove favorites, repeats, delete activities.
  821. refute Activity.get_by_id(activity.id)
  822. end
  823. test "it deletes deactivated user" do
  824. {:ok, user} = insert(:user, deactivated: true) |> User.set_cache()
  825. {:ok, job} = User.delete(user)
  826. {:ok, _user} = ObanHelpers.perform(job)
  827. refute User.get_by_id(user.id)
  828. end
  829. test "it deletes a user, all follow relationships and all activities", %{user: user} do
  830. follower = insert(:user)
  831. {:ok, follower} = User.follow(follower, user)
  832. object = insert(:note, user: user)
  833. activity = insert(:note_activity, user: user, note: object)
  834. object_two = insert(:note, user: follower)
  835. activity_two = insert(:note_activity, user: follower, note: object_two)
  836. {:ok, like, _} = CommonAPI.favorite(activity_two.id, user)
  837. {:ok, like_two, _} = CommonAPI.favorite(activity.id, follower)
  838. {:ok, repeat, _} = CommonAPI.repeat(activity_two.id, user)
  839. {:ok, job} = User.delete(user)
  840. {:ok, _user} = ObanHelpers.perform(job)
  841. follower = User.get_cached_by_id(follower.id)
  842. refute User.following?(follower, user)
  843. refute User.get_by_id(user.id)
  844. assert {:ok, nil} == Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  845. user_activities =
  846. user.ap_id
  847. |> Activity.Queries.by_actor()
  848. |> Repo.all()
  849. |> Enum.map(fn act -> act.data["type"] end)
  850. assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
  851. refute Activity.get_by_id(activity.id)
  852. refute Activity.get_by_id(like.id)
  853. refute Activity.get_by_id(like_two.id)
  854. refute Activity.get_by_id(repeat.id)
  855. end
  856. test_with_mock "it sends out User Delete activity",
  857. %{user: user},
  858. Pleroma.Web.ActivityPub.Publisher,
  859. [:passthrough],
  860. [] do
  861. Pleroma.Config.put([:instance, :federating], true)
  862. {:ok, follower} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
  863. {:ok, _} = User.follow(follower, user)
  864. {:ok, job} = User.delete(user)
  865. {:ok, _user} = ObanHelpers.perform(job)
  866. assert ObanHelpers.member?(
  867. %{
  868. "op" => "publish_one",
  869. "params" => %{
  870. "inbox" => "http://mastodon.example.org/inbox",
  871. "id" => "pleroma:fakeid"
  872. }
  873. },
  874. all_enqueued(worker: Pleroma.Workers.PublisherWorker)
  875. )
  876. end
  877. end
  878. test "get_public_key_for_ap_id fetches a user that's not in the db" do
  879. assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
  880. end
  881. describe "insert or update a user from given data" do
  882. test "with normal data" do
  883. user = insert(:user, %{nickname: "nick@name.de"})
  884. data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
  885. assert {:ok, %User{}} = User.insert_or_update_user(data)
  886. end
  887. test "with overly long fields" do
  888. current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255)
  889. user = insert(:user, nickname: "nickname@supergood.domain")
  890. data = %{
  891. ap_id: user.ap_id,
  892. name: user.name,
  893. nickname: user.nickname,
  894. fields: [
  895. %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}
  896. ]
  897. }
  898. assert {:ok, %User{}} = User.insert_or_update_user(data)
  899. end
  900. test "with an overly long bio" do
  901. current_max_length = Pleroma.Config.get([:instance, :user_bio_length], 5000)
  902. user = insert(:user, nickname: "nickname@supergood.domain")
  903. data = %{
  904. ap_id: user.ap_id,
  905. name: user.name,
  906. nickname: user.nickname,
  907. bio: String.duplicate("h", current_max_length + 1)
  908. }
  909. assert {:ok, %User{}} = User.insert_or_update_user(data)
  910. end
  911. test "with an overly long display name" do
  912. current_max_length = Pleroma.Config.get([:instance, :user_name_length], 100)
  913. user = insert(:user, nickname: "nickname@supergood.domain")
  914. data = %{
  915. ap_id: user.ap_id,
  916. name: String.duplicate("h", current_max_length + 1),
  917. nickname: user.nickname
  918. }
  919. assert {:ok, %User{}} = User.insert_or_update_user(data)
  920. end
  921. end
  922. describe "per-user rich-text filtering" do
  923. test "html_filter_policy returns default policies, when rich-text is enabled" do
  924. user = insert(:user)
  925. assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
  926. end
  927. test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
  928. user = insert(:user, no_rich_text: true)
  929. assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
  930. end
  931. end
  932. describe "caching" do
  933. test "invalidate_cache works" do
  934. user = insert(:user)
  935. User.set_cache(user)
  936. User.invalidate_cache(user)
  937. {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  938. {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
  939. end
  940. test "User.delete() plugs any possible zombie objects" do
  941. user = insert(:user)
  942. {:ok, job} = User.delete(user)
  943. {:ok, _} = ObanHelpers.perform(job)
  944. {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  945. assert cached_user != user
  946. {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
  947. assert cached_user != user
  948. end
  949. end
  950. test "auth_active?/1 works correctly" do
  951. Pleroma.Config.put([:instance, :account_activation_required], true)
  952. local_user = insert(:user, local: true, confirmation_pending: true)
  953. confirmed_user = insert(:user, local: true, confirmation_pending: false)
  954. remote_user = insert(:user, local: false)
  955. refute User.auth_active?(local_user)
  956. assert User.auth_active?(confirmed_user)
  957. assert User.auth_active?(remote_user)
  958. # also shows unactive for deactivated users
  959. deactivated_but_confirmed =
  960. insert(:user, local: true, confirmation_pending: false, deactivated: true)
  961. refute User.auth_active?(deactivated_but_confirmed)
  962. end
  963. describe "superuser?/1" do
  964. test "returns false for unprivileged users" do
  965. user = insert(:user, local: true)
  966. refute User.superuser?(user)
  967. end
  968. test "returns false for remote users" do
  969. user = insert(:user, local: false)
  970. remote_admin_user = insert(:user, local: false, is_admin: true)
  971. refute User.superuser?(user)
  972. refute User.superuser?(remote_admin_user)
  973. end
  974. test "returns true for local moderators" do
  975. user = insert(:user, local: true, is_moderator: true)
  976. assert User.superuser?(user)
  977. end
  978. test "returns true for local admins" do
  979. user = insert(:user, local: true, is_admin: true)
  980. assert User.superuser?(user)
  981. end
  982. end
  983. describe "invisible?/1" do
  984. test "returns true for an invisible user" do
  985. user = insert(:user, local: true, invisible: true)
  986. assert User.invisible?(user)
  987. end
  988. test "returns false for a non-invisible user" do
  989. user = insert(:user, local: true)
  990. refute User.invisible?(user)
  991. end
  992. end
  993. describe "visible_for?/2" do
  994. test "returns true when the account is itself" do
  995. user = insert(:user, local: true)
  996. assert User.visible_for?(user, user)
  997. end
  998. test "returns false when the account is unauthenticated and auth is required" do
  999. Pleroma.Config.put([:instance, :account_activation_required], true)
  1000. user = insert(:user, local: true, confirmation_pending: true)
  1001. other_user = insert(:user, local: true)
  1002. refute User.visible_for?(user, other_user)
  1003. end
  1004. test "returns true when the account is unauthenticated and auth is not required" do
  1005. user = insert(:user, local: true, confirmation_pending: true)
  1006. other_user = insert(:user, local: true)
  1007. assert User.visible_for?(user, other_user)
  1008. end
  1009. test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do
  1010. Pleroma.Config.put([:instance, :account_activation_required], true)
  1011. user = insert(:user, local: true, confirmation_pending: true)
  1012. other_user = insert(:user, local: true, is_admin: true)
  1013. assert User.visible_for?(user, other_user)
  1014. end
  1015. end
  1016. describe "parse_bio/2" do
  1017. test "preserves hosts in user links text" do
  1018. remote_user = insert(:user, local: false, nickname: "nick@domain.com")
  1019. user = insert(:user)
  1020. bio = "A.k.a. @nick@domain.com"
  1021. expected_text =
  1022. ~s(A.k.a. <span class="h-card"><a data-user="#{remote_user.id}" class="u-url mention" href="#{
  1023. remote_user.ap_id
  1024. }" rel="ugc">@<span>nick@domain.com</span></a></span>)
  1025. assert expected_text == User.parse_bio(bio, user)
  1026. end
  1027. test "Adds rel=me on linkbacked urls" do
  1028. user = insert(:user, ap_id: "https://social.example.org/users/lain")
  1029. bio = "http://example.com/rel_me/null"
  1030. expected_text = "<a href=\"#{bio}\">#{bio}</a>"
  1031. assert expected_text == User.parse_bio(bio, user)
  1032. bio = "http://example.com/rel_me/link"
  1033. expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
  1034. assert expected_text == User.parse_bio(bio, user)
  1035. bio = "http://example.com/rel_me/anchor"
  1036. expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
  1037. assert expected_text == User.parse_bio(bio, user)
  1038. end
  1039. end
  1040. test "follower count is updated when a follower is blocked" do
  1041. user = insert(:user)
  1042. follower = insert(:user)
  1043. follower2 = insert(:user)
  1044. follower3 = insert(:user)
  1045. {:ok, follower} = User.follow(follower, user)
  1046. {:ok, _follower2} = User.follow(follower2, user)
  1047. {:ok, _follower3} = User.follow(follower3, user)
  1048. {:ok, _user_relationship} = User.block(user, follower)
  1049. user = refresh_record(user)
  1050. assert user.follower_count == 2
  1051. end
  1052. describe "list_inactive_users_query/1" do
  1053. defp days_ago(days) do
  1054. NaiveDateTime.add(
  1055. NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
  1056. -days * 60 * 60 * 24,
  1057. :second
  1058. )
  1059. end
  1060. test "Users are inactive by default" do
  1061. total = 10
  1062. users =
  1063. Enum.map(1..total, fn _ ->
  1064. insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
  1065. end)
  1066. inactive_users_ids =
  1067. Pleroma.User.list_inactive_users_query()
  1068. |> Pleroma.Repo.all()
  1069. |> Enum.map(& &1.id)
  1070. Enum.each(users, fn user ->
  1071. assert user.id in inactive_users_ids
  1072. end)
  1073. end
  1074. test "Only includes users who has no recent activity" do
  1075. total = 10
  1076. users =
  1077. Enum.map(1..total, fn _ ->
  1078. insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
  1079. end)
  1080. {inactive, active} = Enum.split(users, trunc(total / 2))
  1081. Enum.map(active, fn user ->
  1082. to = Enum.random(users -- [user])
  1083. {:ok, _} =
  1084. CommonAPI.post(user, %{
  1085. "status" => "hey @#{to.nickname}"
  1086. })
  1087. end)
  1088. inactive_users_ids =
  1089. Pleroma.User.list_inactive_users_query()
  1090. |> Pleroma.Repo.all()
  1091. |> Enum.map(& &1.id)
  1092. Enum.each(active, fn user ->
  1093. refute user.id in inactive_users_ids
  1094. end)
  1095. Enum.each(inactive, fn user ->
  1096. assert user.id in inactive_users_ids
  1097. end)
  1098. end
  1099. test "Only includes users with no read notifications" do
  1100. total = 10
  1101. users =
  1102. Enum.map(1..total, fn _ ->
  1103. insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false)
  1104. end)
  1105. [sender | recipients] = users
  1106. {inactive, active} = Enum.split(recipients, trunc(total / 2))
  1107. Enum.each(recipients, fn to ->
  1108. {:ok, _} =
  1109. CommonAPI.post(sender, %{
  1110. "status" => "hey @#{to.nickname}"
  1111. })
  1112. {:ok, _} =
  1113. CommonAPI.post(sender, %{
  1114. "status" => "hey again @#{to.nickname}"
  1115. })
  1116. end)
  1117. Enum.each(active, fn user ->
  1118. [n1, _n2] = Pleroma.Notification.for_user(user)
  1119. {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
  1120. end)
  1121. inactive_users_ids =
  1122. Pleroma.User.list_inactive_users_query()
  1123. |> Pleroma.Repo.all()
  1124. |> Enum.map(& &1.id)
  1125. Enum.each(active, fn user ->
  1126. refute user.id in inactive_users_ids
  1127. end)
  1128. Enum.each(inactive, fn user ->
  1129. assert user.id in inactive_users_ids
  1130. end)
  1131. end
  1132. end
  1133. describe "toggle_confirmation/1" do
  1134. test "if user is confirmed" do
  1135. user = insert(:user, confirmation_pending: false)
  1136. {:ok, user} = User.toggle_confirmation(user)
  1137. assert user.confirmation_pending
  1138. assert user.confirmation_token
  1139. end
  1140. test "if user is unconfirmed" do
  1141. user = insert(:user, confirmation_pending: true, confirmation_token: "some token")
  1142. {:ok, user} = User.toggle_confirmation(user)
  1143. refute user.confirmation_pending
  1144. refute user.confirmation_token
  1145. end
  1146. end
  1147. describe "ensure_keys_present" do
  1148. test "it creates keys for a user and stores them in info" do
  1149. user = insert(:user)
  1150. refute is_binary(user.keys)
  1151. {:ok, user} = User.ensure_keys_present(user)
  1152. assert is_binary(user.keys)
  1153. end
  1154. test "it doesn't create keys if there already are some" do
  1155. user = insert(:user, keys: "xxx")
  1156. {:ok, user} = User.ensure_keys_present(user)
  1157. assert user.keys == "xxx"
  1158. end
  1159. end
  1160. describe "get_ap_ids_by_nicknames" do
  1161. test "it returns a list of AP ids for a given set of nicknames" do
  1162. user = insert(:user)
  1163. user_two = insert(:user)
  1164. ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
  1165. assert length(ap_ids) == 2
  1166. assert user.ap_id in ap_ids
  1167. assert user_two.ap_id in ap_ids
  1168. end
  1169. end
  1170. describe "sync followers count" do
  1171. setup do
  1172. user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
  1173. user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
  1174. insert(:user, local: true)
  1175. insert(:user, local: false, deactivated: true)
  1176. {:ok, user1: user1, user2: user2}
  1177. end
  1178. test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
  1179. [fdb_user1] = User.external_users(limit: 1)
  1180. assert fdb_user1.ap_id
  1181. assert fdb_user1.ap_id == user1.ap_id
  1182. assert fdb_user1.id == user1.id
  1183. [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
  1184. assert fdb_user2.ap_id
  1185. assert fdb_user2.ap_id == user2.ap_id
  1186. assert fdb_user2.id == user2.id
  1187. assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
  1188. end
  1189. end
  1190. describe "is_internal_user?/1" do
  1191. test "non-internal user returns false" do
  1192. user = insert(:user)
  1193. refute User.is_internal_user?(user)
  1194. end
  1195. test "user with no nickname returns true" do
  1196. user = insert(:user, %{nickname: nil})
  1197. assert User.is_internal_user?(user)
  1198. end
  1199. test "user with internal-prefixed nickname returns true" do
  1200. user = insert(:user, %{nickname: "internal.test"})
  1201. assert User.is_internal_user?(user)
  1202. end
  1203. end
  1204. describe "update_and_set_cache/1" do
  1205. test "returns error when user is stale instead Ecto.StaleEntryError" do
  1206. user = insert(:user)
  1207. changeset = Ecto.Changeset.change(user, bio: "test")
  1208. Repo.delete(user)
  1209. assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
  1210. User.update_and_set_cache(changeset)
  1211. end
  1212. test "performs update cache if user updated" do
  1213. user = insert(:user)
  1214. assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1215. changeset = Ecto.Changeset.change(user, bio: "test-bio")
  1216. assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
  1217. assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1218. assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
  1219. end
  1220. end
  1221. describe "following/followers synchronization" do
  1222. clear_config([:instance, :external_user_synchronization])
  1223. test "updates the counters normally on following/getting a follow when disabled" 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. {:ok, user} = Pleroma.User.follow(user, other_user)
  1236. other_user = Pleroma.User.get_by_id(other_user.id)
  1237. assert user.following_count == 1
  1238. assert other_user.follower_count == 1
  1239. end
  1240. test "syncronizes the counters with the remote instance for the followed 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, _user} = User.follow(user, other_user)
  1254. other_user = User.get_by_id(other_user.id)
  1255. assert other_user.follower_count == 437
  1256. end
  1257. test "syncronizes the counters with the remote instance for the follower when enabled" do
  1258. Pleroma.Config.put([:instance, :external_user_synchronization], false)
  1259. user = insert(:user)
  1260. other_user =
  1261. insert(:user,
  1262. local: false,
  1263. follower_address: "http://localhost:4001/users/masto_closed/followers",
  1264. following_address: "http://localhost:4001/users/masto_closed/following",
  1265. ap_enabled: true
  1266. )
  1267. assert other_user.following_count == 0
  1268. assert other_user.follower_count == 0
  1269. Pleroma.Config.put([:instance, :external_user_synchronization], true)
  1270. {:ok, other_user} = User.follow(other_user, user)
  1271. assert other_user.following_count == 152
  1272. end
  1273. end
  1274. describe "change_email/2" do
  1275. setup do
  1276. [user: insert(:user)]
  1277. end
  1278. test "blank email returns error", %{user: user} do
  1279. assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
  1280. assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
  1281. end
  1282. test "non unique email returns error", %{user: user} do
  1283. %{email: email} = insert(:user)
  1284. assert {:error, %{errors: [email: {"has already been taken", _}]}} =
  1285. User.change_email(user, email)
  1286. end
  1287. test "invalid email returns error", %{user: user} do
  1288. assert {:error, %{errors: [email: {"has invalid format", _}]}} =
  1289. User.change_email(user, "cofe")
  1290. end
  1291. test "changes email", %{user: user} do
  1292. assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
  1293. end
  1294. end
  1295. describe "get_cached_by_nickname_or_id" do
  1296. setup do
  1297. limit_to_local_content = Pleroma.Config.get([:instance, :limit_to_local_content])
  1298. local_user = insert(:user)
  1299. remote_user = insert(:user, nickname: "nickname@example.com", local: false)
  1300. on_exit(fn ->
  1301. Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local_content)
  1302. end)
  1303. [local_user: local_user, remote_user: remote_user]
  1304. end
  1305. test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
  1306. remote_user: remote_user
  1307. } do
  1308. Pleroma.Config.put([:instance, :limit_to_local_content], false)
  1309. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1310. Pleroma.Config.put([:instance, :limit_to_local_content], true)
  1311. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1312. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1313. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1314. end
  1315. test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
  1316. %{remote_user: remote_user} do
  1317. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1318. assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
  1319. end
  1320. test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
  1321. %{remote_user: remote_user, local_user: local_user} do
  1322. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1323. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
  1324. end
  1325. test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
  1326. %{remote_user: remote_user} do
  1327. Pleroma.Config.put([:instance, :limit_to_local_content], true)
  1328. assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
  1329. end
  1330. test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
  1331. %{local_user: local_user} do
  1332. Pleroma.Config.put([:instance, :limit_to_local_content], false)
  1333. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1334. Pleroma.Config.put([:instance, :limit_to_local_content], true)
  1335. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1336. Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
  1337. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1338. end
  1339. end
  1340. describe "update_email_notifications/2" do
  1341. setup do
  1342. user = insert(:user, email_notifications: %{"digest" => true})
  1343. {:ok, user: user}
  1344. end
  1345. test "Notifications are updated", %{user: user} do
  1346. true = user.email_notifications["digest"]
  1347. assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
  1348. assert result.email_notifications["digest"] == false
  1349. end
  1350. end
  1351. end