Skip to content

Commit

Permalink
Merge pull request #600 from CakeDC/develop
Browse files Browse the repository at this point in the history
update develop
  • Loading branch information
ajibarra authored Aug 24, 2017
2 parents 1414871 + e75c1ef commit c0897ae
Show file tree
Hide file tree
Showing 28 changed files with 2,680 additions and 24 deletions.
4 changes: 2 additions & 2 deletions .semver
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
:major: 5
:minor: 0
:patch: 3
:minor: 1
:patch: 0
:special: ''
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Changelog
Releases for CakePHP 3
-------------

* 5.1.0
* New resend validation method in RegisterBehavior
* Allow upgrade to CakePHP 3.5.x
* New feature connect social account
* New polish translations
* Fixed bugs reported

* 5.0.3
* Implemented event dispatching on social login
* Fixed bugs reported
Expand Down
1 change: 1 addition & 0 deletions Docs/Documentation/Translations.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The Plugin is translated into several languages:
* Spanish (es) by @florenciohernandez
* Brazillian Portuguese (pt_BR) by @andtxr
* French (fr_FR) by @jtraulle
* Polish (pl) by @joulbex

**Note:** To overwrite the plugin translations, create a file inside your project 'src/Locale/{$lang}/' folder, with the name 'Users.po' and add the strings with the new translations.

Expand Down
14 changes: 14 additions & 0 deletions Docs/Documentation/UserHelper.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ echo $this->User->socialLogin($provider); //provider is 'facebook', 'twitter', e

We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons.

Connect Social Account
-----------------

You can use the helper included with the plugin to create some 'Connect with Facebook/Twitter' buttons:

In templates, call socialConnectLinkList method to get links for all social providers enabled
```php
echo $this->User->socialConnectLinkList($user->social_accounts);
```

We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons.

The user must be allowed to access the urls "/link-social/[provider]" and "/callback-link-social/[provider]".

