@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Use modern UI for OAuthServer details page

Summary: Mostly just UI updates and policy enforcement. Improves error message when trying to authorize an already-authorized application.

Test Plan:
{F131584}

{F131585}

{F131586}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Differential Revision: https://secure.phabricator.com/D8564

+222 -158
+5 -1
src/__phutil_library_map__.php
··· 4465 4465 'PhabricatorOAuthClientBaseController' => 'PhabricatorOAuthServerController', 4466 4466 'PhabricatorOAuthClientDeleteController' => 'PhabricatorOAuthClientBaseController', 4467 4467 'PhabricatorOAuthClientEditController' => 'PhabricatorOAuthClientBaseController', 4468 - 'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientBaseController', 4468 + 'PhabricatorOAuthClientListController' => 4469 + array( 4470 + 0 => 'PhabricatorOAuthClientBaseController', 4471 + 1 => 'PhabricatorApplicationSearchResultsControllerInterface', 4472 + ), 4469 4473 'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientBaseController', 4470 4474 'PhabricatorOAuthResponse' => 'AphrontResponse', 4471 4475 'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO',
+1 -1
src/applications/oauthserver/application/PhabricatorApplicationOAuthServer.php
··· 36 36 '(?:query/(?P<queryKey>[^/]+)/)?' 37 37 => 'PhabricatorOAuthClientListController', 38 38 'auth/' => 'PhabricatorOAuthServerAuthController', 39 - 'test/' => 'PhabricatorOAuthServerTestController', 39 + 'test/(?P<id>\d+)/' => 'PhabricatorOAuthServerTestController', 40 40 'token/' => 'PhabricatorOAuthServerTokenController', 41 41 'client/' => array( 42 42 'create/' => 'PhabricatorOAuthClientEditController',
+59 -33
src/applications/oauthserver/controller/PhabricatorOAuthServerTestController.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group oauthserver 5 - */ 6 3 final class PhabricatorOAuthServerTestController 7 - extends PhabricatorOAuthServerController { 4 + extends PhabricatorOAuthServerController { 5 + 6 + private $id; 8 7 9 8 public function shouldRequireLogin() { 10 9 return true; 11 10 } 12 11 12 + public function willProcessRequest(array $data) { 13 + $this->id = $data['id']; 14 + } 15 + 13 16 public function processRequest() { 14 - $request = $this->getRequest(); 15 - $current_user = $request->getUser(); 16 - $server = new PhabricatorOAuthServer(); 17 + $request = $this->getRequest(); 18 + $viewer = $request->getUser(); 19 + 17 20 $panels = array(); 18 21 $results = array(); 19 22 20 - if (!$request->isFormPost()) { 21 - return new Aphront400Response(); 22 - } 23 - 24 - $action = $request->getStr('action'); 25 - if ($action !== 'testclientauthorization') { 23 + $client = id(new PhabricatorOAuthServerClientQuery()) 24 + ->setViewer($viewer) 25 + ->withIDs(array($this->id)) 26 + ->executeOne(); 27 + if (!$client) { 26 28 return new Aphront404Response(); 27 29 } 28 30 29 - $user_phid = $current_user->getPHID(); 30 - $client_phid = $request->getStr('client_phid'); 31 - $client = id(new PhabricatorOAuthServerClient) 32 - ->loadOneWhere('phid = %s', $client_phid); 33 - if (!$client) { 34 - throw new Exception('Failed to load client!'); 31 + $view_uri = $client->getViewURI(); 32 + 33 + // Look for an existing authorization. 34 + $authorization = id(new PhabricatorOAuthClientAuthorizationQuery()) 35 + ->setViewer($viewer) 36 + ->withUserPHIDs(array($viewer->getPHID())) 37 + ->withClientPHIDs(array($client->getPHID())) 38 + ->executeOne(); 39 + if ($authorization) { 40 + $dialog = id(new AphrontDialogView()) 41 + ->setUser($viewer) 42 + ->setTitle(pht('Already Authorized')) 43 + ->appendParagraph( 44 + pht( 45 + 'You have already authorized this application to access your '. 46 + 'account.')) 47 + ->addCancelButton($view_uri, pht('Close')); 48 + 49 + return id(new AphrontDialogResponse())->setDialog($dialog); 35 50 } 36 - if ($client->getCreatorPHID() != $user_phid || 37 - $current_user->getPHID() != $user_phid) { 38 - throw new Exception( 39 - 'Only allowed to make test data for yourself '. 40 - 'for clients you own!' 41 - ); 51 + 52 + if ($request->isFormPost()) { 53 + $server = id(new PhabricatorOAuthServer()) 54 + ->setUser($viewer) 55 + ->setClient($client); 56 + 57 + $scope = array(); 58 + $authorization = $server->authorizeClient($scope); 59 + 60 + $id = $authorization->getID(); 61 + $panel_uri = '/settings/panel/oauthorizations/?id='.$id; 62 + 63 + return id(new AphrontRedirectResponse())->setURI($panel_uri); 42 64 } 43 65 44 - // blankclientauthorizations don't get scope 45 - $scope = array(); 46 - $server->setUser($current_user); 47 - $server->setClient($client); 48 - $authorization = $server->authorizeClient($scope); 66 + // TODO: It would be nice to put scope options in this dialog, maybe? 49 67 50 - $id = $authorization->getID(); 51 - $panel_uri = '/settings/panel/oauthorizations/?id='.$id; 68 + $dialog = id(new AphrontDialogView()) 69 + ->setUser($viewer) 70 + ->setTitle(pht('Authorize Application?')) 71 + ->appendParagraph( 72 + pht( 73 + 'This will create an authorization, permitting %s to access '. 74 + 'your account.', 75 + phutil_tag('strong', array(), $client->getName()))) 76 + ->addCancelButton($view_uri) 77 + ->addSubmitButton(pht('Authorize Application')); 52 78 53 - return id(new AphrontRedirectResponse())->setURI($panel_uri); 79 + return id(new AphrontDialogResponse())->setDialog($dialog); 54 80 } 55 81 }
+25 -30
src/applications/oauthserver/controller/client/PhabricatorOAuthClientDeleteController.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group oauthserver 5 - */ 6 3 final class PhabricatorOAuthClientDeleteController 7 - extends PhabricatorOAuthClientBaseController { 4 + extends PhabricatorOAuthClientBaseController { 8 5 9 6 public function processRequest() { 10 - $phid = $this->getClientPHID(); 11 - $title = 'Delete OAuth Client'; 12 - $request = $this->getRequest(); 13 - $current_user = $request->getUser(); 14 - $client = id(new PhabricatorOAuthServerClient()) 15 - ->loadOneWhere('phid = %s', 16 - $phid); 7 + $request = $this->getRequest(); 8 + $viewer = $request->getUser(); 17 9 18 - if (empty($client)) { 10 + $client = id(new PhabricatorOAuthServerClientQuery()) 11 + ->setViewer($viewer) 12 + ->withPHIDs(array($this->getClientPHID())) 13 + ->requireCapabilities( 14 + array( 15 + PhabricatorPolicyCapability::CAN_VIEW, 16 + PhabricatorPolicyCapability::CAN_EDIT, 17 + )) 18 + ->executeOne(); 19 + if (!$client) { 19 20 return new Aphront404Response(); 20 21 } 21 - if ($client->getCreatorPHID() != $current_user->getPHID()) { 22 - $message = 'Access denied to client with phid '.$phid.'. '. 23 - 'Only the user who created the client has permission to '. 24 - 'delete the client.'; 25 - return id(new Aphront403Response()) 26 - ->setForbiddenText($message); 27 - } 28 22 29 23 if ($request->isFormPost()) { 30 24 $client->delete(); 31 - return id(new AphrontRedirectResponse()) 32 - ->setURI('/oauthserver/client/?deleted=1'); 25 + $app_uri = $this->getApplicationURI(); 26 + return id(new AphrontRedirectResponse())->setURI($app_uri); 33 27 } 34 28 35 - $title .= ' '.$client->getName(); 29 + $dialog = id(new AphrontDialogView()) 30 + ->setUser($viewer) 31 + ->setTitle(pht('Delete OAuth Application?')) 32 + ->appendParagraph( 33 + pht( 34 + 'Really delete the OAuth application %s?', 35 + phutil_tag('strong', array(), $client->getName()))) 36 + ->addCancelButton($client->getViewURI()) 37 + ->addSubmitButton(pht('Delete Application')); 36 38 37 - $dialog = new AphrontDialogView(); 38 - $dialog->setUser($current_user); 39 - $dialog->setTitle($title); 40 - $dialog->appendChild(phutil_tag('p', array(), pht( 41 - 'Are you sure you want to delete this client?'))); 42 - $dialog->addSubmitButton(); 43 - $dialog->addCancelButton($client->getEditURI()); 44 39 return id(new AphrontDialogResponse())->setDialog($dialog); 40 + } 45 41 46 - } 47 42 }
+105 -93
src/applications/oauthserver/controller/client/PhabricatorOAuthClientViewController.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group oauthserver 5 - */ 6 3 final class PhabricatorOAuthClientViewController 7 - extends PhabricatorOAuthClientBaseController { 4 + extends PhabricatorOAuthClientBaseController { 5 + 6 + public function processRequest() { 7 + $request = $this->getRequest(); 8 + $viewer = $request->getUser(); 9 + 10 + $client = id(new PhabricatorOAuthServerClientQuery()) 11 + ->setViewer($viewer) 12 + ->withPHIDs(array($this->getClientPHID())) 13 + ->executeOne(); 14 + if (!$client) { 15 + return new Aphront404Response(); 16 + } 8 17 9 - protected function getFilter() { 10 - return 'client/view/'.$this->getClientPHID(); 18 + $header = $this->buildHeaderView($client); 19 + $actions = $this->buildActionView($client); 20 + $properties = $this->buildPropertyListView($client); 21 + $properties->setActionList($actions); 22 + 23 + $crumbs = $this->buildApplicationCrumbs(); 24 + $crumbs->addTextCrumb($client->getName()); 25 + 26 + $box = id(new PHUIObjectBoxView()) 27 + ->setHeader($header) 28 + ->addPropertyList($properties); 29 + 30 + return $this->buildApplicationPage( 31 + array( 32 + $crumbs, 33 + $box, 34 + ), 35 + array( 36 + 'title' => pht('OAuth Application: %s', $client->getName()), 37 + 'device' => true, 38 + )); 11 39 } 12 40 13 - protected function getExtraClientFilters() { 14 - return array( 15 - array('url' => $this->getFilter(), 16 - 'label' => 'View Client') 17 - ); 41 + private function buildHeaderView(PhabricatorOAuthServerClient $client) { 42 + $viewer = $this->getRequest()->getUser(); 43 + 44 + $header = id(new PHUIHeaderView()) 45 + ->setUser($viewer) 46 + ->setHeader(pht('OAuth Application: %s', $client->getName())) 47 + ->setPolicyObject($client); 48 + 49 + return $header; 18 50 } 19 51 20 - public function processRequest() { 21 - $request = $this->getRequest(); 22 - $current_user = $request->getUser(); 23 - $error = null; 24 - $phid = $this->getClientPHID(); 52 + private function buildActionView(PhabricatorOAuthServerClient $client) { 53 + $viewer = $this->getRequest()->getUser(); 25 54 26 - $client = id(new PhabricatorOAuthServerClient()) 27 - ->loadOneWhere('phid = %s', 28 - $phid); 29 - $title = 'View OAuth Client'; 55 + $can_edit = PhabricatorPolicyFilter::hasCapability( 56 + $viewer, 57 + $client, 58 + PhabricatorPolicyCapability::CAN_EDIT); 30 59 31 - // validate the client 32 - if (empty($client)) { 33 - $message = 'No client found with id '.$phid.'.'; 34 - return $this->buildStandardPageResponse( 35 - $this->buildErrorView($message), 36 - array('title' => $title)); 37 - } 60 + $authorization = id(new PhabricatorOAuthClientAuthorizationQuery()) 61 + ->setViewer($viewer) 62 + ->withUserPHIDs(array($viewer->getPHID())) 63 + ->withClientPHIDs(array($client->getPHID())) 64 + ->executeOne(); 65 + $is_authorized = (bool)$authorization; 38 66 39 - $panel = new AphrontPanelView(); 40 - $panel->setHeader($title); 67 + $view = id(new PhabricatorActionListView()) 68 + ->setUser($viewer); 41 69 42 - $form = id(new AphrontFormView()) 43 - ->setUser($current_user) 44 - ->appendChild( 45 - id(new AphrontFormStaticControl()) 46 - ->setLabel('Name') 47 - ->setValue($client->getName())) 48 - ->appendChild( 49 - id(new AphrontFormStaticControl()) 50 - ->setLabel('ID') 51 - ->setValue($phid)); 52 - if ($current_user->getPHID() == $client->getCreatorPHID()) { 53 - $form 54 - ->appendChild( 55 - id(new AphrontFormStaticControl()) 56 - ->setLabel('Secret') 57 - ->setValue($client->getSecret())); 58 - } 59 - $form 60 - ->appendChild( 61 - id(new AphrontFormStaticControl()) 62 - ->setLabel('Redirect URI') 63 - ->setValue($client->getRedirectURI())); 64 - $created = phabricator_datetime($client->getDateCreated(), 65 - $current_user); 66 - $updated = phabricator_datetime($client->getDateModified(), 67 - $current_user); 68 - $form 69 - ->appendChild( 70 - id(new AphrontFormStaticControl()) 71 - ->setLabel('Created') 72 - ->setValue($created)) 73 - ->appendChild( 74 - id(new AphrontFormStaticControl()) 75 - ->setLabel('Last Updated') 76 - ->setValue($updated)); 77 - $panel->appendChild($form); 78 - $admin_panel = null; 79 - if ($client->getCreatorPHID() == $current_user->getPHID()) { 80 - $edit_button = phutil_tag( 81 - 'a', 82 - array( 83 - 'href' => $client->getEditURI(), 84 - 'class' => 'grey button', 85 - ), 86 - 'Edit OAuth Client'); 87 - $panel->addButton($edit_button); 70 + $view->addAction( 71 + id(new PhabricatorActionView()) 72 + ->setName(pht('Edit Application')) 73 + ->setIcon('edit') 74 + ->setWorkflow(!$can_edit) 75 + ->setDisabled(!$can_edit) 76 + ->setHref($client->getEditURI())); 77 + 78 + $view->addAction( 79 + id(new PhabricatorActionView()) 80 + ->setName(pht('Delete Application')) 81 + ->setIcon('delete') 82 + ->setWorkflow(true) 83 + ->setDisabled(!$can_edit) 84 + ->setHref($client->getDeleteURI())); 85 + 86 + $view->addAction( 87 + id(new PhabricatorActionView()) 88 + ->setName(pht('Create Test Authorization')) 89 + ->setIcon('wrench') 90 + ->setWorkflow(true) 91 + ->setDisabled($is_authorized) 92 + ->setHref($this->getApplicationURI('test/'.$client->getID().'/'))); 93 + 94 + return $view; 95 + } 96 + 97 + private function buildPropertyListView(PhabricatorOAuthServerClient $client) { 98 + $viewer = $this->getRequest()->getUser(); 99 + 100 + $view = id(new PHUIPropertyListView()) 101 + ->setUser($viewer); 102 + 103 + $view->addProperty( 104 + pht('Client ID'), 105 + $client->getPHID()); 106 + 107 + $view->addProperty( 108 + pht('Client Secret'), 109 + $client->getSecret()); 110 + 111 + $view->addProperty( 112 + pht('Redirect URI'), 113 + $client->getRedirectURI()); 88 114 89 - $create_authorization_form = id(new AphrontFormView()) 90 - ->setUser($current_user) 91 - ->addHiddenInput('action', 'testclientauthorization') 92 - ->addHiddenInput('client_phid', $phid) 93 - ->setAction('/oauthserver/test/') 94 - ->appendChild( 95 - id(new AphrontFormSubmitControl()) 96 - ->setValue('Create Scopeless Test Authorization')); 97 - $admin_panel = id(new AphrontPanelView()) 98 - ->setHeader('Admin Tools') 99 - ->appendChild($create_authorization_form); 100 - } 115 + $view->addProperty( 116 + pht('Created'), 117 + phabricator_datetime($client->getDateCreated(), $viewer)); 101 118 102 - return $this->buildStandardPageResponse( 103 - array($error, 104 - $panel, 105 - $admin_panel 106 - ), 107 - array('title' => $title)); 119 + return $view; 108 120 } 109 121 }
+14
src/applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php
··· 5 5 6 6 private $phids; 7 7 private $userPHIDs; 8 + private $clientPHIDs; 8 9 9 10 public function witHPHIDs(array $phids) { 10 11 $this->phids = $phids; ··· 13 14 14 15 public function withUserPHIDs(array $phids) { 15 16 $this->userPHIDs = $phids; 17 + return $this; 18 + } 19 + 20 + public function withClientPHIDs(array $phids) { 21 + $this->clientPHIDs = $phids; 16 22 return $this; 17 23 } 18 24 ··· 45 51 $client = idx($clients, $authorization->getClientPHID()); 46 52 if (!$client) { 47 53 unset($authorizations[$key]); 54 + continue; 48 55 } 49 56 $authorization->attachClient($client); 50 57 } ··· 67 74 $conn_r, 68 75 'userPHID IN (%Ls)', 69 76 $this->userPHIDs); 77 + } 78 + 79 + if ($this->clientPHIDs) { 80 + $where[] = qsprintf( 81 + $conn_r, 82 + 'clientPHID IN (%Ls)', 83 + $this->clientPHIDs); 70 84 } 71 85 72 86 $where[] = $this->buildPagingClause($conn_r);
+13
src/applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php
··· 3 3 final class PhabricatorOAuthServerClientQuery 4 4 extends PhabricatorCursorPagedPolicyAwareQuery { 5 5 6 + private $ids; 6 7 private $phids; 7 8 private $creatorPHIDs; 9 + 10 + public function withIDs(array $ids) { 11 + $this->ids = $ids; 12 + return $this; 13 + } 8 14 9 15 public function withPHIDs(array $phids) { 10 16 $this->phids = $phids; ··· 34 40 35 41 private function buildWhereClause($conn_r) { 36 42 $where = array(); 43 + 44 + if ($this->ids) { 45 + $where[] = qsprintf( 46 + $conn_r, 47 + 'id IN (%Ld)', 48 + $this->ids); 49 + } 37 50 38 51 if ($this->phids) { 39 52 $where[] = qsprintf(