Path: blob/master/src/applications/auth/management/PhabricatorAuthManagementRevokeWorkflow.php
12256 views
<?php12final class PhabricatorAuthManagementRevokeWorkflow3extends PhabricatorAuthManagementWorkflow {45protected function didConstruct() {6$this7->setName('revoke')8->setExamples(9"**revoke** --list\n".10"**revoke** --type __type__ --from __@user__\n".11"**revoke** --everything --everywhere")12->setSynopsis(13pht(14'Revoke credentials which may have been leaked or disclosed.'))15->setArguments(16array(17array(18'name' => 'from',19'param' => 'object',20'help' => pht(21'Revoke credentials for the specified object. To revoke '.22'credentials for a user, use "@username".'),23),24array(25'name' => 'type',26'param' => 'type',27'help' => pht('Revoke credentials of the given type.'),28),29array(30'name' => 'list',31'help' => pht(32'List information about available credential revokers.'),33),34array(35'name' => 'everything',36'help' => pht('Revoke all credentials types.'),37),38array(39'name' => 'everywhere',40'help' => pht('Revoke from all credential owners.'),41),42array(43'name' => 'force',44'help' => pht('Revoke credentials without prompting.'),45),46));47}4849public function execute(PhutilArgumentParser $args) {50$viewer = $this->getViewer();5152$all_types = PhabricatorAuthRevoker::getAllRevokers();53$is_force = $args->getArg('force');5455// The "--list" flag is compatible with revoker selection flags like56// "--type" to filter the list, but not compatible with target selection57// flags like "--from".58$is_list = $args->getArg('list');5960$type = $args->getArg('type');61$is_everything = $args->getArg('everything');62if ($type === null && !$is_everything) {63if ($is_list) {64// By default, "bin/revoke --list" implies "--everything".65$types = $all_types;66} else {67throw new PhutilArgumentUsageException(68pht(69'Specify the credential type to revoke with "--type" or specify '.70'"--everything". Use "--list" to list available credential '.71'types.'));72}73} else if (strlen($type) && $is_everything) {74throw new PhutilArgumentUsageException(75pht(76'Specify the credential type to revoke with "--type" or '.77'"--everything", but not both.'));78} else if ($is_everything) {79$types = $all_types;80} else {81if (empty($all_types[$type])) {82throw new PhutilArgumentUsageException(83pht(84'Credential type "%s" is not valid. Valid credential types '.85'are: %s.',86$type,87implode(', ', array_keys($all_types))));88}89$types = array($all_types[$type]);90}9192$is_everywhere = $args->getArg('everywhere');93$from = $args->getArg('from');9495if ($is_list) {96if ($from !== null || $is_everywhere) {97throw new PhutilArgumentUsageException(98pht(99'You can not "--list" and revoke credentials (with "--from" or '.100'"--everywhere") in the same operation.'));101}102}103104if ($is_list) {105$last_key = last_key($types);106foreach ($types as $key => $type) {107echo tsprintf(108"**%s** (%s)\n\n",109$type->getRevokerKey(),110$type->getRevokerName());111112id(new PhutilConsoleBlock())113->addParagraph(tsprintf('%B', $type->getRevokerDescription()))114->draw();115}116117return 0;118}119120$target = null;121if (!strlen($from) && !$is_everywhere) {122throw new PhutilArgumentUsageException(123pht(124'Specify the target to revoke credentials from with "--from" or '.125'specify "--everywhere".'));126} else if (strlen($from) && $is_everywhere) {127throw new PhutilArgumentUsageException(128pht(129'Specify the target to revoke credentials from with "--from" or '.130'specify "--everywhere", but not both.'));131} else if ($is_everywhere) {132// Just carry the flag through.133} else {134$target = id(new PhabricatorObjectQuery())135->setViewer($viewer)136->withNames(array($from))137->executeOne();138if (!$target) {139throw new PhutilArgumentUsageException(140pht(141'Target "%s" is not a valid target to revoke credentials from. '.142'Usually, revoke from "@username".',143$from));144}145}146147if ($is_everywhere && !$is_force) {148echo id(new PhutilConsoleBlock())149->addParagraph(150pht(151'You are destroying an entire class of credentials. This may be '.152'very disruptive to users. You should normally do this only if '.153'you suspect there has been a widespread compromise which may '.154'have impacted everyone.'))155->drawConsoleString();156157$prompt = pht('Really destroy credentials everywhere?');158if (!phutil_console_confirm($prompt)) {159throw new PhutilArgumentUsageException(160pht('Aborted workflow.'));161}162}163164foreach ($types as $type) {165$type->setViewer($viewer);166if ($is_everywhere) {167$count = $type->revokeAllCredentials();168} else {169$count = $type->revokeCredentialsFrom($target);170}171172echo tsprintf(173"%s\n",174pht(175'Destroyed %s credential(s) of type "%s".',176new PhutilNumber($count),177$type->getRevokerKey()));178179$guidance = $type->getRevokerNextSteps();180if ($guidance !== null) {181echo tsprintf(182"%s\n",183$guidance);184}185}186187echo tsprintf(188"%s\n",189pht('Done.'));190191return 0;192}193194}195196197