diff --git a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php --- a/src/applications/auth/engine/PhabricatorAuthSessionEngine.php +++ b/src/applications/auth/engine/PhabricatorAuthSessionEngine.php @@ -490,8 +490,7 @@ PhabricatorAuthSession $session, $force = false) { - $until = $session->getHighSecurityUntil(); - if ($until > time() || $force) { + if ($session->isHighSecuritySession() || $force) { return new PhabricatorAuthHighSecurityToken(); } diff --git a/src/applications/auth/storage/PhabricatorAuthSession.php b/src/applications/auth/storage/PhabricatorAuthSession.php --- a/src/applications/auth/storage/PhabricatorAuthSession.php +++ b/src/applications/auth/storage/PhabricatorAuthSession.php @@ -74,6 +74,22 @@ } } + public function isHighSecuritySession() { + $until = $this->getHighSecurityUntil(); + + if (!$until) { + return false; + } + + $now = PhabricatorTime::getNow(); + if ($until < $now) { + return false; + } + + return true; + } + + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/people/storage/PhabricatorUser.php b/src/applications/people/storage/PhabricatorUser.php --- a/src/applications/people/storage/PhabricatorUser.php +++ b/src/applications/people/storage/PhabricatorUser.php @@ -306,6 +306,14 @@ return ($this->session !== self::ATTACHABLE); } + public function hasHighSecuritySession() { + if (!$this->hasSession()) { + return false; + } + + return $this->getSession()->isHighSecuritySession(); + } + private function generateConduitCertificate() { return Filesystem::readRandomCharacters(255); } diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php --- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php +++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php @@ -850,6 +850,10 @@ $xaction->setIsSilentTransaction(true); } + if ($actor->hasHighSecuritySession()) { + $xaction->setIsMFATransaction(true); + } + return $xaction; } diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -165,6 +165,14 @@ return (bool)$this->getMetadataValue('core.silent', false); } + public function setIsMFATransaction($mfa) { + return $this->setMetadataValue('core.mfa', $mfa); + } + + public function getIsMFATransaction() { + return (bool)$this->getMetadataValue('core.mfa', false); + } + public function attachComment( PhabricatorApplicationTransactionComment $comment) { $this->comment = $comment; @@ -1461,6 +1469,12 @@ if ($is_silent != $xaction->getIsSilentTransaction()) { return false; } + + // Don't group MFA and non-MFA transactions together. + $is_mfa = $this->getIsMFATransaction(); + if ($is_mfa != $xaction->getIsMFATransaction()) { + return false; + } } return true; diff --git a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php --- a/src/applications/transactions/view/PhabricatorApplicationTransactionView.php +++ b/src/applications/transactions/view/PhabricatorApplicationTransactionView.php @@ -424,7 +424,8 @@ ->setIcon($xaction->getIcon()) ->setColor($xaction->getColor()) ->setHideCommentOptions($this->getHideCommentOptions()) - ->setIsSilent($xaction->getIsSilentTransaction()); + ->setIsSilent($xaction->getIsSilentTransaction()) + ->setIsMFA($xaction->getIsMFATransaction()); list($token, $token_removed) = $xaction->getToken(); if ($token) { diff --git a/src/view/phui/PHUITimelineEventView.php b/src/view/phui/PHUITimelineEventView.php --- a/src/view/phui/PHUITimelineEventView.php +++ b/src/view/phui/PHUITimelineEventView.php @@ -30,6 +30,7 @@ private $badges = array(); private $pinboardItems = array(); private $isSilent; + private $isMFA; public function setAuthorPHID($author_phid) { $this->authorPHID = $author_phid; @@ -187,6 +188,15 @@ return $this->isSilent; } + public function setIsMFA($is_mfa) { + $this->isMFA = $is_mfa; + return $this; + } + + public function getIsMFA() { + return $this->isMFA; + } + public function setReallyMajorEvent($me) { $this->reallyMajorEvent = $me; return $this; @@ -590,6 +600,14 @@ ->setIcon('fa-bell-slash', 'red') ->setTooltip(pht('Silent Edit')); } + + // If this edit was applied while the actor was in high-security mode, + // provide a hint that it was extra authentic. + if ($this->getIsMFA()) { + $extra[] = id(new PHUIIconView()) + ->setIcon('fa-vcard', 'green') + ->setTooltip(pht('MFA Authenticated')); + } } $extra = javelin_tag(