Completed
Pull Request — 1.x (#641)
by
unknown
15:00
created

Db::getMapper()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
namespace ZfcUser\Authentication\Adapter;
4
5
use Zend\Authentication\Result as AuthenticationResult;
6
use Zend\ServiceManager\ServiceManager;
7
use Zend\Crypt\Password\Bcrypt;
8
use Zend\Session\Container as SessionContainer;
9
use ZfcUser\Authentication\Adapter\AdapterChainEvent as AuthEvent;
10
use ZfcUser\Mapper\User as UserMapperInterface;
11
use ZfcUser\Options\AuthenticationOptionsInterface;
12
13
class Db extends AbstractAdapter
14
{
15
    /**
16
     * @var UserMapperInterface
17
     */
18
    protected $mapper;
19
20
    /**
21
     * @var closure / invokable object
22
     */
23
    protected $credentialPreprocessor;
24
25
    /**
26
     * @var ServiceManager
27
     */
28
    protected $serviceManager;
29
30
    /**
31
     * @var AuthenticationOptionsInterface
32
     */
33
    protected $options;
34
35
    /**
36
     * Called when user id logged out
37
     * @param  AuthEvent $e event passed
38
     */
39
    public function logout(AuthEvent $e)
40
    {
41
        $this->getStorage()->clear();
42
    }
43
44
    public function authenticate(AuthEvent $e)
45
    {
46
        if ($this->isSatisfied()) {
47
            $storage = $this->getStorage()->read();
48
            $e->setIdentity($storage['identity'])
49
              ->setCode(AuthenticationResult::SUCCESS)
50
              ->setMessages(array('Authentication successful.'));
51
            return;
52
        }
53
54
        $identity   = $e->getRequest()->getPost()->get('identity');
55
        $credential = $e->getRequest()->getPost()->get('credential');
56
        $credential = $this->preProcessCredential($credential);
57
        $userObject = null;
58
59
        // Cycle through the configured identity sources and test each
60
        $fields = $this->getOptions()->getAuthIdentityFields();
61
        while (!is_object($userObject) && count($fields) > 0) {
62
            $mode = array_shift($fields);
63
            switch ($mode) {
64
                case 'username':
65
                    $userObject = $this->getMapper()->findByUsername($identity);
66
                    break;
67
                case 'email':
68
                    $userObject = $this->getMapper()->findByEmail($identity);
69
                    break;
70
            }
71
        }
72
73
        if (!$userObject) {
74
            $e->setCode(AuthenticationResult::FAILURE_IDENTITY_NOT_FOUND)
75
              ->setMessages(array('A record with the supplied identity could not be found.'));
76
            $this->setSatisfied(false);
77
            return false;
78
        }
79
80
        if ($this->getOptions()->getEnableUserState()) {
81
            // Don't allow user to login if state is not in allowed list
82
            if (!in_array($userObject->getState(), $this->getOptions()->getAllowedLoginStates())) {
83
                $e->setCode(AuthenticationResult::FAILURE_UNCATEGORIZED)
84
                  ->setMessages(array('A record with the supplied identity is not active.'));
85
                $this->setSatisfied(false);
86
                return false;
87
            }
88
        }
89
90
        $bcrypt = new Bcrypt();
91
        $bcrypt->setCost($this->getOptions()->getPasswordCost());
92
        if (!$bcrypt->verify($credential, $userObject->getPassword())) {
93
            // Password does not match
94
            $e->setCode(AuthenticationResult::FAILURE_CREDENTIAL_INVALID)
95
              ->setMessages(array('Supplied credential is invalid.'));
96
            $this->setSatisfied(false);
97
            return false;
98
        }
99
100
        // regen the id
101
        $session = new SessionContainer($this->getStorage()->getNameSpace());
102
        $session->getManager()->regenerateId();
103
104
        // Success!
105
        $e->setIdentity($userObject->getId());
106
        // Update user's password hash if the cost parameter has changed
107
        $this->updateUserPasswordHash($userObject, $credential, $bcrypt);
108
        $this->setSatisfied(true);
109
        $storage = $this->getStorage()->read();
110
        $storage['identity'] = $e->getIdentity();
111
        $this->getStorage()->write($storage);
112
        $e->setCode(AuthenticationResult::SUCCESS)
113
          ->setMessages(array('Authentication successful.'));
114
    }
115
116
    protected function updateUserPasswordHash($userObject, $password, $bcrypt)
117
    {
118
        $hash = explode('$', $userObject->getPassword());
119
        if ($hash[2] === $bcrypt->getCost()) {
120
            return;
121
        }
122
        $userObject->setPassword($bcrypt->create($password));
123
        $this->getMapper()->update($userObject);
124
        return $this;
125
    }
126
127
    public function preprocessCredential($credential)
128
    {
129
        $processor = $this->getCredentialPreprocessor();
130
        if (is_callable($processor)) {
131
            return $processor($credential);
132
        }
133
        return $credential;
134
    }
135
136
    /**
137
     * getMapper
138
     *
139
     * @return UserMapperInterface
140
     */
141
    public function getMapper()
142
    {
143
        if (null === $this->mapper) {
144
            $this->mapper = $this->getServiceManager()->get('zfcuser_user_mapper');
145
        }
146
        return $this->mapper;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->mapper; of type object|array adds the type array to the return on line 146 which is incompatible with the return type documented by ZfcUser\Authentication\Adapter\Db::getMapper of type ZfcUser\Mapper\User.
Loading history...
147
    }
148
149
    /**
150
     * setMapper
151
     *
152
     * @param UserMapperInterface $mapper
153
     * @return Db
154
     */
155
    public function setMapper(UserMapperInterface $mapper)
156
    {
157
        $this->mapper = $mapper;
158
        return $this;
159
    }
160
161
    /**
162
     * Get credentialPreprocessor.
163
     *
164
     * @return \callable
165
     */
166
    public function getCredentialPreprocessor()
167
    {
168
        return $this->credentialPreprocessor;
169
    }
170
171
    /**
172
     * Set credentialPreprocessor.
173
     *
174
     * @param $credentialPreprocessor the value to be set
175
     */
176
    public function setCredentialPreprocessor($credentialPreprocessor)
177
    {
178
        $this->credentialPreprocessor = $credentialPreprocessor;
179
        return $this;
180
    }
181
182
    /**
183
     * Retrieve service manager instance
184
     *
185
     * @return ServiceManager
186
     */
187
    public function getServiceManager()
188
    {
189
        return $this->serviceManager;
190
    }
191
192
    /**
193
     * Set service manager instance
194
     *
195
     * @param ServiceManager $locator
196
     * @return void
197
     */
198
    public function setServiceManager(ServiceManager $serviceManager)
199
    {
200
        $this->serviceManager = $serviceManager;
201
    }
202
203
    /**
204
     * @param AuthenticationOptionsInterface $options
205
     */
206
    public function setOptions(AuthenticationOptionsInterface $options)
207
    {
208
        $this->options = $options;
209
    }
210
211
    /**
212
     * @return AuthenticationOptionsInterface
213
     */
214
    public function getOptions()
215
    {
216
        if (!$this->options instanceof AuthenticationOptionsInterface) {
217
            $this->setOptions($this->getServiceManager()->get('zfcuser_module_options'));
218
        }
219
        return $this->options;
220
    }
221
}
222