Completed
Push — master ( 232009...3c190c )
by Robbie
14s
created

LDAPChangePasswordHandler   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 147
Duplicated Lines 17.01 %

Coupling/Cohesion

Components 0
Dependencies 12

Importance

Changes 0
Metric Value
wmc 14
lcom 0
cbo 12
dl 25
loc 147
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A changePasswordForm() 0 4 1
D doChangePassword() 25 119 13

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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