Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: Feature/ajax login #789

Open
wants to merge 27 commits into
base: 8.next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f1a70c6
wip Ajax login
ajibarra Apr 16, 2019
e40cb9b
Ability to pass associated models for register
yeliparra Apr 17, 2019
dde0234
Fix url
yeliparra Apr 17, 2019
d3eadc9
WIP Ajax register
yeliparra Apr 23, 2019
ee64ccb
Update Login and Register for ajax
ajibarra Apr 24, 2019
e6385ea
Merge branch '8.next' into feature/ajax-login
ajibarra Apr 24, 2019
e70c4c7
Fix some php cs issues
ajibarra Apr 24, 2019
3a4b419
Fixed url
yeliparra Apr 24, 2019
1975fc4
fix php cs
yeliparra Apr 24, 2019
a0a9763
Fix login with fb
ajibarra Apr 30, 2019
a5b8383
Merge branch 'master' of https://github.com/CakeDC/users into feature…
ajibarra May 15, 2019
29f1738
Merge branch '8.next' of https://github.com/CakeDC/users into feature…
ajibarra May 15, 2019
dd951ea
Fix duplicate table registry
ajibarra May 15, 2019
0564a09
Fix tableregistry
ajibarra May 15, 2019
247d48d
Handle RedirectRoute while parsing url to check permissions
rochamarcelo Aug 5, 2019
a61562f
phpcs fix
rochamarcelo Aug 12, 2019
137438b
fixed phpunit version
rochamarcelo Aug 12, 2019
6f8a8ad
Merge branch '8.next' into issue/route-redirect-exception
rochamarcelo Aug 12, 2019
dd8e2ba
Merge pull request #809 from CakeDC/issue/route-redirect-exception
steinkel Aug 12, 2019
2e20bd1
Authorization check should consider 'redirect' rules
rochamarcelo Aug 12, 2019
771aec5
#ajax-login fix some tests
steinkel Aug 12, 2019
4a0dfe2
#ajax-login fix conflicts
steinkel Aug 12, 2019
95c14c5
#ajax-login fix more tests
steinkel Aug 13, 2019
71fe4cc
#ajax-login fix tests
steinkel Aug 13, 2019
07b559f
#ajax-login fix tests
steinkel Aug 13, 2019
5079623
fixed invalid test case related to removal at ffe93368b9dd4ed5f2e4841…
rochamarcelo Aug 13, 2019
2bf543c
phpcs fixes
rochamarcelo Aug 13, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion config/bootstrap.php
Expand Up @@ -22,7 +22,9 @@
Configure::load($file);
});

TableRegistry::getTableLocator()->setConfig('Users', ['className' => Configure::read('Users.table')]);
if (!TableRegistry::getTableLocator()->exists('Users')) {
TableRegistry::getTableLocator()->setConfig('Users', ['className' => Configure::read('Users.table')]);
}
TableRegistry::getTableLocator()->setConfig('CakeDC/Users.Users', ['className' => Configure::read('Users.table')]);

if (Configure::check('Users.auth')) {
Expand Down
1 change: 1 addition & 0 deletions src/Auth/Social/Mapper/AbstractMapper.php
Expand Up @@ -65,6 +65,7 @@ public function __construct($rawData, $mapFields = null)
}
$this->_mapFields = array_merge($this->_defaultMapFields, $this->_mapFields);
}

