1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-23 22:10:55 +01:00

Refactor user settings

Summary:
I want to do two things here:

  - Add SSH Keys
  - Move "Preferences" into this panel

But this controller was pretty gigantic and messy. Split it apart and use
delegation instead.

There are no functional changes. I changed some of the conduit certificate text
to simplify it since no one should need to go through that workflow anymore,
given the existence of "arc install-certificate".

Test Plan:
  - Edited realname, including attempting to remove it.
  - Edited profile picture.
  - Edited timezone.
  - Edited email, including attempting to remove it.
  - Regenerated condiut certificate.
  - Linked and unlinked an OAuth account.

Reviewed By: jungejason
Reviewers: jungejason, tuomaspelkonen, aran
CC: aran, jungejason
Differential Revision: 688
This commit is contained in:
epriestley 2011-07-18 08:02:00 -07:00
parent 1bf8180d65
commit 7b40c616d6
13 changed files with 730 additions and 516 deletions

View file

@ -561,12 +561,17 @@ phutil_register_library_map(array(
'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/listfilter', 'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/listfilter',
'PhabricatorUIPagerExample' => 'applications/uiexample/examples/pager', 'PhabricatorUIPagerExample' => 'applications/uiexample/examples/pager',
'PhabricatorUser' => 'applications/people/storage/user', 'PhabricatorUser' => 'applications/people/storage/user',
'PhabricatorUserAccountSettingsPanelController' => 'applications/people/controller/settings/panels/account',
'PhabricatorUserConduitSettingsPanelController' => 'applications/people/controller/settings/panels/conduit',
'PhabricatorUserDAO' => 'applications/people/storage/base', 'PhabricatorUserDAO' => 'applications/people/storage/base',
'PhabricatorUserEmailSettingsPanelController' => 'applications/people/controller/settings/panels/email',
'PhabricatorUserLog' => 'applications/people/storage/log', 'PhabricatorUserLog' => 'applications/people/storage/log',
'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo', 'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo',
'PhabricatorUserOAuthSettingsPanelController' => 'applications/people/controller/settings/panels/oauth',
'PhabricatorUserPreferences' => 'applications/people/storage/preferences', 'PhabricatorUserPreferences' => 'applications/people/storage/preferences',
'PhabricatorUserProfile' => 'applications/people/storage/profile', 'PhabricatorUserProfile' => 'applications/people/storage/profile',
'PhabricatorUserSettingsController' => 'applications/people/controller/settings', 'PhabricatorUserSettingsController' => 'applications/people/controller/settings',
'PhabricatorUserSettingsPanelController' => 'applications/people/controller/settings/panels/base',
'PhabricatorWorker' => 'infrastructure/daemon/workers/worker', 'PhabricatorWorker' => 'infrastructure/daemon/workers/worker',
'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/base', 'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/base',
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/task', 'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/task',
@ -1070,12 +1075,17 @@ phutil_register_library_map(array(
'PhabricatorUIListFilterExample' => 'PhabricatorUIExample', 'PhabricatorUIListFilterExample' => 'PhabricatorUIExample',
'PhabricatorUIPagerExample' => 'PhabricatorUIExample', 'PhabricatorUIPagerExample' => 'PhabricatorUIExample',
'PhabricatorUser' => 'PhabricatorUserDAO', 'PhabricatorUser' => 'PhabricatorUserDAO',
'PhabricatorUserAccountSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserConduitSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserDAO' => 'PhabricatorLiskDAO', 'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserEmailSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserLog' => 'PhabricatorUserDAO', 'PhabricatorUserLog' => 'PhabricatorUserDAO',
'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO', 'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO',
'PhabricatorUserOAuthSettingsPanelController' => 'PhabricatorUserSettingsPanelController',
'PhabricatorUserPreferences' => 'PhabricatorUserDAO', 'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
'PhabricatorUserProfile' => 'PhabricatorUserDAO', 'PhabricatorUserProfile' => 'PhabricatorUserDAO',
'PhabricatorUserSettingsController' => 'PhabricatorPeopleController', 'PhabricatorUserSettingsController' => 'PhabricatorPeopleController',
'PhabricatorUserSettingsPanelController' => 'PhabricatorPeopleController',
'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO', 'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO',
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',

View file

@ -19,7 +19,7 @@
class PhabricatorUserSettingsController extends PhabricatorPeopleController { class PhabricatorUserSettingsController extends PhabricatorPeopleController {
private $page; private $page;
private $accountEditable; private $pages;
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->page = idx($data, 'page'); $this->page = idx($data, 'page');
@ -28,13 +28,12 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$user = $request->getUser();
$pages = array( $this->pages = array(
'account' => 'Account', 'account' => 'Account',
'email' => 'Email', 'email' => 'Email',
// 'password' => 'Password', // 'password' => 'Password',
'arcanist' => 'Arcanist Certificate', 'conduit' => 'Conduit Certificate',
); );
$oauth_providers = PhabricatorOAuthProvider::getAllProviders(); $oauth_providers = PhabricatorOAuthProvider::getAllProviders();
@ -44,148 +43,49 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
} }
$key = $provider->getProviderKey(); $key = $provider->getProviderKey();
$name = $provider->getProviderName(); $name = $provider->getProviderName();
$pages[$key] = $name.' Account'; $this->pages[$key] = $name.' Account';
} }
if (empty($pages[$this->page])) { if (empty($this->pages[$this->page])) {
$this->page = key($pages); $this->page = key($this->pages);
} }
$account_editable = PhabricatorEnv::getEnvConfig('account.editable');
$this->accountEditable = $account_editable;
$e_realname = true;
$e_email = true;
$errors = array();
if ($request->isFormPost()) {
switch ($this->page) {
case 'email':
if (!$account_editable) {
return new Aphront400Response();
}
$user->setEmail($request->getStr('email'));
if (!strlen($user->getEmail())) {
$errors[] = 'You must enter an e-mail address';
$e_email = 'Required';
}
if (!$errors) {
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/email/?saved=true');
}
break;
case 'arcanist':
if (!$request->isDialogFormPost()) {
$dialog = new AphrontDialogView();
$dialog->setUser($user);
$dialog->setTitle('Really regenerate session?');
$dialog->setSubmitURI('/settings/page/arcanist/');
$dialog->addSubmitButton('Regenerate');
$dialog->addCancelbutton('/settings/page/arcanist/');
$dialog->appendChild(
'<p>Really destroy the old certificate? Any established '.
'sessions will be terminated.');
return id(new AphrontDialogResponse())
->setDialog($dialog);
}
$conn = $user->establishConnection('w');
queryfx(
$conn,
'DELETE FROM %T WHERE userPHID = %s AND type LIKE %>',
PhabricatorUser::SESSION_TABLE,
$user->getPHID(),
'conduit');
// This implicitly regenerates the certificate.
$user->setConduitCertificate(null);
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/arcanist/?regenerated=true');
break;
case 'account':
if (!$account_editable) {
return new Aphront400Response();
}
if (!empty($_FILES['profile'])) {
$err = idx($_FILES['profile'], 'error');
if ($err != UPLOAD_ERR_NO_FILE) {
$file = PhabricatorFile::newFromPHPUpload(
$_FILES['profile'],
array(
'authorPHID' => $user->getPHID(),
));
$okay = $file->isTransformableImage();
if ($okay) {
$xformer = new PhabricatorImageTransformer();
$xformed = $xformer->executeProfileTransform(
$file,
$width = 50,
$min_height = 50,
$max_height = 50);
$user->setProfileImagePHID($xformed->getPHID());
} else {
$errors[] =
'Only valid image files (jpg, jpeg, png or gif) '.
'will be accepted.';
}
}
}
$user->setRealName($request->getStr('realname'));
if (!strlen($user->getRealName())) {
$errors[] = 'Real name must be nonempty.';
$e_realname = 'Required';
}
$new_timezone = $request->getStr('timezone');
if (in_array($new_timezone, DateTimeZone::listIdentifiers(), true)) {
$user->setTimezoneIdentifier($new_timezone);
} else {
$errors[] =
'The selected timezone is not a valid timezone.';
}
if (!$errors) {
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/account/?saved=true');
}
break;
}
}
switch ($this->page) { switch ($this->page) {
case 'arcanist':
$content = $this->renderArcanistCertificateForm();
break;
case 'account': case 'account':
$content = $this->renderAccountForm($errors, $e_realname); $delegate = new PhabricatorUserAccountSettingsPanelController($request);
break; break;
case 'email': case 'email':
$content = $this->renderEmailForm($errors, $e_email); $delegate = new PhabricatorUserEmailSettingsPanelController($request);
break;
case 'conduit':
$delegate = new PhabricatorUserConduitSettingsPanelController($request);
break; break;
default: default:
if (empty($pages[$this->page])) { if (empty($this->pages[$this->page])) {
return new Aphront404Response(); return new Aphront404Response();
} }
$content = $this->renderOAuthForm($oauth_providers[$this->page]); $delegate = new PhabricatorUserOAuthSettingsPanelController($request);
break; $delegate->setOAuthProvider($oauth_providers[$this->page]);
} }
$response = $this->delegateToController($delegate);
if ($response instanceof AphrontView) {
$sidenav = $this->renderSideNav();
$sidenav->appendChild($response);
return $this->buildStandardPageResponse(
$sidenav,
array(
'title' => 'Account Settings',
));
} else {
return $response;
}
}
private function renderSideNav() {
$sidenav = new AphrontSideNavView(); $sidenav = new AphrontSideNavView();
foreach ($pages as $page => $name) { foreach ($this->pages as $page => $name) {
$sidenav->addNavItem( $sidenav->addNavItem(
phutil_render_tag( phutil_render_tag(
'a', 'a',
@ -197,369 +97,6 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
), ),
phutil_escape_html($name))); phutil_escape_html($name)));
} }
return $sidenav;
$sidenav->appendChild($content);
return $this->buildStandardPageResponse(
$sidenav,
array(
'title' => 'Account Settings',
));
}
private function renderArcanistCertificateForm() {
$request = $this->getRequest();
$user = $request->getUser();
if ($request->getStr('regenerated')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Certificate Regenerated');
$notice->appendChild(
'<p>Your old certificate has been destroyed and you have been issued '.
'a new certificate. Sessions established under the old certificate '.
'are no longer valid.</p>');
$notice = $notice->render();
} else {
$notice = null;
}
$host = PhabricatorEnv::getEnvConfig('phabricator.base-uri') . 'api/';
$conduit_setting = sprintf(
' %s: {'."\n".
' "user" : %s,'."\n".
' "cert" : %s'."\n".
' }'."\n",
json_encode($host),
json_encode($user->getUserName()),
json_encode($user->getConduitCertificate()));
$cert_form = new AphrontFormView();
$cert_form
->setUser($user)
->appendChild(
'<p class="aphront-form-instructions">Copy and paste the host info '.
'including the certificate into your <tt>~/.arcrc</tt> in the "hosts" '.
'session to enable Arcanist to authenticate against this host.</p>')
->appendChild(
id(new AphrontFormMarkupControl())
->setControlStyle('white-space: pre; font-family: monospace')
->setValue(
'{'."\n".
' ...'."\n".
' "hosts" : {'."\n"))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Credentials')
->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT)
->setControlStyle('font-family: monospace')
->setValue($conduit_setting))
->appendChild(
id(new AphrontFormStaticControl())
->setControlStyle('white-space: pre; font-family: monospace')
->setValue(
' }'."\n".
' ...'."\n".
'}'));
$cert = new AphrontPanelView();
$cert->setHeader('Arcanist Certificate');
$cert->appendChild($cert_form);
$cert->setWidth(AphrontPanelView::WIDTH_FORM);
$regen_form = new AphrontFormView();
$regen_form
->setUser($user)
->setAction('/settings/page/arcanist/')
->appendChild(
'<p class="aphront-form-instructions">You can regenerate this '.
'certificate, which will invalidate the old certificate and create '.
'a new one.</p>')
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Regenerate Certificate'));
$regen = new AphrontPanelView();
$regen->setHeader('Regenerate Certificate');
$regen->appendChild($regen_form);
$regen->setWidth(AphrontPanelView::WIDTH_FORM);
return $notice.$cert->render().$regen->render();
}
private function renderAccountForm(array $errors, $e_realname) {
$request = $this->getRequest();
$user = $request->getUser();
$img_src = PhabricatorFileURI::getViewURIForPHID(
$user->getProfileImagePHID());
$editable = $this->accountEditable;
$notice = null;
if (!$errors) {
if ($request->getStr('saved')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Changes Saved');
$notice->appendChild('<p>Your changes have been saved.</p>');
$notice = $notice->render();
}
} else {
$notice = new AphrontErrorView();
$notice->setTitle('Form Errors');
$notice->setErrors($errors);
$notice = $notice->render();
}
$form = new AphrontFormView();
$form
->setUser($user)
->setEncType('multipart/form-data')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Username')
->setValue($user->getUsername()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Real Name')
->setName('realname')
->setError($e_realname)
->setValue($user->getRealName())
->setDisabled(!$editable))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Profile Image')
->setValue(
phutil_render_tag(
'img',
array(
'src' => $img_src,
))));
if ($editable) {
$timezone_ids = DateTimeZone::listIdentifiers();
$timezone_id_map = array_combine($timezone_ids, $timezone_ids);
$form
->appendChild(
id(new AphrontFormFileControl())
->setLabel('Change Image')
->setName('profile'))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel('Timezone')
->setName('timezone')
->setOptions($timezone_id_map)
->setValue($user->getTimezoneIdentifier()))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save'));
}
$panel = new AphrontPanelView();
$panel->setHeader('Profile Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
return $notice.$panel->render();
}
private function renderEmailForm(array $errors, $e_email) {
$request = $this->getRequest();
$user = $request->getUser();
$editable = $this->accountEditable;
$notice = null;
if (!$errors) {
if ($request->getStr('saved')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Changes Saved');
$notice->appendChild('<p>Your changes have been saved.</p>');
$notice = $notice->render();
}
} else {
$notice = new AphrontErrorView();
$notice->setTitle('Form Errors');
$notice->setErrors($errors);
$notice = $notice->render();
}
$form = new AphrontFormView();
$form
->setUser($user)
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Email')
->setName('email')
->setDisabled(!$editable)
->setCaption(
'Note: there is no email validation yet; double-check your '.
'typing.')
->setValue($user->getEmail())
->setError($e_email));
if ($editable) {
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save'));
}
$panel = new AphrontPanelView();
$panel->setHeader('Email Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
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()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' Name')
->setValue($oauth_info->getAccountName()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' URI')
->setValue($oauth_info->getAccountURI()));
if (!$provider->isProviderLinkPermanent()) {
$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;
}
$expires = $oauth_info->getTokenExpires();
if ($expires) {
if ($expires <= time()) {
$expires = "Expired";
} else {
$expires = phabricator_format_timestamp($expires);
}
} else {
$expires = 'No Information Available';
}
$scope = $oauth_info->getTokenScope();
if (!$scope) {
$scope = 'No Information Available';
}
$status = $oauth_info->getTokenStatus();
$status = PhabricatorUserOAuthInfo::getReadableTokenStatus($status);
$token_form = new AphrontFormView();
$token_form
->setUser($user)
->appendChild(
'<p class="aphront-from-instructions">insert rap about tokens</p>')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Token Status')
->setValue($status))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Expires')
->setValue($expires))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Scope')
->setValue($scope));
$forms['Account Token Information'] = $token_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,32 +6,14 @@
phutil_require_module('phabricator', 'aphront/response/400');
phutil_require_module('phabricator', 'aphront/response/404'); 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/auth/oauth/provider/base');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/files/transform');
phutil_require_module('phabricator', 'applications/files/uri');
phutil_require_module('phabricator', 'applications/people/controller/base'); phutil_require_module('phabricator', 'applications/people/controller/base');
phutil_require_module('phabricator', 'applications/people/storage/user'); phutil_require_module('phabricator', 'applications/people/controller/settings/panels/account');
phutil_require_module('phabricator', 'applications/people/storage/useroauthinfo'); phutil_require_module('phabricator', 'applications/people/controller/settings/panels/conduit');
phutil_require_module('phabricator', 'infrastructure/env'); phutil_require_module('phabricator', 'applications/people/controller/settings/panels/email');
phutil_require_module('phabricator', 'storage/queryfx'); phutil_require_module('phabricator', 'applications/people/controller/settings/panels/oauth');
phutil_require_module('phabricator', 'view/dialog');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/file');
phutil_require_module('phabricator', 'view/form/control/markup');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/layout/sidenav'); phutil_require_module('phabricator', 'view/layout/sidenav');
phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup'); phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils'); phutil_require_module('phutil', 'utils');

