Path: blob/master/src/applications/passphrase/view/PassphraseCredentialControl.php
12256 views
<?php12final class PassphraseCredentialControl extends AphrontFormControl {34private $options = array();5private $credentialType;6private $defaultUsername;7private $allowNull;89public function setAllowNull($allow_null) {10$this->allowNull = $allow_null;11return $this;12}1314public function setDefaultUsername($default_username) {15$this->defaultUsername = $default_username;16return $this;17}1819public function setCredentialType($credential_type) {20$this->credentialType = $credential_type;21return $this;22}2324public function getCredentialType() {25return $this->credentialType;26}2728public function setOptions(array $options) {29assert_instances_of($options, 'PassphraseCredential');30$this->options = $options;31return $this;32}3334protected function getCustomControlClass() {35return 'passphrase-credential-control';36}3738protected function renderInput() {3940$options_map = array();41foreach ($this->options as $option) {42$options_map[$option->getPHID()] = pht(43'%s %s',44$option->getMonogram(),45$option->getName());46}4748// The user editing the form may not have permission to see the current49// credential. Populate it into the menu to allow them to save the form50// without making any changes.51$current_phid = $this->getValue();52if ($current_phid !== null && strlen($current_phid)53&& empty($options_map[$current_phid])) {5455$viewer = $this->getViewer();5657$current_name = null;58try {59$user_credential = id(new PassphraseCredentialQuery())60->setViewer($viewer)61->withPHIDs(array($current_phid))62->executeOne();6364if ($user_credential) {65$current_name = pht(66'%s %s',67$user_credential->getMonogram(),68$user_credential->getName());69}70} catch (PhabricatorPolicyException $policy_exception) {71// Pull the credential with the omnipotent viewer so we can look up72// the ID and provide the monogram.73$omnipotent_credential = id(new PassphraseCredentialQuery())74->setViewer(PhabricatorUser::getOmnipotentUser())75->withPHIDs(array($current_phid))76->executeOne();77if ($omnipotent_credential) {78$current_name = pht(79'%s (Restricted Credential)',80$omnipotent_credential->getMonogram());81}82}8384if ($current_name === null) {85$current_name = pht(86'Invalid Credential ("%s")',87$current_phid);88}8990$options_map = array(91$current_phid => $current_name,92) + $options_map;93}949596$disabled = $this->getDisabled();97if ($this->allowNull) {98$options_map = array('' => pht('(No Credentials)')) + $options_map;99} else {100if (!$options_map) {101$options_map[''] = pht('(No Existing Credentials)');102$disabled = true;103}104}105106Javelin::initBehavior('passphrase-credential-control');107108$options = AphrontFormSelectControl::renderSelectTag(109$this->getValue(),110$options_map,111array(112'id' => $this->getControlID(),113'name' => $this->getName(),114'disabled' => $disabled ? 'disabled' : null,115'sigil' => 'passphrase-credential-select',116));117118if ($this->credentialType) {119$button = javelin_tag(120'a',121array(122'href' => '#',123'class' => 'button button-grey mll',124'sigil' => 'passphrase-credential-add',125'mustcapture' => true,126'style' => 'height: 20px;', // move aphront-form to tables127),128pht('Add New Credential'));129} else {130$button = null;131}132133return javelin_tag(134'div',135array(136'sigil' => 'passphrase-credential-control',137'meta' => array(138'type' => $this->getCredentialType(),139'username' => $this->defaultUsername,140'allowNull' => $this->allowNull,141),142),143array(144$options,145$button,146));147}148149/**150* Verify that a given actor has permission to use all of the credentials151* in a list of credential transactions.152*153* In general, the rule here is:154*155* - If you're editing an object and it uses a credential you can't use,156* that's fine as long as you don't change the credential.157* - If you do change the credential, the new credential must be one you158* can use.159*160* @param PhabricatorUser The acting user.161* @param list<PhabricatorApplicationTransaction> List of credential altering162* transactions.163* @return bool True if the transactions are valid.164*/165public static function validateTransactions(166PhabricatorUser $actor,167array $xactions) {168169$new_phids = array();170foreach ($xactions as $xaction) {171$new = $xaction->getNewValue();172if (!$new) {173// Removing a credential, so this is OK.174continue;175}176177$old = $xaction->getOldValue();178if ($old == $new) {179// This is a no-op transaction, so this is also OK.180continue;181}182183// Otherwise, we need to check this credential.184$new_phids[] = $new;185}186187if (!$new_phids) {188// No new credentials being set, so this is fine.189return true;190}191192$usable_credentials = id(new PassphraseCredentialQuery())193->setViewer($actor)194->withPHIDs($new_phids)195->execute();196$usable_credentials = mpull($usable_credentials, null, 'getPHID');197198foreach ($new_phids as $phid) {199if (empty($usable_credentials[$phid])) {200return false;201}202}203204return true;205}206207208}209210211