1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-18 21:02:41 +01:00

OAuth linking/unlinking controls.

Summary:

Test Plan:

Reviewers:

CC:
This commit is contained in:
epriestley 2011-02-21 22:51:34 -08:00
parent c3c16d0ac0
commit b462349ec8
10 changed files with 256 additions and 11 deletions

View file

@ -218,6 +218,7 @@ phutil_register_library_map(array(
'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base',
'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook',
'PhabricatorOAuthProviderGithub' => 'applications/auth/oauth/provider/github',
'PhabricatorOAuthUnlinkController' => 'applications/auth/controller/unlink',
'PhabricatorObjectHandle' => 'applications/phid/handle',
'PhabricatorObjectHandleData' => 'applications/phid/handle/data',
'PhabricatorObjectSelectorDialog' => 'view/control/objectselector',
@ -467,6 +468,7 @@ phutil_register_library_map(array(
'PhabricatorOAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorOAuthProviderFacebook' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthProviderGithub' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
'PhabricatorPHID' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDAllocateController' => 'PhabricatorPHIDController',
'PhabricatorPHIDController' => 'PhabricatorController',

View file

@ -134,6 +134,7 @@ class AphrontDefaultApplicationConfiguration
'(?P<provider>github|facebook)/' => array(
'login/$' => 'PhabricatorOAuthLoginController',
'diagnose/$' => 'PhabricatorOAuthDiagnosticsController',
'unlink/$' => 'PhabricatorOAuthUnlinkController',
),
),

View file

@ -25,6 +25,11 @@ class PhabricatorLoginController extends PhabricatorAuthController {
public function processRequest() {
$request = $this->getRequest();
if ($request->getUser()->getPHID()) {
// Kick the user out if they're already logged in.
return id(new AphrontRedirectResponse())->setURI('/');
}
$error = false;
$username = $request->getCookie('phusr');
if ($request->isFormPost()) {

View file

@ -32,17 +32,15 @@ class PhabricatorOAuthLoginController extends PhabricatorAuthController {
public function processRequest() {
$current_user = $this->getRequest()->getUser();
if ($current_user->getPHID()) {
// If we're already logged in, ignore everything going on here. TODO:
// restore account linking.
return id(new AphrontRedirectResponse())->setURI('/');
}
$provider = $this->provider;
if (!$provider->isProviderEnabled()) {
return new Aphront400Response();
}
$provider_name = $provider->getProviderName();
$provider_key = $provider->getProviderKey();
$request = $this->getRequest();
if ($request->getStr('error')) {
@ -115,12 +113,60 @@ class PhabricatorOAuthLoginController extends PhabricatorAuthController {
$user_id = $this->retrieveUserID();
// Login with known auth.
$known_oauth = id(new PhabricatorUserOAuthInfo())->loadOneWhere(
'oauthProvider = %s and oauthUID = %s',
$provider->getProviderKey(),
$user_id);
if ($current_user->getPHID()) {
if ($known_oauth) {
if ($known_oauth->getUserID() != $current_user->getID()) {
$dialog = new AphrontDialogView();
$dialog->setUser($current_user);
$dialog->setTitle('Already Linked to Another Account');
$dialog->appendChild(
'<p>The '.$provider_name.' account you just authorized '.
'is already linked to another Phabricator account. Before you can '.
'associate your '.$provider_name.' account with this Phabriactor '.
'account, you must unlink it from the Phabricator account it is '.
'currently linked to.</p>');
$dialog->addCancelButton('/settings/page/'.$provider_key.'/');
return id(new AphrontDialogResponse())->setDialog($dialog);
} else {
return id(new AphrontRedirectResponse())
->setURI('/settings/page/'.$provider_key.'/');
}
}
if (!$request->isDialogFormPost()) {
$dialog = new AphrontDialogView();
$dialog->setUser($current_user);
$dialog->setTitle('Link '.$provider_name.' Account');
$dialog->appendChild(
'<p>Link your '.$provider_name.' account to your Phabricator '.
'account?</p>');
$dialog->addHiddenInput('token', $token);
$dialog->addSubmitButton('Link Accounts');
$dialog->addCancelButton('/settings/page/'.$provider_key.'/');
return id(new AphrontDialogResponse())->setDialog($dialog);
}
$oauth_info = new PhabricatorUserOAuthInfo();
$oauth_info->setUserID($current_user->getID());
$oauth_info->setOAuthProvider($provider_key);
$oauth_info->setOAuthUID($user_id);
$oauth_info->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/'.$provider_key.'/');
}
// Login with known auth.
if ($known_oauth) {
$known_user = id(new PhabricatorUser())->load($known_oauth->getUserID());
$session_key = $known_user->establishSession('web');

View file

@ -7,6 +7,7 @@
phutil_require_module('phabricator', 'aphront/response/400');
phutil_require_module('phabricator', 'aphront/response/dialog');
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/auth/controller/base');
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
@ -14,6 +15,7 @@ phutil_require_module('phabricator', 'applications/auth/view/oauthfailure');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/people/storage/user');
phutil_require_module('phabricator', 'applications/people/storage/useroauthinfo');
phutil_require_module('phabricator', 'view/dialog');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');

View file

@ -0,0 +1,63 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class PhabricatorOAuthUnlinkController extends PhabricatorAuthController {
private $provider;
public function willProcessRequest(array $data) {
$this->provider = PhabricatorOAuthProvider::newProvider($data['provider']);
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$provider = $this->provider;
$provider_name = $provider->getProviderName();
$provider_key = $provider->getProviderKey();
$oauth_info = id(new PhabricatorUserOAuthInfo())->loadOneWhere(
'userID = %d AND oauthProvider = %s',
$user->getID(),
$provider_key);
if (!$oauth_info) {
return new Aphront400Response();
}
if (!$request->isDialogFormPost()) {
$dialog = new AphrontDialogView();
$dialog->setUser($user);
$dialog->setTitle('Really unlink account?');
$dialog->appendChild(
'<p><strong>You will not be able to login</strong> using this account '.
'once you unlink it. Continue?</p>');
$dialog->addSubmitButton('Unlink Account');
$dialog->addCancelButton('/settings/page/'.$provider_key.'/');
return id(new AphrontDialogResponse())->setDialog($dialog);
}
$oauth_info->delete();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/'.$provider_key.'/');
}
}

View file

@ -0,0 +1,20 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/400');
phutil_require_module('phabricator', 'aphront/response/dialog');
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/auth/controller/base');
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
phutil_require_module('phabricator', 'applications/people/storage/useroauthinfo');
phutil_require_module('phabricator', 'view/dialog');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorOAuthUnlinkController.php');

View file

@ -57,7 +57,7 @@ abstract class PhabricatorOAuthProvider {
);
$providers = array();
foreach ($all as $provider) {
$providers[] = self::newProvider($provider);
$providers[$provider] = self::newProvider($provider);
}
return $providers;
}

View file

@ -33,10 +33,19 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
'account' => 'Account',
'email' => 'Email',
// 'password' => 'Password',
// 'facebook' => 'Facebook Account',
'arcanist' => 'Arcanist Certificate',
);
$oauth_providers = PhabricatorOAuthProvider::getAllProviders();
foreach ($oauth_providers as $provider) {
if (!$provider->isProviderEnabled()) {
continue;
}
$key = $provider->getProviderKey();
$name = $provider->getProviderName();
$pages[$key] = $name.' Account';
}
if (empty($pages[$this->page])) {
$this->page = key($pages);
}
@ -103,7 +112,10 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
$content = $this->renderEmailForm();
break;
default:
$content = 'derp derp';
if (empty($pages[$this->page])) {
return new Aphront404Response();
}
$content = $this->renderOAuthForm($oauth_providers[$this->page]);
break;
}
@ -244,7 +256,6 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
$request = $this->getRequest();
$user = $request->getUser();
if ($request->getStr('saved')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
@ -278,4 +289,95 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
return $notice.$panel->render();
}
private function renderOAuthForm(PhabricatorOAuthProvider $provider) {
$request = $this->getRequest();
$user = $request->getUser();
$notice = null;
$provider_name = $provider->getProviderName();
$provider_key = $provider->getProviderKey();
$oauth_info = id(new PhabricatorUserOAuthInfo())->loadOneWhere(
'userID = %d AND oauthProvider = %s',
$user->getID(),
$provider->getProviderKey());
$form = new AphrontFormView();
$form
->setUser($user);
$forms = array();
$forms[] = $form;
if (!$oauth_info) {
$form
->appendChild(
'<p class="aphront-form-instructions">There is currently no '.
$provider_name.' account linked to your Phabricator account. You '.
'can link an account, which will allow you to use it to log into '.
'Phabricator.</p>');
switch ($provider_key) {
case PhabricatorOAuthProvider::PROVIDER_GITHUB:
$form->appendChild(
'<p class="aphront-form-instructions">Additionally, you must '.
'link your Github account before Phabricator can access any '.
'information about hosted repositories.</p>');
break;
}
$auth_uri = $provider->getAuthURI();
$client_id = $provider->getClientID();
$redirect_uri = $provider->getRedirectURI();
$form
->setAction($auth_uri)
->setMethod('GET')
->addHiddenInput('redirect_uri', $redirect_uri)
->addHiddenInput('client_id', $client_id)
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Link '.$provider_name." Account \xC2\xBB"));
} else {
$form
->appendChild(
'<p class="aphront-form-instructions">Your account is linked with '.
'a '.$provider_name.' account. You may use your '.$provider_name.' '.
'credentials to log into Phabricator.</p>')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' ID')
->setValue($oauth_info->getOAuthUID()));
$unlink = 'Unlink '.$provider_name.' Account';
$unlink_form = new AphrontFormView();
$unlink_form
->setUser($user)
->appendChild(
'<p class="aphront-form-instructions">You may unlink this account '.
'from your '.$provider_name.' account. This will prevent you from '.
'logging in with your '.$provider_name.' credentials.</p>')
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/oauth/'.$provider_key.'/unlink/', $unlink));
$forms['Unlink Account'] = $unlink_form;
}
$panel = new AphrontPanelView();
$panel->setHeader($provider_name.' Account Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
foreach ($forms as $name => $form) {
if ($name) {
$panel->appendChild('<br /><br /><h1>'.$name.'</h1>');
}
$panel->appendChild($form);
}
return $notice.$panel->render();
}
}

View file

@ -6,16 +6,20 @@
phutil_require_module('phabricator', 'aphront/response/404');
phutil_require_module('phabricator', 'aphront/response/dialog');
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/files/uri');
phutil_require_module('phabricator', 'applications/people/controller/base');
phutil_require_module('phabricator', 'applications/people/storage/user');
phutil_require_module('phabricator', 'applications/people/storage/useroauthinfo');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/dialog');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');