View file

@ -0,0 +1,166 @@
<?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 PhabricatorUserAccountSettingsPanelController
extends PhabricatorUserSettingsPanelController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$editable = $this->getAccountEditable();
$e_realname = true;
$errors = array();
if ($request->isFormPost()) {
if (!$editable) {
return new Aphront400Response();
}
if (!empty($_FILES['profile'])) {
$err = idx($_FILES['profile'], 'error');
if ($err != UPLOAD_ERR_NO_FILE) {
$file = PhabricatorFile::newFromPHPUpload(
$_FILES['profile'],
array(
'authorPHID' => $user->getPHID(),
));
$okay = $file->isTransformableImage();
if ($okay) {
$xformer = new PhabricatorImageTransformer();
$xformed = $xformer->executeProfileTransform(
$file,
$width = 50,
$min_height = 50,
$max_height = 50);
$user->setProfileImagePHID($xformed->getPHID());
} else {
$errors[] =
'Only valid image files (jpg, jpeg, png or gif) '.
'will be accepted.';
}
}
}
$user->setRealName($request->getStr('realname'));
if (!strlen($user->getRealName())) {
$errors[] = 'Real name must be nonempty.';
$e_realname = 'Required';
}
$new_timezone = $request->getStr('timezone');
if (in_array($new_timezone, DateTimeZone::listIdentifiers(), true)) {
$user->setTimezoneIdentifier($new_timezone);
} else {
$errors[] = 'The selected timezone is not a valid timezone.';
}
if (!$errors) {
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/account/?saved=true');
}
}
$img_src = PhabricatorFileURI::getViewURIForPHID(
$user->getProfileImagePHID());
$notice = null;
if (!$errors) {
if ($request->getStr('saved')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Changes Saved');
$notice->appendChild('<p>Your changes have been saved.</p>');
$notice = $notice->render();
}
} else {
$notice = new AphrontErrorView();
$notice->setTitle('Form Errors');
$notice->setErrors($errors);
$notice = $notice->render();
}
$form = new AphrontFormView();
$form
->setUser($user)
->setEncType('multipart/form-data')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Username')
->setValue($user->getUsername()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Real Name')
->setName('realname')
->setError($e_realname)
->setValue($user->getRealName())
->setDisabled(!$editable))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Profile Image')
->setValue(
phutil_render_tag(
'img',
array(
'src' => $img_src,
))));
if ($editable) {
$timezone_ids = DateTimeZone::listIdentifiers();
$timezone_id_map = array_combine($timezone_ids, $timezone_ids);
$form
->appendChild(
id(new AphrontFormFileControl())
->setLabel('Change Image')
->setName('profile'))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel('Timezone')
->setName('timezone')
->setOptions($timezone_id_map)
->setValue($user->getTimezoneIdentifier()))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save'));
}
$panel = new AphrontPanelView();
$panel->setHeader('Profile Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
return id(new AphrontNullView())
->appendChild(
array(
$notice,
$panel,
));
}
}

