diff --git a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php index 3a40d253c9..99b6711ae6 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialRevealController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialRevealController.php @@ -1,107 +1,104 @@ getViewer(); $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->needSecrets(true) ->executeOne(); if (!$credential) { return new Aphront404Response(); } - $view_uri = '/K'.$credential->getID(); + $view_uri = $credential->getURI(); - $token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession( - $viewer, - $request, - $view_uri); $is_locked = $credential->getIsLocked(); if ($is_locked) { return $this->newDialog() ->setUser($viewer) ->setTitle(pht('Credential is locked')) ->appendChild( pht( 'This credential can not be shown, because it is locked.')) ->addCancelButton($view_uri); } - if ($request->isFormPost()) { + if ($request->isFormOrHisecPost()) { $secret = $credential->getSecret(); if (!$secret) { $body = pht('This credential has no associated secret.'); } else if (!strlen($secret->openEnvelope())) { $body = pht('This credential has an empty secret.'); } else { $body = id(new PHUIFormLayoutView()) ->appendChild( id(new AphrontFormTextAreaControl()) ->setLabel(pht('Plaintext')) ->setReadOnly(true) ->setCustomClass('PhabricatorMonospaced') ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) ->setValue($secret->openEnvelope())); } // NOTE: Disable workflow on the cancel button to reload the page so // the viewer can see that their view was logged. $dialog = id(new AphrontDialogView()) ->setUser($viewer) ->setWidth(AphrontDialogView::WIDTH_FORM) ->setTitle(pht('Credential Secret (%s)', $credential->getMonogram())) ->appendChild($body) ->setDisableWorkflowOnCancel(true) ->addCancelButton($view_uri, pht('Done')); $type_secret = PassphraseCredentialLookedAtTransaction::TRANSACTIONTYPE; $xactions = array( id(new PassphraseCredentialTransaction()) ->setTransactionType($type_secret) ->setNewValue(true), ); $editor = id(new PassphraseCredentialTransactionEditor()) ->setActor($viewer) + ->setCancelURI($view_uri) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request) ->applyTransactions($credential, $xactions); return id(new AphrontDialogResponse())->setDialog($dialog); } $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); if ($is_serious) { $body = pht( 'The secret associated with this credential will be shown in plain '. 'text on your screen.'); } else { $body = pht( 'The secret associated with this credential will be shown in plain '. 'text on your screen. Before continuing, wrap your arms around '. 'your monitor to create a human shield, keeping it safe from '. 'prying eyes. Protect company secrets!'); } return $this->newDialog() ->setUser($viewer) ->setTitle(pht('Really show secret?')) ->appendChild($body) ->addSubmitButton(pht('Show Secret')) ->addCancelButton($view_uri); } } diff --git a/src/applications/passphrase/storage/PassphraseCredential.php b/src/applications/passphrase/storage/PassphraseCredential.php index b10d392d36..c470ea661f 100644 --- a/src/applications/passphrase/storage/PassphraseCredential.php +++ b/src/applications/passphrase/storage/PassphraseCredential.php @@ -1,198 +1,202 @@ setViewer($actor) ->withClasses(array('PhabricatorPassphraseApplication')) ->executeOne(); $view_policy = $app->getPolicy(PassphraseDefaultViewCapability::CAPABILITY); $edit_policy = $app->getPolicy(PassphraseDefaultEditCapability::CAPABILITY); return id(new PassphraseCredential()) ->setName('') ->setUsername('') ->setDescription('') ->setIsDestroyed(0) ->setAuthorPHID($actor->getPHID()) ->setViewPolicy($view_policy) ->setEditPolicy($edit_policy) ->setSpacePHID($actor->getDefaultSpacePHID()); } public function getMonogram() { return 'K'.$this->getID(); } + public function getURI() { + return '/'.$this->getMonogram(); + } + protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( 'name' => 'text255', 'credentialType' => 'text64', 'providesType' => 'text64', 'description' => 'text', 'username' => 'text255', 'secretID' => 'id?', 'isDestroyed' => 'bool', 'isLocked' => 'bool', 'allowConduit' => 'bool', ), self::CONFIG_KEY_SCHEMA => array( 'key_secret' => array( 'columns' => array('secretID'), 'unique' => true, ), 'key_type' => array( 'columns' => array('credentialType'), ), 'key_provides' => array( 'columns' => array('providesType'), ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PassphraseCredentialPHIDType::TYPECONST); } public function attachSecret(PhutilOpaqueEnvelope $secret = null) { $this->secret = $secret; return $this; } public function getSecret() { return $this->assertAttached($this->secret); } public function getCredentialTypeImplementation() { $type = $this->getCredentialType(); return PassphraseCredentialType::getTypeByConstant($type); } public function attachImplementation(PassphraseCredentialType $impl) { $this->implementation = $impl; return $this; } public function getImplementation() { return $this->assertAttached($this->implementation); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new PassphraseCredentialTransactionEditor(); } public function getApplicationTransactionTemplate() { return new PassphraseCredentialTransaction(); } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } /* -( PhabricatorSubscribableInterface )----------------------------------- */ public function isAutomaticallySubscribed($phid) { return false; } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $this->openTransaction(); $secrets = id(new PassphraseSecret())->loadAllWhere( 'id = %d', $this->getSecretID()); foreach ($secrets as $secret) { $secret->delete(); } $this->delete(); $this->saveTransaction(); } /* -( PhabricatorSpacesInterface )----------------------------------------- */ public function getSpacePHID() { return $this->spacePHID; } /* -( PhabricatorFulltextInterface )--------------------------------------- */ public function newFulltextEngine() { return new PassphraseCredentialFulltextEngine(); } /* -( PhabricatorFerretInterface )----------------------------------------- */ public function newFerretEngine() { return new PassphraseCredentialFerretEngine(); } } diff --git a/src/applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php b/src/applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php index 3d8cb36f31..fc76ab0d56 100644 --- a/src/applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php +++ b/src/applications/passphrase/xaction/PassphraseCredentialLookedAtTransaction.php @@ -1,33 +1,39 @@ renderAuthor()); } public function getTitleForFeed() { return pht( '%s examined the secret plaintext for credential %s.', $this->renderAuthor(), $this->renderObject()); } public function getIcon() { return 'fa-eye'; } public function getColor() { return 'blue'; } + public function shouldTryMFA( + $object, + PhabricatorApplicationTransaction $xaction) { + return true; + } + }