Skip to content

Commit 87cdb5b

Browse files
imorlandStyleCIBot
andauthored
feat: Allow additional reset password params, introduce ForgotPasswordValidator (#3671)
* feat: Allow additional reset password params, introduce 'ForgotPasswordValidator' * Apply fixes from StyleCI Co-authored-by: StyleCI Bot <[email protected]>
1 parent bc4b0b8 commit 87cdb5b

File tree

3 files changed

+87
-38
lines changed

3 files changed

+87
-38
lines changed

framework/core/js/src/forum/components/ForgotPasswordModal.tsx

+50-24
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import extractText from '../../common/utils/extractText';
55
import Stream from '../../common/utils/Stream';
66
import Mithril from 'mithril';
77
import RequestError from '../../common/utils/RequestError';
8+
import ItemList from '../../common/utils/ItemList';
89

910
export interface IForgotPasswordModalAttrs extends IInternalModalAttrs {
1011
email?: string;
@@ -52,38 +53,55 @@ export default class ForgotPasswordModal<CustomAttrs extends IForgotPasswordModa
5253
);
5354
}
5455

55-
const emailLabel = extractText(app.translator.trans('core.forum.forgot_password.email_placeholder'));
56-
5756
return (
5857
<div className="Modal-body">
5958
<div className="Form Form--centered">
6059
<p className="helpText">{app.translator.trans('core.forum.forgot_password.text')}</p>
61-
<div className="Form-group">
62-
<input
63-
className="FormControl"
64-
name="email"
65-
type="email"
66-
placeholder={emailLabel}
67-
aria-label={emailLabel}
68-
bidi={this.email}
69-
disabled={this.loading}
70-
/>
71-
</div>
72-
<div className="Form-group">
73-
{Button.component(
74-
{
75-
className: 'Button Button--primary Button--block',
76-
type: 'submit',
77-
loading: this.loading,
78-
},
79-
app.translator.trans('core.forum.forgot_password.submit_button')
80-
)}
81-
</div>
60+
{this.fields().toArray()}
8261
</div>
8362
</div>
8463
);
8564
}
8665

66+
fields() {
67+
const items = new ItemList();
68+
69+
const emailLabel = extractText(app.translator.trans('core.forum.forgot_password.email_placeholder'));
70+
71+
items.add(
72+
'email',
73+
<div className="Form-group">
74+
<input
75+
className="FormControl"
76+
name="email"
77+
type="email"
78+
placeholder={emailLabel}
79+
aria-label={emailLabel}
80+
bidi={this.email}
81+
disabled={this.loading}
82+
/>
83+
</div>,
84+
50
85+
);
86+
87+
items.add(
88+
'submit',
89+
<div className="Form-group">
90+
{Button.component(
91+
{
92+
className: 'Button Button--primary Button--block',
93+
type: 'submit',
94+
loading: this.loading,
95+
},
96+
app.translator.trans('core.forum.forgot_password.submit_button')
97+
)}
98+
</div>,
99+
-10
100+
);
101+
102+
return items;
103+
}
104+
87105
onsubmit(e: SubmitEvent) {
88106
e.preventDefault();
89107

@@ -93,7 +111,7 @@ export default class ForgotPasswordModal<CustomAttrs extends IForgotPasswordModa
93111
.request({
94112
method: 'POST',
95113
url: app.forum.attribute('apiUrl') + '/forgot',
96-
body: { email: this.email() },
114+
body: this.requestParams(),
97115
errorHandler: this.onerror.bind(this),
98116
})
99117
.then(() => {
@@ -104,6 +122,14 @@ export default class ForgotPasswordModal<CustomAttrs extends IForgotPasswordModa
104122
.then(this.loaded.bind(this));
105123
}
106124

125+
requestParams(): Record<string, unknown> {
126+
const data = {
127+
email: this.email(),
128+
};
129+
130+
return data;
131+
}
132+
107133
onerror(error: RequestError) {
108134
if (error.status === 404 && error.alert) {
109135
error.alert.content = app.translator.trans('core.forum.forgot_password.not_found_message');

framework/core/src/Api/Controller/ForgotPasswordController.php

+8-14
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99

1010
namespace Flarum\Api\Controller;
1111

12+
use Flarum\Api\ForgotPasswordValidator;
1213
use Flarum\User\Job\RequestPasswordResetJob;
1314
use Illuminate\Contracts\Queue\Queue;
14-
use Illuminate\Contracts\Validation\Factory;
1515
use Illuminate\Support\Arr;
16-
use Illuminate\Validation\ValidationException;
1716
use Laminas\Diactoros\Response\EmptyResponse;
1817
use Psr\Http\Message\ResponseInterface;
1918
use Psr\Http\Message\ServerRequestInterface;
@@ -27,31 +26,26 @@ class ForgotPasswordController implements RequestHandlerInterface
2726
protected $queue;
2827

2928
/**
30-
* @var Factory
29+
* @var ForgotPasswordValidator
3130
*/
32-
protected $validatorFactory;
31+
protected $validator;
3332

34-
public function __construct(Queue $queue, Factory $validatorFactory)
33+
public function __construct(Queue $queue, ForgotPasswordValidator $validator)
3534
{
3635
$this->queue = $queue;
37-
$this->validatorFactory = $validatorFactory;
36+
$this->validator = $validator;
3837
}
3938

4039
/**
4140
* {@inheritdoc}
4241
*/
4342
public function handle(ServerRequestInterface $request): ResponseInterface
4443
{
45-
$email = Arr::get($request->getParsedBody(), 'email');
44+
$params = $request->getParsedBody();
4645

47-
$validation = $this->validatorFactory->make(
48-
compact('email'),
49-
['email' => 'required|email']
50-
);
46+
$this->validator->assertValid($params);
5147

52-
if ($validation->fails()) {
53-
throw new ValidationException($validation);
54-
}
48+
$email = Arr::get($params, 'email');
5549

5650
// Prevents leaking user existence by not throwing an error.
5751
// Prevents leaking user existence by duration by using a queued job.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Flarum.
5+
*
6+
* For detailed copyright and license information, please view the
7+
* LICENSE file that was distributed with this source code.
8+
*/
9+
10+
namespace Flarum\Api;
11+
12+
/*
13+
* This file is part of Flarum.
14+
*
15+
* For detailed copyright and license information, please view the
16+
* LICENSE file that was distributed with this source code.
17+
*/
18+
19+
use Flarum\Foundation\AbstractValidator;
20+
21+
class ForgotPasswordValidator extends AbstractValidator
22+
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
protected $rules = [
27+
'email' => ['required', 'email']
28+
];
29+
}

0 commit comments

Comments
 (0)