View file

@ -0,0 +1,30 @@
<?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/redirect');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/files/transform');
phutil_require_module('phabricator', 'applications/files/uri');
phutil_require_module('phabricator', 'applications/people/controller/settings/panels/base');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/file');
phutil_require_module('phabricator', 'view/form/control/markup');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/null');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorUserAccountSettingsPanelController.php');

View file

@ -0,0 +1,26 @@
<?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.
*/
abstract class PhabricatorUserSettingsPanelController
extends PhabricatorPeopleController {
public function getAccountEditable() {
return PhabricatorEnv::getEnvConfig('account.editable');
}
}

View file

@ -0,0 +1,13 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/people/controller/base');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_source('PhabricatorUserSettingsPanelController.php');

View file

@ -0,0 +1,114 @@
<?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 PhabricatorUserConduitSettingsPanelController
extends PhabricatorUserSettingsPanelController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
if ($request->isFormPost()) {
if (!$request->isDialogFormPost()) {
$dialog = new AphrontDialogView();
$dialog->setUser($user);
$dialog->setTitle('Really regenerate session?');
$dialog->setSubmitURI('/settings/page/conduit/');
$dialog->addSubmitButton('Regenerate');
$dialog->addCancelbutton('/settings/page/conduit/');
$dialog->appendChild(
'<p>Really destroy the old certificate? Any established '.
'sessions will be terminated.');
return id(new AphrontDialogResponse())
->setDialog($dialog);
}
$conn = $user->establishConnection('w');
queryfx(
$conn,
'DELETE FROM %T WHERE userPHID = %s AND type LIKE %>',
PhabricatorUser::SESSION_TABLE,
$user->getPHID(),
'conduit');
// This implicitly regenerates the certificate.
$user->setConduitCertificate(null);
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/conduit/?regenerated=true');
}
if ($request->getStr('regenerated')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Certificate Regenerated');
$notice->appendChild(
'<p>Your old certificate has been destroyed and you have been issued '.
'a new certificate. Sessions established under the old certificate '.
'are no longer valid.</p>');
$notice = $notice->render();
} else {
$notice = null;
}
$cert_form = new AphrontFormView();
$cert_form
->setUser($user)
->appendChild(
'<p class="aphront-form-instructions">This certificate allows you to '.
'authenticate over Conduit, the Phabricator API. Normally, you just '.
'run <tt>arc install-certificate</tt> to install it.')
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Certificate')
->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT)
->setValue($user->getConduitCertificate()));
$cert = new AphrontPanelView();
$cert->setHeader('Arcanist Certificate');
$cert->appendChild($cert_form);
$cert->setWidth(AphrontPanelView::WIDTH_FORM);
$regen_form = new AphrontFormView();
$regen_form
->setUser($user)
->setAction('/settings/page/conduit/')
->appendChild(
'<p class="aphront-form-instructions">You can regenerate this '.
'certificate, which will invalidate the old certificate and create '.
'a new one.</p>')
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Regenerate Certificate'));
$regen = new AphrontPanelView();
$regen->setHeader('Regenerate Certificate');
$regen->appendChild($regen_form);
$regen->setWidth(AphrontPanelView::WIDTH_FORM);
return id(new AphrontNullView())
->appendChild(
array(
$notice,
$cert,
$regen,
));
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/dialog');
phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/people/controller/settings/panels/base');
phutil_require_module('phabricator', 'applications/people/storage/user');
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/submit');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/null');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorUserConduitSettingsPanelController.php');

View file

@ -0,0 +1,96 @@
<?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 PhabricatorUserEmailSettingsPanelController
extends PhabricatorUserSettingsPanelController {
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$editable = $this->getAccountEditable();
$e_email = true;
$errors = array();
if ($request->isFormPost()) {
if (!$editable) {
return new Aphront400Response();
}
$user->setEmail($request->getStr('email'));
if (!strlen($user->getEmail())) {
$errors[] = 'You must enter an e-mail address.';
$e_email = 'Required';
}
if (!$errors) {
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/email/?saved=true');
}
}
$notice = null;
if (!$errors) {
if ($request->getStr('saved')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Changes Saved');
$notice->appendChild('<p>Your changes have been saved.</p>');
}
} else {
$notice = new AphrontErrorView();
$notice->setTitle('Form Errors');
$notice->setErrors($errors);
}
$form = new AphrontFormView();
$form
->setUser($user)
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Email')
->setName('email')
->setDisabled(!$editable)
->setCaption(
'Note: there is no email validation yet; double-check your '.
'typing.')
->setValue($user->getEmail())
->setError($e_email));
if ($editable) {
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save'));
}
$panel = new AphrontPanelView();
$panel->setHeader('Email Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
return id(new AphrontNullView())
->appendChild(
array(
$notice,
$panel,
));
}
}

