Passed
Pull Request — master (#5)
by Robbie
02:50 queued 32s
created

validateForgotPasswordData()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 44
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 27
nc 10
nop 2
dl 0
loc 44
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\LDAP\Authenticators;
4
5
use SilverStripe\Control\Controller;
6
use SilverStripe\Control\Email\Email;
7
use SilverStripe\Control\HTTPResponse;
8
use SilverStripe\Core\Config\Config;
9
use SilverStripe\Core\Convert;
10
use SilverStripe\Core\Injector\Injector;
11
use SilverStripe\Forms\FieldList;
12
use SilverStripe\Forms\Form;
13
use SilverStripe\Forms\FormAction;
14
use SilverStripe\Forms\TextField;
15
use SilverStripe\LDAP\Services\LDAPService;
16
use SilverStripe\ORM\FieldType\DBField;
17
use SilverStripe\Security\Member;
18
use SilverStripe\Security\MemberAuthenticator\LostPasswordForm;
19
use SilverStripe\Security\MemberAuthenticator\LostPasswordHandler;
20
use SilverStripe\Security\Security;
21
22
class LDAPLostPasswordHandler extends LostPasswordHandler
23
{
24
    protected $authenticatorClass = LDAPAuthenticator::class;
25
26
    /**
27
     * Since the logout and dologin actions may be conditionally removed, it's necessary to ensure these
28
     * remain valid actions regardless of the member login state.
29
     *
30
     * @var array
31
     * @config
32
     */
33
    private static $allowed_actions = [
0 ignored issues
show
Unused Code introduced by
The property $allowed_actions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
34
        'lostpassword',
35
        'LostPasswordForm',
36
        'passwordsent',
37
    ];
38
39
    private static $dependencies = [
0 ignored issues
show
Unused Code introduced by
The property $dependencies is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
40
        'service' => '%$' . LDAPService::class,
41
    ];
42
43
    /**
44
     * @var LDAPService
45
     */
46
    protected $service;
47
48
    /**
49
     * LDAP data for the provided member - is loaded by validateForgotPasswordData
50
     *
51
     * @var array
52
     */
53
    protected $ldapUserData = [];
54
55
56
    /**
57
     * @param string $link The URL to recreate this request handler
58
     * @param LDAPAuthenticator $authenticator
59
     */
60
    public function __construct($link, LDAPAuthenticator $authenticator)
61
    {
62
        $this->link = $link;
0 ignored issues
show
Bug Best Practice introduced by
The property $link is declared private in SilverStripe\Security\Me...tor\LostPasswordHandler. Since you implement __set, consider adding a @property or @property-write.
Loading history...
63
        $this->authenticatorClass = get_class($authenticator);
64
        parent::__construct($link);
65
    }
66
67
    protected function validateForgotPasswordData(array $data, LostPasswordForm $form)
68
    {
69
        Config::modify()->set(Member::class, 'unique_identifier_field', 'Login');
70
71
        // No need to protect against injections, LDAPService will ensure that this is safe
72
        $login = isset($data['Login']) ? trim($data['Login']) : '';
73
74
        // Ensure something was provided
75
        if (empty($login)) {
76
            if (Config::inst()->get(LDAPAuthenticator::class, 'allow_email_login') === 'yes') {
77
                $form->sessionMessage(
78
                    _t(
79
                        'SilverStripe\\LDAP\\Forms\\LDAPLoginForm.ENTERUSERNAMEOREMAIL',
80
                        'Please enter your username or your email address to get a password reset link.'
81
                    ),
82
                    'bad'
83
                );
84
            } else {
85
                $form->sessionMessage(
86
                    _t(
87
                        'SilverStripe\\LDAP\\Forms\\LDAPLoginForm.ENTERUSERNAME',
88
                        'Please enter your username to get a password reset link.'
89
                    ),
90
                    'bad'
91
                );
92
            }
93
            return $this->redirectBack();
94
        }
95
96
        // Look up the user and store it
97
        if (Email::is_valid_address($login)) {
98
            if (Config::inst()->get(LDAPAuthenticator::class, 'allow_email_login') != 'yes') {
99
                $form->sessionMessage(
100
                    _t(
101
                        'SilverStripe\\LDAP\\Forms\\LDAPLoginForm.USERNAMEINSTEADOFEMAIL',
102
                        'Please enter your username instead of your email to get a password reset link.'
103
                    ),
104
                    'bad'
105
                );
106
                return $this->redirect($this->Link('lostpassword'));
107
            }
108
            $this->ldapUserData = $this->getService()->getUserByEmail($login);
109
        } else {
110
            $this->ldapUserData = $this->getService()->getUserByUsername($login);
111
        }
112
    }
113
114
    protected function getMemberFromData(array $data, $uniqueIdentifier)
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed. ( Ignorable by Annotation )

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

114
    protected function getMemberFromData(/** @scrutinizer ignore-unused */ array $data, $uniqueIdentifier)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $uniqueIdentifier is not used and could be removed. ( Ignorable by Annotation )

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

114
    protected function getMemberFromData(array $data, /** @scrutinizer ignore-unused */ $uniqueIdentifier)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
115
    {
116
        $member = Member::get()->filter('GUID', $this->ldapUserData['objectguid'])->limit(1)->first();
117
118
        // User haven't been imported yet so do that now
119 View Code Duplication
        if (!$member || !$member->exists()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
120
            $member = Member::create();
121
            $member->GUID = $this->ldapUserData['objectguid'];
122
        }
123
124
        // Update the users from LDAP so we are sure that the email is correct.
125
        // This will also write the Member record.
126
        $this->getService()->updateMemberFromLDAP($member, $this->ldapUserData, false);
127
128
        return $member;
129
    }
130
131
    /**
132
     * Factory method for the lost password form
133
     *
134
     * @return Form Returns the lost password form
135
     */
136
    public function lostPasswordForm()
137
    {
138
        $loginFieldLabel = (Config::inst()->get(LDAPAuthenticator::class, 'allow_email_login') === 'yes') ?
139
            _t('SilverStripe\\LDAP\\Forms\\LDAPLoginForm.USERNAMEOREMAIL', 'Username or email') :
140
            _t('SilverStripe\\LDAP\\Forms\\LDAPLoginForm.USERNAME', 'Username');
141
        $loginField = TextField::create('Login', $loginFieldLabel);
0 ignored issues
show
Bug introduced by
'Login' of type string is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

141
        $loginField = TextField::create(/** @scrutinizer ignore-type */ 'Login', $loginFieldLabel);
Loading history...
142
143
        $action = FormAction::create(
144
            'forgotPassword',
145
            _t('SilverStripe\\Security\\Security.BUTTONSEND', 'Send me the password reset link')
146
        );
147
        return LostPasswordForm::create(
148
            $this,
0 ignored issues
show
Bug introduced by
$this of type SilverStripe\LDAP\Authen...LDAPLostPasswordHandler is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

148
            /** @scrutinizer ignore-type */ $this,
Loading history...
149
            $this->authenticatorClass,
150
            'LostPasswordForm',
151
            FieldList::create([$loginField]),
0 ignored issues
show
Bug introduced by
It seems like SilverStripe\Forms\Field...ate(array($loginField)) can also be of type object; however, parameter $args of SilverStripe\View\ViewableData::create() does only seem to accept array, 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

151
            /** @scrutinizer ignore-type */ FieldList::create([$loginField]),
Loading history...
152
            FieldList::create([$action]),
153
            false
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type array expected by parameter $args of SilverStripe\View\ViewableData::create(). ( Ignorable by Annotation )

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

153
            /** @scrutinizer ignore-type */ false
Loading history...
154
        );
155
    }
156
157
    public function lostpassword()
158
    {
159
        if (Config::inst()->get(LDAPAuthenticator::class, 'allow_email_login') === 'yes') {
160
            $message = _t(
161
                __CLASS__ . '.NOTERESETPASSWORDUSERNAMEOREMAIL',
162
                'Enter your username or your email address and we will send you a link with which '
163
                . 'you can reset your password'
164
            );
165
        } else {
166
            $message = _t(
167
                __CLASS__ . '.NOTERESETPASSWORDUSERNAME',
168
                'Enter your username and we will send you a link with which you can reset your password'
169
            );
170
        }
171
172
        return [
173
            'Content' => DBField::create_field('HTMLFragment', "<p>$message</p>"),
174
            'Form' => $this->lostPasswordForm(),
175
        ];
176
    }
177
178
    public function passwordsent()
179
    {
180
        $username = Convert::raw2xml(
181
            rawurldecode($this->getRequest()->param('OtherID'))
182
        );
183
        $username .= ($extension = $this->getRequest()->getExtension()) ? '.' . $extension : '';
184
185
        return [
186
            'Title' => _t(
187
                __CLASS__ . '.PASSWORDSENTHEADER',
188
                "Password reset link sent to '{username}'",
189
                ['username' => $username]
190
            ),
191
            'Content' =>
192
                _t(
193
                    __CLASS__ . '.PASSWORDSENTTEXT',
194
                    "Thank you! A reset link has been sent to '{username}', provided an account exists.",
195
                    ['username' => $username]
196
                ),
197
            'Username' => $username
198
        ];
199
    }
200
201
    /**
202
     * Get the LDAP service
203
     *
204
     * @return LDAPService
205
     */
206
    public function getService()
207
    {
208
        return $this->service;
209
    }
210
211
    /**
212
     * Set the LDAP service
213
     *
214
     * @param LDAPService $service
215
     * @return $this
216
     */
217
    public function setService(LDAPService $service)
218
    {
219
        $this->service = $service;
220
        return $this;
221
    }
222
}
223