Issues (281)

Branch: master

Modules/Authentication/Actions/ResetPassword.php (2 issues)

1
<?php
2
3
namespace Backend\Modules\Authentication\Actions;
4
5
use Backend\Core\Engine\Base\ActionAdd as BackendBaseActionAdd;
6
use Backend\Core\Engine\Authentication as BackendAuthentication;
7
use Backend\Core\Engine\Form as BackendForm;
8
use Backend\Core\Engine\Model as BackendModel;
9
use Backend\Core\Language\Language as BL;
10
use Backend\Core\Engine\User as BackendUser;
11
use Backend\Modules\Users\Engine\Model as BackendUsersModel;
12
13
/**
14
 * This is the reset password action, it will display a form that allows the user to reset his/her password.
15
 */
16
class ResetPassword extends BackendBaseActionAdd
17
{
18
    /**
19
     * User email
20
     *
21
     * @var string $email
22
     */
23
    private $email;
24
25
    /**
26
     * Reset password key
27
     *
28
     * @var string $key
29
     */
30
    private $key;
31
32
    /**
33
     * User record
34
     *
35
     * @var BackendUser
36
     */
37
    private $user;
38
39
    public function execute(): void
40
    {
41
        parent::execute();
42
43
        // the user email and key provided match
44
        if (!$this->isThePasswordResetKeyCorrect()) {
45
            $this->redirect(BackendModel::createUrlForAction('Index'));
46
        }
47
48
        $this->loadForm();
49
        $this->validateForm();
50
        $this->parse();
51
        $this->display();
52
    }
53
54
    private function isThePasswordResetKeyCorrect(): bool
55
    {
56
        // catch the key and e-mail address from GET
57
        $this->email = urldecode($this->getRequest()->query->get('email', ''));
58
        $this->key = $this->getRequest()->query->get('key', '');
59
60
        // if the email or the key aren't set, redirect the user
61
        if ($this->email !== '' && $this->key !== '') {
62
            // fetch the user
63
            $userId = BackendUsersModel::getIdByEmail($this->email);
64
            $this->user = new BackendUser($userId);
0 ignored issues
show
It seems like $userId can also be of type false; however, parameter $userId of Backend\Core\Engine\User::__construct() does only seem to accept integer|null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
            $this->user = new BackendUser(/** @scrutinizer ignore-type */ $userId);
Loading history...
65
            $requestTime = $this->user->getSetting('reset_password_timestamp');
66
67
            // check if the request was made within 24 hours
68
            if ((time() - $requestTime) > 86400) {
69
                // remove the reset_password_key and reset_password_timestamp usersettings
70
                BackendUsersModel::deleteResetPasswordSettings($userId);
0 ignored issues
show
It seems like $userId can also be of type false; however, parameter $id of Backend\Modules\Users\En...ResetPasswordSettings() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
                BackendUsersModel::deleteResetPasswordSettings(/** @scrutinizer ignore-type */ $userId);
Loading history...
71
72
                // redirect to the login form, with a timeout error
73
                $this->redirect(BackendModel::createUrlForAction('Index', null, null, ['reset' => 'timeout']));
74
            }
75
76
            // check if the provided key matches the one in the user record
77
            if ($this->key === $this->user->getSetting('reset_password_key')) {
78
                return true;
79
            }
80
        }
81
82
        // if we made it here the user is not allowed to access this page
83
        return false;
84
    }
85
86
    private function loadForm(): void
87
    {
88
        $this->form = new BackendForm();
89
        $this->form->addPassword('backend_new_password');
90
        $this->form->addPassword('backend_new_password_repeated');
91
92
        $this->form->getField('backend_new_password')->setAttributes(['autocomplete' => 'new-password']);
93
        $this->form->getField('backend_new_password_repeated')->setAttributes(['autocomplete' => 'new-password']);
94
    }
95
96
    private function validateForm(): void
97
    {
98
        if ($this->form->isSubmitted()) {
99
            // shorten fields
100
            $newPassword = $this->form->getField('backend_new_password');
101
            $newPasswordRepeated = $this->form->getField('backend_new_password_repeated');
102
103
            // required fields
104
            $newPassword->isFilled(BL::err('PasswordIsRequired'));
105
            $newPasswordRepeated->isFilled(BL::err('PasswordRepeatIsRequired'));
106
107
            // all fields are ok?
108
            if ($newPassword->isFilled() && $newPasswordRepeated->isFilled()) {
109
                // the passwords entered match
110
                if ($newPassword->getValue() !== $newPasswordRepeated->getValue()) {
111
                    // add error
112
                    $this->form->addError(BL::err('PasswordsDontMatch'));
113
114
                    // show error
115
                    $this->template->assign('error', BL::err('PasswordsDontMatch'));
116
                }
117
            }
118
119
            if ($this->form->isCorrect()) {
120
                // change the users password
121
                BackendUsersModel::updatePassword($this->user, $newPassword->getValue());
122
123
                // attempt to login the user
124
                if (!BackendAuthentication::loginUser($this->user->getEmail(), $newPassword->getValue())) {
125
                    // redirect to the login form with an error
126
                    $this->redirect(BackendModel::createUrlForAction('Index', null, null, ['login' => 'failed']));
127
                }
128
129
                // redirect to the login form
130
                $this->redirect(
131
                    BackendModel::createUrlForAction('Index', 'Dashboard', null, ['password_reset' => 'success'])
132
                );
133
            }
134
        }
135
    }
136
}
137