/**
* Invoke method
*
Expand Down
41 changes: 25 additions & 16 deletions src/Controller/Component/UsersAuthComponent.php
Expand Up @@ -19,8 +19,10 @@
use Cake\Event\EventManager;
use Cake\Http\ServerRequest;
use Cake\Routing\Exception\MissingRouteException;
use Cake\Routing\Exception\RedirectException;
use Cake\Routing\Router;
use Cake\Utility\Hash;
use Zend\Diactoros\Uri;

class UsersAuthComponent extends Component
{
Expand Down Expand Up @@ -166,23 +168,31 @@ public function isUrlAuthorized(Event $event)
return false;
}

if (is_array($url)) {
$requestUrl = Router::normalize(Router::reverse($url));
$requestParams = Router::parseRequest(new ServerRequest($requestUrl));
} else {
try {
//remove base from $url if exists
$normalizedUrl = Router::normalize($url);
$requestParams = Router::parseRequest(new ServerRequest($normalizedUrl));
} catch (MissingRouteException $ex) {
//if it's a url pointing to our own app
if (substr($normalizedUrl, 0, 1) === '/') {
throw $ex;
}
try {
if (is_array($url)) {
$requestUrl = Router::normalize(Router::reverse($url));
$requestParams = Router::parseRequest(new ServerRequest($requestUrl));
} else {
try {
//remove base from $url if exists
$normalizedUrl = Router::normalize($url);
$requestParams = Router::parseRequest(new ServerRequest($normalizedUrl));
} catch (MissingRouteException $ex) {
//if it's a url pointing to our own app
if (substr($normalizedUrl, 0, 1) === '/') {
throw $ex;
}

return true;
return true;
}
$requestUrl = $url;
}
$requestUrl = $url;
} catch (RedirectException $e) {
$uri = new Uri($e->getMessage());
$requestParams = Router::parseRequest(
new ServerRequest(['uri' => $uri])
);
$requestUrl = $uri->getPath();
}
// check if controller action is allowed
if ($this->_isActionAllowed($requestParams)) {
Expand All @@ -194,7 +204,6 @@ public function isUrlAuthorized(Event $event)
if (empty($user)) {
return false;
}

$request = new ServerRequest($requestUrl);
$request = $request->withAttribute('params', $requestParams);

Expand Down
28 changes: 25 additions & 3 deletions src/Controller/Traits/LoginTrait.php
Expand Up @@ -22,8 +22,8 @@
use Cake\Core\Exception\Exception;
use Cake\Event\Event;
use Cake\Http\Exception\NotFoundException;
use Cake\Http\Response;
use Cake\Utility\Hash;
use League\OAuth1\Client\Server\Twitter;

/**
* Covers the login, logout and social login
Expand Down Expand Up @@ -197,7 +197,7 @@ public function login()
}

if (!$this->request->is('post') && !$socialLogin) {
if ($this->Auth->user()) {
if ($user = $this->Auth->user()) {
if (!$this->request->getSession()->read('Users.successSocialLogin')) {
$msg = __d('CakeDC/Users', 'You are already logged in');
$this->Flash->error($msg);
Expand All @@ -207,6 +207,13 @@ public function login()
}
$url = $this->Auth->redirectUrl();

if ($this->getRequest()->is('ajax')) {
$this->set('user', $user);
$this->set('_serialize', ['user']);

return;
}

return $this->redirect($url);
}
}
Expand Down Expand Up @@ -375,11 +382,24 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen

$url = $this->Auth->redirectUrl();

if ($this->request->is('ajax')) {
$this->set('user', $user);
$this->set('_serialize', ['user']);

return;
}

return $this->redirect($url);
} else {
if (!$socialLogin) {
$message = __d('CakeDC/Users', 'Username or password is incorrect');
$this->Flash->error($message, 'default', [], 'auth');
if ($this->request->is('ajax')) {
$this->set('error', $message);
$this->set('_serialize', ['error']);

return;
}
}

return $this->redirect(Configure::read('Auth.loginAction'));
Expand Down Expand Up @@ -408,7 +428,9 @@ public function logout()
return $this->redirect($eventAfter->result);
}

return $this->redirect($this->Auth->logout());
$redirectUrl = $this->request->getQuery('redirect_url');

return $this->redirect($redirectUrl ?: $this->Auth->logout());
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/Controller/Traits/PasswordManagementTrait.php
Expand Up @@ -168,6 +168,9 @@ public function resetGoogleAuthenticator($id = null)
{
if ($this->request->is('post')) {
try {
if (empty($id)) {
throw new \Exception(__('Invalid user id'));
}
$query = $this->getUsersTable()->query();
$query->update()
->set(['secret_verified' => false, 'secret' => null])
Expand All @@ -177,8 +180,7 @@ public function resetGoogleAuthenticator($id = null)
$message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset');
$this->Flash->success($message, 'default');
} catch (\Exception $e) {
$message = $e->getMessage();
$this->Flash->error($message, 'default');
$this->Flash->error(__('Could not reset the token'), 'default');
}
}

Expand Down
26 changes: 23 additions & 3 deletions src/Controller/Traits/RegisterTrait.php
Expand Up @@ -34,11 +34,16 @@ trait RegisterTrait
*/
public function register()
{
if ($this->request->is('ajax')) {
$this->viewBuilder()->setLayout('ajax');
}

if (!Configure::read('Users.Registration.active')) {
throw new NotFoundException();
}

$userId = $this->Auth->user('id');

if (!empty($userId) && !Configure::read('Users.Registration.allowLoggedIn')) {
$this->Flash->error(__d('CakeDC/Users', 'You must log out to register a new user account'));

Expand All @@ -61,14 +66,20 @@ public function register()
'options' => $options,
'userEntity' => $user,
]);
$this->set(compact('user'));
$this->set('_serialize', ['user']);

