From 06d0b7048ebcdfdf6e24eec3ac7dc8fb0327dd6f Mon Sep 17 00:00:00 2001 From: Frédéric Guillot Date: Mon, 30 Jun 2014 21:52:02 -0300 Subject: Merge pull-request: Github authentication #162 --- app/Model/Acl.php | 4 +- app/Model/GitHub.php | 178 ++++++++++++++++++++++++++++++++++++++++++++++++ app/Model/LastLogin.php | 1 + app/Model/User.php | 12 ++++ 4 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 app/Model/GitHub.php (limited to 'app/Model') diff --git a/app/Model/Acl.php b/app/Model/Acl.php index 035fd7c3..8a87a6b2 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -17,7 +17,7 @@ class Acl extends Base * @var array */ private $public_actions = array( - 'user' => array('login', 'check', 'google'), + 'user' => array('login', 'check', 'google', 'github'), 'task' => array('add'), 'board' => array('readonly'), ); @@ -32,7 +32,7 @@ class Acl extends Base 'app' => array('index'), 'board' => array('index', 'show', 'assign', 'assigntask', 'save', 'check'), 'project' => array('tasks', 'index', 'forbidden', 'search'), - 'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index', 'unlinkgoogle'), + 'user' => array('index', 'edit', 'update', 'forbidden', 'logout', 'index', 'unlinkgoogle', 'unlinkgithub'), 'config' => array('index', 'removeremembermetoken'), 'comment' => array('create', 'save', 'confirm', 'remove', 'update', 'edit', 'forbidden'), 'file' => array('create', 'save', 'download', 'confirm', 'remove', 'open', 'image'), diff --git a/app/Model/GitHub.php b/app/Model/GitHub.php new file mode 100644 index 00000000..3380218d --- /dev/null +++ b/app/Model/GitHub.php @@ -0,0 +1,178 @@ +db, $this->event); + + $user = $userModel->getByGitHubId($github_id); + + if ($user) { + + // Create the user session + $userModel->updateSession($user); + + // Update login history + $lastLogin = new LastLogin($this->db, $this->event); + $lastLogin->create( + LastLogin::AUTH_GITHUB, + $user['id'], + $userModel->getIpAddress(), + $userModel->getUserAgent() + ); + + return true; + } + + return false; + } + + /** + * Unlink a GitHub account for a given user + * + * @access public + * @param integer $user_id User id + * @return boolean + */ + public function unlink($user_id) + { + $userModel = new User($this->db, $this->event); + + return $userModel->update(array( + 'id' => $user_id, + 'github_id' => '', + )); + } + + /** + * Update the user table based on the GitHub profile information + * + * @access public + * @param integer $user_id User id + * @param array $profile GitHub profile + * @return boolean + * @todo Don't overwrite existing email/name with empty GitHub data + */ + public function updateUser($user_id, array $profile) + { + $userModel = new User($this->db, $this->event); + + return $userModel->update(array( + 'id' => $user_id, + 'github_id' => $profile['id'], + 'email' => $profile['email'], + 'name' => $profile['name'], + )); + } + + /** + * Get the GitHub service instance + * + * @access public + * @return \OAuth\OAuth2\Service\GitHub + */ + public function getService() + { + $uriFactory = new UriFactory(); + $currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER); + $currentUri->setQuery('controller=user&action=gitHub'); + + $storage = new Session(false); + + $credentials = new Credentials( + GITHUB_CLIENT_ID, + GITHUB_CLIENT_SECRET, + $currentUri->getAbsoluteUri() + ); + + $serviceFactory = new ServiceFactory(); + + return $serviceFactory->createService( + 'gitHub', + $credentials, + $storage, + array('') + ); + } + + /** + * Get the authorization URL + * + * @access public + * @return \OAuth\Common\Http\Uri\Uri + */ + public function getAuthorizationUrl() + { + return $this->getService()->getAuthorizationUri(); + } + + /** + * Get GitHub profile information from the API + * + * @access public + * @param string $code GitHub authorization code + * @return bool|array + */ + public function getGitHubProfile($code) + { + try { + $gitHubService = $this->getService(); + $gitHubService->requestAccessToken($code); + + return json_decode($gitHubService->request('user'), true); + } + catch (TokenResponseException $e) { + return false; + } + + return false; + } + + /** + * Revokes this user's GitHub tokens for Kanboard + * + * @access public + * @return bool|array + * @todo Currently this simply removes all our tokens for this user, ideally it should + * restrict itself to the one in question + */ + public function revokeGitHubAccess() + { + try { + $gitHubService = $this->getService(); + + $basicAuthHeader = array('Authorization' => 'Basic ' . + base64_encode(GITHUB_CLIENT_ID.':'.GITHUB_CLIENT_SECRET)); + + return json_decode($gitHubService->request('/applications/'.GITHUB_CLIENT_ID.'/tokens', 'DELETE', null, $basicAuthHeader), true); + } + catch (TokenResponseException $e) { + return false; + } + + return false; + } +} diff --git a/app/Model/LastLogin.php b/app/Model/LastLogin.php index 56739b48..db4c4a57 100644 --- a/app/Model/LastLogin.php +++ b/app/Model/LastLogin.php @@ -33,6 +33,7 @@ class LastLogin extends Base const AUTH_REMEMBER_ME = 'remember_me'; const AUTH_LDAP = 'ldap'; const AUTH_GOOGLE = 'google'; + const AUTH_GITHUB = 'github'; /** * Create a new record diff --git a/app/Model/User.php b/app/Model/User.php index 8769d69a..ba1acb90 100644 --- a/app/Model/User.php +++ b/app/Model/User.php @@ -51,6 +51,18 @@ class User extends Base return $this->db->table(self::TABLE)->eq('google_id', $google_id)->findOne(); } + /** + * Get a specific user by the GitHub id + * + * @access public + * @param string $github_id GitHub user id + * @return array + */ + public function getByGitHubId($github_id) + { + return $this->db->table(self::TABLE)->eq('github_id', $github_id)->findOne(); + } + /** * Get a specific user by the username * -- cgit v1.2.3