Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

burzum / cakephp-user-tools / 318

7 Sep 2017 - 14:12 coverage: 37.811% (-0.6%) from 38.365%
318

Pull #46

travis-ci

9181eb84f9c35729a3bad740fb7f9d93?size=18&default=identiconweb-flow
Improving the code and doc blocks
Pull Request #46: Updating the plugin to CakePHP 3.4 changes

43 of 114 new or added lines in 7 files covered. (37.72%)

21 existing lines in 4 files now uncovered.

304 of 804 relevant lines covered (37.81%)

2.15 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

17.62
/src/Controller/Component/UserToolComponent.php
1
<?php
2
/**
3
 * UserToolComponent
4
 *
5
 * @author Florian Krämer
6
 * @copyright 2013 - 2017 Florian Krämer
7
 * @license MIT
8
 */
9
namespace Burzum\UserTools\Controller\Component;
10

11
use Cake\Controller\Component;
12
use Cake\Controller\ComponentRegistry;
13
use Cake\Core\Configure;
14
use Cake\Datasource\EntityInterface;
15
use Cake\Datasource\Exception\RecordNotFoundException;
16
use Cake\Event\Event;
17
use Cake\Event\EventDispatcherTrait;
18
use Cake\Http\Response;
19
use Cake\Network\Exception\NotFoundException;
20
use Cake\ORM\Table;
21
use Cake\ORM\TableRegistry;
22
use Cake\Utility\Hash;
23
use Cake\View\Exception\MissingTemplateException;
24
use RuntimeException;
25

26
/**
27
 * UserToolComponent
28
 */
29
class UserToolComponent extends Component {
30

31
        use EventDispatcherTrait;
32
        use FlashAndRedirectTrait;
33

34
        /**
35
         * Components
36
         *
37
         * @var array
38
         */
39
        public $components = [
40
                'Session',
41
                'Flash',
42
        ];
43

44
        /**
45
         * Default config
46
         *
47
         * These are merged with user-provided config when the component is used.
48
         *
49
         * @var array
50
         */
51
        protected $_defaultConfig = [
52
                'autoloadBehavior' => true,
53
                'actionMapping' => true,
54
                'directMapping' => false,
55
                'userModel' => null,
56
                'passwordReset' => 'token',
57
                'auth' => [
58
                        'authenticate' => [
59
                                'Form' => [
60
                                        'userModel' => 'Users',
61
                                        'fields' => [
62
                                                'username' => 'email',
63
                                                'password' => 'password'
64
                                        ],
65
                                        'scope' => [
66
                                                'Users.email_verified' => 1
67
                                        ]
68
                                ]
69
                        ]
70
                ],
71
                'registration' => [
72
                        'enabled' => true,
73
                        'successFlashOptions' => [],
74
                        'successRedirectUrl' => '/',
75
                        'errorFlashOptions' => [],
76
                        'errorRedirectUrl' => false,
77
                        'setEntity' => true,
78
                        'validation' => 'default'
79
                ],
80
                'login' => [
81
                        'alreadyLoggedInFlashOptions' => [],
82
                        'alreadyLoggedInRedirectUrl' => null,
83
                        'successRedirectUrl' => null,
84
                        'successFlashOptions' => [],
85
                        'errorFlashOptions' => [],
86
                        'errorRedirectUrl' => false,
87
                        'setEntity' => true,
88
                ],
89
                'logout' => [
90
                        'successFlashOptions' => [],
91
                        'successRedirectUrl' => null,
92
                ],
93
                'verifyEmailToken' => [
94
                        'queryParam' => 'token',
95
                        'successRedirectUrl' => [
96
                                'action' => 'login'
97
                        ],
98
                        'errorRedirectUrl' => '/'
99
                ],
100
                'requestPassword' => [
101
                        'successFlashOptions' => [],
102
                        'successRedirectUrl' => '/',
103
                        'errorFlashOptions' => [],
104
                        'errorRedirectUrl' => '/',
105
                        'field' => 'email',
106
                        'setEntity' => true,
107
                ],
108
                'resetPassword' => [
109
                        'queryParam' => 'token',
110
                        'tokenOptions' => [],
111
                        // Success
112
                        'successFlashOptions' => [],
113
                        'successRedirectUrl' => '/',
114
                        // Normal error
115
                        'errorFlashOptions' => [],
116
                        'errorRedirectUrl' => false,
117
                        // Invalid Token error
118
                        'invalidErrorFlashOptions' => [
119
                                'element' => 'Flash/error'
120
                        ],
121
                        'invalidErrorRedirectUrl' => '/',
122
                        // Token expired error
123
                        'expiredErrorFlashOptions' => [
124
                                'element' => 'Flash/error'
125
                        ],
126
                        'expiredErrorRedirectUrl' => '/'
127
                ],
128
                'changePassword' => [
129
                        'successFlashOptions' => [],
130
                        'successRedirectUrl' => '/',
131
                        'errorFlashOptions' => [],
132
                        'errorRedirectUrl' => false,
133
                ],
134
                'verifyToken' => [
135
                        'queryParam' => 'token',
136
                        'type' => 'Email',
137
                        'successRedirectUrl' => [
138
                                'action' => 'login'
139
                        ],
140
                        'errorMessage' => null,
141
                        'errorRedirectUrl' => '/'
142
                ],
143
                'getUser' => [
144
                        'viewVar' => 'user'
145
                ],
146
                'actionMap' => [
147
                        'index' => [
148
                                'method' => 'listing',
149
                                'view' => 'Burzum/UserTools.UserTools/index',
150
                        ],
151
                        'register' => [
152
                                'method' => 'register',
153
                                'view' => 'Burzum/UserTools.UserTools/register'
154
                        ],
155
                        'login' => [
156
                                'method' => 'login',
157
                                'view' => 'Burzum/UserTools.UserTools/login',
158
                        ],
159
                        'logout' => [
160
                                'method' => 'logout',
161
                                'view' => null
162
                        ],
163
                        'view' => [
164
                                'method' => 'getUser',
165
                                'view' => 'Burzum/UserTools.UserTools/view',
166
                        ],
167
                        // camelCased method names
168
                        'resetPassword' => [
169
                                'method' => 'resetPassword',
170
                                'view' => 'Burzum/UserTools.UserTools/reset_password',
171
                        ],
172
                        'requestPassword' => [
173
                                'method' => 'requestPassword',
174
                                'view' => 'Burzum/UserTools.UserTools/request_password',
175
                        ],
176
                        'changePassword' => [
177
                                'method' => 'changePassword',
178
                                'view' => 'Burzum/UserTools.UserTools/change_password',
179
                        ],
180
                        'verifyEmail' => [
181
                                'method' => 'verifyEmailToken',
182
                                'view' => 'Burzum/UserTools.UserTools/verify_email',
183
                        ],
184
                        // DEPRECATED underscored method names
185
                        'reset_password' => [
186
                                'method' => 'resetPassword',
187
                                'view' => 'Burzum/UserTools.UserTools/reset_password',
188
                        ],
189
                        'request_password' => [
190
                                'method' => 'requestPassword',
191
                                'view' => 'Burzum/UserTools.UserTools/request_password',
192
                        ],
193
                        'change_password' => [
194
                                'method' => 'changePassword',
195
                                'view' => 'Burzum/UserTools.UserTools/change_password',
196
                        ],
197
                        'verify_email' => [
198
                                'method' => 'verifyEmailToken',
199
                                'view' => 'Burzum/UserTools.UserTools/verify_email',
200
                        ]
201
                ]
202
        ];
203

204
        /**
205
         * User Table
206
         *
207
         * @var \Cake\ORM\Table $UserTable
208
         */
209
        public $UserTable = null;
210

211
        /**
212
         * Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT
213
         *
214
         * @param ComponentRegistry $registry ComponentRegistry object.
215
         * @param array $config Config options array
216
         */
217
        public function __construct(ComponentRegistry $registry, $config = []) {
218
                $this->_defaultConfig = Hash::merge(
3×
219
                        $this->_defaultConfig,
3×
220
                        $this->_translateConfigMessages(),
3×
221
                        (array)Configure::read('UserTools.Component')
3×
222
                );
223

224
                parent::__construct($registry, $config);
3×
225
        }
3×
226

227
        /**
228
         * Gets the request from the controller
229
         *
230
         * @return \Cake\Http\ServerRequest
231
         */
232
        protected function _getRequest() {
233
                return $this->getController()->request;
1×
234
        }
235

236
        /**
237
         * Gets the response from the controller
238
         *
239
         * @return \Cake\Http\Response
240
         */
241
        protected function _getResponse() {
NEW
242
                return $this->getController()->response;
!
243
        }
244

245
        /**
246
         * Translates the messages in the configuration array
247
         *
248
         * @return array
249
         */
250
        protected function _translateConfigMessages() {
251
                return [
252
                        'requestPassword' => [
253
                                'successMessage' => __d('burzum/user_tools', 'An email was send to your address, please check your inbox.'),
3×
254
                                'errorMessage' => __d('burzum/user_tools', 'Invalid user.'),
3×
255
                        ],
256
                        'resetPassword' => [
257
                                'successMessage' => __d('burzum/user_tools', 'Your password has been reset, you can now login.'),
3×
258
                                'errorMessage' => __d('burzum/user_tools', 'Please check your inputs.'),
3×
259
                                'invalidErrorMessage' => __d('burzum/user_tools', 'Invalid token!'),
3×
260
                                'expiredErrorMessage' => __d('burzum/user_tools', 'The token has expired!')
3×
261
                        ],
262
                        'changePassword' => [
263
                                'successMessage' => __d('burzum/user_tools', 'Your password has been updated.'),
3×
264
                                'errorMessage' => __d('burzum/user_tools', 'Could not update your password, please check for errors and try again.'),
3×
265
                        ],
266
                        'registration' => [
267
                                'successMessage' => __d('burzum/user_tools', 'Thank you for signing up!'),
3×
268
                                'errorMessage' => __d('burzum/user_tools', 'Please check your inputs'),
3×
269
                        ],
270
                        'login' => [
271
                                'successMessage' => __d('burzum/user_tools', 'You are logged in!'),
3×
272
                                'errorMessage' => __d('burzum/user_tools', 'Invalid login credentials.'),
3×
273
                        ],
274
                        'logout' => [
275
                                'successMessage' => __d('burzum/user_tools', 'You are logged out!'),
3×
276
                        ],
277
                        'verifyEmailToken' => [
278
                                'successMessage' => __d('burzum/user_tools', 'Email verified, you can now login!'),
3×
279
                                'errorMessage' => __d('burzum/user_tools', 'Invalid email token!'),
3×
280
                        ],
281
                        'verifyToken' => [
282
                                'successMessage' => __d('burzum/user_tools', 'Token verified!'),
3×
283
                        ]
284
                ];
285
        }
286

287
        /**
288
         * Initializes the component.
289
         *
290
         * @param array $config Config array
291
         * @return void
292
         */
293
        public function initialize(array $config) {
294
                $this->setUserTable($this->getConfig('userModel'));
3×
295
                $this->loadUserBehaviour();
3×
296
        }
3×
297

298
        /**
299
         * User listing with pagination.
300
         *
301
         * @param array $options Pagination options
302
         * @return void
303
         */
304
        public function listing($options = []) {
305
                $this->getController()->set('users', $this->getController()->paginate($this->UserTable, $options));
1×
306
                $this->getController()->set('_serialize', ['users']);
1×
307
        }
1×
308

309
        /**
310
         * Loads the User behavior for the user model if it is not already loaded
311
         *
312
         * @return void
313
         */
314
        public function loadUserBehaviour() {
315
                if ($this->getConfig('autoloadBehavior') && !$this->UserTable->hasBehavior('UserTools.User')) {
3×
316
                        if (is_array($this->getConfig('autoloadBehavior'))) {
3×
NEW
317
                                $this->UserTable->addBehavior('Burzum/UserTools.User', $this->getConfig('autoloadBehavior'));
!
318
                        } else {
319
                                $this->UserTable->addBehavior('Burzum/UserTools.User');
3×
320
                        }
321
                }
322
        }
3×
323

324
        /**
325
         * Sets or instantiates the user model class.
326
         *
327
         * @param null|string|\Cake\ORM\Table $table Table name or a table object
328
         * @throws \RuntimeException
329
         * @return void
330
         */
331
        public function setUserTable($table = null) {
332
                if ($table === null) {
3×
333
                        $this->UserTable = $this->getController()->{$this->getController()->modelClass};
3×
334
                } else {
335
                        if (is_object($table)) {
!
NEW
336
                                if (!is_a($table, Table::class)) {
!
NEW
337
                                        throw new RuntimeException('Passed object is not of type \Cake\ORM\Table!');
!
338
                                }
339
                                $this->UserTable = $table->alias();
!
340
                        }
341
                        if (is_string($table)) {
!
342
                                $this->UserTable = TableRegistry::get($table);
!
343
                        }
344
                }
345
                $this->getController()->set('userTable', $this->UserTable->alias());
3×
346
        }
3×
347

348
        /**
349
         * Start up
350
         *
351
         * @link https://github.com/cakephp/cakephp/issues/4530
352
         * @param \Cake\Event\Event $Event Event object
353
         * @return void|\Cake\Http\Response
354
         */
355
        public function startup(Event $Event) {
NEW
356
                if ($this->getConfig('actionMapping') === true) {
!
357
                        $result = $this->mapAction();
!
358
                        if ($result instanceof Response) {
!
359
                                return $result;
!
360
                        }
361
                }
362
        }
!
363

364
        /**
365
         * Maps a called controller action to a component method
366
         *
367
         * @return bool|\Cake\Http\Response
368
         */
369
        public function mapAction() {
NEW
370
                $action = $this->_getRequest()->params['action'];
!
NEW
371
                if ($this->getConfig('directMapping') === true) {
!
UNCOV
372
                        $this->_directMapping($action);
!
373
                }
374

UNCOV
375
                return $this->_mapAction($action);
!
376
        }
377

378
        /**
379
         * Direct Mapping
380
         *
381
         * @param string $action Action name
382
         * @return \Cake\Http\Response|bool A response object containing the rendered view.
383
         */
384
        protected function _directMapping($action) {
385
                if (!method_exists($this, $action)) {
!
386
                        return false;
!
387
                }
388

NEW
389
                $pass = (array)$this->_getRequest()->param('pass');
!
390
                $result = call_user_func_array([$this, $action], $pass);
!
391

392
                if ($result instanceof Response) {
!
393
                        return $result;
!
394
                }
395

NEW
396
                return $this->getController()->render($action);
!
397
        }
398

399
        /**
400
         * Maps an action of the controller to the component
401
         *
402
         * @param string $action Action name
403
         * @return bool|\Cake\Http\Response
404
         */
405
        protected function _mapAction($action) {
NEW
406
                $actionMap = $this->getConfig('actionMap');
!
407
                if (isset($actionMap[$action]) && method_exists($this, $actionMap[$action]['method'])) {
!
NEW
408
                        $pass = (array)$this->_getRequest()->param('pass');
!
409
                        call_user_func_array([$this, $actionMap[$action]['method']], $pass);
!
410

411
                        if ($this->_redirectResponse instanceof Response) {
!
412
                                return $this->_redirectResponse;
!
413
                        }
414

415
                        if (is_string($actionMap[$action]['view'])) {
!
416
                                try {
NEW
417
                                        return $this->getController()->render($this->getController()->request->param('action'));
!
418
                                } catch (MissingTemplateException $e) {
!
NEW
419
                                        return $this->getController()->render($actionMap[$action]['view']);
!
420
                                }
421
                        }
422

NEW
423
                        return $this->_getResponse();
!
424
                }
425

426
                return false;
!
427
        }
428

429
        /**
430
         * Handles the case when the user is already logged in and triggers a redirect
431
         * and flash message if configured for that.
432
         *
433
         * @see UserToolComponent::login()
434
         * @param array $options Options
435
         * @return void
436
         */
437
        protected function _handleUserBeingAlreadyLoggedIn(array $options) {
438
                $Auth = $this->_getAuthObject();
!
439
                if ((bool)$Auth->user()) {
!
440
                        if ($options['alreadyLoggedInRedirectUrl'] === null) {
!
NEW
441
                                $options['alreadyLoggedInRedirectUrl'] = $this->_getRequest()->referer();
!
442
                        }
443
                        $this->handleFlashAndRedirect('alreadyLoggedIn', $options);
!
444
                }
445
        }
!
446

447
        /**
448
         * Internal callback to prepare the credentials for the login.
449
         *
450
         * @param \Cake\Datasource\EntityInterface $entity User entity
451
         * @param array $options Options
452
         * @return mixed
453
         */
454
        protected function _beforeLogin(EntityInterface $entity, array $options) {
NEW
455
                $entity = $this->UserTable->patchEntity($entity, $this->_getRequest()->getData(), ['validate' => false]);
!
456

NEW
457
                $event = $this->dispatchEvent('User.beforeLogin', [
!
458
                        'options' => $options,
!
459
                        'entity' => $entity
!
460
                ]);
461

462
                if ($event->isStopped()) {
!
463
                        return $event->result;
!
464
                }
465

466
                return $this->_getAuthObject()->identify();
!
467
        }
468

469
        /**
470
         * Internal callback to handle the after login procedure.
471
         *
472
         * @param array $user User data
473
         * @param array $options Options
474
         * @return mixed
475
         */
476
        protected function _afterLogin($user, array $options) {
NEW
477
                $event = $this->dispatchEvent('User.afterLogin', [
!
478
                        'user' => $user,
!
479
                        'options' => $options
!
480
                ]);
481
                if ($event->isStopped()) {
!
482
                        return $event->result;
!
483
                }
484

485
                $Auth = $this->_getAuthObject();
!
486
                $Auth->setUser($user);
!
487

488
                if ($options['successRedirectUrl'] === null) {
!
489
                        $options['successRedirectUrl'] = $Auth->redirectUrl();
!
490
                }
491

492
                $this->handleFlashAndRedirect('success', $options);
!
493

UNCOV
494
                return true;
!
495
        }
496

497
        /**
498
         * Login
499
         *
500
         * @param array $options Options
501
         * @return bool
502
         */
503
        public function login($options = []) {
NEW
504
                $options = Hash::merge($this->getConfig('login'), $options);
!
505
                $this->_handleUserBeingAlreadyLoggedIn($options);
!
506
                $entity = $this->UserTable->newEntity(null, ['validate' => false]);
!
507

NEW
508
                if ($this->_getRequest()->is('post')) {
!
509
                        $user = $this->_beforeLogin($entity, $options);
!
510
                        if ($user) {
!
511
                                return $this->_afterLogin($user, $options);
!
512
                        } else {
513
                                $this->handleFlashAndRedirect('error', $options);
!
514
                        }
515
                }
516

517
                if ($options['setEntity']) {
!
518
                        $this->_setViewVar('userEntity', $entity);
!
519
                }
520

UNCOV
521
                return false;
!
522
        }
523

524
        /**
525
         * Gets an user based on it's user id.
526
         *
527
         * - `viewVar` it sets the entity to the view. It's set by default to `user`. To
528
         *    disable setting the view var just set it to false.
529
         *
530
         * @param int|string $userId UUID or integer type user id.
531
         * @param array $options Configuration options.
532
         * @return mixed
533
         */
534
        public function getUser($userId = null, $options = []) {
535
                $options = Hash::merge($this->getConfig('getUser'), $options);
1×
536
                if (is_null($userId)) {
1×
537
                        if (isset($this->_getRequest()->params['pass'][0])) {
1×
538
                                $userId = $this->_getRequest()->params['pass'][0];
1×
539
                        }
540
                }
541

542
                $entity = $this->UserTable->getUser($userId);
1×
543
                if ($options['viewVar'] !== false) {
1×
544
                        $this->getController()->set($options['viewVar'], $entity);
1×
545
                        $this->getController()->set('_serialize', [$options['viewVar']]);
1×
546
                }
547

548
                return $entity;
1×
549
        }
550

551
        /**
552
         * Deletes an user record
553
         *
554
         * @param mixed $userId User ID
555
         * @param array $options Options
556
         * @return bool
557
         */
558
        public function deleteUser($userId = null, $options = []) {
559
                $entity = $this->_getUserEntity($userId);
!
560
                if ($this->UserTable->delete($entity)) {
!
561
                        $this->handleFlashAndRedirect('success', $options);
!
562

UNCOV
563
                        return true;
!
564
                } else {
565
                        $this->handleFlashAndRedirect('error', $options);
!
566

UNCOV
567
                        return false;
!
568
                }
569
        }
570

571
        /**
572
         * Gets or constructs an user entity with a given id.
573
         *
574
         * @param mixed array|int|string $userId User ID
575
         * @return \Cake\Datasource\EntityInterface
576
         */
577
        protected function _getUserEntity($userId) {
NEW
578
                if (is_a($userId, EntityInterface::class)) {
!
579
                        return $userId;
!
580
                }
581

582
                if (is_string($userId) || is_integer($userId)) {
!
NEW
583
                        $entity = $this->UserTable->newEntity();
!
584

NEW
585
                        return $this->UserTable->patchEntity(
!
NEW
586
                                $entity,
!
NEW
587
                                [$this->UserTable->primaryKey() => $userId],
!
NEW
588
                                ['guard' => false]
!
589
                        );
590
                }
591

592
                if (is_array($userId)) {
!
NEW
593
                        $entity = $this->UserTable->newEntity();
!
594

NEW
595
                        return $this->UserTable->patchEntity(
!
NEW
596
                                $entity,
!
NEW
597
                                $userId,
!
NEW
598
                                ['guard' => false]
!
599
                        );
600
                }
601
        }
!
602

603
        /**
604
         * Logout
605
         *
606
         * @param array $options Options array.
607
         * @return \Cake\Http\Response
608
         */
609
        public function logout($options = []) {
NEW
610
                $options = Hash::merge($this->getConfig('logout'), $options);
!
611
                $Auth = $this->_getAuthObject();
!
612
                $user = $Auth->user();
!
613

614
                if (empty($user)) {
!
NEW
615
                        return $this->getController()->redirect($this->getController()->referer());
!
616
                }
617

618
                $logoutRedirect = $Auth->logout();
!
619
                if (is_null($options['successRedirectUrl'])) {
!
620
                        $options['successRedirectUrl'] = $logoutRedirect;
!
621
                }
622

623
                return $this->handleFlashAndRedirect('success', $options);
!
624
        }
625

626
        /**
627
         * User registration
628
         *
629
         * Options:
630
         *
631
         * - `enabled` Disables/enables the registration. If false a NotFoundException is thrown. Default true.
632
         * - `successMessage` The success flash message.
633
         * - `successRedirectUrl` Success redirect url. Default /.
634
         * - `errorMessage` The error flash message.
635
         * - `errorRedirectUrl` The error redirect url.
636
         * - `setEntity` Set the entity to the view or not, default is true.
637
         *
638
         * @throws \Cake\Error\NotFoundException
639
         * @param array $options Options
640
         * @return bool|null
641
         */
642
        public function register($options = []) {
NEW
643
                $options = Hash::merge($this->getConfig('registration'), $options);
!
644
                if ($options['enabled'] === false) {
!
645
                        throw new NotFoundException();
!
646
                }
647

648
                $return = false;
!
649
                $entity = $this->UserTable->newEntity();
!
650
                // Make the field accessible in the case the default entity class is used.
651
                $entity->accessible('confirm_password', true);
!
NEW
652
                if ($this->_getRequest()->is('post')) {
!
NEW
653
                        $entity = $this->UserTable->patchEntity($entity, $this->_getRequest()->getData(), [
!
UNCOV
654
                                'validate' => $options['validation']
!
655
                        ]);
656
                        if ($this->UserTable->register($entity)) {
!
657
                                $this->handleFlashAndRedirect('success', $options);
!
658
                                $return = true;
!
659
                        } else {
660
                                $this->handleFlashAndRedirect('error', $options);
!
661
                        }
662
                }
663
                if ($options['setEntity'] === true) {
!
664
                        $this->_setViewVar('userEntity', $entity);
!
665
                        // For backward compatibility
666
                        $this->_setViewVar('usersEntity', $entity);
!
667
                }
668

UNCOV
669
                return $return;
!
670
        }
671

672
        /**
673
         * Verifies an email token
674
         *
675
         * @param array $options Options
676
         * @return mixed
677
         */
678
        public function verifyEmailToken($options = []) {
679
                $options = Hash::merge(
!
NEW
680
                        $this->getConfig('verifyEmailToken'),
!
681
                        $options,
!
682
                        ['type' => 'Email']
!
683
                );
684

685
                return $this->verifyToken($options);
!
686
        }
687

688
        /**
689
         * The user can request a new password reset token, an email is send to him.
690
         *
691
         * @param array $options Options
692
         * @throws \Cake\Datasource\Exception\RecordNotFoundException
693
         * @return bool|null
694
         */
695
        public function requestPassword($options = []) {
NEW
696
                $options = Hash::merge($this->getConfig('requestPassword'), $options);
!
697
                $entity = $this->UserTable->newEntity(null, [
!
698
                        'validate' => 'requestPassword'
!
699
                ]);
700

NEW
701
                if ($this->_getRequest()->is('post')) {
!
NEW
702
                        $entity = $this->UserTable->patchEntity($entity, $this->_getRequest()->getData(), [
!
UNCOV
703
                                'validate' => 'requestPassword'
!
704
                        ]);
705

706
                        if (!$entity->errors($options['field']) && $this->_initPasswordReset($entity, $options)) {
!
707
                                return true;
!
708
                        }
709

710
                        if ($options['setEntity']) {
!
711
                                if ($entity->dirty('email') && !$entity->errors('email')) {
!
712
                                        $entity->email = '';
!
713
                                }
714
                                $this->_setViewVar('userEntity', $entity);
!
715
                        }
NEW
716
                        unset($this->_getRequest()->data[$options['field']]);
!
717

UNCOV
718
                        return false;
!
719
                }
720

721
                if ($options['setEntity']) {
!
NEW
722
                        $this->getController()->set('userEntity', $entity);
!
723
                }
724
        }
!
725

726
        /**
727
         * Initializes the password reset and handles a possible errors.
728
         *
729
         * @param \Cake\Datasource\EntityInterface $entity User entity
730
         * @param array $options Options array Options
731
         * @return bool
732
         */
733
        protected function _initPasswordReset(EntityInterface $entity, $options) {
734
                try {
NEW
735
                        $this->UserTable->initPasswordReset($this->_getRequest()->getData($options['field']), $options);
!
736
                        $this->handleFlashAndRedirect('success', $options);
!
737
                        if ($options['setEntity']) {
!
738
                                $this->_setViewVar('userEntity', $entity);
!
739
                        }
740

741
                        return true;
!
742
                } catch (RecordNotFoundException $e) {
!
743
                        $this->handleFlashAndRedirect('error', $options);
!
744
                }
745

746
                return false;
!
747
        }
748

749
        /**
750
         * Allows the user to enter a new password.
751
         *
752
         * @param string|null $token Token
753
         * @param array $options Options
754
         * @return null|\Cake\Http\Response
755
         */
756
        public function resetPassword($token = null, $options = []) {
NEW
757
                $options = Hash::merge($this->getConfig('resetPassword'), $options);
!
758

NEW
759
                $tokenParam = $this->_getRequest()->getQuery($options['queryParam']);
!
NEW
760
                if (!empty($tokenParam)) {
!
NEW
761
                        $token = $tokenParam;
!
762
                }
763

764
                // Check of the token exists
765
                try {
766
                        $entity = $this->UserTable->verifyPasswordResetToken($token, $options['tokenOptions']);
!
767
                } catch (RecordNotFoundException $e) {
!
768
                        if (empty($options['errorMessage']) && $options['errorMessage'] !== false) {
!
769
                                $options['errorMessage'] = $e->getMessage();
!
770
                        }
771

772
                        $redirect = $this->handleFlashAndRedirect('invalidError', $options);
!
773
                        if ($redirect instanceof Response) {
!
774
                                return $redirect;
!
775
                        }
776
                        $entity = $this->UserTable->newEntity();
!
777
                }
778

779
                // Check if the token has expired
780
                if ($entity->get('token_is_expired') === true) {
!
781
                        if (empty($options['invalidErrorMessage'])) {
!
782
                                $options['invalidErrorMessage'] = $e->getMessage();
!
783
                        }
784
                        $redirect = $this->handleFlashAndRedirect('expiredError', $options);
!
785
                        if ($redirect instanceof Response) {
!
786
                                return $redirect;
!
787
                        }
788
                }
789

790
                // Handle the POST
NEW
791
                if ($this->_getRequest()->is('post')) {
!
NEW
792
                        $entity = $this->UserTable->patchEntity($entity, $this->_getRequest()->getData());
!
793
                        if ($this->UserTable->resetPassword($entity)) {
!
794
                                $redirect = $this->handleFlashAndRedirect('success', $options);
!
795
                        } else {
796
                                $redirect = $this->handleFlashAndRedirect('error', $options);
!
797
                        }
798
                        if ($redirect instanceof Response) {
!
799
                                return $redirect;
!
800
                        }
801
                } else {
802
                        $entity = $this->UserTable->newEntity();
!
803
                }
804

805
                $this->_setViewVar('entity', $entity);
!
806
        }
!
807

808
        /**
809
         * Let the logged in user change his password.
810
         *
811
         * @param array $options Options
812
         * @return void
813
         */
814
        public function changePassword($options = []) {
NEW
815
                $options = Hash::merge($this->getConfig('changePassword'), $options);
!
816

817
                $entity = $this->UserTable->newEntity();
!
818
                $entity->accessible([
!
819
                        'old_password',
!
820
                        'password',
821
                        'new_password',
822
                        'confirm_password'
823
                ], true);
!
824

NEW
825
                if ($this->_getRequest()->is(['post', 'put'])) {
!
826
                        $entity = $this->UserTable->get($this->_getAuthObject()->user('id'));
!
NEW
827
                        $entity = $this->UserTable->patchEntity($entity, $this->_getRequest()->data, [
!
828
                                'validate' => 'changePassword'
!
829
                        ]);
830

831
                        if ($this->UserTable->changePassword($entity)) {
!
NEW
832
                                $this->_getRequest()->data = [];
!
833
                                $entity = $this->UserTable->newEntity();
!
834
                                $this->handleFlashAndRedirect('success', $options);
!
835
                        } else {
836
                                $this->handleFlashAndRedirect('error', $options);
!
837
                        }
838
                }
839

840
                $this->_setViewVar('entity', $entity);
!
841
        }
!
842

843
        /**
844
         * Verify Token
845
         *
846
         * @param array $options Options
847
         * @throws \Cake\Error\NotFoundException;
848
         * @return mixed
849
         */
850
        public function verifyToken($options = []) {
851
                $options = Hash::merge($this->_defaultConfig['verifyToken'], $options);
!
852

NEW
853
                $token = $this->_getRequest()->getQuery($options['queryParam']);
!
NEW
854
                if (empty($token)) {
!
UNCOV
855
                        throw new NotFoundException(__d('burzum/user_tools', 'No token present!'));
!
856
                }
857

858
                $methodName = 'verify' . $options['type'] . 'Token';
!
859

860
                try {
NEW
861
                        $result = $this->UserTable->$methodName($token);
!
862
                        $this->handleFlashAndRedirect('success', $options);
!
863
                } catch (RecordNotFoundException $e) {
!
864
                        if (is_null($options['errorMessage'])) {
!
865
                                $options['errorMessage'] = $e->getMessage();
!
866
                        }
867
                        $this->handleFlashAndRedirect('error', $options);
!
868
                        $result = false;
!
869
                }
870

871
                return $result;
!
872
        }
873

874
        /**
875
         * Gets the auth component object
876
         *
877
         * If there is an auth component loaded it will take that one from the
878
         * controller. If not the configured default settings will be used to create
879
         * a new instance of the auth component. This is mostly thought as a fallback,
880
         * in a real world scenario the app should have set auth set up in it's
881
         * AppController.
882
         *
883
         * @return \Cake\Controller\Component\AuthComponent
884
         */
885
        protected function _getAuthObject() {
886
                if (!$this->_registry->has('Auth')) {
!
NEW
887
                        $Auth = $this->_registry->load('Auth', $this->getConfig('auth'));
!
NEW
888
                        $Auth->request = $this->_getRequest();
!
NEW
889
                        $Auth->response = $this->_getResponse();
!
890

891
                        return $Auth;
!
892
                }
893

NEW
894
                return $this->_registry->Auth;
!
895
        }
896

897
        /**
898
         * Handles the optional setting of view vars within the component.
899
         *
900
         * @param bool $viewVar Set the view var or not
901
         * @param \Cake\Datasource\EntityInterface $entity User entity
902
         * @return void
903
         */
904
        protected function _setViewVar($viewVar, $entity) {
905
                if ($viewVar === false) {
!
906
                        return;
!
907
                }
908

NEW
909
                $this->getController()->set($viewVar, $entity);
!
910
        }
!
911
}
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2023 Coveralls, Inc