View file

@ -0,0 +1,22 @@
<?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/redirect');
phutil_require_module('phabricator', 'applications/people/controller/settings/panels/base');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/null');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorUserEmailSettingsPanelController.php');

View file

@ -0,0 +1,171 @@
<?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 PhabricatorUserOAuthSettingsPanelController
extends PhabricatorUserSettingsPanelController {
private $provider;
public function setOAuthProvider(PhabricatorOAuthProvider $oauth_provider) {
$this->provider = $oauth_provider;
return $this;
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$provider = $this->provider;
$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()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' Name')
->setValue($oauth_info->getAccountName()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' URI')
->setValue($oauth_info->getAccountURI()));
if (!$provider->isProviderLinkPermanent()) {
$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;
}
$expires = $oauth_info->getTokenExpires();
if ($expires) {
if ($expires <= time()) {
$expires = "Expired";
} else {
$expires = phabricator_format_timestamp($expires);
}
} else {
$expires = 'No Information Available';
}
$scope = $oauth_info->getTokenScope();
if (!$scope) {
$scope = 'No Information Available';
}
$status = $oauth_info->getTokenStatus();
$status = PhabricatorUserOAuthInfo::getReadableTokenStatus($status);
$token_form = new AphrontFormView();
$token_form
->setUser($user)
->appendChild(
'<p class="aphront-from-instructions">insert rap about tokens</p>')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Token Status')
->setValue($status))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Expires')
->setValue($expires))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Scope')
->setValue($scope));
$forms['Account Token Information'] = $token_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 id(new AphrontNullView())
->appendChild(
array(
$notice,
$panel,
));
}
}

View file

@ -0,0 +1,22 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
phutil_require_module('phabricator', 'applications/people/controller/settings/panels/base');
phutil_require_module('phabricator', 'applications/people/storage/useroauthinfo');
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/layout/panel');
phutil_require_module('phabricator', 'view/null');
phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorUserOAuthSettingsPanelController.php');