Passed
Push — master ( 6151ba...17a32e )
by Chauncey
52s queued 10s
created

Authenticator::changeUserPassword()   B

Complexity

Conditions 9
Paths 14

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 56
rs 7.4044
c 0
b 0
f 0
cc 9
nc 14
nop 3

How to fix   Long Method   

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 Charcoal\User;
4
5
use InvalidArgumentException;
6
7
// From 'charcoal-object'
8
use Charcoal\Object\ContentInterface;
9
10
// From 'charcoal-user'
11
use Charcoal\User\Access\AuthenticatableInterface;
12
use Charcoal\User\UserInterface;
13
14
/**
15
 * The User Authenticator
16
 */
17
class Authenticator extends AbstractAuthenticator
18
{
19
    /**
20
     * Log a user into the application.
21
     *
22
     * @param  AuthenticatableInterface $user     The authenticated user to log in.
23
     * @param  boolean                  $remember Whether to "remember" the user or not.
24
     * @return void
25
     */
26
    public function login(AuthenticatableInterface $user, $remember = false)
27
    {
28
        parent::login($user, $remember);
29
30
        $this->touchUserLogin($user);
31
    }
32
33
    /**
34
     * Validate the user authentication state is okay.
35
     *
36
     * For example, inactive users can not authenticate.
37
     *
38
     * @param  AuthenticatableInterface $user The user to validate.
39
     * @return boolean
40
     */
41
    public function validateAuthentication(AuthenticatableInterface $user)
42
    {
43
        if ($user instanceof ContentInterface) {
44
            if (!$user['active']) {
45
                return false;
46
            }
47
        }
48
49
        return parent::validateAuthentication($user);
50
    }
51
52
    /**
53
     * Updates the user's timestamp for their last log in.
54
     *
55
     * @param  AuthenticatableInterface $user   The user to update.
56
     * @param  boolean                  $update Whether to persist changes to storage.
57
     * @throws InvalidArgumentException If the user has no ID.
58
     * @return boolean Returns TRUE if the password was changed, or FALSE otherwise.
59
     */
60
    public function touchUserLogin(AuthenticatableInterface $user, $update = true)
61
    {
62
        if (!($user instanceof UserInterface)) {
63
            return false;
64
        }
65
66
        if (!$user->getAuthId()) {
67
            throw new InvalidArgumentException(
68
                'Can not touch user: user has no ID'
69
            );
70
        }
71
72
        $userId = $user->getAuthId();
73
74
        if ($update && $userId) {
75
            $userClass = get_class($user);
76
77
            $this->logger->info(sprintf(
78
                'Updating last login fields for user "%s" (%s)',
79
                $userId,
80
                $userClass
81
            ));
82
        }
83
84
        $user['lastLoginDate'] = 'now';
85
        $user['lastLoginIp']   = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
86
87
        if ($update && $userId) {
88
            $result = $user->update([
89
                'last_login_ip',
90
                'last_login_date',
91
            ]);
92
93
            if ($result) {
94
                $this->logger->notice(sprintf(
95
                    'Last login fields were updated for user "%s" (%s)',
96
                    $userId,
97
                    $userClass
0 ignored issues
show
Bug introduced by
The variable $userClass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
98
                ));
99
            } else {
100
                $this->logger->warning(sprintf(
101
                    'Last login fields failed to be updated for user "%s" (%s)',
102
                    $userId,
103
                    $userClass
104
                ));
105
            }
106
        }
107
108
        return $result;
0 ignored issues
show
Bug introduced by
The variable $result does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
109
    }
110
111
    /**
112
     * Updates the user's password hash.
113
     *
114
     * @param  AuthenticatableInterface $user     The user to update.
115
     * @param  string                   $password The plain-text password to hash.
116
     * @param  boolean                  $update   Whether to persist changes to storage.
117
     * @throws InvalidArgumentException If the password is invalid.
118
     * @return boolean Returns TRUE if the password was changed, or FALSE otherwise.
119
     */
120
    public function changeUserPassword(AuthenticatableInterface $user, $password, $update = true)
121
    {
122
        if (!($user instanceof UserInterface)) {
123
            return parent::changeUserPassword($user, $password);
124
        }
125
126
        if (!$this->validateAuthPassword($password)) {
127
            throw new InvalidArgumentException(
128
                'Can not change password: password is invalid'
129
            );
130
        }
131
132
        $userId = $user->getAuthId();
133
134
        if ($update && $userId) {
135
            $userClass = get_class($user);
136
137
            $this->logger->info(sprintf(
138
                '[Authenticator] Changing password for user "%s" (%s)',
139
                $userId,
140
                $userClass
141
            ));
142
        }
143
144
        $passwordKey = $user->getAuthPasswordKey();
145
146
        $user[$passwordKey]       = password_hash($password, PASSWORD_DEFAULT);
147
        $user['lastPasswordDate'] = 'now';
148
        $user['lastPasswordIp']   = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null;
149
150
        if ($update && $userId) {
151
            $result = $user->update([
152
                $passwordKey,
153
                'last_password_date',
154
                'last_password_ip',
155
            ]);
156
157
            if ($result) {
158
                $this->logger->notice(sprintf(
159
                    '[Authenticator] Password was changed for user "%s" (%s)',
160
                    $userId,
161
                    $userClass
0 ignored issues
show
Bug introduced by
The variable $userClass does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
162
                ));
163
            } else {
164
                $this->logger->warning(sprintf(
165
                    '[Authenticator] Password failed to be changed for user "%s" (%s)',
166
                    $userId,
167
                    $userClass
168
                ));
169
            }
170
171
            return $result;
172
        }
173
174
        return true;
175
    }
176
}
177