From 2a47b08fec67ebd84048a946500a7674446f39ec Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Fri, 11 Oct 2013 21:51:23 +0100 Subject: [PATCH] Removed Github configuration from ProjectController / ProjectForm and added it to a new settings area. --- PHPCI/Controller/PluginController.php | 12 ++ PHPCI/Controller/ProjectController.php | 107 +++++++++--------- PHPCI/Controller/SettingsController.php | 140 ++++++++++++++++++++++++ PHPCI/Model/Build/GithubBuild.php | 9 +- PHPCI/View/Home/index.phtml | 2 - PHPCI/View/Plugin/index.phtml | 3 - PHPCI/View/Settings/index.phtml | 62 +++++++++++ PHPCI/View/layout.phtml | 27 ++++- public/assets/css/phpci.css | 24 ++-- public/assets/js/phpci.js | 32 ++++-- 10 files changed, 331 insertions(+), 87 deletions(-) create mode 100644 PHPCI/Controller/SettingsController.php create mode 100644 PHPCI/View/Settings/index.phtml diff --git a/PHPCI/Controller/PluginController.php b/PHPCI/Controller/PluginController.php index 0dd3f2b4..22b25bfc 100644 --- a/PHPCI/Controller/PluginController.php +++ b/PHPCI/Controller/PluginController.php @@ -47,6 +47,10 @@ class PluginController extends \PHPCI\Controller public function index() { + if (!$_SESSION['user']->getIsAdmin()) { + throw new \Exception('You do not have permission to do that.'); + } + $this->view->canWrite = is_writable(APPLICATION_PATH . 'composer.json'); $this->view->canInstall = $this->canInstall; $this->view->required = $this->required; @@ -60,6 +64,10 @@ class PluginController extends \PHPCI\Controller public function remove() { + if (!$_SESSION['user']->getIsAdmin()) { + throw new \Exception('You do not have permission to do that.'); + } + $package = $this->getParam('package', null); $json = $this->getComposerJson(); @@ -81,6 +89,10 @@ class PluginController extends \PHPCI\Controller public function install() { + if (!$_SESSION['user']->getIsAdmin()) { + throw new \Exception('You do not have permission to do that.'); + } + $package = $this->getParam('package', null); $version = $this->getParam('version', '*'); diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index db684051..1a4fc496 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -12,6 +12,7 @@ namespace PHPCI\Controller; use PHPCI\Model\Build; use PHPCI\Model\Project; use b8; +use b8\Config; use b8\Controller; use b8\Store; use b8\Form; @@ -87,7 +88,7 @@ class ProjectController extends \PHPCI\Controller throw new \Exception('You do not have permission to do that.'); } - $project = $this->projectStore->getById($projectId); + $project = $this->projectStore->getById($projectId); $this->projectStore->delete($project); header('Location: '.PHPCI_URL); @@ -127,7 +128,6 @@ class ProjectController extends \PHPCI\Controller } $method = $this->request->getMethod(); - $this->handleGithubResponse(); if ($method == 'POST') { $values = $this->getParams(); @@ -154,10 +154,10 @@ class ProjectController extends \PHPCI\Controller $pub = file_get_contents($keyFile . '.pub'); $prv = file_get_contents($keyFile); - $values = array('key' => $prv, 'pubkey' => $pub, 'token' => $_SESSION['github_token']); + $values = array('key' => $prv, 'pubkey' => $pub); } - $form = $this->projectForm($values); + $form = $this->projectForm($values); if ($method != 'POST' || ($method == 'POST' && !$form->validate())) { $view = new b8\View('ProjectForm'); @@ -165,12 +165,11 @@ class ProjectController extends \PHPCI\Controller $view->project = null; $view->form = $form; $view->key = $pub; - $view->token = $_SESSION['github_token']; return $view->render(); } - $values = $form->getValues(); + $values = $form->getValues(); if ($values['type'] == "gitlab") { preg_match('`^(.*)@(.*):(.*)/(.*)\.git`', $values['reference'], $matches); @@ -192,33 +191,6 @@ class ProjectController extends \PHPCI\Controller die; } - /** - * Handles log in with Github - */ - protected function handleGithubResponse() - { - $github = \b8\Config::getInstance()->get('phpci.github'); - $code = $this->getParam('code', null); - - if (!is_null($code)) { - $http = new \b8\HttpClient(); - $url = 'https://github.com/login/oauth/access_token'; - $params = array('client_id' => $github['id'], 'client_secret' => $github['secret'], 'code' => $code); - $resp = $http->post($url, $params); - - if ($resp['success']) { - parse_str($resp['body'], $resp); - $_SESSION['github_token'] = $resp['access_token']; - header('Location: '.PHPCI_URL.'project/add'); - die; - } - } - - if (!isset($_SESSION['github_token'])) { - $_SESSION['github_token'] = null; - } - } - /** * Edit a project. Handles both the form and processing. */ @@ -236,6 +208,7 @@ class ProjectController extends \PHPCI\Controller } else { $values = $project->getDataArray(); $values['key'] = $values['git_key']; + if ($values['type'] == "gitlab") { $accessInfo = $project->getAccessInformation(); $reference = $accessInfo["user"].'@'.$accessInfo["domain"].':' . $project->getReference().".git"; @@ -284,7 +257,6 @@ class ProjectController extends \PHPCI\Controller $form->setMethod('POST'); $form->setAction(PHPCI_URL.'project/' . $type); $form->addField(new Form\Element\Csrf('csrf')); - $form->addField(new Form\Element\Hidden('token')); $form->addField(new Form\Element\Hidden('pubkey')); $options = array( @@ -306,14 +278,16 @@ class ProjectController extends \PHPCI\Controller $field->setContainerClass('form-group'); $form->addField($field); - if (isset($_SESSION['github_token'])) { - $field = new Form\Element\Select('github'); - $field->setLabel('Choose a Github repository:'); - $field->setClass('form-control'); - $field->setContainerClass('form-group'); - $field->setOptions($this->getGithubRepositories()); - $form->addField($field); - } + + $container = new Form\ControlGroup('github-container'); + $container->setClass('github-container'); + + $field = new Form\Element\Select('github'); + $field->setLabel('Choose a Github repository:'); + $field->setClass('form-control'); + $field->setContainerClass('form-group'); + $container->addField($field); + $form->addField($container); $field = new Form\Element\Text('reference'); $field->setRequired(true); @@ -351,21 +325,48 @@ class ProjectController extends \PHPCI\Controller /** * Get an array of repositories from Github's API. */ - protected function getGithubRepositories() + protected function githubRepositories() { - $http = new \b8\HttpClient(); - $url = 'https://api.github.com/user/repos'; - $res = $http->get($url, array('type' => 'all', 'access_token' => $_SESSION['github_token'])); + $token = Config::getInstance()->get('phpci.github.token'); - $rtn = array(); - $rtn['choose'] = 'Select a repository...'; - if ($res['success']) { - foreach ($res['body'] as $repo) { - $rtn[$repo['full_name']] = $repo['full_name']; - } + if (!$token) { + die(json_encode(null)); } - return $rtn; + $cache = \b8\Cache::getCache(\b8\Cache::TYPE_APC); + $rtn = $cache->get('phpci_github_repos'); + + if (!$rtn) { + $orgs = $this->doGithubApiRequest('/user/orgs', array('access_token' => $token)); + + $params = array('type' => 'all', 'access_token' => $token); + $repos = array(); + $repos['user'] = $this->doGithubApiRequest('/user/repos', $params); + + + foreach ($orgs as $org) { + $repos[$org['login']] = $this->doGithubApiRequest('/orgs/'.$org['login'].'/repos', $params); + } + + $rtn = array(); + foreach ($repos as $repoGroup) { + foreach ($repoGroup as $repo) { + $rtn['repos'][] = $repo['full_name']; + } + } + + $cache->set('phpci_github_repos', $rtn); + } + + die(json_encode($rtn)); + } + + protected function doGithubApiRequest($url, $params) + { + $http = new \b8\HttpClient('https://api.github.com'); + $res = $http->get($url, $params); + + return $res['body']; } protected function getReferenceValidator($values) diff --git a/PHPCI/Controller/SettingsController.php b/PHPCI/Controller/SettingsController.php new file mode 100644 index 00000000..d0582f6a --- /dev/null +++ b/PHPCI/Controller/SettingsController.php @@ -0,0 +1,140 @@ + + * @package PHPCI + * @subpackage Web + */ +class SettingsController extends Controller +{ + protected $settings; + + public function init() + { + parent::init(); + + $parser = new Parser(); + $yaml = file_get_contents(APPLICATION_PATH . 'PHPCI/config.yml'); + $this->settings = $parser->parse($yaml); + } + + public function index() + { + $this->view->settings = $this->settings; + $this->view->github = $this->getGithubForm(); + + if (!empty($this->settings['phpci']['github']['token'])) { + $this->view->githubUser = $this->getGithubUser($this->settings['phpci']['github']['token']); + } + + return $this->view->render(); + } + + public function github() + { + $this->settings['phpci']['github']['id'] = $this->getParam('githubid', ''); + $this->settings['phpci']['github']['secret'] = $this->getParam('githubsecret', ''); + + $this->storeSettings(); + + header('Location: ' . PHPCI_URL . 'settings?saved=1'); + die; + } + + /** + * Github redirects users back to this URL when t + */ + public function githubCallback() + { + $code = $this->getParam('code', null); + $github = $this->settings['phpci']['github']; + + if (!is_null($code)) { + $http = new HttpClient(); + $url = 'https://github.com/login/oauth/access_token'; + $params = array('client_id' => $github['id'], 'client_secret' => $github['secret'], 'code' => $code); + $resp = $http->post($url, $params); + + if ($resp['success']) { + parse_str($resp['body'], $resp); + + $this->settings['phpci']['github']['token'] = $resp['access_token']; + $this->storeSettings(); + + header('Location: ' . PHPCI_URL . 'settings?linked=1'); + die; + } + } + + + header('Location: ' . PHPCI_URL . 'settings?linked=2'); + die; + } + + protected function storeSettings() + { + $dumper = new Dumper(); + $yaml = $dumper->dump($this->settings); + file_put_contents(APPLICATION_PATH . 'PHPCI/config.yml', $yaml); + } + + protected function getGithubForm() + { + $form = new Form(); + $form->setMethod('POST'); + $form->setAction(PHPCI_URL . 'settings/github'); + $form->addField(new Form\Element\Csrf('csrf')); + + $field = new Form\Element\Text('githubid'); + $field->setRequired(true); + $field->setPattern('[a-zA-Z0-9]+'); + $field->setLabel('Application ID'); + $field->setClass('form-control'); + $field->setContainerClass('form-group'); + $field->setValue($this->settings['phpci']['github']['id']); + $form->addField($field); + + $field = new Form\Element\Text('githubsecret'); + $field->setRequired(true); + $field->setPattern('[a-zA-Z0-9]+'); + $field->setLabel('Application Secret'); + $field->setClass('form-control'); + $field->setContainerClass('form-group'); + $field->setValue($this->settings['phpci']['github']['secret']); + $form->addField($field); + + + $field = new Form\Element\Submit(); + $field->setValue('Save »'); + $field->setClass('btn btn-success pull-right'); + $form->addField($field); + + return $form; + } + + protected function getGithubUser($token) + { + $http = new HttpClient('https://api.github.com'); + $user = $http->get('/user', array('access_token' => $token)); + + return $user['body']; + } +} diff --git a/PHPCI/Model/Build/GithubBuild.php b/PHPCI/Model/Build/GithubBuild.php index 1b41fb75..98d7a8eb 100644 --- a/PHPCI/Model/Build/GithubBuild.php +++ b/PHPCI/Model/Build/GithubBuild.php @@ -40,13 +40,14 @@ class GithubBuild extends RemoteGitBuild */ public function sendStatusPostback() { - $project = $this->getProject(); + $token = \b8\Config::getInstance()->get('phpci.github.token'); - // The postback will only work if we have an access token. - if (!$project->getToken()) { + if (empty($token)) { return; } + $project = $this->getProject(); + $url = 'https://api.github.com/repos/'.$project->getReference().'/statuses/'.$this->getCommitId(); $http = new \b8\HttpClient(); @@ -71,7 +72,7 @@ class GithubBuild extends RemoteGitBuild $params = array( 'state' => $status, 'target_url' => $phpciUrl . '/build/view/' . $this->getId()); $headers = array( - 'Authorization: token ' . $project->getToken(), + 'Authorization: token ' . $token, 'Content-Type: application/x-www-form-urlencoded' ); diff --git a/PHPCI/View/Home/index.phtml b/PHPCI/View/Home/index.phtml index 452ec7c6..d372786d 100644 --- a/PHPCI/View/Home/index.phtml +++ b/PHPCI/View/Home/index.phtml @@ -5,8 +5,6 @@
diff --git a/PHPCI/View/Plugin/index.phtml b/PHPCI/View/Plugin/index.phtml index a21c4a35..f3f10e60 100644 --- a/PHPCI/View/Plugin/index.phtml +++ b/PHPCI/View/Plugin/index.phtml @@ -175,6 +175,3 @@
- - -
Loading...
\ No newline at end of file diff --git a/PHPCI/View/Settings/index.phtml b/PHPCI/View/Settings/index.phtml new file mode 100644 index 00000000..c8206811 --- /dev/null +++ b/PHPCI/View/Settings/index.phtml @@ -0,0 +1,62 @@ + +

+ Your settings have been saved. +

+ + + +

+ Your Github account has been linked. +

+ + + +

+ Your Github account could not be linked. +

+ + +
+
+
+

Github Application

+ + + +

+ Before you can start using Github, you need to sign in and grant PHPCI access to your account. +

+ + + +

+ PHPCI is successfully linked to Github account + + + +

+ +
+ +
+ +
+ +
+
+
+

Where to find these...

+
+ +
+

If you own the application you would like to use, you can find this information within your + applications settings area.

+
+
+
+
+
diff --git a/PHPCI/View/layout.phtml b/PHPCI/View/layout.phtml index 3b3c2dc9..da33cd3c 100644 --- a/PHPCI/View/layout.phtml +++ b/PHPCI/View/layout.phtml @@ -6,7 +6,7 @@ - + @@ -36,12 +36,25 @@ @@ -52,5 +65,7 @@
+ +
Loading...
diff --git a/public/assets/css/phpci.css b/public/assets/css/phpci.css index fce6ee20..ce34fe82 100644 --- a/public/assets/css/phpci.css +++ b/public/assets/css/phpci.css @@ -7,6 +7,14 @@ body padding-top: 70px; } + strong, th, .control-label { + font-weight: 500; + } + + .btn, .dropdown-menu>li>a, .controls, .controls input, .controls label { + font-weight: 300; + } + #content { -border: 10px solid #369; @@ -61,6 +69,11 @@ td .label { padding: 0; } + h2 { + color: #246; + font-size: 1.8em; + } + .icon-build-ok { background: url('../img/icon-build-ok.png') no-repeat top left; @@ -81,13 +94,6 @@ td .label { background: url('../img/icon-build-running.png') no-repeat top left; } -h3 -{ - border-bottom: 1px solid #f0f0f0; - margin-top: 0; - padding-top: 0; -} - .navbar-brand { padding: 10px 15px; } @@ -102,7 +108,9 @@ h3 border-bottom: 1px solid #eee; cursor: move; font-size: 1.2em; - padding: 8px; + margin: 0; + margin-bottom: 20px; + padding: 8px 0; } .box .box-content { diff --git a/public/assets/js/phpci.js b/public/assets/js/phpci.js index c14c41bc..d662825b 100644 --- a/public/assets/js/phpci.js +++ b/public/assets/js/phpci.js @@ -18,6 +18,8 @@ function confirmDelete(url) */ function setupProjectForm() { + $('.github-container').hide(); + $('#element-reference').change(function() { var el = $(this); @@ -41,18 +43,26 @@ function setupProjectForm() $('#element-type').change(function() { - if(!window.github_app_id || $(this).val() != 'github' || window.github_token) { - return; - } - - // Show sign in with Github button. - var el = $('#element-reference'); - var rtn = window.return_url; - var url = 'https://github.com/login/oauth/authorize?client_id=' + window.github_app_id + '&scope=repo&redirect_uri=' + rtn; - var btn = $('').addClass('btn btn-inverse').text('Sign in with Github').attr('href', url); + if ($(this).val() == 'github') { + $('#loading').show(); - el.after(btn); - el.remove(); + $.getJSON(window.PHPCI_URL + 'project/github-repositories', function (data) { + $('#loading').hide(); + + if (data.repos) { + $('#element-github').empty(); + + for (var i in data.repos) { + var name = data.repos[i]; + $('#element-github').append($('').text(name).val(name)); + } + + $('.github-container').slideDown(); + } + }); + } else { + $('.github-container').slideUp(); + } }); $('#element-github').change(function()