public static function loadAndApplyRules(HeraldAdapter $adapter) { $engine = new HeraldEngine(); $rules = $engine->loadRulesForAdapter($adapter); $effects = $engine->applyRules($rules, $adapter); $engine->applyEffects($effects, $adapter, $rules); return $engine->getTranscript(); }
public function saveDiff(DifferentialDiff $diff) { $actor = $this->requireActor(); // Generate a PHID first, so the transcript will point at the object if // we deicde to preserve it. $phid = $diff->generatePHID(); $diff->setPHID($phid); $adapter = id(new HeraldDifferentialDiffAdapter())->setDiff($diff); $adapter->setContentSource($this->getContentSource()); $adapter->setIsNewObject(true); $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 = idx($rules, $effect->getRuleID()); if ($rule && strlen($rule->getName())) { $rule_name = $rule->getName(); } else { $rule_name = pht('Unnamed Herald Rule'); } $message = $effect->getTarget(); if (!strlen($message)) { $message = pht('(None.)'); } throw new DifferentialDiffCreationRejectException(pht("Creation of this diff was rejected by Herald rule %s.\n" . " Rule: %s\n" . "Reason: %s", 'H' . $effect->getRuleID(), $rule_name, $message)); } $diff->save(); // NOTE: We only save the transcript if we didn't block the diff. // Otherwise, we might save some of the diff's content in the transcript // table, which would defeat the purpose of allowing rules to block // storage of key material. $engine->applyEffects($effects, $adapter, $rules); $xscript = $engine->getTranscript(); }
private function applyHeraldRules(array $updates, HeraldAdapter $adapter_template, array $all_updates) { if (!$updates) { return; } $adapter_template->setHookEngine($this); $engine = new HeraldEngine(); $rules = null; $blocking_effect = null; $blocked_update = null; $blocking_xscript = null; foreach ($updates as $update) { $adapter = id(clone $adapter_template)->setPushLog($update); if ($rules === null) { $rules = $engine->loadRulesForAdapter($adapter); } $effects = $engine->applyRules($rules, $adapter); $engine->applyEffects($effects, $adapter, $rules); $xscript = $engine->getTranscript(); // Store any PHIDs we want to send email to for later. foreach ($adapter->getEmailPHIDs() as $email_phid) { $this->emailPHIDs[$email_phid] = $email_phid; } $block_action = DiffusionBlockHeraldAction::ACTIONCONST; if ($blocking_effect === null) { foreach ($effects as $effect) { if ($effect->getAction() == $block_action) { $blocking_effect = $effect; $blocked_update = $update; $blocking_xscript = $xscript; break; } } } } if ($blocking_effect) { $rule = $blocking_effect->getRule(); $this->rejectCode = PhabricatorRepositoryPushLog::REJECT_HERALD; $this->rejectDetails = $rule->getPHID(); $message = $blocking_effect->getTarget(); if (!strlen($message)) { $message = pht('(None.)'); } $blocked_ref_name = coalesce($blocked_update->getRefName(), $blocked_update->getRefNewShort()); $blocked_name = $blocked_update->getRefType() . '/' . $blocked_ref_name; throw new DiffusionCommitHookRejectException(pht("This push was rejected by Herald push rule %s.\n" . " Change: %s\n" . " Rule: %s\n" . " Reason: %s\n" . "Transcript: %s", $rule->getMonogram(), $blocked_name, $rule->getName(), $message, PhabricatorEnv::getProductionURI('/herald/transcript/' . $blocking_xscript->getID() . '/'))); } }
/** * @task mail */ private function runHeraldMailRules(array $messages) { foreach ($messages as $message) { $engine = new HeraldEngine(); $adapter = id(new PhabricatorMailOutboundMailHeraldAdapter())->setObject($message); $rules = $engine->loadRulesForAdapter($adapter); $effects = $engine->applyRules($rules, $adapter); $engine->applyEffects($effects, $adapter, $rules); } }
/** * 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; }