Archived
1
0
Fork 0

Merge branch '15-settings-oauth-connect-disconnect'

This commit is contained in:
Henrik Hautakoski 2018-06-12 23:04:01 +02:00
commit 313ba55098
6 changed files with 175 additions and 11 deletions

View file

@ -126,6 +126,9 @@ $di->setShared('router', function() {
'action' => '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(
'controller' => 'user',
'action' => 'settings',

View file

@ -8,6 +8,13 @@ use App\Form\Login as LoginForm;
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()
{
$form = new LoginForm();
@ -54,22 +61,42 @@ class AuthController extends ControllerBase
// NOTE: Should pass $state here also.
$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
if (is_array($result)) {
$msg = '';
foreach($result as $message) {
$msg .= '<li>' . $message->getMessage() . '</li>';
$name = ucfirst($provider_name);
$user->{'set' . $name . 'Id'}($data->getId());
$user->save();
$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) {
$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

View file

@ -8,6 +8,13 @@ use App\Controller\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()
{
$user = $this->_getAuth()->getUser();
@ -33,6 +40,7 @@ class UserController extends ControllerBase
}
}
$this->view->user = $user;
$this->view->form = $form;
}
@ -45,4 +53,51 @@ class UserController extends ControllerBase
$this->view->page = $paginator->getPaginate();
$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');
}
}

View file

@ -6,6 +6,7 @@ use Phalcon\Mvc\User\Plugin,
Phalcon\Events\Event,
App\Model\Data\User,
App\Model\Data\ActivityLog as ActivityLogger,
Httpcb\OAuth\UserData\UserDataInterface as OAuthUserDataInterface,
Httpcb\Auth;
class ActivityLog extends Plugin
@ -45,6 +46,32 @@ class ActivityLog extends Plugin
$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)
{
$ip = (new \Phalcon\Http\Request())->getClientAddress();

View file

@ -227,6 +227,17 @@ class User extends Model
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)
{
$oauth_id = 'set' . $data->getProvider() . 'Id';

View file

@ -37,9 +37,50 @@
</div>
<div class="form-group">
<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') }}
</div>
</div>
</form>
</div>