diff --git a/framework/core/js/src/forum/components/ForgotPasswordModal.tsx b/framework/core/js/src/forum/components/ForgotPasswordModal.tsx index d3da52a9b..eee707b23 100644 --- a/framework/core/js/src/forum/components/ForgotPasswordModal.tsx +++ b/framework/core/js/src/forum/components/ForgotPasswordModal.tsx @@ -5,6 +5,7 @@ import extractText from '../../common/utils/extractText'; import Stream from '../../common/utils/Stream'; import Mithril from 'mithril'; import RequestError from '../../common/utils/RequestError'; +import ItemList from '../../common/utils/ItemList'; export interface IForgotPasswordModalAttrs extends IInternalModalAttrs { email?: string; @@ -52,38 +53,55 @@ export default class ForgotPasswordModal

{app.translator.trans('core.forum.forgot_password.text')}

-
- -
-
- {Button.component( - { - className: 'Button Button--primary Button--block', - type: 'submit', - loading: this.loading, - }, - app.translator.trans('core.forum.forgot_password.submit_button') - )} -
+ {this.fields().toArray()}
); } + fields() { + const items = new ItemList(); + + const emailLabel = extractText(app.translator.trans('core.forum.forgot_password.email_placeholder')); + + items.add( + 'email', +
+ +
, + 50 + ); + + items.add( + 'submit', +
+ {Button.component( + { + className: 'Button Button--primary Button--block', + type: 'submit', + loading: this.loading, + }, + app.translator.trans('core.forum.forgot_password.submit_button') + )} +
, + -10 + ); + + return items; + } + onsubmit(e: SubmitEvent) { e.preventDefault(); @@ -93,7 +111,7 @@ export default class ForgotPasswordModal { @@ -104,6 +122,14 @@ export default class ForgotPasswordModal { + const data = { + email: this.email(), + }; + + return data; + } + onerror(error: RequestError) { if (error.status === 404 && error.alert) { error.alert.content = app.translator.trans('core.forum.forgot_password.not_found_message'); diff --git a/framework/core/src/Api/Controller/ForgotPasswordController.php b/framework/core/src/Api/Controller/ForgotPasswordController.php index 43c5a15c4..1bb741fa2 100644 --- a/framework/core/src/Api/Controller/ForgotPasswordController.php +++ b/framework/core/src/Api/Controller/ForgotPasswordController.php @@ -9,11 +9,10 @@ namespace Flarum\Api\Controller; +use Flarum\Api\ForgotPasswordValidator; use Flarum\User\Job\RequestPasswordResetJob; use Illuminate\Contracts\Queue\Queue; -use Illuminate\Contracts\Validation\Factory; use Illuminate\Support\Arr; -use Illuminate\Validation\ValidationException; use Laminas\Diactoros\Response\EmptyResponse; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -27,14 +26,14 @@ class ForgotPasswordController implements RequestHandlerInterface protected $queue; /** - * @var Factory + * @var ForgotPasswordValidator */ - protected $validatorFactory; + protected $validator; - public function __construct(Queue $queue, Factory $validatorFactory) + public function __construct(Queue $queue, ForgotPasswordValidator $validator) { $this->queue = $queue; - $this->validatorFactory = $validatorFactory; + $this->validator = $validator; } /** @@ -42,16 +41,11 @@ class ForgotPasswordController implements RequestHandlerInterface */ public function handle(ServerRequestInterface $request): ResponseInterface { - $email = Arr::get($request->getParsedBody(), 'email'); + $params = $request->getParsedBody(); - $validation = $this->validatorFactory->make( - compact('email'), - ['email' => 'required|email'] - ); + $this->validator->assertValid($params); - if ($validation->fails()) { - throw new ValidationException($validation); - } + $email = Arr::get($params, 'email'); // Prevents leaking user existence by not throwing an error. // Prevents leaking user existence by duration by using a queued job. diff --git a/framework/core/src/Api/ForgotPasswordValidator.php b/framework/core/src/Api/ForgotPasswordValidator.php new file mode 100644 index 000000000..80f596c31 --- /dev/null +++ b/framework/core/src/Api/ForgotPasswordValidator.php @@ -0,0 +1,29 @@ + ['required', 'email'] + ]; +}