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.

2028 lines
62KB

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