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