Merge branch '15-settings-oauth-connect-disconnect'
This commit is contained in:
commit
313ba55098
6 changed files with 175 additions and 11 deletions
|
|
@ -126,6 +126,9 @@ $di->setShared('router', function() {
|
||||||
'action' => 'oauth'
|
'action' => 'oauth'
|
||||||
))->setName('oauth');
|
))->setName('oauth');
|
||||||
|
|
||||||
|
$router->add('/oauth/{provider:([a-z]+)}/disconnect', 'User::oauthdisconnect')->setName('oauth-disconnect');
|
||||||
|
$router->add('/oauth/{provider:([a-z]+)}/disconnect/{confirm}', 'User::oauthdisconnect')->setName('oauth-disconnect-confirm');
|
||||||
|
|
||||||
$router->add('/settings', array(
|
$router->add('/settings', array(
|
||||||
'controller' => 'user',
|
'controller' => 'user',
|
||||||
'action' => 'settings',
|
'action' => 'settings',
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@ use App\Form\Login as LoginForm;
|
||||||
|
|
||||||
class AuthController extends ControllerBase
|
class AuthController extends ControllerBase
|
||||||
{
|
{
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
// We need event manager here from DI.
|
||||||
|
$eventManager = $this->di->get('eventsManager');
|
||||||
|
$this->setEventsManager($eventManager);
|
||||||
|
}
|
||||||
|
|
||||||
public function indexAction()
|
public function indexAction()
|
||||||
{
|
{
|
||||||
$form = new LoginForm();
|
$form = new LoginForm();
|
||||||
|
|
@ -54,22 +61,42 @@ class AuthController extends ControllerBase
|
||||||
// NOTE: Should pass $state here also.
|
// NOTE: Should pass $state here also.
|
||||||
$data = $client->authenticate($code);
|
$data = $client->authenticate($code);
|
||||||
|
|
||||||
$result = $this->auth->loginOauth($data);
|
// If user is authed already, we connect.
|
||||||
|
$user = $this->auth->getUser();
|
||||||
|
if ($user) {
|
||||||
|
|
||||||
// There was an error when creating the account
|
$name = ucfirst($provider_name);
|
||||||
if (is_array($result)) {
|
$user->{'set' . $name . 'Id'}($data->getId());
|
||||||
$msg = '';
|
$user->save();
|
||||||
foreach($result as $message) {
|
|
||||||
$msg .= '<li>' . $message->getMessage() . '</li>';
|
$this->getEventsManager()->fire('user:onOAuthConnected', $user, $data);
|
||||||
|
|
||||||
|
$this->flash->message('success', "<strong>{$name}</strong> was connected!");
|
||||||
|
$this->response->redirect('/settings');
|
||||||
|
}
|
||||||
|
// Perform Auth.
|
||||||
|
else {
|
||||||
|
$result = $this->auth->loginOauth($data);
|
||||||
|
|
||||||
|
// There was an error when creating the account
|
||||||
|
if (is_array($result)) {
|
||||||
|
$msg = '';
|
||||||
|
foreach ($result as $message) {
|
||||||
|
$msg .= '<li>' . $message->getMessage() . '</li>';
|
||||||
|
}
|
||||||
|
$this->flash->message('error', "Failed to create account: <ul>{$msg}</ul>");
|
||||||
|
$this->response->redirect('/login');
|
||||||
|
} else {
|
||||||
|
$this->response->redirect('/');
|
||||||
}
|
}
|
||||||
$this->flash->message('error', "Failed to create account: <ul>{$msg}</ul>");
|
|
||||||
$this->response->redirect('/login');
|
|
||||||
} else {
|
|
||||||
$this->response->redirect('/');
|
|
||||||
}
|
}
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
$this->flash->message('error', 'Failed to authenticate.');
|
$this->flash->message('error', 'Failed to authenticate.');
|
||||||
$this->response->redirect('/login');
|
if ($this->auth->getUser()) {
|
||||||
|
$this->response->redirect('/settings');
|
||||||
|
} else {
|
||||||
|
$this->response->redirect('/login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No code
|
// No code
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@ use App\Controller\ControllerBase,
|
||||||
|
|
||||||
class UserController extends ControllerBase
|
class UserController extends ControllerBase
|
||||||
{
|
{
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
// We need event manager here from DI.
|
||||||
|
$eventManager = $this->di->get('eventsManager');
|
||||||
|
$this->setEventsManager($eventManager);
|
||||||
|
}
|
||||||
|
|
||||||
public function settingsAction()
|
public function settingsAction()
|
||||||
{
|
{
|
||||||
$user = $this->_getAuth()->getUser();
|
$user = $this->_getAuth()->getUser();
|
||||||
|
|
@ -33,6 +40,7 @@ class UserController extends ControllerBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->view->user = $user;
|
||||||
$this->view->form = $form;
|
$this->view->form = $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,4 +53,51 @@ class UserController extends ControllerBase
|
||||||
$this->view->page = $paginator->getPaginate();
|
$this->view->page = $paginator->getPaginate();
|
||||||
$this->view->pagination_url = '/user/activity/';
|
$this->view->pagination_url = '/user/activity/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function oauthDisconnectAction($provider, $last_unlink_confirmed = false)
|
||||||
|
{
|
||||||
|
$user = $this->_getAuth()->getUser();
|
||||||
|
|
||||||
|
// Check if we are unlinking the last provider
|
||||||
|
if (count($user->getSocialLinks()) <= 1) {
|
||||||
|
|
||||||
|
// If user does not have a password, we wont allow it.
|
||||||
|
if (strlen($user->getPassword()) < 1) {
|
||||||
|
$msg = 'Unlinking your last OAuth provider cannot be done '
|
||||||
|
. 'if you don\'t have a password as it would be impossible for you to log in.';
|
||||||
|
|
||||||
|
$this->flash->message('error', $msg);
|
||||||
|
$this->response->redirect('/settings');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give a warning to the user about password as the only login option.
|
||||||
|
if ($last_unlink_confirmed == false) {
|
||||||
|
|
||||||
|
$url = $this->url->get([
|
||||||
|
'for' => 'oauth-disconnect-confirm',
|
||||||
|
'provider' => $provider,
|
||||||
|
'confirm' => 'confirm',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$msg = '<p>You are about to unlink the last OAuth provider.'
|
||||||
|
. ' Your <strong>only</strong> login option will be <strong>password</strong> if you do this.</p>'
|
||||||
|
. '<p>Are you sure? <a class="alert-link" href="' . $url .'">Yes</a></p>';
|
||||||
|
|
||||||
|
$this->flash->message('warning', $msg);
|
||||||
|
$this->response->redirect('/settings');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$provider = ucfirst($provider);
|
||||||
|
$user->{'set' . $provider . 'Id'}(null);
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
$this->getEventsManager()->fire('user:onOAuthDisconnect', $user, $provider);
|
||||||
|
|
||||||
|
$this->flash->message('success', "<p><strong>{$provider}</strong> was disconnected</p>");
|
||||||
|
|
||||||
|
$this->response->redirect('/settings');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use Phalcon\Mvc\User\Plugin,
|
||||||
Phalcon\Events\Event,
|
Phalcon\Events\Event,
|
||||||
App\Model\Data\User,
|
App\Model\Data\User,
|
||||||
App\Model\Data\ActivityLog as ActivityLogger,
|
App\Model\Data\ActivityLog as ActivityLogger,
|
||||||
|
Httpcb\OAuth\UserData\UserDataInterface as OAuthUserDataInterface,
|
||||||
Httpcb\Auth;
|
Httpcb\Auth;
|
||||||
|
|
||||||
class ActivityLog extends Plugin
|
class ActivityLog extends Plugin
|
||||||
|
|
@ -45,6 +46,32 @@ class ActivityLog extends Plugin
|
||||||
$this->_log($user, "Changed password");
|
$this->_log($user, "Changed password");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when a user is connected to a OAuth provider.
|
||||||
|
*
|
||||||
|
* @param Event $event
|
||||||
|
* @param User $user
|
||||||
|
* @param OAuthUserDataInterface $provider
|
||||||
|
*/
|
||||||
|
public function onOAuthConnected(Event $event, User $user, OAuthUserDataInterface $provider)
|
||||||
|
{
|
||||||
|
$name = $provider->getProvider();
|
||||||
|
|
||||||
|
$this->_log($user, "OAuth connected ({$name})");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when a user is connected to a OAuth provider.
|
||||||
|
*
|
||||||
|
* @param Event $event
|
||||||
|
* @param User $user
|
||||||
|
* @param string $providerName
|
||||||
|
*/
|
||||||
|
public function onOAuthDisconnect(Event $event, User $user, $providerName)
|
||||||
|
{
|
||||||
|
$this->_log($user, "OAuth disconnected ({$providerName})");
|
||||||
|
}
|
||||||
|
|
||||||
protected function _log(User $user, $message)
|
protected function _log(User $user, $message)
|
||||||
{
|
{
|
||||||
$ip = (new \Phalcon\Http\Request())->getClientAddress();
|
$ip = (new \Phalcon\Http\Request())->getClientAddress();
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,17 @@ class User extends Model
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getSocialLinks()
|
||||||
|
{
|
||||||
|
$providers = [
|
||||||
|
'github' => $this->getGithubId(),
|
||||||
|
'gitlab' => $this->getGitlabId(),
|
||||||
|
'google' => $this->getGoogleId()
|
||||||
|
];
|
||||||
|
|
||||||
|
return array_filter($providers);
|
||||||
|
}
|
||||||
|
|
||||||
static public function createFromOAuthData(UserDataInterface $data)
|
static public function createFromOAuthData(UserDataInterface $data)
|
||||||
{
|
{
|
||||||
$oauth_id = 'set' . $data->getProvider() . 'Id';
|
$oauth_id = 'set' . $data->getProvider() . 'Id';
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,50 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
|
||||||
|
<h4>Social sign-in</h4>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div class="col-sm-2 text-center">
|
||||||
|
<div>{{ icon('brand/github', [ '3x' ]) }}</div>
|
||||||
|
{% if user.getGithubId() > 0 %}
|
||||||
|
<a href="{{ url(['for': 'oauth-disconnect', 'provider': 'github']) }}">Disconnect</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url(['for': 'oauth', 'strategy': 'github']) }}">Connect</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-2 text-center">
|
||||||
|
<div class="text-gitlab">{{ icon('brand/gitlab', [ '3x' ]) }}</div>
|
||||||
|
{% if user.getGitlabId() > 0 %}
|
||||||
|
<a href="{{ url(['for': 'oauth-disconnect', 'provider': 'gitlab' ]) }}">Disconnect</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url(['for': 'oauth', 'strategy': 'gitlab']) }}">Connect</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-2 text-center">
|
||||||
|
<div class="text-google">{{ icon('brand/google', [ '3x' ]) }}</div>
|
||||||
|
{% if user.getGoogleId() > 0 %}
|
||||||
|
<a href="{{ url(['for': 'oauth-disconnect', 'provider': 'google']) }}">Connect</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{url(['for': 'oauth', 'strategy': 'google']) }}">Connect</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<hr />
|
||||||
{{ form.render('Save') }}
|
{{ form.render('Save') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Reference in a new issue