Completed
Push — master ( 7a48ac...3c190c )
by Robbie
13:00
created

LDAPChangePasswordHandler::doChangePassword()   D

Complexity

Conditions 13
Paths 54

Size

Total Lines 119
Code Lines 70

Duplication

Lines 25
Ratio 21.01 %

Importance

Changes 0
Metric Value
dl 25
loc 119
rs 4.9922
c 0
b 0
f 0
cc 13
eloc 70
nc 54
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SilverStripe\ActiveDirectory\Authenticators;
4
5
use Exception;
6
use Psr\Log\LoggerInterface;
7
use SilverStripe\ActiveDirectory\Forms\LDAPChangePasswordForm;
8
use SilverStripe\ActiveDirectory\Services\LDAPService;
9
use SilverStripe\Control\Director;
10
use SilverStripe\Control\HTTP;
11
use SilverStripe\Control\HTTPResponse;
12
use SilverStripe\Core\Injector\Injector;
13
use SilverStripe\ORM\ValidationResult;
14
use SilverStripe\Security\Member;
15
use SilverStripe\Security\MemberAuthenticator\ChangePasswordHandler;
16
use SilverStripe\Security\Security;
17
18
class LDAPChangePasswordHandler extends ChangePasswordHandler
19
{
20
    /**
21
     * @var array Allowed Actions
22
     */
23
    private static $allowed_actions = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
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...
24
        'changepassword',
25
        'changePasswordForm',
26
    ];
27
28
    /**
29
     * Factory method for the lost password form
30
     *
31
     * @return LDAPChangePasswordForm Returns the lost password form
32
     */
33
    public function changePasswordForm()
34
    {
35
        return LDAPChangePasswordForm::create($this, 'ChangePasswordForm');
36
    }
37
38
    /**
39
     * Change the password
40
     *
41
     * @param array $data The user submitted data
42
     * @param LDAPChangePasswordForm $form
43
     * @return HTTPResponse
44
     */
45
    public function doChangePassword(array $data, $form)
46
    {
47
        /**
48
         * @var LDAPService $service
49
         */
50
        $service = Injector::inst()->get(LDAPService::class);
51
        $member = Security::getCurrentUser();
52
        if ($member) {
53
            try {
54
                $userData = $service->getUserByGUID($member->GUID);
55
            } catch (Exception $e) {
56
                Injector::inst()->get(LoggerInterface::class)->error($e->getMessage());
57
58
                $form->clearMessage();
59
                $form->sessionMessage(
60
                    _t(
61
                        __CLASS__ . '.NOUSER',
62
                        'Your account hasn\'t been setup properly, please contact an administrator.'
63
                    ),
64
                    'bad'
65
                );
66
                return $form->getController()->redirect($form->getController()->Link('changepassword'));
67
            }
68
            $loginResult = $service->authenticate($userData['samaccountname'], $data['OldPassword']);
69 View Code Duplication
            if (!$loginResult['success']) {
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...
70
                $form->clearMessage();
71
                $form->sessionMessage(
72
                    _t(
73
                        'SilverStripe\\Security\\Member.ERRORPASSWORDNOTMATCH',
74
                        'Your current password does not match, please try again'
75
                    ),
76
                    'bad'
77
                );
78
                // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
79
                return $form->getController()->redirect($form->getController()->Link('changepassword'));
80
            }
81
        }
82
83
        if (!$member) {
84
            if ($this->getRequest()->getSession()->get('AutoLoginHash')) {
85
                $member = Member::member_from_autologinhash($this->getRequest()->getSession()->get('AutoLoginHash'));
86
            }
87
88
            // The user is not logged in and no valid auto login hash is available
89
            if (!$member) {
90
                $this->getRequest()->getSession()->clear('AutoLoginHash');
91
                return $form->getController()->redirect($form->getController()->Link('login'));
92
            }
93
        }
94
95
        // Check the new password
96
        if (empty($data['NewPassword1'])) {
97
            $form->clearMessage();
98
            $form->sessionMessage(
99
                _t(
100
                    'SilverStripe\\Security\\Member.EMPTYNEWPASSWORD',
101
                    "The new password can't be empty, please try again"
102
                ),
103
                'bad'
104
            );
105
106
            // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
107
            return $form->getController()->redirect($form->getController()->Link('changepassword'));
108
        } elseif ($data['NewPassword1'] == $data['NewPassword2']) {
109
            // Providing OldPassword to perform password _change_ operation. This will respect the
110
            // password history policy. Unfortunately we cannot support password history policy on password _reset_
111
            // at the moment, which means it will not be enforced on SilverStripe-driven email password reset.
112
            $oldPassword = !empty($data['OldPassword']) ? $data['OldPassword']: null;
113
114
            /** @var ValidationResult $validationResult */
115
            $validationResult = $service->setPassword($member, $data['NewPassword1'], $oldPassword);
116
117
            // try to catch connection and other errors that the ldap service can through
118
            if ($validationResult->isValid()) {
119
                Security::setCurrentUser($member);
120
121
                $this->getRequest()->getSession()->clear('AutoLoginHash');
122
123
                // Clear locked out status
124
                $member->LockedOutUntil = null;
125
                $member->FailedLoginCount = null;
126
                $member->write();
127
128
                if (!empty($this->getRequest()->requestVar('BackURL'))
129
                    // absolute redirection URLs may cause spoofing
130
                    && Director::is_site_url($this->getRequest()->requestVar('BackURL'))
131
                ) {
132
                    $url = Director::absoluteURL($this->getRequest()->requestVar('BackURL'));
133
                    return $form->getController()->redirect($url);
0 ignored issues
show
Security Bug introduced by
It seems like $url defined by \SilverStripe\Control\Di...>requestVar('BackURL')) on line 132 can also be of type false; however, SilverStripe\Control\RequestHandler::redirect() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
134
                } else {
135
                    // Redirect to default location - the login form saying "You are logged in as..."
136
                    $redirectURL = HTTP::setGetVar(
137
                        'BackURL',
138
                        Director::absoluteBaseURL(),
0 ignored issues
show
Security Bug introduced by
It seems like \SilverStripe\Control\Director::absoluteBaseURL() targeting SilverStripe\Control\Director::absoluteBaseURL() can also be of type false; however, SilverStripe\Control\HTTP::setGetVar() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
139
                        $form->getController()->Link('login')
140
                    );
141
                    return $form->getController()->redirect($redirectURL);
142
                }
143
            } else {
144
                $form->clearMessage();
145
                $messages = implode('. ', array_column($validationResult->getMessages(), 'message'));
146
                $form->sessionMessage($messages, 'bad');
147
                // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
148
                return $form->getController()->redirect($form->getController()->Link('changepassword'));
149
            }
150 View Code Duplication
        } else {
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...
151
            $form->clearMessage();
152
            $form->sessionMessage(
153
                _t(
154
                    'SilverStripe\\Security\\Member.ERRORNEWPASSWORD',
155
                    'You have entered your new password differently, try again'
156
                ),
157
                'bad'
158
            );
159
160
            // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
161
            return $form->getController()->redirect($form->getController()->Link('changepassword'));
162
        }
163
    }
164
}
165