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.

2342 lines
72KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 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.Endpoint.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, is_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, is_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, is_locked: true)
  155. pending_follower = insert(:user, %{is_active: false})
  156. CommonAPI.follow(pending_follower, locked)
  157. refute pending_follower.is_active
  158. assert [] = User.get_follow_requests(locked)
  159. end
  160. test "clears follow requests when requester is blocked" do
  161. followed = insert(:user, is_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, followed_zero} = 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, followed} = 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, %{is_active: false})
  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, is_locked: true)
  226. followed = insert(:user, is_locked: true)
  227. {:ok, follower, followed} = 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. clear_config([: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, followed} = 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, followed} = 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([:instance, :autofollowing_nicknames])
  292. setup do: clear_config([:welcome])
  293. setup do: clear_config([:instance, :account_activation_required])
  294. test "it autofollows accounts that are set for it" do
  295. user = insert(:user)
  296. remote_user = insert(:user, %{local: false})
  297. clear_config([:instance, :autofollowed_nicknames], [
  298. user.nickname,
  299. remote_user.nickname
  300. ])
  301. cng = User.register_changeset(%User{}, @full_user_data)
  302. {:ok, registered_user} = User.register(cng)
  303. assert User.following?(registered_user, user)
  304. refute User.following?(registered_user, remote_user)
  305. end
  306. test "it adds automatic followers for new registered accounts" do
  307. user1 = insert(:user)
  308. user2 = insert(:user)
  309. clear_config([:instance, :autofollowing_nicknames], [
  310. user1.nickname,
  311. user2.nickname
  312. ])
  313. cng = User.register_changeset(%User{}, @full_user_data)
  314. {:ok, registered_user} = User.register(cng)
  315. assert User.following?(user1, registered_user)
  316. assert User.following?(user2, registered_user)
  317. end
  318. test "it sends a welcome message if it is set" do
  319. welcome_user = insert(:user)
  320. clear_config([:welcome, :direct_message, :enabled], true)
  321. clear_config([:welcome, :direct_message, :sender_nickname], welcome_user.nickname)
  322. clear_config([:welcome, :direct_message, :message], "Hello, this is a direct 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, fetch: false).data["content"] =~ "direct message"
  329. assert activity.actor == welcome_user.ap_id
  330. end
  331. test "it sends a welcome chat message if it is set" do
  332. welcome_user = insert(:user)
  333. clear_config([:welcome, :chat_message, :enabled], true)
  334. clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
  335. clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
  336. cng = User.register_changeset(%User{}, @full_user_data)
  337. {:ok, registered_user} = User.register(cng)
  338. ObanHelpers.perform_all()
  339. activity = Repo.one(Pleroma.Activity)
  340. assert registered_user.ap_id in activity.recipients
  341. assert Object.normalize(activity, fetch: false).data["content"] =~ "chat message"
  342. assert activity.actor == welcome_user.ap_id
  343. end
  344. setup do:
  345. clear_config(:mrf_simple,
  346. media_removal: [],
  347. media_nsfw: [],
  348. federated_timeline_removal: [],
  349. report_removal: [],
  350. reject: [],
  351. followers_only: [],
  352. accept: [],
  353. avatar_removal: [],
  354. banner_removal: [],
  355. reject_deletes: []
  356. )
  357. setup do:
  358. clear_config(:mrf,
  359. policies: [
  360. Pleroma.Web.ActivityPub.MRF.SimplePolicy
  361. ]
  362. )
  363. test "it sends a welcome chat message when Simple policy applied to local instance" do
  364. clear_config([:mrf_simple, :media_nsfw], ["localhost"])
  365. welcome_user = insert(:user)
  366. clear_config([:welcome, :chat_message, :enabled], true)
  367. clear_config([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
  368. clear_config([:welcome, :chat_message, :message], "Hello, this is a chat message")
  369. cng = User.register_changeset(%User{}, @full_user_data)
  370. {:ok, registered_user} = User.register(cng)
  371. ObanHelpers.perform_all()
  372. activity = Repo.one(Pleroma.Activity)
  373. assert registered_user.ap_id in activity.recipients
  374. assert Object.normalize(activity, fetch: false).data["content"] =~ "chat message"
  375. assert activity.actor == welcome_user.ap_id
  376. end
  377. test "it sends a welcome email message if it is set" do
  378. welcome_user = insert(:user)
  379. clear_config([:welcome, :email, :enabled], true)
  380. clear_config([:welcome, :email, :sender], welcome_user.email)
  381. clear_config(
  382. [:welcome, :email, :subject],
  383. "Hello, welcome to cool site: <%= instance_name %>"
  384. )
  385. instance_name = Pleroma.Config.get([:instance, :name])
  386. cng = User.register_changeset(%User{}, @full_user_data)
  387. {:ok, registered_user} = User.register(cng)
  388. ObanHelpers.perform_all()
  389. assert_email_sent(
  390. from: {instance_name, welcome_user.email},
  391. to: {registered_user.name, registered_user.email},
  392. subject: "Hello, welcome to cool site: #{instance_name}",
  393. html_body: "Welcome to #{instance_name}"
  394. )
  395. end
  396. test "it sends a confirm email" do
  397. clear_config([:instance, :account_activation_required], true)
  398. cng = User.register_changeset(%User{}, @full_user_data)
  399. {:ok, registered_user} = User.register(cng)
  400. ObanHelpers.perform_all()
  401. Pleroma.Emails.UserEmail.account_confirmation_email(registered_user)
  402. # temporary hackney fix until hackney max_connections bug is fixed
  403. # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
  404. |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
  405. |> assert_email_sent()
  406. end
  407. test "sends a pending approval email" do
  408. clear_config([:instance, :account_approval_required], true)
  409. {:ok, user} =
  410. User.register_changeset(%User{}, @full_user_data)
  411. |> User.register()
  412. ObanHelpers.perform_all()
  413. assert_email_sent(
  414. from: Pleroma.Config.Helpers.sender(),
  415. to: {user.name, user.email},
  416. subject: "Your account is awaiting approval"
  417. )
  418. end
  419. test "it sends a registration confirmed email if no others will be sent" do
  420. clear_config([:welcome, :email, :enabled], false)
  421. clear_config([:instance, :account_activation_required], false)
  422. clear_config([:instance, :account_approval_required], false)
  423. {:ok, user} =
  424. User.register_changeset(%User{}, @full_user_data)
  425. |> User.register()
  426. ObanHelpers.perform_all()
  427. instance_name = Pleroma.Config.get([:instance, :name])
  428. sender = Pleroma.Config.get([:instance, :notify_email])
  429. assert_email_sent(
  430. from: {instance_name, sender},
  431. to: {user.name, user.email},
  432. subject: "Account registered on #{instance_name}"
  433. )
  434. end
  435. test "it requires an email, name, nickname and password, bio is optional when account_activation_required is enabled" do
  436. clear_config([:instance, :account_activation_required], true)
  437. @full_user_data
  438. |> Map.keys()
  439. |> Enum.each(fn key ->
  440. params = Map.delete(@full_user_data, key)
  441. changeset = User.register_changeset(%User{}, params)
  442. assert if key == :bio, do: changeset.valid?, else: not changeset.valid?
  443. end)
  444. end
  445. test "it requires an name, nickname and password, bio and email are optional when account_activation_required is disabled" do
  446. clear_config([:instance, :account_activation_required], false)
  447. @full_user_data
  448. |> Map.keys()
  449. |> Enum.each(fn key ->
  450. params = Map.delete(@full_user_data, key)
  451. changeset = User.register_changeset(%User{}, params)
  452. assert if key in [:bio, :email], do: changeset.valid?, else: not changeset.valid?
  453. end)
  454. end
  455. test "it restricts certain nicknames" do
  456. [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
  457. assert is_bitstring(restricted_name)
  458. params =
  459. @full_user_data
  460. |> Map.put(:nickname, restricted_name)
  461. changeset = User.register_changeset(%User{}, params)
  462. refute changeset.valid?
  463. end
  464. test "it blocks blacklisted email domains" do
  465. clear_config([User, :email_blacklist], ["trolling.world"])
  466. # Block with match
  467. params = Map.put(@full_user_data, :email, "troll@trolling.world")
  468. changeset = User.register_changeset(%User{}, params)
  469. refute changeset.valid?
  470. # Block with subdomain match
  471. params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
  472. changeset = User.register_changeset(%User{}, params)
  473. refute changeset.valid?
  474. # Pass with different domains that are similar
  475. params = Map.put(@full_user_data, :email, "troll@gnomestrolling.world")
  476. changeset = User.register_changeset(%User{}, params)
  477. assert changeset.valid?
  478. params = Map.put(@full_user_data, :email, "troll@trolling.world.us")
  479. changeset = User.register_changeset(%User{}, params)
  480. assert changeset.valid?
  481. end
  482. test "it sets the password_hash and ap_id" do
  483. changeset = User.register_changeset(%User{}, @full_user_data)
  484. assert changeset.valid?
  485. assert is_binary(changeset.changes[:password_hash])
  486. assert changeset.changes[:ap_id] == User.ap_id(%User{nickname: @full_user_data.nickname})
  487. assert changeset.changes.follower_address == "#{changeset.changes.ap_id}/followers"
  488. end
  489. test "it sets the 'accepts_chat_messages' set to true" do
  490. changeset = User.register_changeset(%User{}, @full_user_data)
  491. assert changeset.valid?
  492. {:ok, user} = Repo.insert(changeset)
  493. assert user.accepts_chat_messages
  494. end
  495. test "it creates a confirmed user" do
  496. changeset = User.register_changeset(%User{}, @full_user_data)
  497. assert changeset.valid?
  498. {:ok, user} = Repo.insert(changeset)
  499. assert user.is_confirmed
  500. end
  501. end
  502. describe "user registration, with :account_activation_required" do
  503. @full_user_data %{
  504. bio: "A guy",
  505. name: "my name",
  506. nickname: "nick",
  507. password: "test",
  508. password_confirmation: "test",
  509. email: "email@example.com"
  510. }
  511. setup do: clear_config([:instance, :account_activation_required], true)
  512. test "it creates unconfirmed user" do
  513. changeset = User.register_changeset(%User{}, @full_user_data)
  514. assert changeset.valid?
  515. {:ok, user} = Repo.insert(changeset)
  516. refute user.is_confirmed
  517. assert user.confirmation_token
  518. end
  519. test "it creates confirmed user if :confirmed option is given" do
  520. changeset = User.register_changeset(%User{}, @full_user_data, confirmed: true)
  521. assert changeset.valid?
  522. {:ok, user} = Repo.insert(changeset)
  523. assert user.is_confirmed
  524. refute user.confirmation_token
  525. end
  526. end
  527. describe "user registration, with :account_approval_required" do
  528. @full_user_data %{
  529. bio: "A guy",
  530. name: "my name",
  531. nickname: "nick",
  532. password: "test",
  533. password_confirmation: "test",
  534. email: "email@example.com",
  535. registration_reason: "I'm a cool guy :)"
  536. }
  537. setup do: clear_config([:instance, :account_approval_required], true)
  538. test "it creates unapproved user" do
  539. changeset = User.register_changeset(%User{}, @full_user_data)
  540. assert changeset.valid?
  541. {:ok, user} = Repo.insert(changeset)
  542. refute user.is_approved
  543. assert user.registration_reason == "I'm a cool guy :)"
  544. end
  545. test "it restricts length of registration reason" do
  546. reason_limit = Pleroma.Config.get([:instance, :registration_reason_length])
  547. assert is_integer(reason_limit)
  548. params =
  549. @full_user_data
  550. |> Map.put(
  551. :registration_reason,
  552. "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."
  553. )
  554. changeset = User.register_changeset(%User{}, params)
  555. refute changeset.valid?
  556. end
  557. end
  558. describe "get_or_fetch/1" do
  559. test "gets an existing user by nickname" do
  560. user = insert(:user)
  561. {:ok, fetched_user} = User.get_or_fetch(user.nickname)
  562. assert user == fetched_user
  563. end
  564. test "gets an existing user by ap_id" do
  565. ap_id = "http://mastodon.example.org/users/admin"
  566. user =
  567. insert(
  568. :user,
  569. local: false,
  570. nickname: "admin@mastodon.example.org",
  571. ap_id: ap_id
  572. )
  573. {:ok, fetched_user} = User.get_or_fetch(ap_id)
  574. freshed_user = refresh_record(user)
  575. assert freshed_user == fetched_user
  576. end
  577. end
  578. describe "fetching a user from nickname or trying to build one" do
  579. test "gets an existing user" do
  580. user = insert(:user)
  581. {:ok, fetched_user} = User.get_or_fetch_by_nickname(user.nickname)
  582. assert user == fetched_user
  583. end
  584. test "gets an existing user, case insensitive" do
  585. user = insert(:user, nickname: "nick")
  586. {:ok, fetched_user} = User.get_or_fetch_by_nickname("NICK")
  587. assert user == fetched_user
  588. end
  589. test "gets an existing user by fully qualified nickname" do
  590. user = insert(:user)
  591. {:ok, fetched_user} =
  592. User.get_or_fetch_by_nickname(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  593. assert user == fetched_user
  594. end
  595. test "gets an existing user by fully qualified nickname, case insensitive" do
  596. user = insert(:user, nickname: "nick")
  597. casing_altered_fqn = String.upcase(user.nickname <> "@" <> Pleroma.Web.Endpoint.host())
  598. {:ok, fetched_user} = User.get_or_fetch_by_nickname(casing_altered_fqn)
  599. assert user == fetched_user
  600. end
  601. @tag capture_log: true
  602. test "returns nil if no user could be fetched" do
  603. {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
  604. assert fetched_user == "not found nonexistant@social.heldscal.la"
  605. end
  606. test "returns nil for nonexistant local user" do
  607. {:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant")
  608. assert fetched_user == "not found nonexistant"
  609. end
  610. test "updates an existing user, if stale" do
  611. a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
  612. orig_user =
  613. insert(
  614. :user,
  615. local: false,
  616. nickname: "admin@mastodon.example.org",
  617. ap_id: "http://mastodon.example.org/users/admin",
  618. last_refreshed_at: a_week_ago
  619. )
  620. assert orig_user.last_refreshed_at == a_week_ago
  621. {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
  622. assert user.inbox
  623. refute user.last_refreshed_at == orig_user.last_refreshed_at
  624. end
  625. test "if nicknames clash, the old user gets a prefix with the old id to the nickname" do
  626. a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
  627. orig_user =
  628. insert(
  629. :user,
  630. local: false,
  631. nickname: "admin@mastodon.example.org",
  632. ap_id: "http://mastodon.example.org/users/harinezumigari",
  633. last_refreshed_at: a_week_ago
  634. )
  635. assert orig_user.last_refreshed_at == a_week_ago
  636. {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
  637. assert user.inbox
  638. refute user.id == orig_user.id
  639. orig_user = User.get_by_id(orig_user.id)
  640. assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
  641. end
  642. @tag capture_log: true
  643. test "it returns the old user if stale, but unfetchable" do
  644. a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
  645. orig_user =
  646. insert(
  647. :user,
  648. local: false,
  649. nickname: "admin@mastodon.example.org",
  650. ap_id: "http://mastodon.example.org/users/raymoo",
  651. last_refreshed_at: a_week_ago
  652. )
  653. assert orig_user.last_refreshed_at == a_week_ago
  654. {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/raymoo")
  655. assert user.last_refreshed_at == orig_user.last_refreshed_at
  656. end
  657. end
  658. test "returns an ap_id for a user" do
  659. user = insert(:user)
  660. assert User.ap_id(user) ==
  661. Pleroma.Web.Router.Helpers.user_feed_url(
  662. Pleroma.Web.Endpoint,
  663. :feed_redirect,
  664. user.nickname
  665. )
  666. end
  667. test "returns an ap_followers link for a user" do
  668. user = insert(:user)
  669. assert User.ap_followers(user) ==
  670. Pleroma.Web.Router.Helpers.user_feed_url(
  671. Pleroma.Web.Endpoint,
  672. :feed_redirect,
  673. user.nickname
  674. ) <> "/followers"
  675. end
  676. describe "remote user changeset" do
  677. @valid_remote %{
  678. bio: "hello",
  679. name: "Someone",
  680. nickname: "a@b.de",
  681. ap_id: "http...",
  682. avatar: %{some: "avatar"}
  683. }
  684. setup do: clear_config([:instance, :user_bio_length])
  685. setup do: clear_config([:instance, :user_name_length])
  686. test "it confirms validity" do
  687. cs = User.remote_user_changeset(@valid_remote)
  688. assert cs.valid?
  689. end
  690. test "it sets the follower_adress" do
  691. cs = User.remote_user_changeset(@valid_remote)
  692. # remote users get a fake local follower address
  693. assert cs.changes.follower_address ==
  694. User.ap_followers(%User{nickname: @valid_remote[:nickname]})
  695. end
  696. test "it enforces the fqn format for nicknames" do
  697. cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
  698. assert Ecto.Changeset.get_field(cs, :local) == false
  699. assert cs.changes.avatar
  700. refute cs.valid?
  701. end
  702. test "it has required fields" do
  703. [:ap_id]
  704. |> Enum.each(fn field ->
  705. cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
  706. refute cs.valid?
  707. end)
  708. end
  709. test "it is invalid given a local user" do
  710. user = insert(:user)
  711. cs = User.remote_user_changeset(user, %{name: "tom from myspace"})
  712. refute cs.valid?
  713. end
  714. end
  715. describe "followers and friends" do
  716. test "gets all followers for a given user" do
  717. user = insert(:user)
  718. follower_one = insert(:user)
  719. follower_two = insert(:user)
  720. not_follower = insert(:user)
  721. {:ok, follower_one, user} = User.follow(follower_one, user)
  722. {:ok, follower_two, user} = User.follow(follower_two, user)
  723. res = User.get_followers(user)
  724. assert Enum.member?(res, follower_one)
  725. assert Enum.member?(res, follower_two)
  726. refute Enum.member?(res, not_follower)
  727. end
  728. test "gets all friends (followed users) for a given user" do
  729. user = insert(:user)
  730. followed_one = insert(:user)
  731. followed_two = insert(:user)
  732. not_followed = insert(:user)
  733. {:ok, user, followed_one} = User.follow(user, followed_one)
  734. {:ok, user, followed_two} = User.follow(user, followed_two)
  735. res = User.get_friends(user)
  736. followed_one = User.get_cached_by_ap_id(followed_one.ap_id)
  737. followed_two = User.get_cached_by_ap_id(followed_two.ap_id)
  738. assert Enum.member?(res, followed_one)
  739. assert Enum.member?(res, followed_two)
  740. refute Enum.member?(res, not_followed)
  741. end
  742. end
  743. describe "updating note and follower count" do
  744. test "it sets the note_count property" do
  745. note = insert(:note)
  746. user = User.get_cached_by_ap_id(note.data["actor"])
  747. assert user.note_count == 0
  748. {:ok, user} = User.update_note_count(user)
  749. assert user.note_count == 1
  750. end
  751. test "it increases the note_count property" do
  752. note = insert(:note)
  753. user = User.get_cached_by_ap_id(note.data["actor"])
  754. assert user.note_count == 0
  755. {:ok, user} = User.increase_note_count(user)
  756. assert user.note_count == 1
  757. {:ok, user} = User.increase_note_count(user)
  758. assert user.note_count == 2
  759. end
  760. test "it decreases the note_count property" do
  761. note = insert(:note)
  762. user = User.get_cached_by_ap_id(note.data["actor"])
  763. assert user.note_count == 0
  764. {:ok, user} = User.increase_note_count(user)
  765. assert user.note_count == 1
  766. {:ok, user} = User.decrease_note_count(user)
  767. assert user.note_count == 0
  768. {:ok, user} = User.decrease_note_count(user)
  769. assert user.note_count == 0
  770. end
  771. test "it sets the follower_count property" do
  772. user = insert(:user)
  773. follower = insert(:user)
  774. User.follow(follower, user)
  775. assert user.follower_count == 0
  776. {:ok, user} = User.update_follower_count(user)
  777. assert user.follower_count == 1
  778. end
  779. end
  780. describe "mutes" do
  781. test "it mutes people" do
  782. user = insert(:user)
  783. muted_user = insert(:user)
  784. refute User.mutes?(user, muted_user)
  785. refute User.muted_notifications?(user, muted_user)
  786. {:ok, _user_relationships} = User.mute(user, muted_user)
  787. assert User.mutes?(user, muted_user)
  788. assert User.muted_notifications?(user, muted_user)
  789. end
  790. test "expiring" do
  791. user = insert(:user)
  792. muted_user = insert(:user)
  793. {:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
  794. assert User.mutes?(user, muted_user)
  795. worker = Pleroma.Workers.MuteExpireWorker
  796. args = %{"op" => "unmute_user", "muter_id" => user.id, "mutee_id" => muted_user.id}
  797. assert_enqueued(
  798. worker: worker,
  799. args: args
  800. )
  801. assert :ok = perform_job(worker, args)
  802. refute User.mutes?(user, muted_user)
  803. refute User.muted_notifications?(user, muted_user)
  804. end
  805. test "it unmutes users" do
  806. user = insert(:user)
  807. muted_user = insert(:user)
  808. {:ok, _user_relationships} = User.mute(user, muted_user)
  809. {:ok, _user_mute} = User.unmute(user, muted_user)
  810. refute User.mutes?(user, muted_user)
  811. refute User.muted_notifications?(user, muted_user)
  812. end
  813. test "it unmutes users by id" do
  814. user = insert(:user)
  815. muted_user = insert(:user)
  816. {:ok, _user_relationships} = User.mute(user, muted_user)
  817. {:ok, _user_mute} = User.unmute(user.id, muted_user.id)
  818. refute User.mutes?(user, muted_user)
  819. refute User.muted_notifications?(user, muted_user)
  820. end
  821. test "it mutes user without notifications" do
  822. user = insert(:user)
  823. muted_user = insert(:user)
  824. refute User.mutes?(user, muted_user)
  825. refute User.muted_notifications?(user, muted_user)
  826. {:ok, _user_relationships} = User.mute(user, muted_user, %{notifications: false})
  827. assert User.mutes?(user, muted_user)
  828. refute User.muted_notifications?(user, muted_user)
  829. end
  830. end
  831. describe "blocks" do
  832. test "it blocks people" do
  833. user = insert(:user)
  834. blocked_user = insert(:user)
  835. refute User.blocks?(user, blocked_user)
  836. {:ok, _user_relationship} = User.block(user, blocked_user)
  837. assert User.blocks?(user, blocked_user)
  838. end
  839. test "it unblocks users" do
  840. user = insert(:user)
  841. blocked_user = insert(:user)
  842. {:ok, _user_relationship} = User.block(user, blocked_user)
  843. {:ok, _user_block} = User.unblock(user, blocked_user)
  844. refute User.blocks?(user, blocked_user)
  845. end
  846. test "blocks tear down cyclical follow relationships" do
  847. blocker = insert(:user)
  848. blocked = insert(:user)
  849. {:ok, blocker, blocked} = User.follow(blocker, blocked)
  850. {:ok, blocked, blocker} = User.follow(blocked, blocker)
  851. assert User.following?(blocker, blocked)
  852. assert User.following?(blocked, blocker)
  853. {:ok, _user_relationship} = User.block(blocker, blocked)
  854. blocked = User.get_cached_by_id(blocked.id)
  855. assert User.blocks?(blocker, blocked)
  856. refute User.following?(blocker, blocked)
  857. refute User.following?(blocked, blocker)
  858. end
  859. test "blocks tear down blocker->blocked follow relationships" do
  860. blocker = insert(:user)
  861. blocked = insert(:user)
  862. {:ok, blocker, blocked} = User.follow(blocker, blocked)
  863. assert User.following?(blocker, blocked)
  864. refute User.following?(blocked, blocker)
  865. {:ok, _user_relationship} = User.block(blocker, blocked)
  866. blocked = User.get_cached_by_id(blocked.id)
  867. assert User.blocks?(blocker, blocked)
  868. refute User.following?(blocker, blocked)
  869. refute User.following?(blocked, blocker)
  870. end
  871. test "blocks tear down blocked->blocker follow relationships" do
  872. blocker = insert(:user)
  873. blocked = insert(:user)
  874. {:ok, blocked, blocker} = User.follow(blocked, blocker)
  875. refute User.following?(blocker, blocked)
  876. assert User.following?(blocked, blocker)
  877. {:ok, _user_relationship} = User.block(blocker, blocked)
  878. blocked = User.get_cached_by_id(blocked.id)
  879. assert User.blocks?(blocker, blocked)
  880. refute User.following?(blocker, blocked)
  881. refute User.following?(blocked, blocker)
  882. end
  883. test "blocks tear down blocked->blocker subscription relationships" do
  884. blocker = insert(:user)
  885. blocked = insert(:user)
  886. {:ok, _subscription} = User.subscribe(blocked, blocker)
  887. assert User.subscribed_to?(blocked, blocker)
  888. refute User.subscribed_to?(blocker, blocked)
  889. {:ok, _user_relationship} = User.block(blocker, blocked)
  890. assert User.blocks?(blocker, blocked)
  891. refute User.subscribed_to?(blocker, blocked)
  892. refute User.subscribed_to?(blocked, blocker)
  893. end
  894. end
  895. describe "domain blocking" do
  896. test "blocks domains" do
  897. user = insert(:user)
  898. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  899. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  900. assert User.blocks?(user, collateral_user)
  901. end
  902. test "does not block domain with same end" do
  903. user = insert(:user)
  904. collateral_user =
  905. insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
  906. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  907. refute User.blocks?(user, collateral_user)
  908. end
  909. test "does not block domain with same end if wildcard added" do
  910. user = insert(:user)
  911. collateral_user =
  912. insert(:user, %{ap_id: "https://another-awful-and-rude-instance.com/user/bully"})
  913. {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
  914. refute User.blocks?(user, collateral_user)
  915. end
  916. test "blocks domain with wildcard for subdomain" do
  917. user = insert(:user)
  918. user_from_subdomain =
  919. insert(:user, %{ap_id: "https://subdomain.awful-and-rude-instance.com/user/bully"})
  920. user_with_two_subdomains =
  921. insert(:user, %{
  922. ap_id: "https://subdomain.second_subdomain.awful-and-rude-instance.com/user/bully"
  923. })
  924. user_domain = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  925. {:ok, user} = User.block_domain(user, "*.awful-and-rude-instance.com")
  926. assert User.blocks?(user, user_from_subdomain)
  927. assert User.blocks?(user, user_with_two_subdomains)
  928. assert User.blocks?(user, user_domain)
  929. end
  930. test "unblocks domains" do
  931. user = insert(:user)
  932. collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"})
  933. {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com")
  934. {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com")
  935. refute User.blocks?(user, collateral_user)
  936. end
  937. test "follows take precedence over domain blocks" do
  938. user = insert(:user)
  939. good_eggo = insert(:user, %{ap_id: "https://meanies.social/user/cuteposter"})
  940. {:ok, user} = User.block_domain(user, "meanies.social")
  941. {:ok, user, good_eggo} = User.follow(user, good_eggo)
  942. refute User.blocks?(user, good_eggo)
  943. end
  944. end
  945. describe "get_recipients_from_activity" do
  946. test "works for announces" do
  947. actor = insert(:user)
  948. user = insert(:user, local: true)
  949. {:ok, activity} = CommonAPI.post(actor, %{status: "hello"})
  950. {:ok, announce} = CommonAPI.repeat(activity.id, user)
  951. recipients = User.get_recipients_from_activity(announce)
  952. assert user in recipients
  953. end
  954. test "get recipients" do
  955. actor = insert(:user)
  956. user = insert(:user, local: true)
  957. user_two = insert(:user, local: false)
  958. addressed = insert(:user, local: true)
  959. addressed_remote = insert(:user, local: false)
  960. {:ok, activity} =
  961. CommonAPI.post(actor, %{
  962. status: "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
  963. })
  964. assert Enum.map([actor, addressed], & &1.ap_id) --
  965. Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
  966. {:ok, user, actor} = User.follow(user, actor)
  967. {:ok, _user_two, _actor} = User.follow(user_two, actor)
  968. recipients = User.get_recipients_from_activity(activity)
  969. assert length(recipients) == 3
  970. assert user in recipients
  971. assert addressed in recipients
  972. end
  973. test "has following" do
  974. actor = insert(:user)
  975. user = insert(:user)
  976. user_two = insert(:user)
  977. addressed = insert(:user, local: true)
  978. {:ok, activity} =
  979. CommonAPI.post(actor, %{
  980. status: "hey @#{addressed.nickname}"
  981. })
  982. assert Enum.map([actor, addressed], & &1.ap_id) --
  983. Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
  984. {:ok, _actor, _user} = User.follow(actor, user)
  985. {:ok, _actor, _user_two} = User.follow(actor, user_two)
  986. recipients = User.get_recipients_from_activity(activity)
  987. assert length(recipients) == 2
  988. assert addressed in recipients
  989. end
  990. end
  991. describe ".set_activation" do
  992. test "can de-activate then re-activate a user" do
  993. user = insert(:user)
  994. assert user.is_active
  995. {:ok, user} = User.set_activation(user, false)
  996. refute user.is_active
  997. {:ok, user} = User.set_activation(user, true)
  998. assert user.is_active
  999. end
  1000. test "hide a user from followers" do
  1001. user = insert(:user)
  1002. user2 = insert(:user)
  1003. {:ok, user, user2} = User.follow(user, user2)
  1004. {:ok, _user} = User.set_activation(user, false)
  1005. user2 = User.get_cached_by_id(user2.id)
  1006. assert user2.follower_count == 0
  1007. assert [] = User.get_followers(user2)
  1008. end
  1009. test "hide a user from friends" do
  1010. user = insert(:user)
  1011. user2 = insert(:user)
  1012. {:ok, user2, user} = User.follow(user2, user)
  1013. assert user2.following_count == 1
  1014. assert User.following_count(user2) == 1
  1015. {:ok, _user} = User.set_activation(user, false)
  1016. user2 = User.get_cached_by_id(user2.id)
  1017. assert refresh_record(user2).following_count == 0
  1018. assert user2.following_count == 0
  1019. assert User.following_count(user2) == 0
  1020. assert [] = User.get_friends(user2)
  1021. end
  1022. test "hide a user's statuses from timelines and notifications" do
  1023. user = insert(:user)
  1024. user2 = insert(:user)
  1025. {:ok, user2, user} = User.follow(user2, user)
  1026. {:ok, activity} = CommonAPI.post(user, %{status: "hey @#{user2.nickname}"})
  1027. activity = Repo.preload(activity, :bookmark)
  1028. [notification] = Pleroma.Notification.for_user(user2)
  1029. assert notification.activity.id == activity.id
  1030. assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
  1031. assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
  1032. ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
  1033. user: user2
  1034. })
  1035. {:ok, _user} = User.set_activation(user, false)
  1036. assert [] == ActivityPub.fetch_public_activities(%{})
  1037. assert [] == Pleroma.Notification.for_user(user2)
  1038. assert [] ==
  1039. ActivityPub.fetch_activities([user2.ap_id | User.following(user2)], %{
  1040. user: user2
  1041. })
  1042. end
  1043. end
  1044. describe "approve" do
  1045. test "approves a user" do
  1046. user = insert(:user, is_approved: false)
  1047. refute user.is_approved
  1048. {:ok, user} = User.approve(user)
  1049. assert user.is_approved
  1050. end
  1051. test "approves a list of users" do
  1052. unapproved_users = [
  1053. insert(:user, is_approved: false),
  1054. insert(:user, is_approved: false),
  1055. insert(:user, is_approved: false)
  1056. ]
  1057. {:ok, users} = User.approve(unapproved_users)
  1058. assert Enum.count(users) == 3
  1059. Enum.each(users, fn user ->
  1060. assert user.is_approved
  1061. end)
  1062. end
  1063. test "it sends welcome email if it is set" do
  1064. clear_config([:welcome, :email, :enabled], true)
  1065. clear_config([:welcome, :email, :sender], "tester@test.me")
  1066. user = insert(:user, is_approved: false)
  1067. welcome_user = insert(:user, email: "tester@test.me")
  1068. instance_name = Pleroma.Config.get([:instance, :name])
  1069. User.approve(user)
  1070. ObanHelpers.perform_all()
  1071. assert_email_sent(
  1072. from: {instance_name, welcome_user.email},
  1073. to: {user.name, user.email},
  1074. html_body: "Welcome to #{instance_name}"
  1075. )
  1076. end
  1077. test "approving an approved user does not trigger post-register actions" do
  1078. clear_config([:welcome, :email, :enabled], true)
  1079. user = insert(:user, is_approved: true)
  1080. User.approve(user)
  1081. ObanHelpers.perform_all()
  1082. assert_no_email_sent()
  1083. end
  1084. end
  1085. describe "confirm" do
  1086. test "confirms a user" do
  1087. user = insert(:user, is_confirmed: false)
  1088. refute user.is_confirmed
  1089. {:ok, user} = User.confirm(user)
  1090. assert user.is_confirmed
  1091. end
  1092. test "confirms a list of users" do
  1093. unconfirmed_users = [
  1094. insert(:user, is_confirmed: false),
  1095. insert(:user, is_confirmed: false),
  1096. insert(:user, is_confirmed: false)
  1097. ]
  1098. {:ok, users} = User.confirm(unconfirmed_users)
  1099. assert Enum.count(users) == 3
  1100. Enum.each(users, fn user ->
  1101. assert user.is_confirmed
  1102. end)
  1103. end
  1104. test "sends approval emails when `is_approved: false`" do
  1105. admin = insert(:user, is_admin: true)
  1106. user = insert(:user, is_confirmed: false, is_approved: false)
  1107. User.confirm(user)
  1108. ObanHelpers.perform_all()
  1109. user_email = Pleroma.Emails.UserEmail.approval_pending_email(user)
  1110. admin_email = Pleroma.Emails.AdminEmail.new_unapproved_registration(admin, user)
  1111. notify_email = Pleroma.Config.get([:instance, :notify_email])
  1112. instance_name = Pleroma.Config.get([:instance, :name])
  1113. # User approval email
  1114. assert_email_sent(
  1115. from: {instance_name, notify_email},
  1116. to: {user.name, user.email},
  1117. html_body: user_email.html_body
  1118. )
  1119. # Admin email
  1120. assert_email_sent(
  1121. from: {instance_name, notify_email},
  1122. to: {admin.name, admin.email},
  1123. html_body: admin_email.html_body
  1124. )
  1125. end
  1126. test "confirming a confirmed user does not trigger post-register actions" do
  1127. user = insert(:user, is_confirmed: true, is_approved: false)
  1128. User.confirm(user)
  1129. ObanHelpers.perform_all()
  1130. assert_no_email_sent()
  1131. end
  1132. end
  1133. describe "delete" do
  1134. setup do
  1135. {:ok, user} = insert(:user) |> User.set_cache()
  1136. [user: user]
  1137. end
  1138. setup do: clear_config([:instance, :federating])
  1139. test ".delete_user_activities deletes all create activities", %{user: user} do
  1140. {:ok, activity} = CommonAPI.post(user, %{status: "2hu"})
  1141. User.delete_user_activities(user)
  1142. # TODO: Test removal favorites, repeats, delete activities.
  1143. refute Activity.get_by_id(activity.id)
  1144. end
  1145. test "it deactivates a user, all follow relationships and all activities", %{user: user} do
  1146. follower = insert(:user)
  1147. {:ok, follower, user} = User.follow(follower, user)
  1148. locked_user = insert(:user, name: "locked", is_locked: true)
  1149. {:ok, _, _} = User.follow(user, locked_user, :follow_pending)
  1150. object = insert(:note, user: user)
  1151. activity = insert(:note_activity, user: user, note: object)
  1152. object_two = insert(:note, user: follower)
  1153. activity_two = insert(:note_activity, user: follower, note: object_two)
  1154. {:ok, like} = CommonAPI.favorite(user, activity_two.id)
  1155. {:ok, like_two} = CommonAPI.favorite(follower, activity.id)
  1156. {:ok, repeat} = CommonAPI.repeat(activity_two.id, user)
  1157. {:ok, job} = User.delete(user)
  1158. {:ok, _user} = ObanHelpers.perform(job)
  1159. follower = User.get_cached_by_id(follower.id)
  1160. refute User.following?(follower, user)
  1161. assert %{is_active: false} = User.get_by_id(user.id)
  1162. assert [] == User.get_follow_requests(locked_user)
  1163. user_activities =
  1164. user.ap_id
  1165. |> Activity.Queries.by_actor()
  1166. |> Repo.all()
  1167. |> Enum.map(fn act -> act.data["type"] end)
  1168. assert Enum.all?(user_activities, fn act -> act in ~w(Delete Undo) end)
  1169. refute Activity.get_by_id(activity.id)
  1170. refute Activity.get_by_id(like.id)
  1171. refute Activity.get_by_id(like_two.id)
  1172. refute Activity.get_by_id(repeat.id)
  1173. end
  1174. end
  1175. test "delete/1 when confirmation is pending deletes the user" do
  1176. clear_config([:instance, :account_activation_required], true)
  1177. user = insert(:user, is_confirmed: false)
  1178. {:ok, job} = User.delete(user)
  1179. {:ok, _} = ObanHelpers.perform(job)
  1180. refute User.get_cached_by_id(user.id)
  1181. refute User.get_by_id(user.id)
  1182. end
  1183. test "delete/1 when approval is pending deletes the user" do
  1184. user = insert(:user, is_approved: false)
  1185. {:ok, job} = User.delete(user)
  1186. {:ok, _} = ObanHelpers.perform(job)
  1187. refute User.get_cached_by_id(user.id)
  1188. refute User.get_by_id(user.id)
  1189. end
  1190. test "delete/1 purges a user when they wouldn't be fully deleted" do
  1191. user =
  1192. insert(:user, %{
  1193. bio: "eyy lmao",
  1194. name: "qqqqqqq",
  1195. password_hash: "pdfk2$1b3n159001",
  1196. keys: "RSA begin buplic key",
  1197. public_key: "--PRIVATE KEYE--",
  1198. avatar: %{"a" => "b"},
  1199. tags: ["qqqqq"],
  1200. banner: %{"a" => "b"},
  1201. background: %{"a" => "b"},
  1202. note_count: 9,
  1203. follower_count: 9,
  1204. following_count: 9001,
  1205. is_locked: true,
  1206. is_confirmed: false,
  1207. password_reset_pending: true,
  1208. is_approved: false,
  1209. registration_reason: "ahhhhh",
  1210. confirmation_token: "qqqq",
  1211. domain_blocks: ["lain.com"],
  1212. is_active: false,
  1213. ap_enabled: true,
  1214. is_moderator: true,
  1215. is_admin: true,
  1216. mastofe_settings: %{"a" => "b"},
  1217. mascot: %{"a" => "b"},
  1218. emoji: %{"a" => "b"},
  1219. pleroma_settings_store: %{"q" => "x"},
  1220. fields: [%{"gg" => "qq"}],
  1221. raw_fields: [%{"gg" => "qq"}],
  1222. is_discoverable: true,
  1223. also_known_as: ["https://lol.olo/users/loll"]
  1224. })
  1225. {:ok, job} = User.delete(user)
  1226. {:ok, _} = ObanHelpers.perform(job)
  1227. user = User.get_by_id(user.id)
  1228. assert %User{
  1229. bio: "",
  1230. raw_bio: nil,
  1231. email: nil,
  1232. name: nil,
  1233. password_hash: nil,
  1234. keys: nil,
  1235. public_key: nil,
  1236. avatar: %{},
  1237. tags: [],
  1238. last_refreshed_at: nil,
  1239. last_digest_emailed_at: nil,
  1240. banner: %{},
  1241. background: %{},
  1242. note_count: 0,
  1243. follower_count: 0,
  1244. following_count: 0,
  1245. is_locked: false,
  1246. is_confirmed: true,
  1247. password_reset_pending: false,
  1248. is_approved: true,
  1249. registration_reason: nil,
  1250. confirmation_token: nil,
  1251. domain_blocks: [],
  1252. is_active: false,
  1253. ap_enabled: false,
  1254. is_moderator: false,
  1255. is_admin: false,
  1256. mastofe_settings: nil,
  1257. mascot: nil,
  1258. emoji: %{},
  1259. pleroma_settings_store: %{},
  1260. fields: [],
  1261. raw_fields: [],
  1262. is_discoverable: false,
  1263. also_known_as: []
  1264. } = user
  1265. end
  1266. test "get_public_key_for_ap_id fetches a user that's not in the db" do
  1267. assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
  1268. end
  1269. describe "per-user rich-text filtering" do
  1270. test "html_filter_policy returns default policies, when rich-text is enabled" do
  1271. user = insert(:user)
  1272. assert Pleroma.Config.get([:markup, :scrub_policy]) == User.html_filter_policy(user)
  1273. end
  1274. test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do
  1275. user = insert(:user, no_rich_text: true)
  1276. assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user)
  1277. end
  1278. end
  1279. describe "caching" do
  1280. test "invalidate_cache works" do
  1281. user = insert(:user)
  1282. User.set_cache(user)
  1283. User.invalidate_cache(user)
  1284. {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1285. {:ok, nil} = Cachex.get(:user_cache, "nickname:#{user.nickname}")
  1286. end
  1287. test "User.delete() plugs any possible zombie objects" do
  1288. user = insert(:user)
  1289. {:ok, job} = User.delete(user)
  1290. {:ok, _} = ObanHelpers.perform(job)
  1291. {:ok, cached_user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1292. assert cached_user != user
  1293. {:ok, cached_user} = Cachex.get(:user_cache, "nickname:#{user.ap_id}")
  1294. assert cached_user != user
  1295. end
  1296. end
  1297. describe "account_status/1" do
  1298. setup do: clear_config([:instance, :account_activation_required])
  1299. test "return confirmation_pending for unconfirm user" do
  1300. clear_config([:instance, :account_activation_required], true)
  1301. user = insert(:user, is_confirmed: false)
  1302. assert User.account_status(user) == :confirmation_pending
  1303. end
  1304. test "return active for confirmed user" do
  1305. clear_config([:instance, :account_activation_required], true)
  1306. user = insert(:user, is_confirmed: true)
  1307. assert User.account_status(user) == :active
  1308. end
  1309. test "return active for remote user" do
  1310. user = insert(:user, local: false)
  1311. assert User.account_status(user) == :active
  1312. end
  1313. test "returns :password_reset_pending for user with reset password" do
  1314. user = insert(:user, password_reset_pending: true)
  1315. assert User.account_status(user) == :password_reset_pending
  1316. end
  1317. test "returns :deactivated for deactivated user" do
  1318. user = insert(:user, local: true, is_confirmed: true, is_active: false)
  1319. assert User.account_status(user) == :deactivated
  1320. end
  1321. test "returns :approval_pending for unapproved user" do
  1322. user = insert(:user, local: true, is_approved: false)
  1323. assert User.account_status(user) == :approval_pending
  1324. user = insert(:user, local: true, is_confirmed: false, is_approved: false)
  1325. assert User.account_status(user) == :approval_pending
  1326. end
  1327. end
  1328. describe "superuser?/1" do
  1329. test "returns false for unprivileged users" do
  1330. user = insert(:user, local: true)
  1331. refute User.superuser?(user)
  1332. end
  1333. test "returns false for remote users" do
  1334. user = insert(:user, local: false)
  1335. remote_admin_user = insert(:user, local: false, is_admin: true)
  1336. refute User.superuser?(user)
  1337. refute User.superuser?(remote_admin_user)
  1338. end
  1339. test "returns true for local moderators" do
  1340. user = insert(:user, local: true, is_moderator: true)
  1341. assert User.superuser?(user)
  1342. end
  1343. test "returns true for local admins" do
  1344. user = insert(:user, local: true, is_admin: true)
  1345. assert User.superuser?(user)
  1346. end
  1347. end
  1348. describe "invisible?/1" do
  1349. test "returns true for an invisible user" do
  1350. user = insert(:user, local: true, invisible: true)
  1351. assert User.invisible?(user)
  1352. end
  1353. test "returns false for a non-invisible user" do
  1354. user = insert(:user, local: true)
  1355. refute User.invisible?(user)
  1356. end
  1357. end
  1358. describe "visible_for/2" do
  1359. test "returns true when the account is itself" do
  1360. user = insert(:user, local: true)
  1361. assert User.visible_for(user, user) == :visible
  1362. end
  1363. test "returns false when the account is unconfirmed and confirmation is required" do
  1364. clear_config([:instance, :account_activation_required], true)
  1365. user = insert(:user, local: true, is_confirmed: false)
  1366. other_user = insert(:user, local: true)
  1367. refute User.visible_for(user, other_user) == :visible
  1368. end
  1369. test "returns true when the account is unconfirmed and confirmation is required but the account is remote" do
  1370. clear_config([:instance, :account_activation_required], true)
  1371. user = insert(:user, local: false, is_confirmed: false)
  1372. other_user = insert(:user, local: true)
  1373. assert User.visible_for(user, other_user) == :visible
  1374. end
  1375. test "returns true when the account is unconfirmed and being viewed by a privileged account (confirmation required)" do
  1376. clear_config([:instance, :account_activation_required], true)
  1377. user = insert(:user, local: true, is_confirmed: false)
  1378. other_user = insert(:user, local: true, is_admin: true)
  1379. assert User.visible_for(user, other_user) == :visible
  1380. end
  1381. end
  1382. describe "parse_bio/2" do
  1383. test "preserves hosts in user links text" do
  1384. remote_user = insert(:user, local: false, nickname: "nick@domain.com")
  1385. user = insert(:user)
  1386. bio = "A.k.a. @nick@domain.com"
  1387. expected_text =
  1388. ~s(A.k.a. <span class="h-card"><a class="u-url mention" data-user="#{remote_user.id}" href="#{
  1389. remote_user.ap_id
  1390. }" rel="ugc">@<span>nick@domain.com</span></a></span>)
  1391. assert expected_text == User.parse_bio(bio, user)
  1392. end
  1393. test "Adds rel=me on linkbacked urls" do
  1394. user = insert(:user, ap_id: "https://social.example.org/users/lain")
  1395. bio = "http://example.com/rel_me/null"
  1396. expected_text = "<a href=\"#{bio}\">#{bio}</a>"
  1397. assert expected_text == User.parse_bio(bio, user)
  1398. bio = "http://example.com/rel_me/link"
  1399. expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
  1400. assert expected_text == User.parse_bio(bio, user)
  1401. bio = "http://example.com/rel_me/anchor"
  1402. expected_text = "<a href=\"#{bio}\" rel=\"me\">#{bio}</a>"
  1403. assert expected_text == User.parse_bio(bio, user)
  1404. end
  1405. end
  1406. test "follower count is updated when a follower is blocked" do
  1407. user = insert(:user)
  1408. follower = insert(:user)
  1409. follower2 = insert(:user)
  1410. follower3 = insert(:user)
  1411. {:ok, follower, user} = User.follow(follower, user)
  1412. {:ok, _follower2, _user} = User.follow(follower2, user)
  1413. {:ok, _follower3, _user} = User.follow(follower3, user)
  1414. {:ok, _user_relationship} = User.block(user, follower)
  1415. user = refresh_record(user)
  1416. assert user.follower_count == 2
  1417. end
  1418. describe "list_inactive_users_query/1" do
  1419. defp days_ago(days) do
  1420. NaiveDateTime.add(
  1421. NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second),
  1422. -days * 60 * 60 * 24,
  1423. :second
  1424. )
  1425. end
  1426. test "Users are inactive by default" do
  1427. total = 10
  1428. users =
  1429. Enum.map(1..total, fn _ ->
  1430. insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
  1431. end)
  1432. inactive_users_ids =
  1433. Pleroma.User.list_inactive_users_query()
  1434. |> Pleroma.Repo.all()
  1435. |> Enum.map(& &1.id)
  1436. Enum.each(users, fn user ->
  1437. assert user.id in inactive_users_ids
  1438. end)
  1439. end
  1440. test "Only includes users who has no recent activity" do
  1441. total = 10
  1442. users =
  1443. Enum.map(1..total, fn _ ->
  1444. insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
  1445. end)
  1446. {inactive, active} = Enum.split(users, trunc(total / 2))
  1447. Enum.map(active, fn user ->
  1448. to = Enum.random(users -- [user])
  1449. {:ok, _} =
  1450. CommonAPI.post(user, %{
  1451. status: "hey @#{to.nickname}"
  1452. })
  1453. end)
  1454. inactive_users_ids =
  1455. Pleroma.User.list_inactive_users_query()
  1456. |> Pleroma.Repo.all()
  1457. |> Enum.map(& &1.id)
  1458. Enum.each(active, fn user ->
  1459. refute user.id in inactive_users_ids
  1460. end)
  1461. Enum.each(inactive, fn user ->
  1462. assert user.id in inactive_users_ids
  1463. end)
  1464. end
  1465. test "Only includes users with no read notifications" do
  1466. total = 10
  1467. users =
  1468. Enum.map(1..total, fn _ ->
  1469. insert(:user, last_digest_emailed_at: days_ago(20), is_active: true)
  1470. end)
  1471. [sender | recipients] = users
  1472. {inactive, active} = Enum.split(recipients, trunc(total / 2))
  1473. Enum.each(recipients, fn to ->
  1474. {:ok, _} =
  1475. CommonAPI.post(sender, %{
  1476. status: "hey @#{to.nickname}"
  1477. })
  1478. {:ok, _} =
  1479. CommonAPI.post(sender, %{
  1480. status: "hey again @#{to.nickname}"
  1481. })
  1482. end)
  1483. Enum.each(active, fn user ->
  1484. [n1, _n2] = Pleroma.Notification.for_user(user)
  1485. {:ok, _} = Pleroma.Notification.read_one(user, n1.id)
  1486. end)
  1487. inactive_users_ids =
  1488. Pleroma.User.list_inactive_users_query()
  1489. |> Pleroma.Repo.all()
  1490. |> Enum.map(& &1.id)
  1491. Enum.each(active, fn user ->
  1492. refute user.id in inactive_users_ids
  1493. end)
  1494. Enum.each(inactive, fn user ->
  1495. assert user.id in inactive_users_ids
  1496. end)
  1497. end
  1498. end
  1499. describe "ensure_keys_present" do
  1500. test "it creates keys for a user and stores them in info" do
  1501. user = insert(:user)
  1502. refute is_binary(user.keys)
  1503. {:ok, user} = User.ensure_keys_present(user)
  1504. assert is_binary(user.keys)
  1505. end
  1506. test "it doesn't create keys if there already are some" do
  1507. user = insert(:user, keys: "xxx")
  1508. {:ok, user} = User.ensure_keys_present(user)
  1509. assert user.keys == "xxx"
  1510. end
  1511. end
  1512. describe "get_ap_ids_by_nicknames" do
  1513. test "it returns a list of AP ids for a given set of nicknames" do
  1514. user = insert(:user)
  1515. user_two = insert(:user)
  1516. ap_ids = User.get_ap_ids_by_nicknames([user.nickname, user_two.nickname, "nonexistent"])
  1517. assert length(ap_ids) == 2
  1518. assert user.ap_id in ap_ids
  1519. assert user_two.ap_id in ap_ids
  1520. end
  1521. end
  1522. describe "sync followers count" do
  1523. setup do
  1524. user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed")
  1525. user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2")
  1526. insert(:user, local: true)
  1527. insert(:user, local: false, is_active: false)
  1528. {:ok, user1: user1, user2: user2}
  1529. end
  1530. test "external_users/1 external active users with limit", %{user1: user1, user2: user2} do
  1531. [fdb_user1] = User.external_users(limit: 1)
  1532. assert fdb_user1.ap_id
  1533. assert fdb_user1.ap_id == user1.ap_id
  1534. assert fdb_user1.id == user1.id
  1535. [fdb_user2] = User.external_users(max_id: fdb_user1.id, limit: 1)
  1536. assert fdb_user2.ap_id
  1537. assert fdb_user2.ap_id == user2.ap_id
  1538. assert fdb_user2.id == user2.id
  1539. assert User.external_users(max_id: fdb_user2.id, limit: 1) == []
  1540. end
  1541. end
  1542. describe "is_internal_user?/1" do
  1543. test "non-internal user returns false" do
  1544. user = insert(:user)
  1545. refute User.is_internal_user?(user)
  1546. end
  1547. test "user with no nickname returns true" do
  1548. user = insert(:user, %{nickname: nil})
  1549. assert User.is_internal_user?(user)
  1550. end
  1551. test "user with internal-prefixed nickname returns true" do
  1552. user = insert(:user, %{nickname: "internal.test"})
  1553. assert User.is_internal_user?(user)
  1554. end
  1555. end
  1556. describe "update_and_set_cache/1" do
  1557. test "returns error when user is stale instead Ecto.StaleEntryError" do
  1558. user = insert(:user)
  1559. changeset = Ecto.Changeset.change(user, bio: "test")
  1560. Repo.delete(user)
  1561. assert {:error, %Ecto.Changeset{errors: [id: {"is stale", [stale: true]}], valid?: false}} =
  1562. User.update_and_set_cache(changeset)
  1563. end
  1564. test "performs update cache if user updated" do
  1565. user = insert(:user)
  1566. assert {:ok, nil} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1567. changeset = Ecto.Changeset.change(user, bio: "test-bio")
  1568. assert {:ok, %User{bio: "test-bio"} = user} = User.update_and_set_cache(changeset)
  1569. assert {:ok, user} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}")
  1570. assert %User{bio: "test-bio"} = User.get_cached_by_ap_id(user.ap_id)
  1571. end
  1572. end
  1573. describe "following/followers synchronization" do
  1574. setup do: clear_config([:instance, :external_user_synchronization])
  1575. test "updates the counters normally on following/getting a follow when disabled" do
  1576. clear_config([:instance, :external_user_synchronization], false)
  1577. user = insert(:user)
  1578. other_user =
  1579. insert(:user,
  1580. local: false,
  1581. follower_address: "http://localhost:4001/users/masto_closed/followers",
  1582. following_address: "http://localhost:4001/users/masto_closed/following",
  1583. ap_enabled: true
  1584. )
  1585. assert other_user.following_count == 0
  1586. assert other_user.follower_count == 0
  1587. {:ok, user, other_user} = Pleroma.User.follow(user, other_user)
  1588. assert user.following_count == 1
  1589. assert other_user.follower_count == 1
  1590. end
  1591. test "syncronizes the counters with the remote instance for the followed when enabled" do
  1592. clear_config([:instance, :external_user_synchronization], false)
  1593. user = insert(:user)
  1594. other_user =
  1595. insert(:user,
  1596. local: false,
  1597. follower_address: "http://localhost:4001/users/masto_closed/followers",
  1598. following_address: "http://localhost:4001/users/masto_closed/following",
  1599. ap_enabled: true
  1600. )
  1601. assert other_user.following_count == 0
  1602. assert other_user.follower_count == 0
  1603. clear_config([:instance, :external_user_synchronization], true)
  1604. {:ok, _user, other_user} = User.follow(user, other_user)
  1605. assert other_user.follower_count == 437
  1606. end
  1607. test "syncronizes the counters with the remote instance for the follower when enabled" do
  1608. clear_config([:instance, :external_user_synchronization], false)
  1609. user = insert(:user)
  1610. other_user =
  1611. insert(:user,
  1612. local: false,
  1613. follower_address: "http://localhost:4001/users/masto_closed/followers",
  1614. following_address: "http://localhost:4001/users/masto_closed/following",
  1615. ap_enabled: true
  1616. )
  1617. assert other_user.following_count == 0
  1618. assert other_user.follower_count == 0
  1619. clear_config([:instance, :external_user_synchronization], true)
  1620. {:ok, other_user, _user} = User.follow(other_user, user)
  1621. assert other_user.following_count == 152
  1622. end
  1623. end
  1624. describe "change_email/2" do
  1625. setup do
  1626. [user: insert(:user)]
  1627. end
  1628. test "blank email returns error", %{user: user} do
  1629. assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, "")
  1630. assert {:error, %{errors: [email: {"can't be blank", _}]}} = User.change_email(user, nil)
  1631. end
  1632. test "non unique email returns error", %{user: user} do
  1633. %{email: email} = insert(:user)
  1634. assert {:error, %{errors: [email: {"has already been taken", _}]}} =
  1635. User.change_email(user, email)
  1636. end
  1637. test "invalid email returns error", %{user: user} do
  1638. assert {:error, %{errors: [email: {"has invalid format", _}]}} =
  1639. User.change_email(user, "cofe")
  1640. end
  1641. test "changes email", %{user: user} do
  1642. assert {:ok, %User{email: "cofe@cofe.party"}} = User.change_email(user, "cofe@cofe.party")
  1643. end
  1644. end
  1645. describe "get_cached_by_nickname_or_id" do
  1646. setup do
  1647. local_user = insert(:user)
  1648. remote_user = insert(:user, nickname: "nickname@example.com", local: false)
  1649. [local_user: local_user, remote_user: remote_user]
  1650. end
  1651. setup do: clear_config([:instance, :limit_to_local_content])
  1652. test "allows getting remote users by id no matter what :limit_to_local_content is set to", %{
  1653. remote_user: remote_user
  1654. } do
  1655. clear_config([:instance, :limit_to_local_content], false)
  1656. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1657. clear_config([:instance, :limit_to_local_content], true)
  1658. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1659. clear_config([:instance, :limit_to_local_content], :unauthenticated)
  1660. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.id)
  1661. end
  1662. test "disallows getting remote users by nickname without authentication when :limit_to_local_content is set to :unauthenticated",
  1663. %{remote_user: remote_user} do
  1664. clear_config([:instance, :limit_to_local_content], :unauthenticated)
  1665. assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
  1666. end
  1667. test "allows getting remote users by nickname with authentication when :limit_to_local_content is set to :unauthenticated",
  1668. %{remote_user: remote_user, local_user: local_user} do
  1669. clear_config([:instance, :limit_to_local_content], :unauthenticated)
  1670. assert %User{} = User.get_cached_by_nickname_or_id(remote_user.nickname, for: local_user)
  1671. end
  1672. test "disallows getting remote users by nickname when :limit_to_local_content is set to true",
  1673. %{remote_user: remote_user} do
  1674. clear_config([:instance, :limit_to_local_content], true)
  1675. assert nil == User.get_cached_by_nickname_or_id(remote_user.nickname)
  1676. end
  1677. test "allows getting local users by nickname no matter what :limit_to_local_content is set to",
  1678. %{local_user: local_user} do
  1679. clear_config([:instance, :limit_to_local_content], false)
  1680. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1681. clear_config([:instance, :limit_to_local_content], true)
  1682. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1683. clear_config([:instance, :limit_to_local_content], :unauthenticated)
  1684. assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname)
  1685. end
  1686. end
  1687. describe "update_email_notifications/2" do
  1688. setup do
  1689. user = insert(:user, email_notifications: %{"digest" => true})
  1690. {:ok, user: user}
  1691. end
  1692. test "Notifications are updated", %{user: user} do
  1693. true = user.email_notifications["digest"]
  1694. assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false})
  1695. assert result.email_notifications["digest"] == false
  1696. end
  1697. end
  1698. describe "local_nickname/1" do
  1699. test "returns nickname without host" do
  1700. assert User.local_nickname("@mentioned") == "mentioned"
  1701. assert User.local_nickname("a_local_nickname") == "a_local_nickname"
  1702. assert User.local_nickname("nickname@host.com") == "nickname"
  1703. end
  1704. end
  1705. describe "full_nickname/1" do
  1706. test "returns fully qualified nickname for local and remote users" do
  1707. local_user =
  1708. insert(:user, nickname: "local_user", ap_id: "https://somehost.com/users/local_user")
  1709. remote_user = insert(:user, nickname: "remote@host.com", local: false)
  1710. assert User.full_nickname(local_user) == "local_user@somehost.com"
  1711. assert User.full_nickname(remote_user) == "remote@host.com"
  1712. end
  1713. test "strips leading @ from mentions" do
  1714. assert User.full_nickname("@mentioned") == "mentioned"
  1715. assert User.full_nickname("@nickname@host.com") == "nickname@host.com"
  1716. end
  1717. test "does not modify nicknames" do
  1718. assert User.full_nickname("nickname") == "nickname"
  1719. assert User.full_nickname("nickname@host.com") == "nickname@host.com"
  1720. end
  1721. end
  1722. test "avatar fallback" do
  1723. user = insert(:user)
  1724. assert User.avatar_url(user) =~ "/images/avi.png"
  1725. clear_config([:assets, :default_user_avatar], "avatar.png")
  1726. user = User.get_cached_by_nickname_or_id(user.nickname)
  1727. assert User.avatar_url(user) =~ "avatar.png"
  1728. assert User.avatar_url(user, no_default: true) == nil
  1729. end
  1730. test "get_host/1" do
  1731. user = insert(:user, ap_id: "https://lain.com/users/lain", nickname: "lain")
  1732. assert User.get_host(user) == "lain.com"
  1733. end
  1734. test "update_last_active_at/1" do
  1735. user = insert(:user)
  1736. assert is_nil(user.last_active_at)
  1737. test_started_at = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
  1738. assert {:ok, user} = User.update_last_active_at(user)
  1739. assert user.last_active_at >= test_started_at
  1740. assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
  1741. last_active_at =
  1742. NaiveDateTime.utc_now()
  1743. |> NaiveDateTime.add(-:timer.hours(24), :millisecond)
  1744. |> NaiveDateTime.truncate(:second)
  1745. assert {:ok, user} =
  1746. user
  1747. |> cast(%{last_active_at: last_active_at}, [:last_active_at])
  1748. |> User.update_and_set_cache()
  1749. assert user.last_active_at == last_active_at
  1750. assert {:ok, user} = User.update_last_active_at(user)
  1751. assert user.last_active_at >= test_started_at
  1752. assert user.last_active_at <= NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)
  1753. end
  1754. test "active_user_count/1" do
  1755. insert(:user)
  1756. insert(:user, %{local: false})
  1757. insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -5)})
  1758. insert(:user, %{last_active_at: Timex.shift(NaiveDateTime.utc_now(), weeks: -3)})
  1759. insert(:user, %{last_active_at: NaiveDateTime.utc_now()})
  1760. assert User.active_user_count() == 2
  1761. assert User.active_user_count(6) == 3
  1762. assert User.active_user_count(1) == 1
  1763. end
  1764. end