if ($event->result instanceof EntityInterface) {
$data = $event->result->toArray();
$data['password'] = $requestData['password']; //since password is a hidden property
if ($userSaved = $usersTable->register($user, $data, $options)) {
$this->set(compact('user'));
$this->set('_serialize', ['user']);

return $this->_afterRegister($userSaved);
} else {
$this->set(compact('user'));
$this->set('error', $user->getErrors());
$this->set('_serialize', ['error']);
$this->Flash->error(__d('CakeDC/Users', 'The user could not be saved'));

return;
Expand All @@ -93,6 +104,8 @@ public function register()

$userSaved = $usersTable->register($user, $requestData, $options);
if (!$userSaved) {
$this->set('error', $user->getErrors());
$this->set('_serialize', ['error']);
$this->Flash->error(__d('CakeDC/Users', 'The user could not be saved'));

return;
Expand Down Expand Up @@ -134,12 +147,19 @@ protected function _afterRegister(EntityInterface $userSaved)
$event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, [
'user' => $userSaved
]);

if ($event->result instanceof Response) {
return $event->result;
}
$this->Flash->success($message);

return $this->redirect(['action' => 'login']);
if (!$this->request->is('ajax')) {
if (Configure::check('Users.Registration.successMessage')) {
$message = Configure::read('Users.Registration.successMessage');
}
$this->Flash->success($message);

return $this->redirect(['action' => 'login']);
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Controller/Traits/U2fTrait.php
Expand Up @@ -37,6 +37,7 @@ public function redirectWithQuery($url)

return $this->redirect($url);
}

/**
* U2f entry point
*
Expand Down
4 changes: 3 additions & 1 deletion src/Model/Behavior/RegisterBehavior.php
Expand Up @@ -53,10 +53,12 @@ public function register($user, $data, $options)
{
$validateEmail = Hash::get($options, 'validate_email');
$tokenExpiration = Hash::get($options, 'token_expiration');
$associated = Configure::read('Users.Registration.associated') ? ['associated' => Configure::read('Users.Registration.associated')] : [];

$user = $this->_table->patchEntity(
$user,
$data,
['validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options)]
array_merge(['validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options)], $associated)
);
$user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user';
$user->validated = false;
Expand Down
1 change: 1 addition & 0 deletions src/Template/Email/text/validation.ctp
Expand Up @@ -15,6 +15,7 @@ $activationUrl = [
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'validateEmail',
'prefix' => false,
isset($token) ? $token : ''
];
?>
Expand Down
1 change: 1 addition & 0 deletions src/View/Helper/UserHelper.php
Expand Up @@ -188,6 +188,7 @@ public function isAuthorized($url = null)

return $this->AuthLink->isAuthorized($url);
}

/**
* Create links for all social providers enabled social link (connect)
*
Expand Down
Expand Up @@ -28,6 +28,7 @@ class RememberMeComponentTest extends TestCase
public $fixtures = [
'plugin.CakeDC/Users.Users'
];

/**
* setUp method
*
Expand Down
40 changes: 39 additions & 1 deletion tests/TestCase/Controller/Component/UsersAuthComponentTest.php
Expand Up @@ -24,6 +24,7 @@
use Cake\Network\Request;
use Cake\ORM\Entity;
use Cake\Routing\Exception\MissingRouteException;
use Cake\Routing\RouteBuilder;
use Cake\Routing\Router;
use Cake\TestSuite\TestCase;
use Cake\Utility\Security;
Expand Down Expand Up @@ -65,7 +66,7 @@ public function setUp()
]);
Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi');
Configure::write('App.namespace', 'Users');
$this->request = $this->getMockBuilder('Cake\Network\Request')
$this->request = $this->getMockBuilder('Cake\Http\ServerRequest')
->setMethods(['is', 'method'])
->getMock();
$this->request->expects($this->any())->method('is')->will($this->returnValue(true));
Expand Down Expand Up @@ -262,6 +263,42 @@ public function testIsUrlAuthorizedUrlRelativeString()
$this->assertTrue($result);
}

/**
* test
*
* @return void
*/
public function testIsUrlAuthorizedUrlWithRedirectRoute()
{
(new RouteBuilder(Router::getRouteCollection(), '/'))->redirect("/my-redirect-route", "/route");
$event = new Event('event');

$event->setData([
'url' => '/my-redirect-route',
]);
$this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent')
->setMethods(['user', 'isAuthorized'])
->disableOriginalConstructor()
->getMock();
$this->Controller->Auth->expects($this->once())
->method('user')
->will($this->returnValue(['id' => 1]));
$this->Controller->Auth->expects($this->once())
->method('isAuthorized')
->with(null, $this->callback(function ($subject) {
return $subject->getAttribute('params') === [
'pass' => [],
'plugin' => 'CakeDC/Users',
'controller' => 'Users',
'action' => 'requestResetPassword',
'_matchedRoute' => '/route/*',
];
}))
->will($this->returnValue(true));
$result = $this->Controller->UsersAuth->isUrlAuthorized($event);
$this->assertTrue($result);
}

/**
* test
*
Expand Down Expand Up @@ -480,6 +517,7 @@ public function testIsUrlAuthorizedBaseUrl()
$result = $this->Controller->UsersAuth->isUrlAuthorized($event);
$this->assertTrue($result);
}

/**
* test The user is logged in and allowed by rules to access this action,
* and we are checking another controller action not allowed
Expand Down