From fffe53c97dc9698d747f56fc0a78222548d0076b Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 19 Apr 2018 16:51:25 +0200 Subject: [PATCH 01/12] adding app/library/OAuth/UserData/Google.php --- app/library/OAuth/UserData/Google.php | 59 +++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 app/library/OAuth/UserData/Google.php diff --git a/app/library/OAuth/UserData/Google.php b/app/library/OAuth/UserData/Google.php new file mode 100644 index 0000000..86a80ab --- /dev/null +++ b/app/library/OAuth/UserData/Google.php @@ -0,0 +1,59 @@ +data = $data; + } + + /** + * {@inheritDoc} + */ + public function getProvider() + { + return 'Google'; + } + + /** + * {@inheritDoc} + */ + public function getId() + { + return (int) $this->data['id']; + } + + /** + * {@inheritDoc} + */ + public function getUsername() + { + return null; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->data['displayName']; + } + + /** + * {@inheritDoc} + */ + public function getEmail() + { + if (isset($this->data['emails'][0]['value'])) { + return $this->data['emails'][0]['value']; + } + return null; + } +} From e7f1029d623af3edce61c860ba5d079cc634f4e7 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 26 Apr 2018 11:18:33 +0200 Subject: [PATCH 02/12] app/library/OAuth/Adapter/League.php: adding Google --- app/library/OAuth/Adapter/League.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/library/OAuth/Adapter/League.php b/app/library/OAuth/Adapter/League.php index cf85b14..3d04fdf 100644 --- a/app/library/OAuth/Adapter/League.php +++ b/app/library/OAuth/Adapter/League.php @@ -15,6 +15,7 @@ class League implements AdapterInterface protected $_providerClasses = array( 'github' => '\League\OAuth2\Client\Provider\Github', 'gitlab' => '\Omines\OAuth2\Client\Provider\Gitlab', + 'google' => '\League\OAuth2\Client\Provider\Google', ); /** From 72713308c4caa09ca28f520a598811a91bf75fea Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 26 Apr 2018 11:18:59 +0200 Subject: [PATCH 03/12] app/library/OAuth/Adapter/League.php: make sure the exception class is found. --- app/library/OAuth/Adapter/League.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/library/OAuth/Adapter/League.php b/app/library/OAuth/Adapter/League.php index 3d04fdf..878b6e6 100644 --- a/app/library/OAuth/Adapter/League.php +++ b/app/library/OAuth/Adapter/League.php @@ -37,7 +37,7 @@ class League implements AdapterInterface public function __construct($provider_name, $options) { if (!array_key_exists($provider_name, $this->_providerClasses)) { - throw new Exception("Provider '{$provider_name}' is not supported."); + throw new \Exception("Provider '{$provider_name}' is not supported."); } $className = $this->_providerClasses[$provider_name]; @@ -45,7 +45,7 @@ class League implements AdapterInterface if (!($provider instanceof AbstractProvider)) { // TODO: Throw a better exception class :) - throw new Exception("Provider object must be an instance of League\\OAuth2\\Client\\Provider\\AbstractProvider"); + throw new \Exception("Provider object must be an instance of League\\OAuth2\\Client\\Provider\\AbstractProvider"); } $this->_provider = $provider; From 481c6c206e63c3a23c821f8c736716a6ba513c9d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 26 Apr 2018 11:18:09 +0200 Subject: [PATCH 04/12] migration: 20180419133825_user_oauth_ids.php --- .../20180419133825_user_oauth_ids.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 app/migrations/20180419133825_user_oauth_ids.php diff --git a/app/migrations/20180419133825_user_oauth_ids.php b/app/migrations/20180419133825_user_oauth_ids.php new file mode 100644 index 0000000..fffb5de --- /dev/null +++ b/app/migrations/20180419133825_user_oauth_ids.php @@ -0,0 +1,22 @@ +table('user') + ->addColumn('gitlab_id', 'integer', [ + 'limit' => 14, + 'null' => true, + 'after' => 'github_user' + ]) + ->addColumn('google_id', 'integer', [ + 'limit' => 21, + 'null' => true, + 'after' => 'gitlab_id' + ])->save(); + } +} From d62914c76491f7cce768b9e336359c6dc59caf76 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 7 Jun 2018 23:06:46 +0200 Subject: [PATCH 05/12] app/models/Data/User.php: adding findFirstByOAuthID() --- app/models/Data/User.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/models/Data/User.php b/app/models/Data/User.php index a676be5..1cd76b1 100644 --- a/app/models/Data/User.php +++ b/app/models/Data/User.php @@ -2,8 +2,9 @@ namespace App\Model\Data; -use Phalcon\Mvc\Model; -use InvalidArgumentException; +use Phalcon\Mvc\Model, + InvalidArgumentException, + Httpcb\OAuth\UserData\UserDataInterface; class User extends Model { @@ -207,6 +208,16 @@ class User extends Model ]); } + static public function findFirstByOAuthID(UserDataInterface $oauth) + { + $column = strtolower($oauth->getProvider()); + + return self::findFirst([ + "{$column}_id = :id:", + "bind" => [ 'id' => $oauth->getId() ] + ]); + } + public function beforeSave() { // Fire event on password create/changed. From 643387b3f3e8747d1c9fefe3427cd96d34ac4a50 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 7 Jun 2018 23:40:58 +0200 Subject: [PATCH 06/12] app/models/Data/User.php: adding createFromOAuthData() --- app/models/Data/User.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/models/Data/User.php b/app/models/Data/User.php index 1cd76b1..2141bc2 100644 --- a/app/models/Data/User.php +++ b/app/models/Data/User.php @@ -194,6 +194,19 @@ class User extends Model return $this; } + static public function createFromOAuthData(UserDataInterface $data) + { + $oauth_id = 'set' . $data->getProvider() . 'Id'; + + $user = new self(); + $user->setUsername($data->getUsername()) + ->setName($data->getName()) + ->setEmail($data->getEmail()) + ->{$oauth_id}($data->getId()); + + return $user; + } + /** * Find the first user by Username or Email * From bbcf6d26443020b5d71280af413a0f469fe9bb49 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 7 Jun 2018 23:41:44 +0200 Subject: [PATCH 07/12] app/library/Auth.php: in loginAuth() lookup by OAuth provider id. --- app/library/Auth.php | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/app/library/Auth.php b/app/library/Auth.php index f65579c..9f1a841 100644 --- a/app/library/Auth.php +++ b/app/library/Auth.php @@ -45,32 +45,20 @@ class Auth extends Component * * @param UserDataInterface $auth */ - public function loginOauth(UserDataInterface $auth) + public function loginOauth(UserDataInterface $data) { - // Look for a user with this email. - $user = User::findFirstByEmail($auth->getEmail()); + $user = User::findFirstByOAuthID($data); if (!$user) { // Did not find any user. create him. - if (strlen($auth->getUsername()) > 0) { - $name = $auth->getUsername(); - } else if(strlen($auth->getName()) > 0) { - $name = $auth->getName(); - } else { - $name = ''; - } - - $user = new User(); - $user->setEmail($auth->getEmail()) - ->setUsername($name); - + $user = User::createFromOAuthData($data); $user->save(); } $this->setIdentity($user->getId()); $this->_eventsManager->fire('auth:onLogin', $this, - "OAuth {$auth->getProvider()}"); + "OAuth {$data->getProvider()}"); } /** From d14741a1718f55a6caa4e545add1de9cedfff50d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 8 Jun 2018 00:06:33 +0200 Subject: [PATCH 08/12] app/models/Data/User.php: add uniqueness validation for username and email. --- app/models/Data/User.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/models/Data/User.php b/app/models/Data/User.php index 2141bc2..524ac56 100644 --- a/app/models/Data/User.php +++ b/app/models/Data/User.php @@ -3,6 +3,8 @@ namespace App\Model\Data; use Phalcon\Mvc\Model, + Phalcon\Validation, + Phalcon\Validation\Validator\Uniqueness, InvalidArgumentException, Httpcb\OAuth\UserData\UserDataInterface; @@ -39,6 +41,17 @@ class User extends Model $this->setEventsManager($this->getDI()->get('eventsManager')); } + public function validation() + { + // Validation + $validator = new Validation(); + + $validator->add('username', new Uniqueness(['message' => 'The username already exists.'])); + $validator->add('email', new Uniqueness(['message' => 'The email address already exists.'])); + + return $this->validate($validator); + } + /** * @return mixed */ From 03a0fa3cb723f876b18969a11f030781e18be2f3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 8 Jun 2018 00:07:42 +0200 Subject: [PATCH 09/12] app/library/Auth.php: make loginOauth() return validation messages if User::save() fails. --- app/library/Auth.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/library/Auth.php b/app/library/Auth.php index 9f1a841..75c622b 100644 --- a/app/library/Auth.php +++ b/app/library/Auth.php @@ -43,7 +43,8 @@ class Auth extends Component /** * Login using OAuth * - * @param UserDataInterface $auth + * @param UserDataInterface $data + * @return bool|\Phalcon\Mvc\Model\MessageInterface[] */ public function loginOauth(UserDataInterface $data) { @@ -52,13 +53,18 @@ class Auth extends Component if (!$user) { // Did not find any user. create him. $user = User::createFromOAuthData($data); - $user->save(); + + if ($user->save() === false) { + return $user->getMessages(); + } } $this->setIdentity($user->getId()); $this->_eventsManager->fire('auth:onLogin', $this, "OAuth {$data->getProvider()}"); + + return true; } /** From 22627a811c57c453ab06b7f0c920275fdd246edd Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 8 Jun 2018 00:12:05 +0200 Subject: [PATCH 10/12] app/controllers/AuthController.php: in oauthAction() show flash message if account creation failed. --- app/controllers/AuthController.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/controllers/AuthController.php b/app/controllers/AuthController.php index b3a84ba..08331e7 100644 --- a/app/controllers/AuthController.php +++ b/app/controllers/AuthController.php @@ -54,8 +54,19 @@ class AuthController extends ControllerBase // NOTE: Should pass $state here also. $data = $client->authenticate($code); - $this->auth->loginOauth($data); - $this->response->redirect('/'); + $result = $this->auth->loginOauth($data); + + // There was an error when creating the account + if (is_array($result)) { + $msg = ''; + foreach($result as $message) { + $msg .= '
  • ' . $message->getMessage() . '
  • '; + } + $this->flash->message('error', "Failed to create account:
      {$msg}
    "); + $this->response->redirect('/login'); + } else { + $this->response->redirect('/'); + } } catch(\Exception $e) { $this->flash->message('error', 'Failed to authenticate.'); $this->response->redirect('/login'); From 25d8e712e4a92311956b1411c16f16749c6625b4 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 8 Jun 2018 00:12:30 +0200 Subject: [PATCH 11/12] app/models/Data/User.php: add gitlab_id and google_id --- app/models/Data/User.php | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/app/models/Data/User.php b/app/models/Data/User.php index 524ac56..82c438e 100644 --- a/app/models/Data/User.php +++ b/app/models/Data/User.php @@ -30,6 +30,10 @@ class User extends Model protected $github_user; + protected $gitlab_id; + + protected $google_id; + public function initialize() { $this->useDynamicUpdate(true); @@ -207,6 +211,42 @@ class User extends Model return $this; } + /** + * @return mixed + */ + public function getGitlabId() + { + return $this->gitlab_id; + } + + /** + * @param mixed $gitlab_id + * @return User + */ + public function setGitlabId($gitlab_id) + { + $this->gitlab_id = $gitlab_id; + return $this; + } + + /** + * @return mixed + */ + public function getGoogleId() + { + return $this->google_id; + } + + /** + * @param mixed $google_id + * @return User + */ + public function setGoogleId($google_id) + { + $this->google_id = $google_id; + return $this; + } + static public function createFromOAuthData(UserDataInterface $data) { $oauth_id = 'set' . $data->getProvider() . 'Id'; From 3d5481ed800971c90874be18c7d95428844885d3 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Fri, 8 Jun 2018 00:22:40 +0200 Subject: [PATCH 12/12] dbmigrate: 20180607222058_user_remove_github_user.php --- .../20180607222058_user_remove_github_user.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 app/migrations/20180607222058_user_remove_github_user.php diff --git a/app/migrations/20180607222058_user_remove_github_user.php b/app/migrations/20180607222058_user_remove_github_user.php new file mode 100644 index 0000000..901bd89 --- /dev/null +++ b/app/migrations/20180607222058_user_remove_github_user.php @@ -0,0 +1,14 @@ +table('user') + ->removeColumn('github_user') + ->save(); + } +}