page = idx($data, 'page'); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $pages = array( 'account' => 'Account', 'email' => 'Email', // 'password' => 'Password', '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); } $account_editable = PhabricatorEnv::getEnvConfig('account.editable'); $this->accountEditable = $account_editable; if ($request->isFormPost()) { switch ($this->page) { case 'email': if (!$account_editable) { return new Aphront400Response(); } $user->setEmail($request->getStr('email')); $user->save(); return id(new AphrontRedirectResponse()) ->setURI('/settings/page/email/?saved=true'); 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( '

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'); 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']); $user->setProfileImagePHID($file->getPHID()); } } $user->save(); return id(new AphrontRedirectResponse()) ->setURI('/settings/page/account/'); } } switch ($this->page) { case 'arcanist': $content = $this->renderArcanistCertificateForm(); break; case 'account': $content = $this->renderAccountForm(); break; case 'email': $content = $this->renderEmailForm(); break; default: if (empty($pages[$this->page])) { return new Aphront404Response(); } $content = $this->renderOAuthForm($oauth_providers[$this->page]); break; } $sidenav = new AphrontSideNavView(); foreach ($pages as $page => $name) { $sidenav->addNavItem( phutil_render_tag( 'a', array( 'href' => '/settings/page/'.$page.'/', 'class' => ($page == $this->page) ? 'aphront-side-nav-selected' : null, ), phutil_escape_html($name))); } $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( '

Your old certificate has been destroyed and you have been issued '. 'a new certificate. Sessions established under the old certificate '. 'are no longer valid.

'); $notice = $notice->render(); } else { $notice = null; } $cert_form = new AphrontFormView(); $cert_form ->setUser($user) ->appendChild( '

Copy and paste this certificate '. 'into your ~/.arcrc in the "hosts" section to enable '. 'Arcanist to authenticate against this host.

') ->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) ->setWorkflow(true) ->setAction('/settings/page/arcanist/') ->appendChild( '

You can regenerate this '. 'certificate, which will invalidate the old certificate and create '. 'a new one.

') ->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() { $request = $this->getRequest(); $user = $request->getUser(); $img_src = PhabricatorFileURI::getViewURIForPHID( $user->getProfileImagePHID()); $editable = $this->accountEditable; $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') ->setValue($user->getRealName()) ->setDisabled(!$editable)) ->appendChild( id(new AphrontFormMarkupControl()) ->setValue('
')) ->appendChild( id(new AphrontFormMarkupControl()) ->setLabel('Profile Image') ->setValue( phutil_render_tag( 'img', array( 'src' => $img_src, )))); if ($editable) { $form ->appendChild( id(new AphrontFormFileControl()) ->setLabel('Change Image') ->setName('profile') ->setCaption('Upload a 50x50px image.')) ->appendChild( id(new AphrontFormMarkupControl()) ->setValue('
')) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue('Save')); } $panel = new AphrontPanelView(); $panel->setHeader('Profile Settings'); $panel->setWidth(AphrontPanelView::WIDTH_FORM); $panel->appendChild($form); return $panel->render(); } private function renderEmailForm() { $request = $this->getRequest(); $user = $request->getUser(); $editable = $this->accountEditable; if ($request->getStr('saved')) { $notice = new AphrontErrorView(); $notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE); $notice->setTitle('Changed Saved'); $notice->appendChild('

Your changes have been saved.

'); $notice = $notice->render(); } else { $notice = null; } $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())); 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( '

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.

'); switch ($provider_key) { case PhabricatorOAuthProvider::PROVIDER_GITHUB: $form->appendChild( '

Additionally, you must '. 'link your Github account before Phabricator can access any '. 'information about hosted repositories.

'); 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( '

Your account is linked with '. 'a '.$provider_name.' account. You may use your '.$provider_name.' '. 'credentials to log into Phabricator.

') ->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( '

You may unlink this account '. 'from your '.$provider_name.' account. This will prevent you from '. 'logging in with your '.$provider_name.' credentials.

') ->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( '

insert rap about tokens

') ->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('

'.$name.'

'); } $panel->appendChild($form); } return $notice.$panel->render(); } }