Merge remote-tracking branch 'origin/develop' into live-dashboard
[akkoma] / test / pleroma / web / twitter_api / password_controller_test.exs
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
5 defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do
6 use Pleroma.Web.ConnCase
7
8 alias Pleroma.Config
9 alias Pleroma.PasswordResetToken
10 alias Pleroma.Repo
11 alias Pleroma.Tests.ObanHelpers
12 alias Pleroma.User
13 alias Pleroma.Web.OAuth.Token
14 import Pleroma.Factory
15 import Swoosh.TestAssertions
16
17 describe "GET /api/pleroma/password_reset/token" do
18 test "it returns error when token invalid", %{conn: conn} do
19 response =
20 conn
21 |> get("/api/pleroma/password_reset/token")
22 |> html_response(:ok)
23
24 assert response =~ "<h2>Invalid Token</h2>"
25 end
26
27 test "it shows password reset form", %{conn: conn} do
28 user = insert(:user)
29 {:ok, token} = PasswordResetToken.create_token(user)
30
31 response =
32 conn
33 |> get("/api/pleroma/password_reset/#{token.token}")
34 |> html_response(:ok)
35
36 assert response =~ "<h2>Password Reset for #{user.nickname}</h2>"
37 end
38
39 test "it returns an error when the token has expired", %{conn: conn} do
40 clear_config([:instance, :password_reset_token_validity], 0)
41
42 user = insert(:user)
43 {:ok, token} = PasswordResetToken.create_token(user)
44 {:ok, token} = time_travel(token, -2)
45
46 response =
47 conn
48 |> get("/api/pleroma/password_reset/#{token.token}")
49 |> html_response(:ok)
50
51 assert response =~ "<h2>Invalid Token</h2>"
52 end
53 end
54
55 describe "POST /api/pleroma/password_reset" do
56 test "it fails for an expired token", %{conn: conn} do
57 clear_config([:instance, :password_reset_token_validity], 0)
58
59 user = insert(:user)
60 {:ok, token} = PasswordResetToken.create_token(user)
61 {:ok, token} = time_travel(token, -2)
62 {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})
63
64 params = %{
65 "password" => "test",
66 password_confirmation: "test",
67 token: token.token
68 }
69
70 response =
71 conn
72 |> assign(:user, user)
73 |> post("/api/pleroma/password_reset", %{data: params})
74 |> html_response(:ok)
75
76 refute response =~ "<h2>Password changed!</h2>"
77 end
78
79 test "it returns HTTP 200", %{conn: conn} do
80 user = insert(:user)
81 {:ok, token} = PasswordResetToken.create_token(user)
82 {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})
83
84 params = %{
85 "password" => "test",
86 password_confirmation: "test",
87 token: token.token
88 }
89
90 response =
91 conn
92 |> assign(:user, user)
93 |> post("/api/pleroma/password_reset", %{data: params})
94 |> html_response(:ok)
95
96 assert response =~ "<h2>Password changed!</h2>"
97
98 user = refresh_record(user)
99 assert Pleroma.Password.Pbkdf2.verify_pass("test", user.password_hash)
100 assert Enum.empty?(Token.get_user_tokens(user))
101 end
102
103 test "it sets password_reset_pending to false", %{conn: conn} do
104 user = insert(:user, password_reset_pending: true)
105
106 {:ok, token} = PasswordResetToken.create_token(user)
107 {:ok, _access_token} = Token.create(insert(:oauth_app), user, %{})
108
109 params = %{
110 "password" => "test",
111 password_confirmation: "test",
112 token: token.token
113 }
114
115 conn
116 |> assign(:user, user)
117 |> post("/api/pleroma/password_reset", %{data: params})
118 |> html_response(:ok)
119
120 assert User.get_by_id(user.id).password_reset_pending == false
121 end
122 end
123
124 describe "POST /auth/password, with valid parameters" do
125 setup %{conn: conn} do
126 user = insert(:user)
127 conn = post(conn, "/auth/password?email=#{user.email}")
128 %{conn: conn, user: user}
129 end
130
131 test "it returns 204", %{conn: conn} do
132 assert empty_json_response(conn)
133 end
134
135 test "it creates a PasswordResetToken record for user", %{user: user} do
136 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
137 assert token_record
138 end
139
140 test "it sends an email to user", %{user: user} do
141 ObanHelpers.perform_all()
142 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
143
144 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
145 notify_email = Config.get([:instance, :notify_email])
146 instance_name = Config.get([:instance, :name])
147
148 assert_email_sent(
149 from: {instance_name, notify_email},
150 to: {user.name, user.email},
151 html_body: email.html_body
152 )
153 end
154 end
155
156 describe "POST /auth/password, with nickname" do
157 test "it returns 204", %{conn: conn} do
158 user = insert(:user)
159
160 assert conn
161 |> post("/auth/password?nickname=#{user.nickname}")
162 |> empty_json_response()
163
164 ObanHelpers.perform_all()
165 token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
166
167 email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
168 notify_email = Config.get([:instance, :notify_email])
169 instance_name = Config.get([:instance, :name])
170
171 assert_email_sent(
172 from: {instance_name, notify_email},
173 to: {user.name, user.email},
174 html_body: email.html_body
175 )
176 end
177
178 test "it doesn't fail when a user has no email", %{conn: conn} do
179 user = insert(:user, %{email: nil})
180
181 assert conn
182 |> post("/auth/password?nickname=#{user.nickname}")
183 |> empty_json_response()
184 end
185 end
186
187 describe "POST /auth/password, with invalid parameters" do
188 setup do
189 user = insert(:user)
190 {:ok, user: user}
191 end
192
193 test "it returns 204 when user is not found", %{conn: conn, user: user} do
194 conn = post(conn, "/auth/password?email=nonexisting_#{user.email}")
195
196 assert empty_json_response(conn)
197 end
198
199 test "it returns 204 when user is not local", %{conn: conn, user: user} do
200 {:ok, user} = Repo.update(Ecto.Changeset.change(user, local: false))
201 conn = post(conn, "/auth/password?email=#{user.email}")
202
203 assert empty_json_response(conn)
204 end
205
206 test "it returns 204 when user is deactivated", %{conn: conn, user: user} do
207 {:ok, user} = Repo.update(Ecto.Changeset.change(user, is_active: false, local: true))
208 conn = post(conn, "/auth/password?email=#{user.email}")
209
210 assert empty_json_response(conn)
211 end
212 end
213 end