Logout link
-----------------

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"source": "https://github.com/CakeDC/users"
},
"require": {
"cakephp/cakephp": "~3.4.0",
"cakephp/cakephp": "^3.4.0",
"cakedc/auth": "^1.0"
},
"require-dev": {
Expand Down
2 changes: 1 addition & 1 deletion config/Migrations/20150513201111_initial.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/

use Phinx\Migration\AbstractMigration;
use Migrations\AbstractMigration;

class Initial extends AbstractMigration
{
Expand Down
Binary file added config/Migrations/schema-dump-default.lock
Binary file not shown.
10 changes: 10 additions & 0 deletions config/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,13 @@
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('/link-social/*', [
'controller' => 'Users',
'action' => 'linkSocial',
'plugin' => 'CakeDC/Users',
]);
Router::connect('/callback-link-social/*', [
'controller' => 'Users',
'action' => 'callbackLinkSocial',
'plugin' => 'CakeDC/Users',
]);
10 changes: 10 additions & 0 deletions config/users.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,30 +154,40 @@
'options' => [
'graphApiVersion' => 'v2.5',
'redirectUri' => Router::fullBaseUrl() . '/auth/facebook',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook',
]
],
'twitter' => [
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/twitter',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/twitter',
]
],
'linkedIn' => [
'className' => 'League\OAuth2\Client\Provider\LinkedIn',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/linkedIn',
]
],
'instagram' => [
'className' => 'League\OAuth2\Client\Provider\Instagram',
'options' => [
'redirectUri' => Router::fullBaseUrl() . '/auth/instagram',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/instagram',
]
],
'google' => [
'className' => 'League\OAuth2\Client\Provider\Google',
'options' => [
'userFields' => ['url', 'aboutMe'],
'redirectUri' => Router::fullBaseUrl() . '/auth/google',
'linkSocialUri' => Router::fullBaseUrl() . '/link-social/google',
'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google',
]
],
],
Expand Down
8 changes: 4 additions & 4 deletions src/Auth/SocialAuthenticate.php
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,10 @@ public function getUser(ServerRequest $request)
protected function _getProviderName($request = null)
{
$provider = false;
if (!is_null($this->_provider)) {
$provider = SocialUtils::getProvider($this->_provider);
} elseif (!empty($request)) {
if (!empty($request->getParam('provider'))) {
$provider = ucfirst($request->getParam('provider'));
} elseif (!is_null($this->_provider)) {
$provider = SocialUtils::getProvider($this->_provider);
}

return $provider;
Expand All @@ -455,7 +455,7 @@ protected function _mapUser($provider, $data)
if (empty($provider)) {
throw new MissingProviderException(__d('CakeDC/Users', "Provider cannot be empty"));
}
$providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider";
$providerMapperClass = $this->getConfig('providers.' . strtolower($provider) . '.options.mapper') ?: "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider";
$providerMapper = new $providerMapperClass($data);
$user = $providerMapper();
$user['provider'] = $provider;
Expand Down
4 changes: 3 additions & 1 deletion src/Controller/AppController.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public function initialize()
{
parent::initialize();
$this->loadComponent('Security');
$this->loadComponent('Csrf');
if ($this->request->getParam('_csrfToken') === false) {
$this->loadComponent('Csrf');
}
$this->loadComponent('CakeDC/Users.UsersAuth');
}
}
180 changes: 180 additions & 0 deletions src/Controller/Traits/LinkSocialTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php
/**
* Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com)
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/

namespace CakeDC\Users\Controller\Traits;

use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use League\OAuth2\Client\Provider\AbstractProvider;

/**
* Ações para "linkar" contas sociais
*
*/
trait LinkSocialTrait
{
/**
* Ação para inicial processo de link e autenticação social (facebook, google)
*
* @param string $alias of the provider.
*
* @throws \Cake\Network\Exception\NotFoundException Quando o provider informado não existe
* @return \Cake\Network\Response Redirects on successful
*/
public function linkSocial($alias = null)
{
$provider = $this->_getSocialProvider($alias);

$authUrl = $provider->getAuthorizationUrl();
$this->request->session()->write('SocialLink.oauth2state', $provider->getState());

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

/**
* Ação para receber o retorno do provedor (facebook, google) referente ao
* processo de link e autenticação social
*
* @param string $alias of the provider.
*
* @throws \Cake\Network\Exception\NotFoundException Quando o provider informado não existe
* @return \Cake\Network\Response Redirects to profile if okay or error
*/
public function callbackLinkSocial($alias = null)
{
$provider = $this->_getSocialProvider($alias);
$message = __d('CakeDC/Users', 'Could not associate account, please try again.');
if (!$this->_validateCallbackSocialLink()) {
$this->Flash->error($message);

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

$code = $this->request->getQuery('code');

try {
$token = $provider->getAccessToken('authorization_code', compact('code'));

$data = compact('token') + $provider->getResourceOwner($token)->toArray();

$data = $this->_mapSocialUser($alias, $data);

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

$this->getUsersTable()->linkSocialAccount($user, $data);

if ($user->errors()) {
$this->Flash->error($message);
} else {
$this->Flash->success(__d('CakeDC/Users', 'Social account was associated.'));
}
} catch (\Exception $e) {
$log = sprintf(
"Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s",
$e->getMessage(),
$e
);
$this->log($log);

$this->Flash->error($message);
}

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

/**
* Get the provider name based on the request or on the provider set.
*
* @param string $alias of the provider.
* @param array $data User data.
*
* @throws MissingProviderException
* @return array
*/
protected function _mapSocialUser($alias, $data)
{
$alias = ucfirst($alias);
$providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$alias";
$providerMapper = new $providerMapperClass($data);
$user = $providerMapper();
$user['provider'] = $alias;

return $user;
}

/**
* Instantiates provider object.
*
* @param string $alias of the provider.
*
* @throws \Cake\Network\Exception\NotFoundException
* @return \League\OAuth2\Client\Provider\AbstractProvider
*/
protected function _getSocialProvider($alias)
{
$config = Configure::read('OAuth.providers.' . $alias);
if (!$config || !isset($config['options'], $config['options']['callbackLinkSocialUri'])) {
throw new NotFoundException;
}

if (!isset($config['options']['clientId'], $config['options']['clientSecret'])) {
throw new NotFoundException;
}

return $this->_createSocialProvider($config);
}

/**
* Instantiates provider object.
*
* @param array $config for social provider.
*
* @throws \Cake\Network\Exception\NotFoundException
* @return \League\OAuth2\Client\Provider\AbstractProvider
*/
protected function _createSocialProvider($config)
{
$class = $config['className'];
$redirectUri = $config['options']['callbackLinkSocialUri'];

unset($config['options']['callbackLinkSocialUri'], $config['options']['linkSocialUri']);

$config['options']['redirectUri'] = $redirectUri;

return new $class($config['options'], []);
}

/**
* Validates OAuth2 request.
*
* @return bool
*/
protected function _validateCallbackSocialLink()
{
$queryParams = $this->request->getQueryParams();
if (isset($queryParams['error']) && !empty($queryParams['error'])) {
$this->log('Got error in _validateCallbackSocialLink: ' . htmlspecialchars($queryParams['error'], ENT_QUOTES, 'UTF-8'));

return false;
}

if (!array_key_exists('code', $queryParams)) {
return false;
}

$sessionKey = 'SocialLink.oauth2state';
$oauth2state = $this->request->session()->read($sessionKey);
$this->request->session()->delete($sessionKey);
$state = $queryParams['state'];

return $oauth2state === $state;
}
}
6 changes: 4 additions & 2 deletions src/Controller/Traits/LoginTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,15 +352,17 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen
*/
public function logout()
{
$eventBefore = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGOUT);
$user = (array)$this->Auth->user();

$eventBefore = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGOUT, ['user' => $user]);
if (is_array($eventBefore->result)) {
return $this->redirect($eventBefore->result);
}

$this->request->session()->destroy();
$this->Flash->success(__d('CakeDC/Users', 'You\'ve successfully logged out'));

$eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT);
$eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT, ['user' => $user]);
if (is_array($eventAfter->result)) {
return $this->redirect($eventAfter->result);
}
Expand Down
2 changes: 2 additions & 0 deletions src/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use CakeDC\Users\Controller\AppController;
use CakeDC\Users\Controller\Component\UsersAuthComponent;
use CakeDC\Users\Controller\Traits\LinkSocialTrait;
use CakeDC\Users\Controller\Traits\LoginTrait;
use CakeDC\Users\Controller\Traits\ProfileTrait;
use CakeDC\Users\Controller\Traits\ReCaptchaTrait;
Expand All @@ -30,6 +31,7 @@
*/
class UsersController extends AppController
{
use LinkSocialTrait;
use LoginTrait;
use ProfileTrait;
use ReCaptchaTrait;
Expand Down
Binary file added src/Locale/pl/Users.mo
Binary file not shown.
Loading

0 comments on commit c0897ae

Please sign in to comment.