diff --git a/src/applications/notification/setup/PhabricatorAphlictSetupCheck.php b/src/applications/notification/setup/PhabricatorAphlictSetupCheck.php index 7a00673ae1..20787c79bd 100644 --- a/src/applications/notification/setup/PhabricatorAphlictSetupCheck.php +++ b/src/applications/notification/setup/PhabricatorAphlictSetupCheck.php @@ -1,41 +1,41 @@ getMessage(), ))); $this->newIssue('aphlict.connect') ->setShortName(pht('Notification Server Down')) ->setName(pht('Unable to Connect to Notification Server')) ->setSummary( pht( - 'Phabricator is configured to use a notification server, '. + 'This server is configured to use a notification server, '. 'but is not able to connect to it.')) ->setMessage($message) ->addRelatedPhabricatorConfig('notification.servers') ->addCommand( pht( "(To start the server, run this command.)\n%s", - 'phabricator/ $ ./bin/aphlict start')); + '$ ./bin/aphlict start')); return; } } } diff --git a/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php b/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php index 2b454e00ef..6b10dd60c5 100644 --- a/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php +++ b/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php @@ -1,316 +1,318 @@ getViewer(); $server = new PhabricatorOAuthServer(); $client_phid = $request->getStr('client_id'); $redirect_uri = $request->getStr('redirect_uri'); $response_type = $request->getStr('response_type'); // state is an opaque value the client sent us for their own purposes // we just need to send it right back to them in the response! $state = $request->getStr('state'); if (!$client_phid) { return $this->buildErrorResponse( 'invalid_request', pht('Malformed Request'), pht( 'Required parameter %s was not present in the request.', phutil_tag('strong', array(), 'client_id'))); } // We require that users must be able to see an OAuth application // in order to authorize it. This allows an application's visibility // policy to be used to restrict authorized users. try { $client = id(new PhabricatorOAuthServerClientQuery()) ->setViewer($viewer) ->withPHIDs(array($client_phid)) ->executeOne(); } catch (PhabricatorPolicyException $ex) { $ex->setContext(self::CONTEXT_AUTHORIZE); throw $ex; } $server->setUser($viewer); $is_authorized = false; $authorization = null; $uri = null; $name = null; // one giant try / catch around all the exciting database stuff so we // can return a 'server_error' response if something goes wrong! try { if (!$client) { return $this->buildErrorResponse( 'invalid_request', pht('Invalid Client Application'), pht( 'Request parameter %s does not specify a valid client application.', phutil_tag('strong', array(), 'client_id'))); } if ($client->getIsDisabled()) { return $this->buildErrorResponse( 'invalid_request', pht('Application Disabled'), pht( 'The %s OAuth application has been disabled.', phutil_tag('strong', array(), 'client_id'))); } $name = $client->getName(); $server->setClient($client); if ($redirect_uri) { $client_uri = new PhutilURI($client->getRedirectURI()); $redirect_uri = new PhutilURI($redirect_uri); if (!($server->validateSecondaryRedirectURI($redirect_uri, $client_uri))) { return $this->buildErrorResponse( 'invalid_request', pht('Invalid Redirect URI'), pht( 'Request parameter %s specifies an invalid redirect URI. '. 'The redirect URI must be a fully-qualified domain with no '. 'fragments, and must have the same domain and at least '. 'the same query parameters as the redirect URI the client '. 'registered.', phutil_tag('strong', array(), 'redirect_uri'))); } $uri = $redirect_uri; } else { $uri = new PhutilURI($client->getRedirectURI()); } if (empty($response_type)) { return $this->buildErrorResponse( 'invalid_request', pht('Invalid Response Type'), pht( 'Required request parameter %s is missing.', phutil_tag('strong', array(), 'response_type'))); } if ($response_type != 'code') { return $this->buildErrorResponse( 'unsupported_response_type', pht('Unsupported Response Type'), pht( 'Request parameter %s specifies an unsupported response type. '. 'Valid response types are: %s.', phutil_tag('strong', array(), 'response_type'), implode(', ', array('code')))); } $requested_scope = $request->getStrList('scope'); $requested_scope = array_fuse($requested_scope); $scope = PhabricatorOAuthServerScope::filterScope($requested_scope); // NOTE: We're always requiring a confirmation dialog to redirect. // Partly this is a general defense against redirect attacks, and // partly this shakes off anchors in the URI (which are not shaken // by 302'ing). $auth_info = $server->userHasAuthorizedClient($scope); list($is_authorized, $authorization) = $auth_info; if ($request->isFormPost()) { if ($authorization) { $authorization->setScope($scope)->save(); } else { $authorization = $server->authorizeClient($scope); } $is_authorized = true; } } catch (Exception $e) { return $this->buildErrorResponse( 'server_error', pht('Server Error'), pht( 'The authorization server encountered an unexpected condition '. 'which prevented it from fulfilling the request.')); } // When we reach this part of the controller, we can be in two states: // // 1. The user has not authorized the application yet. We want to // give them an "Authorize this application?" dialog. // 2. The user has authorized the application. We want to give them // a "Confirm Login" dialog. if ($is_authorized) { // The second case is simpler, so handle it first. The user either // authorized the application previously, or has just authorized the // application. Show them a confirm dialog with a normal link back to // the application. This shakes anchors from the URI. $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); $auth_code = $server->generateAuthorizationCode($uri); unset($unguarded); $full_uri = $this->addQueryParams( $uri, array( 'code' => $auth_code->getCode(), 'scope' => $authorization->getScopeString(), 'state' => $state, )); if ($client->getIsTrusted()) { // NOTE: See T13099. We currently emit a "Content-Security-Policy" // which includes a narrow "form-action". At the time of writing, // Chrome applies "form-action" to redirects following form submission. // This can lead to a situation where a user enters the OAuth workflow // and is prompted for MFA. When they submit an MFA response, the form // can redirect here, and Chrome will block the "Location" redirect. // To avoid this, render an interstitial. We only actually need to do // this in Chrome (but do it everywhere for consistency) and only need // to do it if the request is a redirect after a form submission (but // we can't tell if it is or not). Javelin::initBehavior( 'redirect', array( 'uri' => (string)$full_uri, )); return $this->newDialog() ->setTitle(pht('Authenticate: %s', $name)) ->appendParagraph( pht( 'Authorization for "%s" confirmed, redirecting...', phutil_tag('strong', array(), $name))) ->addCancelButton((string)$full_uri, pht('Continue')); } // TODO: It would be nice to give the user more options here, like // reviewing permissions, canceling the authorization, or aborting // the workflow. $dialog = id(new AphrontDialogView()) ->setUser($viewer) ->setTitle(pht('Authenticate: %s', $name)) ->appendParagraph( pht( - 'This application ("%s") is authorized to use your Phabricator '. + 'This application ("%s") is authorized to use your %s '. 'credentials. Continue to complete the authentication workflow.', - phutil_tag('strong', array(), $name))) + phutil_tag('strong', array(), $name), + PlatformSymbols::getPlatformServerName())) ->addCancelButton((string)$full_uri, pht('Continue to Application')); return id(new AphrontDialogResponse())->setDialog($dialog); } // Here, we're confirming authorization for the application. if ($authorization) { $missing_scope = array_diff_key($scope, $authorization->getScope()); } else { $missing_scope = $scope; } $form = id(new AphrontFormView()) ->addHiddenInput('client_id', $client_phid) ->addHiddenInput('redirect_uri', $redirect_uri) ->addHiddenInput('response_type', $response_type) ->addHiddenInput('state', $state) ->addHiddenInput('scope', $request->getStr('scope')) ->setUser($viewer); $cancel_msg = pht('The user declined to authorize this application.'); $cancel_uri = $this->addQueryParams( $uri, array( 'error' => 'access_denied', 'error_description' => $cancel_msg, )); $dialog = $this->newDialog() ->setShortTitle(pht('Authorize Access')) ->setTitle(pht('Authorize "%s"?', $name)) ->setSubmitURI($request->getRequestURI()->getPath()) ->setWidth(AphrontDialogView::WIDTH_FORM) ->appendParagraph( pht( 'Do you want to authorize the external application "%s" to '. - 'access your Phabricator account data, including your primary '. + 'access your %s account data, including your primary '. 'email address?', - phutil_tag('strong', array(), $name))) + phutil_tag('strong', array(), $name), + PlatformSymbols::getPlatformServerName())) ->appendForm($form) ->addSubmitButton(pht('Authorize Access')) ->addCancelButton((string)$cancel_uri, pht('Do Not Authorize')); if ($missing_scope) { $dialog->appendParagraph( pht( 'This application has requested these additional permissions. '. 'Authorizing it will grant it the permissions it requests:')); foreach ($missing_scope as $scope_key => $ignored) { // TODO: Once we introduce more scopes, explain them here. } } $unknown_scope = array_diff_key($requested_scope, $scope); if ($unknown_scope) { $dialog->appendParagraph( pht( 'This application also requested additional unrecognized '. 'permissions. These permissions may have existed in an older '. - 'version of Phabricator, or may be from a future version of '. - 'Phabricator. They will not be granted.')); + 'version of the software, or may be from a future version of '. + 'the software. They will not be granted.')); $unknown_form = id(new AphrontFormView()) ->setViewer($viewer) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Unknown Scope')) ->setValue(implode(', ', array_keys($unknown_scope))) ->setDisabled(true)); $dialog->appendForm($unknown_form); } return $dialog; } private function buildErrorResponse($code, $title, $message) { $viewer = $this->getRequest()->getUser(); return $this->newDialog() ->setTitle(pht('OAuth: %s', $title)) ->appendParagraph($message) ->appendParagraph( pht('OAuth Error Code: %s', phutil_tag('tt', array(), $code))) ->addCancelButton('/', pht('Alas!')); } private function addQueryParams(PhutilURI $uri, array $params) { $full_uri = clone $uri; foreach ($params as $key => $value) { if (strlen($value)) { $full_uri->replaceQueryParam($key, $value); } } return $full_uri; } } diff --git a/src/applications/oauthserver/controller/client/PhabricatorOAuthClientDisableController.php b/src/applications/oauthserver/controller/client/PhabricatorOAuthClientDisableController.php index 2ea9955365..334ef1b0aa 100644 --- a/src/applications/oauthserver/controller/client/PhabricatorOAuthClientDisableController.php +++ b/src/applications/oauthserver/controller/client/PhabricatorOAuthClientDisableController.php @@ -1,67 +1,67 @@ getViewer(); $client = id(new PhabricatorOAuthServerClientQuery()) ->setViewer($viewer) ->withIDs(array($request->getURIData('id'))) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$client) { return new Aphront404Response(); } $done_uri = $client->getViewURI(); $is_disable = !$client->getIsDisabled(); if ($request->isFormPost()) { $xactions = array(); $xactions[] = id(new PhabricatorOAuthServerTransaction()) ->setTransactionType(PhabricatorOAuthServerTransaction::TYPE_DISABLED) ->setNewValue((int)$is_disable); $editor = id(new PhabricatorOAuthServerEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnNoEffect(true) ->setContinueOnMissingFields(true) ->applyTransactions($client, $xactions); return id(new AphrontRedirectResponse())->setURI($done_uri); } if ($is_disable) { $title = pht('Disable OAuth Application'); $body = pht( 'Really disable the %s OAuth application? Users will no longer be '. - 'able to authenticate against it, nor access Phabricator using '. + 'able to authenticate against it, nor access this server using '. 'tokens generated by this application.', phutil_tag('strong', array(), $client->getName())); $button = pht('Disable Application'); } else { $title = pht('Enable OAuth Application'); $body = pht( 'Really enable the %s OAuth application? Users will be able to '. 'authenticate against it, and existing tokens will become usable '. 'again.', phutil_tag('strong', array(), $client->getName())); $button = pht('Enable Application'); } return $this->newDialog() ->setTitle($title) ->appendParagraph($body) ->addCancelButton($done_uri) ->addSubmitButton($button); } } diff --git a/src/applications/oauthserver/panel/PhabricatorOAuthServerAuthorizationsSettingsPanel.php b/src/applications/oauthserver/panel/PhabricatorOAuthServerAuthorizationsSettingsPanel.php index 89a1cc0281..21fb891330 100644 --- a/src/applications/oauthserver/panel/PhabricatorOAuthServerAuthorizationsSettingsPanel.php +++ b/src/applications/oauthserver/panel/PhabricatorOAuthServerAuthorizationsSettingsPanel.php @@ -1,147 +1,147 @@ getUser(); // TODO: It would be nice to simply disable this panel, but we can't do // viewer-based checks for enabled panels right now. $app_class = 'PhabricatorOAuthServerApplication'; $installed = PhabricatorApplication::isClassInstalledForViewer( $app_class, $viewer); if (!$installed) { $dialog = id(new AphrontDialogView()) ->setUser($viewer) ->setTitle(pht('OAuth Not Available')) ->appendParagraph( pht('You do not have access to OAuth authorizations.')) ->addCancelButton('/settings/'); return id(new AphrontDialogResponse())->setDialog($dialog); } $authorizations = id(new PhabricatorOAuthClientAuthorizationQuery()) ->setViewer($viewer) ->withUserPHIDs(array($viewer->getPHID())) ->execute(); $authorizations = mpull($authorizations, null, 'getID'); $panel_uri = $this->getPanelURI(); $revoke = $request->getInt('revoke'); if ($revoke) { if (empty($authorizations[$revoke])) { return new Aphront404Response(); } if ($request->isFormPost()) { $authorizations[$revoke]->delete(); return id(new AphrontRedirectResponse())->setURI($panel_uri); } $dialog = id(new AphrontDialogView()) ->setUser($viewer) ->setTitle(pht('Revoke Authorization?')) ->appendParagraph( pht( - 'This application will no longer be able to access Phabricator '. + 'This application will no longer be able to access this server '. 'on your behalf.')) ->addSubmitButton(pht('Revoke Authorization')) ->addCancelButton($panel_uri); return id(new AphrontDialogResponse())->setDialog($dialog); } $highlight = $request->getInt('id'); $rows = array(); $rowc = array(); foreach ($authorizations as $authorization) { if ($highlight == $authorization->getID()) { $rowc[] = 'highlighted'; } else { $rowc[] = null; } $button = javelin_tag( 'a', array( 'href' => $this->getPanelURI('?revoke='.$authorization->getID()), 'class' => 'small button button-grey', 'sigil' => 'workflow', ), pht('Revoke')); $rows[] = array( phutil_tag( 'a', array( 'href' => $authorization->getClient()->getViewURI(), ), $authorization->getClient()->getName()), $authorization->getScopeString(), phabricator_datetime($authorization->getDateCreated(), $viewer), phabricator_datetime($authorization->getDateModified(), $viewer), $button, ); } $table = new AphrontTableView($rows); $table->setNoDataString( pht("You haven't authorized any OAuth applications.")); $table->setRowClasses($rowc); $table->setHeaders( array( pht('Application'), pht('Scope'), pht('Created'), pht('Updated'), null, )); $table->setColumnClasses( array( 'pri', 'wide', 'right', 'right', 'action', )); $header = id(new PHUIHeaderView()) ->setHeader(pht('OAuth Application Authorizations')); $panel = id(new PHUIObjectBoxView()) ->setHeader($header) ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) ->appendChild($table); return $panel; } } diff --git a/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php b/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php index 728c3f42a8..26889c0e7a 100644 --- a/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php +++ b/src/applications/owners/query/PhabricatorOwnersPackageSearchEngine.php @@ -1,178 +1,179 @@ setLabel(pht('Authority')) ->setKey('authorityPHIDs') ->setAliases(array('authority', 'authorities')) ->setConduitKey('owners') ->setDescription( pht('Search for packages with specific owners.')) ->setDatasource(new PhabricatorProjectOrUserDatasource()), id(new PhabricatorSearchTextField()) ->setLabel(pht('Name Contains')) ->setKey('name') ->setDescription(pht('Search for packages by name substrings.')), id(new PhabricatorSearchDatasourceField()) ->setLabel(pht('Repositories')) ->setKey('repositoryPHIDs') ->setConduitKey('repositories') ->setAliases(array('repository', 'repositories')) ->setDescription( pht('Search for packages by included repositories.')) ->setDatasource(new DiffusionRepositoryDatasource()), id(new PhabricatorSearchStringListField()) ->setLabel(pht('Paths')) ->setKey('paths') ->setAliases(array('path')) ->setDescription( pht('Search for packages affecting specific paths.')), id(new PhabricatorSearchCheckboxesField()) ->setKey('statuses') ->setLabel(pht('Status')) ->setDescription( pht('Search for active or archived packages.')) ->setOptions( id(new PhabricatorOwnersPackage()) ->getStatusNameMap()), ); } protected function buildQueryFromParameters(array $map) { $query = $this->newQuery(); if ($map['authorityPHIDs']) { $query->withAuthorityPHIDs($map['authorityPHIDs']); } if ($map['repositoryPHIDs']) { $query->withRepositoryPHIDs($map['repositoryPHIDs']); } if ($map['paths']) { $query->withPaths($map['paths']); } if ($map['statuses']) { $query->withStatuses($map['statuses']); } if (strlen($map['name'])) { $query->withNameNgrams($map['name']); } return $query; } protected function getURI($path) { return '/owners/'.$path; } protected function getBuiltinQueryNames() { $names = array(); if ($this->requireViewer()->isLoggedIn()) { $names['authority'] = pht('Owned'); } $names += array( 'active' => pht('Active Packages'), 'all' => pht('All Packages'), ); return $names; } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'all': return $query; case 'active': return $query->setParameter( 'statuses', array( PhabricatorOwnersPackage::STATUS_ACTIVE, )); case 'authority': return $query->setParameter( 'authorityPHIDs', array($this->requireViewer()->getPHID())); } return parent::buildSavedQueryFromBuiltin($query_key); } protected function renderResultList( array $packages, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($packages, 'PhabricatorOwnersPackage'); $viewer = $this->requireViewer(); $list = id(new PHUIObjectItemListView()) ->setUser($viewer); foreach ($packages as $package) { $id = $package->getID(); $item = id(new PHUIObjectItemView()) ->setObject($package) ->setObjectName($package->getMonogram()) ->setHeader($package->getName()) ->setHref($package->getURI()); if ($package->isArchived()) { $item->setDisabled(true); } $list->addItem($item); } $result = new PhabricatorApplicationSearchResultView(); $result->setObjectList($list); $result->setNoDataString(pht('No packages found.')); return $result; } protected function getNewUserBody() { $create_button = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Create a Package')) ->setHref('/owners/edit/') ->setColor(PHUIButtonView::GREEN); $icon = $this->getApplication()->getIcon(); $app_name = $this->getApplication()->getName(); $view = id(new PHUIBigInfoView()) ->setIcon($icon) ->setTitle(pht('Welcome to %s', $app_name)) ->setDescription( - pht('Group sections of a codebase into packages for re-use in other '. - 'areas of Phabricator, like Herald rules.')) + pht( + 'Group sections of a codebase into packages for re-use in other '. + 'applications, like Herald rules.')) ->addAction($create_button); return $view; } } diff --git a/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php b/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php index ac4cbec9bf..971094afc4 100644 --- a/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php +++ b/src/applications/passphrase/query/PassphraseCredentialSearchEngine.php @@ -1,134 +1,133 @@ setLabel(pht('Status')) ->setKey('isDestroyed') ->setOptions( pht('Show All'), pht('Show Only Destroyed Credentials'), pht('Show Only Active Credentials')), id(new PhabricatorSearchTextField()) ->setLabel(pht('Name Contains')) ->setKey('name'), ); } protected function buildQueryFromParameters(array $map) { $query = $this->newQuery(); if ($map['isDestroyed'] !== null) { $query->withIsDestroyed($map['isDestroyed']); } if (strlen($map['name'])) { $query->withNameContains($map['name']); } return $query; } protected function getURI($path) { return '/passphrase/'.$path; } protected function getBuiltinQueryNames() { return array( 'active' => pht('Active Credentials'), 'all' => pht('All Credentials'), ); } public function buildSavedQueryFromBuiltin($query_key) { $query = $this->newSavedQuery(); $query->setQueryKey($query_key); switch ($query_key) { case 'all': return $query; case 'active': return $query->setParameter('isDestroyed', false); } return parent::buildSavedQueryFromBuiltin($query_key); } protected function renderResultList( array $credentials, PhabricatorSavedQuery $query, array $handles) { assert_instances_of($credentials, 'PassphraseCredential'); $viewer = $this->requireViewer(); $list = new PHUIObjectItemListView(); $list->setUser($viewer); foreach ($credentials as $credential) { $item = id(new PHUIObjectItemView()) ->setObjectName('K'.$credential->getID()) ->setHeader($credential->getName()) ->setHref('/K'.$credential->getID()) ->setObject($credential); $item->addAttribute( pht('Login: %s', $credential->getUsername())); if ($credential->getIsDestroyed()) { $item->addIcon('fa-ban', pht('Destroyed')); $item->setDisabled(true); } $type = PassphraseCredentialType::getTypeByConstant( $credential->getCredentialType()); if ($type) { $item->addIcon('fa-wrench', $type->getCredentialTypeName()); } $list->addItem($item); } $result = new PhabricatorApplicationSearchResultView(); $result->setObjectList($list); $result->setNoDataString(pht('No credentials found.')); return $result; } protected function getNewUserBody() { $create_button = id(new PHUIButtonView()) ->setTag('a') ->setText(pht('Create a Credential')) ->setHref('/passphrase/create/') ->setColor(PHUIButtonView::GREEN); $icon = $this->getApplication()->getIcon(); $app_name = $this->getApplication()->getName(); $view = id(new PHUIBigInfoView()) ->setIcon($icon) ->setTitle(pht('Welcome to %s', $app_name)) ->setDescription( - pht('Credential management for re-use in other areas of Phabricator '. - 'or general storage of shared secrets.')) + pht('Credential management and general storage of shared secrets.')) ->addAction($create_button); return $view; } } diff --git a/src/applications/people/controller/PhabricatorPeopleCreateController.php b/src/applications/people/controller/PhabricatorPeopleCreateController.php index c0b232645b..320ed57d3c 100644 --- a/src/applications/people/controller/PhabricatorPeopleCreateController.php +++ b/src/applications/people/controller/PhabricatorPeopleCreateController.php @@ -1,120 +1,120 @@ getUser(); id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession( $admin, $request, $this->getApplicationURI()); $v_type = 'standard'; if ($request->isFormPost()) { $v_type = $request->getStr('type'); if ($v_type == 'standard' || $v_type == 'bot' || $v_type == 'list') { return id(new AphrontRedirectResponse())->setURI( $this->getApplicationURI('new/'.$v_type.'/')); } } $title = pht('Create New User'); $standard_caption = pht( - 'Create a standard user account. These users can log in to Phabricator, '. + 'Create a standard user account. These users can log in, '. 'use the web interface and API, and receive email.'); $standard_admin = pht( 'Administrators are limited in their ability to access or edit these '. 'accounts after account creation.'); $bot_caption = pht( 'Create a bot/script user account, to automate interactions with other '. 'systems. These users can not use the web interface, but can use the '. 'API.'); $bot_admin = pht( 'Administrators have greater access to edit these accounts.'); $types = array(); $can_create = $this->hasApplicationCapability( PeopleCreateUsersCapability::CAPABILITY); if ($can_create) { $types[] = array( 'type' => 'standard', 'name' => pht('Create Standard User'), 'help' => pht('Create a standard user account.'), ); } $types[] = array( 'type' => 'bot', 'name' => pht('Create Bot User'), 'help' => pht('Create a new user for use with automated scripts.'), ); $types[] = array( 'type' => 'list', 'name' => pht('Create Mailing List User'), 'help' => pht( 'Create a mailing list user to represent an existing, external '. 'mailing list like a Google Group or a Mailman list.'), ); $buttons = id(new AphrontFormRadioButtonControl()) ->setLabel(pht('Account Type')) ->setName('type') ->setValue($v_type); foreach ($types as $type) { $buttons->addButton($type['type'], $type['name'], $type['help']); } $form = id(new AphrontFormView()) ->setUser($admin) ->appendRemarkupInstructions( pht( 'Choose the type of user account to create. For a detailed '. 'explanation of user account types, see [[ %s | User Guide: '. 'Account Roles ]].', PhabricatorEnv::getDoclink('User Guide: Account Roles'))) ->appendChild($buttons) ->appendChild( id(new AphrontFormSubmitControl()) ->addCancelButton($this->getApplicationURI()) ->setValue(pht('Continue'))); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title); $crumbs->setBorder(true); $box = id(new PHUIObjectBoxView()) ->setHeaderText($title) ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) ->setForm($form); $guidance_context = new PhabricatorPeopleCreateGuidanceContext(); $guidance = id(new PhabricatorGuidanceEngine()) ->setViewer($admin) ->setGuidanceContext($guidance_context) ->newInfoView(); $view = id(new PHUITwoColumnView()) ->setFooter( array( $guidance, $box, )); return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) ->appendChild($view); } } diff --git a/src/applications/people/controller/PhabricatorPeopleDisableController.php b/src/applications/people/controller/PhabricatorPeopleDisableController.php index 9f2718086b..6e3f436d6f 100644 --- a/src/applications/people/controller/PhabricatorPeopleDisableController.php +++ b/src/applications/people/controller/PhabricatorPeopleDisableController.php @@ -1,118 +1,118 @@ getViewer(); $id = $request->getURIData('id'); $via = $request->getURIData('via'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$user) { return new Aphront404Response(); } // NOTE: We reach this controller via the administrative "Disable User" // on profiles and also via the "X" action on the approval queue. We do // things slightly differently depending on the context the actor is in. // In particular, disabling via "Disapprove" requires you be an // administrator (and bypasses the "Can Disable Users" permission). // Disabling via "Disable" requires the permission only. $is_disapprove = ($via == 'disapprove'); if ($is_disapprove) { $done_uri = $this->getApplicationURI('query/approval/'); if (!$viewer->getIsAdmin()) { return $this->newDialog() ->setTitle(pht('No Permission')) ->appendParagraph(pht('Only administrators can disapprove users.')) ->addCancelButton($done_uri); } if ($user->getIsApproved()) { return $this->newDialog() ->setTitle(pht('Already Approved')) ->appendParagraph(pht('This user has already been approved.')) ->addCancelButton($done_uri); } // On the "Disapprove" flow, bypass the "Can Disable Users" permission. $actor = PhabricatorUser::getOmnipotentUser(); $should_disable = true; } else { $this->requireApplicationCapability( PeopleDisableUsersCapability::CAPABILITY); $actor = $viewer; $done_uri = $this->getApplicationURI("manage/{$id}/"); $should_disable = !$user->getIsDisabled(); } if ($viewer->getPHID() == $user->getPHID()) { return $this->newDialog() ->setTitle(pht('Something Stays Your Hand')) ->appendParagraph( pht( 'Try as you might, you find you can not disable your own account.')) ->addCancelButton($done_uri, pht('Curses!')); } if ($request->isFormPost()) { $xactions = array(); $xactions[] = id(new PhabricatorUserTransaction()) ->setTransactionType(PhabricatorUserDisableTransaction::TRANSACTIONTYPE) ->setNewValue($should_disable); id(new PhabricatorUserTransactionEditor()) ->setActor($actor) ->setActingAsPHID($viewer->getPHID()) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->setContinueOnNoEffect(true) ->applyTransactions($user, $xactions); return id(new AphrontRedirectResponse())->setURI($done_uri); } if ($should_disable) { $title = pht('Disable User?'); $short_title = pht('Disable User'); $body = pht( - 'Disable %s? They will no longer be able to access Phabricator or '. + 'Disable %s? They will no longer be able to access this server or '. 'receive email.', phutil_tag('strong', array(), $user->getUsername())); $submit = pht('Disable User'); } else { $title = pht('Enable User?'); $short_title = pht('Enable User'); $body = pht( - 'Enable %s? They will be able to access Phabricator and receive '. + 'Enable %s? They will be able to access this server and receive '. 'email again.', phutil_tag('strong', array(), $user->getUsername())); $submit = pht('Enable User'); } return $this->newDialog() ->setTitle($title) ->setShortTitle($short_title) ->appendParagraph($body) ->addCancelButton($done_uri) ->addSubmitButton($submit); } } diff --git a/src/applications/people/controller/PhabricatorPeopleEmpowerController.php b/src/applications/people/controller/PhabricatorPeopleEmpowerController.php index 22e7c22b68..b7af73ac02 100644 --- a/src/applications/people/controller/PhabricatorPeopleEmpowerController.php +++ b/src/applications/people/controller/PhabricatorPeopleEmpowerController.php @@ -1,70 +1,70 @@ getViewer(); $id = $request->getURIData('id'); $user = id(new PhabricatorPeopleQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->executeOne(); if (!$user) { return new Aphront404Response(); } $done_uri = $this->getApplicationURI("manage/{$id}/"); $validation_exception = null; if ($request->isFormOrHisecPost()) { $xactions = array(); $xactions[] = id(new PhabricatorUserTransaction()) ->setTransactionType( PhabricatorUserEmpowerTransaction::TRANSACTIONTYPE) ->setNewValue(!$user->getIsAdmin()); $editor = id(new PhabricatorUserTransactionEditor()) ->setActor($viewer) ->setContentSourceFromRequest($request) ->setContinueOnMissingFields(true) ->setCancelURI($done_uri); try { $editor->applyTransactions($user, $xactions); return id(new AphrontRedirectResponse())->setURI($done_uri); } catch (PhabricatorApplicationTransactionValidationException $ex) { $validation_exception = $ex; } } if ($user->getIsAdmin()) { $title = pht('Remove as Administrator?'); $short = pht('Remove Administrator'); $body = pht( 'Remove %s as an administrator? They will no longer be able to '. - 'perform administrative functions on this Phabricator install.', + 'perform administrative functions on this server.', phutil_tag('strong', array(), $user->getUsername())); $submit = pht('Remove Administrator'); } else { $title = pht('Make Administrator?'); $short = pht('Make Administrator'); $body = pht( 'Empower %s as an administrator? They will be able to create users, '. 'approve users, make and remove administrators, delete accounts, and '. - 'perform other administrative functions on this Phabricator install.', + 'perform other administrative functions on this server.', phutil_tag('strong', array(), $user->getUsername())); $submit = pht('Make Administrator'); } return $this->newDialog() ->setValidationException($validation_exception) ->setTitle($title) ->setShortTitle($short) ->appendParagraph($body) ->addCancelButton($done_uri) ->addSubmitButton($submit); } }