Skip to content

Commit

Permalink
Merge pull request #479 from CakeDC/develop
Browse files Browse the repository at this point in the history
Merge develop
  • Loading branch information
steinkel authored Jan 9, 2017
2 parents ec705e7 + bca6c37 commit 2b7ff7c
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .semver
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
:major: 4
:minor: 0
:minor: 1
:patch: 0
:special: ''
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ Changelog

Releases for CakePHP 3
-------------
* 4.1.0
* Add reset action for Google Authenticator

* 4.0.0
* Add Google Authenticator
* Add improvements to SimpleRbac, like star to invert rules and `user.` prefix to match values from the user array
Expand Down
14 changes: 14 additions & 0 deletions config/permissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@
'controller' => 'Users',
'action' => ['register', 'edit', 'view'],
],
[
'role' => '*',
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'resetGoogleAuthenticator',
'allowed' => function (array $user, $role, \Cake\Network\Request $request) {
$userId = \Cake\Utility\Hash::get($request->params, 'pass.0');
if (!empty($userId) && !empty($user)) {
return $userId === $user['id'];
}

return false;
}
],
[
'role' => 'user',
'plugin' => 'CakeDC/Users',
Expand Down
14 changes: 12 additions & 2 deletions config/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @copyright Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
use Cake\Core\Configure;
use Cake\Routing\Router;

Router::plugin('CakeDC/Users', ['path' => '/users'], function ($routes) {
Expand All @@ -25,8 +26,17 @@
'controller' => 'SocialAccounts',
'action' => 'validate'
]);
// Google Authenticator related routes
if (Configure::read('Users.GoogleAuthenticator.login')) {
Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']);

Router::connect('/resetGoogleAuthenticator', [
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'resetGoogleAuthenticator'
]);
}

Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']);
Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']);
Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']);
Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']);

6 changes: 4 additions & 2 deletions src/Controller/Traits/LoginTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,13 @@ public function verify()
}

if ($this->request->is('post')) {
$codeVerified = false;
$verificationCode = $this->request->data('code');
$user = $this->request->session()->read('temporarySession');
$entity = $this->getUsersTable()->get($user['id']);

if (array_key_exists('secret', $user)) {
$codeVerified = $this->GoogleAuthenticator->verifyCode($user['secret'], $verificationCode);
if (!empty($entity['secret'])) {
$codeVerified = $this->GoogleAuthenticator->verifyCode($entity['secret'], $verificationCode);
}

if ($codeVerified) {
Expand Down
30 changes: 30 additions & 0 deletions src/Controller/Traits/PasswordManagementTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,34 @@ public function requestResetPassword()
$this->Flash->error(__d('CakeDC/Users', 'Token could not be reset'));
}
}

/**
* resetGoogleAuthenticator
*
* Resets Google Authenticator token by setting secret_verified
* to false.
*
* @param mixed $id of the user record.
* @return mixed.
*/
public function resetGoogleAuthenticator($id = null)
{
if ($this->request->is('post')) {
try {
$query = $this->getUsersTable()->query();
$query->update()
->set(['secret_verified' => false, 'secret' => null])
->where(['id' => $id]);
$executed = $query->execute();

$message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset');
$this->Flash->success($message, 'default');
} catch (\Exception $e) {
$message = __d('CakeDC/Users', $e->getMessage());
$this->Flash->error($message, 'default');
}
}

return $this->redirect($this->request->referer());
}
}
16 changes: 16 additions & 0 deletions src/Template/Users/edit.ctp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @copyright Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
use Cake\Core\Configure;

$Users = ${$tableAlias};
?>
Expand Down Expand Up @@ -55,4 +56,19 @@ $Users = ${$tableAlias};
</fieldset>
<?= $this->Form->button(__d('CakeDC/Users', 'Submit')) ?>
<?= $this->Form->end() ?>
<?php if(Configure::read('Users.GoogleAuthenticator.login')) : ?>
<fieldset>
<legend>Reset Google Authenticator</legend>
<?= $this->Form->postLink(
__d('CakeDC/Users', 'Reset Google Authenticator Token'), [
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'resetGoogleAuthenticator', $Users->id
], [
'class' => 'btn btn-danger',
'confirm' => __d('CakeDC/Users', 'Are you sure you want to reset token for user "{0}"?', $Users->username)
]);
?>
</fieldset>
<?php endif; ?>
</div>
2 changes: 2 additions & 0 deletions tests/Fixture/UsersFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class UsersFixture extends TestFixture
'api_token' => 'xxx',
'activation_date' => '2015-06-24 17:33:54',
'secret' => 'xxx',
'secret_verified' => true,
'is_superuser' => true,
'tos_date' => '2015-06-24 17:33:54',
'active' => false,
Expand All @@ -133,6 +134,7 @@ class UsersFixture extends TestFixture
'api_token' => 'Lorem ipsum dolor sit amet',
'activation_date' => '2015-06-24 17:33:54',
'secret' => 'Lorem ipsum dolor sit amet',
'secret_verified' => true,
'is_superuser' => false,
'tos_date' => '2015-06-24 17:33:54',
'active' => true,
Expand Down
49 changes: 49 additions & 0 deletions tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -383,4 +383,53 @@ public function ensureUserActiveForResetPasswordFeature()
[$defaultBehavior]
];
}

/**
* @dataProvider ensureGoogleAuthenticatorResets
*
* @return void
*/
public function testRequestGoogleAuthTokenResetWithValidUser($userId, $entityId, $method, $msg)
{
$this->_mockRequestPost();
$this->_mockFlash();

$user = $this->table->get($userId);

$this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent')
->setMethods(['user', 'config'])
->disableOriginalConstructor()
->getMock();

$this->Trait->Auth->expects($this->any())
->method('user')
->will($this->returnValue($user));

$this->Trait->Flash->expects($this->any())
->method($method)
->with($msg);

$this->Trait->resetGoogleAuthenticator($entityId);
}

public function ensureGoogleAuthenticatorResets()
{
$error = 'error';
$success = 'success';
$errorMsg = 'You are not allowed to reset users Google Authenticator token';
$successMsg = 'Google Authenticator token was successfully reset';

return [
//is_superuser = true.
['00000000-0000-0000-0000-000000000003', null, $success, $successMsg],
//is_superuser = true.
['00000000-0000-0000-0000-000000000001', null, $success, $successMsg],
//is_superuser = false, and not his profile.
['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000001', $error, $errorMsg],
//is_superuser = false, editing own record.
['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000004', $success, $successMsg],
//is_superuser = false, and no entity-id given.
['00000000-0000-0000-0000-000000000004', null, $error, $errorMsg],
];
}
}

0 comments on commit 2b7ff7c

Please sign in to comment.