diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1372,6 +1372,7 @@ 'PhabricatorAuthManagementStripWorkflow' => 'applications/auth/management/PhabricatorAuthManagementStripWorkflow.php', 'PhabricatorAuthManagementTrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementTrustOAuthClientWorkflow.php', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php', + 'PhabricatorAuthManagementVerifyWorkflow' => 'applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php', 'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php', 'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php', 'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php', @@ -3768,12 +3769,14 @@ 'DivinerLiveBook' => array( 'DivinerDAO', 'PhabricatorPolicyInterface', + 'PhabricatorDestructibleInterface', ), 'DivinerLivePublisher' => 'DivinerPublisher', 'DivinerLiveSymbol' => array( 'DivinerDAO', 'PhabricatorPolicyInterface', 'PhabricatorMarkupInterface', + 'PhabricatorDestructibleInterface', ), 'DivinerMainController' => 'DivinerController', 'DivinerPHPAtomizer' => 'DivinerAtomizer', @@ -4603,6 +4606,7 @@ 'PhabricatorAuthManagementStripWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementTrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', + 'PhabricatorAuthManagementVerifyWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController', diff --git a/src/applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php b/src/applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php new file mode 100644 --- /dev/null +++ b/src/applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php @@ -0,0 +1,68 @@ +setName('verify') + ->setExamples('**verify** __email__') + ->setSynopsis( + pht( + 'Verify an unverified email address which is already attached to '. + 'an account. This will also re-execute event hooks for addresses '. + 'which are already verified.')) + ->setArguments( + array( + array( + 'name' => 'email', + 'wildcard' => true, + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $emails = $args->getArg('email'); + if (!$emails) { + throw new PhutilArgumentUsageException( + pht('You must specify the email to verify.')); + } else if (count($emails) > 1) { + throw new PhutilArgumentUsageException( + pht('You can only verify one address at a time.')); + } + $address = head($emails); + + $email = id(new PhabricatorUserEmail())->loadOneWhere( + 'address = %s', + $address); + if (!$email) { + throw new PhutilArgumentUsageException( + pht( + 'No email exists with address "%s"!', + $address)); + } + + $viewer = $this->getViewer(); + + $user = id(new PhabricatorPeopleQuery()) + ->setViewer($viewer) + ->withPHIDs(array($email->getUserPHID())) + ->executeOne(); + if (!$user) { + throw new Exception(pht('Email record has invalid user PHID!')); + } + + $editor = id(new PhabricatorUserEditor()) + ->setActor($viewer) + ->verifyEmail($user, $email); + + $console = PhutilConsole::getConsole(); + + $console->writeOut( + "%s\n", + pht('Done.')); + + return 0; + } + +} diff --git a/src/applications/people/editor/PhabricatorUserEditor.php b/src/applications/people/editor/PhabricatorUserEditor.php --- a/src/applications/people/editor/PhabricatorUserEditor.php +++ b/src/applications/people/editor/PhabricatorUserEditor.php @@ -93,6 +93,10 @@ $user->saveTransaction(); + if ($email->getIsVerified()) { + $this->didVerifyEmail($user, $email); + } + return $this; } @@ -574,6 +578,8 @@ $user->endWriteLocking(); $user->saveTransaction(); + + $this->didVerifyEmail($user, $email); } @@ -674,4 +680,20 @@ )); } + private function didVerifyEmail( + PhabricatorUser $user, + PhabricatorUserEmail $email) { + + $event_type = PhabricatorEventType::TYPE_AUTH_DIDVERIFYEMAIL; + $event_data = array( + 'user' => $user, + 'email' => $email, + ); + + $event = id(new PhabricatorEvent($event_type, $event_data)) + ->setUser($user); + PhutilEventEngine::dispatchEvent($event); + } + + } diff --git a/src/infrastructure/events/constant/PhabricatorEventType.php b/src/infrastructure/events/constant/PhabricatorEventType.php --- a/src/infrastructure/events/constant/PhabricatorEventType.php +++ b/src/infrastructure/events/constant/PhabricatorEventType.php @@ -30,6 +30,7 @@ const TYPE_PEOPLE_DIDRENDERMENU = 'people.didRenderMenu'; const TYPE_AUTH_WILLREGISTERUSER = 'auth.willRegisterUser'; const TYPE_AUTH_WILLLOGINUSER = 'auth.willLoginUser'; + const TYPE_AUTH_DIDVERIFYEMAIL = 'auth.didVerifyEmail'; const TYPE_SEARCH_DIDUPDATEINDEX = 'search.didUpdateIndex';