Changeset View
Changeset View
Standalone View
Standalone View
src/abuse/SecureSheldsUpAction.php
- This file was added.
<?php | |||||
final class SecureShieldsUpAction | |||||
extends HeraldAction { | |||||
const ACTIONCONST = 'secure.shields-up'; | |||||
const DO_SHIELD = 'do.secure.shields'; | |||||
public function getHeraldActionName() { | |||||
return pht('Activate Advanced Cyber Defenses'); | |||||
} | |||||
public function getActionGroupKey() { | |||||
return HeraldUtilityActionGroup::ACTIONGROUPKEY; | |||||
} | |||||
public function supportsObject($object) { | |||||
return ($object instanceof ManiphestTask); | |||||
} | |||||
public function supportsRuleType($rule_type) { | |||||
return ($rule_type == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL); | |||||
} | |||||
public function applyEffect($object, HeraldEffect $effect) { | |||||
// This is super janky but we don't currently get a reliable acting user. | |||||
$last_actor_row = queryfx_one( | |||||
$object->establishConnection('r'), | |||||
'SELECT authorPHID FROM %T WHERE objectPHID = %s ORDER BY id DESC | |||||
LIMIT 1', | |||||
id(new ManiphestTransaction())->getTableName(), | |||||
$object->getPHID()); | |||||
if (!$last_actor_row) { | |||||
return; | |||||
} | |||||
$actor = id(new PhabricatorPeopleQuery()) | |||||
->setViewer(PhabricatorUser::getOmnipotentUser()) | |||||
->withPHIDs(array($last_actor_row['authorPHID'])) | |||||
->executeOne(); | |||||
if (!$actor) { | |||||
return; | |||||
} | |||||
if ($this->isFriendlyUser($actor)) { | |||||
return; | |||||
} | |||||
if (!$this->isHostileObject($object)) { | |||||
return; | |||||
} | |||||
$this->quarantineUser($actor); | |||||
$this->quarantineObject($object); | |||||
$this->logEffect(self::DO_SHIELD); | |||||
} | |||||
public function getHeraldActionStandardType() { | |||||
return self::STANDARD_NONE; | |||||
} | |||||
public function renderActionDescription($value) { | |||||
return pht('Shields up.'); | |||||
} | |||||
protected function getActionEffectMap() { | |||||
return array( | |||||
self::DO_BLOCK => array( | |||||
'icon' => 'fa-umbrella', | |||||
'color' => 'indigo', | |||||
'name' => pht('Shields Up'), | |||||
), | |||||
); | |||||
} | |||||
protected function renderActionEffectDescription($type, $data) { | |||||
switch ($type) { | |||||
case self::DO_BLOCK: | |||||
return pht('Shields up.'); | |||||
} | |||||
} | |||||
private function isFriendlyUser(PhabricatorUser $user) { | |||||
if ($user->getIsAdmin()) { | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
private function isHostileObject($object) { | |||||
$content = array(); | |||||
if ($object instanceof ManiphestTask) { | |||||
$content[] = $object->getTitle(); | |||||
$content[] = $object->getDescription(); | |||||
} | |||||
$content = implode("\n\n", $content); | |||||
$patterns = array(); | |||||
// Phone numbers that we'll reject. | |||||
$numbers = array( | |||||
'18443133901', | |||||
); | |||||
foreach ($numbers as $number) { | |||||
$regex = array(); | |||||
for ($ii = 0; $ii < strlen($number); $ii++) { | |||||
$regex[] = $number[$ii]; | |||||
} | |||||
// Reject all variants of the number with other random punctuation or | |||||
// spaces betwee the digits. | |||||
$regex = implode('[^\\d]{0,6}', $regex); | |||||
$patterns[] = '/'.$regex.'/'; | |||||
} | |||||
foreach ($patterns as $pattern) { | |||||
if (preg_match($pattern, $content)) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
private function quarantineUser(PhabricatorUser $user) { | |||||
// For now, just log the user out of all their sessions so it's not a big | |||||
// deal if we hit a friendly user by accident. We could make this more | |||||
// extreme in the future. | |||||
$sessions = id(new PhabricatorAuthSessionQuery()) | |||||
->setViewer($user) | |||||
->withIdentityPHIDs(array($user->getPHID())) | |||||
->execute(); | |||||
foreach ($sessions as $session) { | |||||
$session->delete(); | |||||
} | |||||
} | |||||
private function quarantineObject($object) { | |||||
$title = $object->getTitle(); | |||||
$new_title = '<QUARANTINED> '.$title; | |||||
$object | |||||
->setTitle($new_title) | |||||
->setViewPolicy(PhabricatorPolicies::POLICY_ADMIN) | |||||
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN) | |||||
->save(); | |||||
} | |||||
} |