LDAPChangePasswordForm   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 151
Duplicated Lines 26.49 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 12
dl 40
loc 151
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 11 38 9
C doChangePassword() 29 100 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
class LDAPChangePasswordForm extends ChangePasswordForm
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
4
{
5
    /**
6
     * The sole purpose for overriding the constructor is surfacing the username to the user.
7
     */
8
    public function __construct($controller, $name, $fields = null, $actions = null)
9
    {
10
        parent::__construct($controller, $name, $fields, $actions);
11
12
        // Obtain the Member object. If the user got this far, they must have already been synced.
13
        $member = Member::currentUser();
14 View Code Duplication
        if (!$member) {
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...
15
            if (Session::get('AutoLoginHash')) {
16
                $member = Member::member_from_autologinhash(Session::get('AutoLoginHash'));
17
            }
18
19
            // The user is not logged in and no valid auto login hash is available
20
            if (!$member) {
21
                Session::clear('AutoLoginHash');
22
                return $this->controller->redirect($this->controller->Link('login'));
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
23
            }
24
        }
25
26
        $data = Injector::inst()->get('LDAPService')->getUserByGUID($member->GUID, ['samaccountname']);
27
28
        $emailField = null;
29
        $usernameField = null;
30
        if (Config::inst()->get('LDAPAuthenticator', 'allow_email_login')==='yes' && !empty($member->Email)) {
31
            $emailField = new TextField('Email', _t('LDAPLoginForm.USERNAMEOREMAIL', 'Email'), $member->Email, null, $this);
32
        }
33
        if (!empty($data['samaccountname'])) {
34
            $usernameField = new TextField('Username', _t('LDAPLoginForm.USERNAME', 'Username'), $data['samaccountname'], null, $this);
35
        }
36
37
        if ($emailField) {
38
            $emailFieldReadonly = $emailField->performDisabledTransformation();
39
            $this->Fields()->unshift($emailFieldReadonly);
40
        }
41
        if ($usernameField) {
42
            $usernameFieldReadonly = $usernameField->performDisabledTransformation();
43
            $this->Fields()->unshift($usernameFieldReadonly);
44
        }
45
    }
46
47
    /**
48
     * Change the password
49
     *
50
     * @param array $data The user submitted data
51
     * @return SS_HTTPResponse
52
     */
53
    public function doChangePassword(array $data)
0 ignored issues
show
Coding Style introduced by
doChangePassword uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
54
    {
55
        /**
56
         * @var LDAPService $service
57
         */
58
        $service = Injector::inst()->get('LDAPService');
59
        $member = Member::currentUser();
60
        if ($member) {
61
            try {
62
                $userData = $service->getUserByGUID($member->GUID);
63
            } catch (Exception $e) {
64
                SS_Log::log($e->getMessage(), SS_Log::ERR);
65
                $this->clearMessage();
66
                $this->sessionMessage(
67
                    _t('LDAPAuthenticator.NOUSER', 'Your account hasn\'t been setup properly, please contact an administrator.'),
68
                    'bad'
69
                );
70
                return $this->controller->redirect($this->controller->Link('changepassword'));
71
            }
72
            $loginResult = $service->authenticate($userData['samaccountname'], $data['OldPassword']);
73 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...
74
                $this->clearMessage();
75
                $this->sessionMessage(
76
                    _t('Member.ERRORPASSWORDNOTMATCH', "Your current password does not match, please try again"),
77
                    "bad"
78
                );
79
                // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
80
                return $this->controller->redirect($this->controller->Link('changepassword'));
81
            }
82
        }
83
84 View Code Duplication
        if (!$member) {
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...
85
            if (Session::get('AutoLoginHash')) {
86
                $member = Member::member_from_autologinhash(Session::get('AutoLoginHash'));
87
            }
88
89
            // The user is not logged in and no valid auto login hash is available
90
            if (!$member) {
91
                Session::clear('AutoLoginHash');
92
                return $this->controller->redirect($this->controller->Link('login'));
93
            }
94
        }
95
96
        // Check the new password
97
        if (empty($data['NewPassword1'])) {
98
            $this->clearMessage();
99
            $this->sessionMessage(
100
                _t('Member.EMPTYNEWPASSWORD', "The new password can't be empty, please try again"),
101
                "bad");
102
103
            // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
104
            return $this->controller->redirect($this->controller->Link('changepassword'));
105
        } elseif ($data['NewPassword1'] == $data['NewPassword2']) {
106
            // Providing OldPassword to perform password _change_ operation. This will respect the
107
            // password history policy. Unfortunately we cannot support password history policy on password _reset_
108
            // at the moment, which means it will not be enforced on SilverStripe-driven email password reset.
109
            $oldPassword = !empty($data['OldPassword']) ? $data['OldPassword']: null;
110
            $isValid = $service->setPassword($member, $data['NewPassword1'], $oldPassword);
0 ignored issues
show
Compatibility introduced by
$member of type object<DataObject> is not a sub-type of object<Member>. It seems like you assume a child class of the class DataObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
111
112
            // try to catch connection and other errors that the ldap service can through
113
            if ($isValid->valid()) {
114
                $member->logIn();
115
116
                Session::clear('AutoLoginHash');
117
118
                // Clear locked out status
119
                $member->LockedOutUntil = null;
120
                $member->FailedLoginCount = null;
121
                $member->write();
122
123
                if (!empty($_REQUEST['BackURL'])
124
                    // absolute redirection URLs may cause spoofing
125
                    && Director::is_site_url($_REQUEST['BackURL'])
126
                ) {
127
                    $url = Director::absoluteURL($_REQUEST['BackURL']);
128
                    return $this->controller->redirect($url);
129
                } else {
130
                    // Redirect to default location - the login form saying "You are logged in as..."
131
                    $redirectURL = HTTP::setGetVar(
132
                        'BackURL',
133
                        Director::absoluteBaseURL(), $this->controller->Link('login')
0 ignored issues
show
Security Bug introduced by
It seems like \Director::absoluteBaseURL() targeting Director::absoluteBaseURL() can also be of type false; however, HTTP::setGetVar() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
134
                    );
135
                    return $this->controller->redirect($redirectURL);
136
                }
137
            } else {
138
                $this->clearMessage();
139
                $this->sessionMessage($isValid->message(), "bad");
140
                // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
141
                return $this->controller->redirect($this->controller->Link('changepassword'));
142
            }
143 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...
144
            $this->clearMessage();
145
            $this->sessionMessage(
146
                _t('Member.ERRORNEWPASSWORD', "You have entered your new password differently, try again"),
147
                "bad");
148
149
            // redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
150
            return $this->controller->redirect($this->controller->Link('changepassword'));
151
        }
152
    }
153
}
154