Skip to content

Commit 32352c2

Browse files
committed
Include username tovalidate when using the reset password
1 parent f48b687 commit 32352c2

4 files changed

Lines changed: 92 additions & 1 deletion

File tree

ProcessMaker/Http/Controllers/Auth/ResetPasswordController.php

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Illuminate\Foundation\Auth\ResetsPasswords;
66
use Illuminate\Http\Request;
7+
use Illuminate\Validation\Rules\Password;
8+
use Illuminate\Validation\ValidationException;
79
use ProcessMaker\Http\Controllers\Controller;
810
use ProcessMaker\Models\User;
911

@@ -76,7 +78,9 @@ public function showResetForm(Request $request, $token)
7678
*/
7779
public function reset(Request $request)
7880
{
79-
$user = User::where('email', $request->input('email'))->first();
81+
$user = User::where('email', $request->input('email'))
82+
->where('username', $request->input('username'))
83+
->first();
8084

8185
if ($user && $user->status === 'BLOCKED') {
8286
return $this->sendResetFailedResponse($request, 'passwords.blocked');
@@ -86,6 +90,56 @@ public function reset(Request $request)
8690
return $this->sendResetFailedResponse($request, 'passwords.inactive');
8791
}
8892

93+
if (!$user) {
94+
return redirect()->back()
95+
->withInput($request->only('email', 'username'))
96+
->withErrors(['email' => __('passwords.account_not_found')]);
97+
}
98+
8999
return $this->performPasswordReset($request);
90100
}
101+
102+
/**
103+
* Get the password reset validation rules.
104+
*/
105+
protected function rules(): array
106+
{
107+
return [
108+
'token' => 'required',
109+
'email' => 'required|email',
110+
'username' => 'required|string',
111+
'password' => ['required', 'confirmed', Password::defaults()],
112+
];
113+
}
114+
115+
/**
116+
* Get the password reset credentials from the request.
117+
* Include username so the broker resolves the same user as email+username (not email alone).
118+
*/
119+
protected function credentials(Request $request): array
120+
{
121+
return $request->only(
122+
'email',
123+
'username',
124+
'password',
125+
'password_confirmation',
126+
'token'
127+
);
128+
}
129+
130+
/**
131+
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
132+
*/
133+
protected function sendResetFailedResponse(Request $request, $response)
134+
{
135+
if ($request->wantsJson()) {
136+
throw ValidationException::withMessages([
137+
'email' => [trans($response)],
138+
]);
139+
}
140+
141+
return redirect()->back()
142+
->withInput($request->only('email', 'username'))
143+
->withErrors(['email' => trans($response)]);
144+
}
91145
}

resources/lang/en/passwords.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020
'user' => "We can't find a user with that email address.",
2121
'blocked' => 'Your account has been blocked. Please contact your administrator.',
2222
'inactive' => 'Your account is inactive. Please contact your administrator.',
23+
'account_not_found' => 'We could not find an account with the data provided.',
2324

2425
];

resources/views/auth/passwords/reset.blade.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
@endif
2525

2626
</div>
27+
<div class="form-group">
28+
<label for="username">{{__('Username')}}</label>
29+
<input id="username" type="text" class="form-control" name="username" value="{{ old('username') }}" autocomplete="username" autocapitalize="none" spellcheck="false">
30+
</div>
2731
<div class="form-group">
2832
<label for="password">{{__('New Password')}}</label>
2933
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password">

tests/Feature/Auth/PasswordResetTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public function testResetPasswordRejectsBlockedUser(): void
123123
$response = $this->from(route('password.request'))->post('/password/reset', [
124124
'token' => 'will-not-be-used',
125125
'email' => $user->email,
126+
'username' => $user->username,
126127
'password' => 'NewPassword123!',
127128
'password_confirmation' => 'NewPassword123!',
128129
]);
@@ -142,6 +143,7 @@ public function testResetPasswordRejectsInactiveUser(): void
142143
$response = $this->from(route('password.request'))->post('/password/reset', [
143144
'token' => 'will-not-be-used',
144145
'email' => $user->email,
146+
'username' => $user->username,
145147
'password' => 'NewPassword123!',
146148
'password_confirmation' => 'NewPassword123!',
147149
]);
@@ -151,6 +153,35 @@ public function testResetPasswordRejectsInactiveUser(): void
151153
]);
152154
}
153155

156+
public function testResetPasswordRejectsWrongUsername(): void
157+
{
158+
/** @var User $user */
159+
$user = User::factory()->create([
160+
'email' => 'wrong-username-reset@example.com',
161+
'username' => 'correct_username',
162+
'status' => 'ACTIVE',
163+
]);
164+
165+
/** @var ConcretePasswordBroker $broker */
166+
$broker = Password::broker();
167+
$token = $broker->createToken($user);
168+
169+
$response = $this->from(route('password.reset', ['token' => $token]))->post('/password/reset', [
170+
'token' => $token,
171+
'email' => $user->email,
172+
'username' => 'some_other_username',
173+
'password' => 'NewSecurePass123!',
174+
'password_confirmation' => 'NewSecurePass123!',
175+
]);
176+
177+
$response->assertSessionHasErrors([
178+
'email' => __('passwords.account_not_found'),
179+
]);
180+
181+
$user->refresh();
182+
$this->assertTrue(Hash::check('oneOnlyPassword', $user->password));
183+
}
184+
154185
public function testResetPasswordUpdatesPasswordForActiveUser(): void
155186
{
156187
/** @var User $user */
@@ -167,6 +198,7 @@ public function testResetPasswordUpdatesPasswordForActiveUser(): void
167198
$response = $this->post('/password/reset', [
168199
'token' => $token,
169200
'email' => $user->email,
201+
'username' => $user->username,
170202
'password' => $plaintextSecret,
171203
'password_confirmation' => $plaintextSecret,
172204
]);

0 commit comments

Comments
 (0)