public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions) { $status_accepted = ArcanistDifferentialRevisionStatus::ACCEPTED; // Show the "BRANCH" section only if there's a new diff or the revision // is "Accepted". if (!$editor->getDiffUpdateTransaction($xactions) && $this->getObject()->getStatus() != $status_accepted) { return; } $branch = $this->getBranchDescription($this->getObject()->getActiveDiff()); if ($branch === null) { return; } $body->addTextSection(pht('BRANCH'), $branch); }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case AlmanacBindingTransaction::TYPE_INTERFACE: $missing = $this->validateIsEmptyTextField($object->getInterfacePHID(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Bindings must specify an interface.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } else { if ($xactions) { foreach ($xactions as $xaction) { $interfaces = id(new AlmanacInterfaceQuery())->setViewer($this->requireActor())->withPHIDs(array($xaction->getNewValue()))->execute(); if (!$interfaces) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('You can not bind a service to an invalid or restricted ' . 'interface.'), $xaction); $errors[] = $error; } } $final_value = last($xactions)->getNewValue(); $binding = id(new AlmanacBindingQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withServicePHIDs(array($object->getServicePHID()))->withInterfacePHIDs(array($final_value))->executeOne(); if ($binding && $binding->getID() != $object->getID()) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Already Bound'), pht('You can not bind a service to the same interface multiple ' . 'times.'), last($xactions)); $errors[] = $error; } } } break; } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhamePostTransaction::TYPE_TITLE: $missing = $this->validateIsEmptyTextField($object->getTitle(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Title is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; case PhamePostTransaction::TYPE_PHAME_TITLE: $missing = $this->validateIsEmptyTextField($object->getPhameTitle(), $xactions); $phame_title = last($xactions)->getNewValue(); if ($missing || $phame_title == '/') { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Phame title is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } $duplicate_post = id(new PhamePostQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPhameTitles(array($phame_title))->executeOne(); if ($duplicate_post && $duplicate_post->getID() != $object->getID()) { $error_text = pht('Phame title must be unique; another post already has this phame ' . 'title.'); $error = new PhabricatorApplicationTransactionValidationError($type, pht('Not Unique'), $error_text, nonempty(last($xactions), null)); $errors[] = $error; } break; } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhabricatorMetaMTAApplicationEmailTransaction::TYPE_ADDRESS: foreach ($xactions as $xaction) { $email = $xaction->getNewValue(); if (!strlen($email)) { // We'll deal with this below. continue; } if (!PhabricatorUserEmail::isValidAddress($email)) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('Email address is not formatted properly.')); } } $missing = $this->validateIsEmptyTextField($object->getAddress(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('You must provide an email address.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; } return $errors; }
public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; return $types; }
/** * We run Herald as part of transaction validation because Herald can * block diff creation for Differential diffs. Its important to do this * separately so no Herald logs are saved; these logs could expose * information the Herald rules are inteneded to block. */ protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); foreach ($xactions as $xaction) { switch ($type) { case DifferentialDiffTransaction::TYPE_DIFF_CREATE: $diff = clone $object; $diff = $this->updateDiffFromDict($diff, $xaction->getNewValue()); $adapter = $this->buildHeraldAdapter($diff, $xactions); $adapter->setContentSource($this->getContentSource()); $adapter->setIsNewObject($this->getIsNewObject()); $engine = new HeraldEngine(); $rules = $engine->loadRulesForAdapter($adapter); $rules = mpull($rules, null, 'getID'); $effects = $engine->applyRules($rules, $adapter); $blocking_effect = null; foreach ($effects as $effect) { if ($effect->getAction() == HeraldAdapter::ACTION_BLOCK) { $blocking_effect = $effect; break; } } if ($blocking_effect) { $rule = $blocking_effect->getRule(); $message = $effect->getTarget(); if (!strlen($message)) { $message = pht('(None.)'); } $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Rejected by Herald'), pht("Creation of this diff was rejected by Herald rule %s.\n" . " Rule: %s\n" . "Reason: %s", $rule->getMonogram(), $rule->getName(), $message)); } break; } } return $errors; }
public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = HeraldRuleTransaction::TYPE_DISABLE; return $types; }
protected function buildMailBody(PhabricatorLiskDAO $object, array $xactions) { $body = parent::buildMailBody($object, $xactions); $detail_uri = PhabricatorEnv::getProductionURI($object->getURI()); $body->addLinkSection(pht('PACKAGE DETAIL'), $detail_uri); return $body; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhortuneAccountTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField($object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Account name is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; case PhabricatorTransactions::TYPE_EDGE: foreach ($xactions as $xaction) { switch ($xaction->getMetadataValue('edge:type')) { case PhortuneAccountHasMemberEdgeType::EDGECONST: // TODO: This is a bit cumbersome, but validation happens before // transaction normalization. Maybe provide a cleaner attack on // this eventually? There's no way to generate "+" or "-" // transactions right now. $new = $xaction->getNewValue(); $set = idx($new, '=', array()); if (empty($set[$this->requireActor()->getPHID()])) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), pht('You can not remove yourself as an account member.'), $xaction); $errors[] = $error; } break; } } break; } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case PhabricatorOAuthServerTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField($object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('OAuth applications must have a name.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; case PhabricatorOAuthServerTransaction::TYPE_REDIRECT_URI: $missing = $this->validateIsEmptyTextField($object->getRedirectURI(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('OAuth applications must have a valid redirect URI.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } else { foreach ($xactions as $xaction) { $redirect_uri = $xaction->getNewValue(); try { $server = new PhabricatorOAuthServer(); $server->assertValidRedirectURI($redirect_uri); } catch (Exception $ex) { $errors[] = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $ex->getMessage(), $xaction); } } } break; } return $errors; }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case NuanceRequestorTransaction::TYPE_PROPERTY: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case FundBackerTransaction::TYPE_STATUS: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; $types[] = DrydockBlueprintTransaction::TYPE_NAME; return $types; }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorEditEngineConfigurationTransaction::TYPE_NAME: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case DrydockBlueprintTransaction::TYPE_NAME: case DrydockBlueprintTransaction::TYPE_DISABLED: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case HarbormasterBuildTransaction::TYPE_CREATE: case HarbormasterBuildTransaction::TYPE_COMMAND: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhluxTransaction::TYPE_EDIT_KEY: case PhluxTransaction::TYPE_EDIT_VALUE: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhabricatorProfilePanelConfigurationTransaction::TYPE_PROPERTY: case PhabricatorProfilePanelConfigurationTransaction::TYPE_ORDER: case PhabricatorProfilePanelConfigurationTransaction::TYPE_VISIBILITY: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case NuanceItemTransaction::TYPE_REQUESTOR: case NuanceItemTransaction::TYPE_SOURCE: case NuanceItemTransaction::TYPE_OWNER: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhortunePaymentProviderConfigTransaction::TYPE_CREATE: case PhortunePaymentProviderConfigTransaction::TYPE_PROPERTY: case PhortunePaymentProviderConfigTransaction::TYPE_ENABLE: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case PhortuneProductTransaction::TYPE_NAME: case PhortuneProductTransaction::TYPE_TYPE: case PhortuneProductTransaction::TYPE_PRICE: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case HarbormasterBuildStepTransaction::TYPE_CREATE: case HarbormasterBuildStepTransaction::TYPE_NAME: case HarbormasterBuildStepTransaction::TYPE_DEPENDS_ON: case HarbormasterBuildStepTransaction::TYPE_DESCRIPTION: return; } return parent::applyCustomExternalTransaction($object, $xaction); }
public function updateTransactionMailBody(PhabricatorMetaMTAMailBody $body, PhabricatorApplicationTransactionEditor $editor, array $xactions) { if ($editor->getIsNewObject()) { return; } if ($editor->getIsCloseByCommit()) { return; } $xaction = $editor->getDiffUpdateTransaction($xactions); if (!$xaction) { return; } $original = id(new DifferentialDiffQuery())->setViewer($this->getViewer())->withPHIDs(array($xaction->getOldValue()))->executeOne(); if (!$original) { return; } $revision = $this->getObject(); $current = $revision->getActiveDiff(); $old_id = $original->getID(); $new_id = $current->getID(); $uri = '/' . $revision->getMonogram() . '?vs=' . $old_id . '&id=' . $new_id; $uri = PhabricatorEnv::getProductionURI($uri); $body->addTextSection(pht('CHANGES SINCE LAST UPDATE'), $uri); }
protected function transactionHasEffect(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); $type = $xaction->getTransactionType(); switch ($type) { case PhabricatorConfigTransaction::TYPE_EDIT: // If an edit deletes an already-deleted entry, no-op it. if (idx($old, 'deleted') && idx($new, 'deleted')) { return false; } break; } return parent::transactionHasEffect($object, $xaction); }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case HarbormasterBuildPlanTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField($object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('You must choose a name for your build plan.'), last($xactions)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case FundInitiativeTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField($object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Initiative name is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } break; } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case DrydockBlueprintTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField($object->getBlueprintName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('You must choose a name for this blueprint.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; continue; } break; } return $errors; }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case AlmanacNamespaceTransaction::TYPE_NAME: $missing = $this->validateIsEmptyTextField($object->getName(), $xactions); if ($missing) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Required'), pht('Namespace name is required.'), nonempty(last($xactions), null)); $error->setIsMissingFieldError(true); $errors[] = $error; } else { foreach ($xactions as $xaction) { $name = $xaction->getNewValue(); $message = null; try { AlmanacNames::validateName($name); } catch (Exception $ex) { $message = $ex->getMessage(); } if ($message !== null) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $message, $xaction); $errors[] = $error; continue; } $other = id(new AlmanacNamespaceQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withNames(array($name))->executeOne(); if ($other && $other->getID() != $object->getID()) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Not Unique'), pht('The namespace name "%s" is already in use by another ' . 'namespace. Each namespace must have a unique name.', $name), $xaction); $errors[] = $error; continue; } if ($name === $object->getName()) { continue; } $namespace = AlmanacNamespace::loadRestrictedNamespace($this->getActor(), $name); if ($namespace) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Restricted'), pht('You do not have permission to create Almanac namespaces ' . 'within the "%s" namespace.', $namespace->getName()), $xaction); $errors[] = $error; continue; } } } break; } return $errors; }
protected function transactionHasEffect(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { $old = $xaction->getOldValue(); $new = $xaction->getNewValue(); switch ($xaction->getTransactionType()) { case PhabricatorSlowvoteTransaction::TYPE_RESPONSES: if ($old === null) { return true; } return (int) $old !== (int) $new; case PhabricatorSlowvoteTransaction::TYPE_SHUFFLE: if ($old === null) { return true; } return (bool) $old !== (bool) $new; } return parent::transactionHasEffect($object, $xaction); }
protected function validateTransaction(PhabricatorLiskDAO $object, $type, array $xactions) { $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { case AlmanacTransaction::TYPE_PROPERTY_UPDATE: foreach ($xactions as $xaction) { $property_key = $xaction->getMetadataValue('almanac.property'); $message = null; try { AlmanacNames::validateName($property_key); } catch (Exception $ex) { $message = $ex->getMessage(); } if ($message !== null) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $message, $xaction); $errors[] = $error; continue; } $new_value = $xaction->getNewValue(); try { phutil_json_encode($new_value); } catch (Exception $ex) { $message = pht('Almanac property values must be representable in JSON. %s', $ex->getMessage()); } if ($message !== null) { $error = new PhabricatorApplicationTransactionValidationError($type, pht('Invalid'), $message, $xaction); $errors[] = $error; continue; } } break; case AlmanacTransaction::TYPE_PROPERTY_REMOVE: // NOTE: No name validation on removals since it's OK to delete // an invalid property that somehow came into existence. break; } return $errors; }