1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Mix.Tasks.Pleroma.UserTest do
10 alias Pleroma.Tests.ObanHelpers
12 alias Pleroma.Web.CommonAPI
13 alias Pleroma.Web.OAuth.Authorization
14 alias Pleroma.Web.OAuth.Token
17 use Oban.Testing, repo: Pleroma.Repo
19 import ExUnit.CaptureIO
21 import Pleroma.Factory
24 Mox.stub_with(Pleroma.UnstubbedConfigMock, Pleroma.Config)
29 Mix.shell(Mix.Shell.Process)
32 Mix.shell(Mix.Shell.IO)
38 describe "running new" do
39 test "user is created" do
40 # just get random data
41 unsaved = build(:user)
43 # prepare to answer yes
44 send(self(), {:mix_shell_input, :prompt, "Y"})
46 Mix.Tasks.Pleroma.User.run([
60 assert_received {:mix_shell, :info, [message]}
61 assert message =~ "user will be created"
63 assert_received {:mix_shell, :prompt, [message]}
64 assert message =~ "Continue"
66 assert_received {:mix_shell, :info, [message]}
67 assert message =~ "created"
69 user = User.get_cached_by_nickname(unsaved.nickname)
70 assert user.name == unsaved.name
71 assert user.email == unsaved.email
72 assert user.bio == unsaved.bio
73 assert user.is_moderator
77 test "user is not created" do
78 unsaved = build(:user)
80 # prepare to answer no
81 send(self(), {:mix_shell_input, :prompt, "N"})
83 Mix.Tasks.Pleroma.User.run(["new", unsaved.nickname, unsaved.email])
85 assert_received {:mix_shell, :info, [message]}
86 assert message =~ "user will be created"
88 assert_received {:mix_shell, :prompt, [message]}
89 assert message =~ "Continue"
91 assert_received {:mix_shell, :info, [message]}
92 assert message =~ "will not be created"
94 refute User.get_cached_by_nickname(unsaved.nickname)
98 describe "running rm" do
99 test "user is deleted" do
100 clear_config([:instance, :federating], true)
103 with_mock Pleroma.Web.Federator,
104 publish: fn _ -> nil end do
105 Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
106 ObanHelpers.perform_all()
108 assert_received {:mix_shell, :info, [message]}
109 assert message =~ " deleted"
110 assert %{is_active: false} = User.get_by_nickname(user.nickname)
112 assert called(Pleroma.Web.Federator.publish(:_))
116 test "a remote user's create activity is deleted when the object has been pruned" do
118 user2 = insert(:user)
120 {:ok, post} = CommonAPI.post(user, %{status: "uguu"})
121 {:ok, post2} = CommonAPI.post(user2, %{status: "test"})
122 obj = Object.normalize(post2, fetch: false)
124 {:ok, like_object, meta} = Pleroma.Web.ActivityPub.Builder.like(user, obj)
126 {:ok, like_activity, _meta} =
127 Pleroma.Web.ActivityPub.Pipeline.common_pipeline(
129 Keyword.put(meta, :local, true)
132 like_activity.data["object"]
133 |> Pleroma.Object.get_by_ap_id()
136 clear_config([:instance, :federating], true)
138 object = Object.normalize(post, fetch: false)
141 with_mock Pleroma.Web.Federator,
142 publish: fn _ -> nil end do
143 Mix.Tasks.Pleroma.User.run(["rm", user.nickname])
144 ObanHelpers.perform_all()
146 assert_received {:mix_shell, :info, [message]}
147 assert message =~ " deleted"
148 assert %{is_active: false} = User.get_by_nickname(user.nickname)
150 assert called(Pleroma.Web.Federator.publish(:_))
151 refute Pleroma.Repo.get(Pleroma.Activity, like_activity.id)
154 refute Activity.get_by_id(post.id)
157 test "no user to delete" do
158 Mix.Tasks.Pleroma.User.run(["rm", "nonexistent"])
160 assert_received {:mix_shell, :error, [message]}
161 assert message =~ "No local user"
165 describe "running deactivate" do
166 test "active user is deactivated and unsubscribed" do
167 followed = insert(:user)
168 remote_followed = insert(:user, local: false)
171 User.follow(user, followed, :follow_accept)
172 User.follow(user, remote_followed, :follow_accept)
174 Mix.Tasks.Pleroma.User.run(["deactivate", user.nickname])
176 # Note that the task has delay :timer.sleep(500)
177 assert_received {:mix_shell, :info, [message]}
180 "Successfully deactivated #{user.nickname} and unsubscribed all local followers"
182 user = User.get_cached_by_nickname(user.nickname)
183 assert Enum.empty?(Enum.filter(User.get_friends(user), & &1.local))
184 refute user.is_active
187 test "user is deactivated" do
188 %{id: id, nickname: nickname} = insert(:user, is_active: false)
190 assert :ok = Mix.Tasks.Pleroma.User.run(["deactivate", nickname])
191 assert_received {:mix_shell, :info, [message]}
192 assert message == "User #{nickname} already deactivated"
194 user = Repo.get(User, id)
195 refute user.is_active
198 test "no user to deactivate" do
199 Mix.Tasks.Pleroma.User.run(["deactivate", "nonexistent"])
201 assert_received {:mix_shell, :error, [message]}
202 assert message =~ "No user"
206 describe "running set" do
207 test "All statuses set" do
210 Mix.Tasks.Pleroma.User.run([
219 assert_received {:mix_shell, :info, [message]}
220 assert message =~ ~r/Admin status .* true/
222 assert_received {:mix_shell, :info, [message]}
223 assert message =~ ~r/Confirmation status.* true/
225 assert_received {:mix_shell, :info, [message]}
226 assert message =~ ~r/Locked status .* true/
228 assert_received {:mix_shell, :info, [message]}
229 assert message =~ ~r/Moderator status .* true/
231 user = User.get_cached_by_nickname(user.nickname)
232 assert user.is_moderator
233 assert user.is_locked
235 assert user.is_confirmed
238 test "All statuses unset" do
247 Mix.Tasks.Pleroma.User.run([
256 assert_received {:mix_shell, :info, [message]}
257 assert message =~ ~r/Admin status .* false/
259 assert_received {:mix_shell, :info, [message]}
260 assert message =~ ~r/Confirmation status.* false/
262 assert_received {:mix_shell, :info, [message]}
263 assert message =~ ~r/Locked status .* false/
265 assert_received {:mix_shell, :info, [message]}
266 assert message =~ ~r/Moderator status .* false/
268 user = User.get_cached_by_nickname(user.nickname)
269 refute user.is_moderator
270 refute user.is_locked
272 refute user.is_confirmed
275 test "no user to set status" do
276 Mix.Tasks.Pleroma.User.run(["set", "nonexistent", "--moderator"])
278 assert_received {:mix_shell, :error, [message]}
279 assert message =~ "No local user"
283 describe "running reset_password" do
284 test "password reset token is generated" do
287 assert capture_io(fn ->
288 Mix.Tasks.Pleroma.User.run(["reset_password", user.nickname])
291 assert_received {:mix_shell, :info, [message]}
292 assert message =~ "Generated"
295 test "no user to reset password" do
296 Mix.Tasks.Pleroma.User.run(["reset_password", "nonexistent"])
298 assert_received {:mix_shell, :error, [message]}
299 assert message =~ "No local user"
303 describe "running reset_mfa" do
304 test "disables MFA" do
307 multi_factor_authentication_settings: %MFA.Settings{
309 totp: %MFA.Settings.TOTP{secret: "xx", confirmed: true}
313 Mix.Tasks.Pleroma.User.run(["reset_mfa", user.nickname])
315 assert_received {:mix_shell, :info, [message]}
316 assert message == "Multi-Factor Authentication disabled for #{user.nickname}"
318 assert %{enabled: false, totp: false} ==
320 |> User.get_cached_by_nickname()
321 |> MFA.mfa_settings()
324 test "no user to reset MFA" do
325 Mix.Tasks.Pleroma.User.run(["reset_password", "nonexistent"])
327 assert_received {:mix_shell, :error, [message]}
328 assert message =~ "No local user"
332 describe "running invite" do
333 test "invite token is generated" do
334 assert capture_io(fn ->
335 Mix.Tasks.Pleroma.User.run(["invite"])
338 assert_received {:mix_shell, :info, [message]}
339 assert message =~ "Generated user invite token one time"
342 test "token is generated with expires_at" do
343 assert capture_io(fn ->
344 Mix.Tasks.Pleroma.User.run([
347 Date.to_string(Date.utc_today())
351 assert_received {:mix_shell, :info, [message]}
352 assert message =~ "Generated user invite token date limited"
355 test "token is generated with max use" do
356 assert capture_io(fn ->
357 Mix.Tasks.Pleroma.User.run([
364 assert_received {:mix_shell, :info, [message]}
365 assert message =~ "Generated user invite token reusable"
368 test "token is generated with max use and expires date" do
369 assert capture_io(fn ->
370 Mix.Tasks.Pleroma.User.run([
375 Date.to_string(Date.utc_today())
379 assert_received {:mix_shell, :info, [message]}
380 assert message =~ "Generated user invite token reusable date limited"
384 describe "running invites" do
385 test "invites are listed" do
386 {:ok, invite} = Pleroma.UserInviteToken.create_invite()
389 Pleroma.UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 15})
391 # assert capture_io(fn ->
392 Mix.Tasks.Pleroma.User.run([
398 assert_received {:mix_shell, :info, [message]}
399 assert_received {:mix_shell, :info, [message2]}
400 assert_received {:mix_shell, :info, [message3]}
401 assert message =~ "Invites list:"
402 assert message2 =~ invite.invite_type
403 assert message3 =~ invite2.invite_type
407 describe "running revoke_invite" do
408 test "invite is revoked" do
409 {:ok, invite} = Pleroma.UserInviteToken.create_invite(%{expires_at: Date.utc_today()})
411 assert capture_io(fn ->
412 Mix.Tasks.Pleroma.User.run([
418 assert_received {:mix_shell, :info, [message]}
419 assert message =~ "Invite for token #{invite.token} was revoked."
423 describe "running delete_activities" do
424 test "activities are deleted" do
425 %{nickname: nickname} = insert(:user)
427 assert :ok == Mix.Tasks.Pleroma.User.run(["delete_activities", nickname])
428 assert_received {:mix_shell, :info, [message]}
429 assert message == "User #{nickname} statuses deleted."
432 test "it prints an error message when user is not exist" do
433 Mix.Tasks.Pleroma.User.run(["delete_activities", "foo"])
435 assert_received {:mix_shell, :error, [message]}
436 assert message =~ "No local user"
440 describe "running confirm" do
441 test "user is confirmed" do
442 %{id: id, nickname: nickname} = insert(:user, is_confirmed: true)
444 assert :ok = Mix.Tasks.Pleroma.User.run(["confirm", nickname])
445 assert_received {:mix_shell, :info, [message]}
446 assert message == "#{nickname} doesn't need confirmation."
448 user = Repo.get(User, id)
449 assert user.is_confirmed
450 refute user.confirmation_token
453 test "user is not confirmed" do
454 %{id: id, nickname: nickname} =
455 insert(:user, is_confirmed: false, confirmation_token: "some token")
457 assert :ok = Mix.Tasks.Pleroma.User.run(["confirm", nickname])
458 assert_received {:mix_shell, :info, [message]}
459 assert message == "#{nickname} doesn't need confirmation."
461 user = Repo.get(User, id)
462 assert user.is_confirmed
463 refute user.confirmation_token
466 test "it prints an error message when user is not exist" do
467 Mix.Tasks.Pleroma.User.run(["confirm", "foo"])
469 assert_received {:mix_shell, :error, [message]}
470 assert message =~ "No local user"
474 describe "running activate" do
475 test "user is activated" do
476 %{id: id, nickname: nickname} = insert(:user, is_active: true)
478 assert :ok = Mix.Tasks.Pleroma.User.run(["activate", nickname])
479 assert_received {:mix_shell, :info, [message]}
480 assert message == "User #{nickname} already activated"
482 user = Repo.get(User, id)
483 assert user.is_active
486 test "user is not activated" do
487 %{id: id, nickname: nickname} = insert(:user, is_active: false)
489 assert :ok = Mix.Tasks.Pleroma.User.run(["activate", nickname])
490 assert_received {:mix_shell, :info, [message]}
491 assert message == "Successfully activated #{nickname}"
493 user = Repo.get(User, id)
494 assert user.is_active
497 test "no user to activate" do
498 Mix.Tasks.Pleroma.User.run(["activate", "foo"])
500 assert_received {:mix_shell, :error, [message]}
501 assert message =~ "No user"
506 test "it returns users matching" do
508 moon = insert(:user, nickname: "moon", name: "fediverse expert moon")
509 moot = insert(:user, nickname: "moot")
510 kawen = insert(:user, nickname: "kawen", name: "fediverse expert moon")
512 {:ok, user, moon} = User.follow(user, moon)
514 assert [moon.id, kawen.id] == User.Search.search("moon") |> Enum.map(& &1.id)
516 res = User.search("moo") |> Enum.map(& &1.id)
517 assert Enum.sort([moon.id, moot.id, kawen.id]) == Enum.sort(res)
519 assert [kawen.id, moon.id] == User.Search.search("expert fediverse") |> Enum.map(& &1.id)
521 assert [moon.id, kawen.id] ==
522 User.Search.search("expert fediverse", for_user: user) |> Enum.map(& &1.id)
526 describe "signing out" do
527 test "it deletes all user's tokens and authorizations" do
529 insert(:oauth_token, user: user)
530 insert(:oauth_authorization, user: user)
532 assert Repo.get_by(Token, user_id: user.id)
533 assert Repo.get_by(Authorization, user_id: user.id)
535 :ok = Mix.Tasks.Pleroma.User.run(["sign_out", user.nickname])
537 refute Repo.get_by(Token, user_id: user.id)
538 refute Repo.get_by(Authorization, user_id: user.id)
541 test "it prints an error message when user is not exist" do
542 Mix.Tasks.Pleroma.User.run(["sign_out", "foo"])
544 assert_received {:mix_shell, :error, [message]}
545 assert message =~ "No local user"
549 describe "tagging" do
550 test "it add tags to a user" do
553 :ok = Mix.Tasks.Pleroma.User.run(["tag", user.nickname, "pleroma"])
555 user = User.get_cached_by_nickname(user.nickname)
556 assert "pleroma" in user.tags
559 test "it prints an error message when user is not exist" do
560 Mix.Tasks.Pleroma.User.run(["tag", "foo"])
562 assert_received {:mix_shell, :error, [message]}
563 assert message =~ "Could not change user tags"
567 describe "untagging" do
568 test "it deletes tags from a user" do
569 user = insert(:user, tags: ["pleroma"])
570 assert "pleroma" in user.tags
572 :ok = Mix.Tasks.Pleroma.User.run(["untag", user.nickname, "pleroma"])
574 user = User.get_cached_by_nickname(user.nickname)
575 assert Enum.empty?(user.tags)
578 test "it prints an error message when user is not exist" do
579 Mix.Tasks.Pleroma.User.run(["untag", "foo"])
581 assert_received {:mix_shell, :error, [message]}
582 assert message =~ "Could not change user tags"
586 describe "bulk confirm and unconfirm" do
587 test "confirm all" do
588 user1 = insert(:user, is_confirmed: false)
589 user2 = insert(:user, is_confirmed: false)
591 refute user1.is_confirmed
592 refute user2.is_confirmed
594 Mix.Tasks.Pleroma.User.run(["confirm_all"])
596 user1 = User.get_cached_by_nickname(user1.nickname)
597 user2 = User.get_cached_by_nickname(user2.nickname)
599 assert user1.is_confirmed
600 assert user2.is_confirmed
603 test "unconfirm all" do
604 user1 = insert(:user, is_confirmed: true)
605 user2 = insert(:user, is_confirmed: true)
606 admin = insert(:user, is_admin: true, is_confirmed: true)
607 mod = insert(:user, is_moderator: true, is_confirmed: true)
609 assert user1.is_confirmed
610 assert user2.is_confirmed
612 Mix.Tasks.Pleroma.User.run(["unconfirm_all"])
614 user1 = User.get_cached_by_nickname(user1.nickname)
615 user2 = User.get_cached_by_nickname(user2.nickname)
616 admin = User.get_cached_by_nickname(admin.nickname)
617 mod = User.get_cached_by_nickname(mod.nickname)
619 refute user1.is_confirmed
620 refute user2.is_confirmed
621 assert admin.is_confirmed
622 assert mod.is_confirmed