1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-25 08:12:40 +01:00

Replace "bin/people profileimage" with "bin/user enable|empower"

Summary:
Ref T13382.

  - Remove "bin/people profileimage" which previously generated profile image caches but now feels obsolete.
  - Replace it with "bin/user", with "enable" and "empower" flows. This command is now focused on regaining access to an install after you lock your keys inside.
  - Document the various ways to unlock objects and accounts from the CLI.

Test Plan:
  - Ran `bin/user enable` and `bin/user empower` with various flags.
  - Grepped for `people profileimage` and found no references.
  - Grepped for `bin/people` and found no references.
  - Read documentation.

Maniphest Tasks: T13382

Differential Revision: https://secure.phabricator.com/D20724
This commit is contained in:
epriestley 2019-08-20 13:50:03 -07:00
parent 721a86401f
commit fc34554892
9 changed files with 254 additions and 123 deletions

View file

@ -1 +0,0 @@
../scripts/people/manage_people.php

1
bin/user Symbolic link
View file

@ -0,0 +1 @@
../scripts/setup/manage_user.php

View file

@ -6,8 +6,8 @@ require_once $root.'/scripts/__init_script__.php';
$args = new PhutilArgumentParser($argv); $args = new PhutilArgumentParser($argv);
$args->setSynopsis(<<<EOSYNOPSIS $args->setSynopsis(<<<EOSYNOPSIS
**people** __command__ [__options__] **user** __command__ [__options__]
Manage user profiles and accounts. Modify user accounts to regain access to an install.
EOSYNOPSIS EOSYNOPSIS
); );

View file

@ -4051,6 +4051,8 @@ phutil_register_library_map(array(
'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php', 'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php',
'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php', 'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php',
'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php', 'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php',
'PhabricatorPeopleManagementEmpowerWorkflow' => 'applications/people/management/PhabricatorPeopleManagementEmpowerWorkflow.php',
'PhabricatorPeopleManagementEnableWorkflow' => 'applications/people/management/PhabricatorPeopleManagementEnableWorkflow.php',
'PhabricatorPeopleManagementWorkflow' => 'applications/people/management/PhabricatorPeopleManagementWorkflow.php', 'PhabricatorPeopleManagementWorkflow' => 'applications/people/management/PhabricatorPeopleManagementWorkflow.php',
'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php', 'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php',
'PhabricatorPeopleNoOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php', 'PhabricatorPeopleNoOwnerDatasource' => 'applications/people/typeahead/PhabricatorPeopleNoOwnerDatasource.php',
@ -4060,7 +4062,6 @@ phutil_register_library_map(array(
'PhabricatorPeopleProfileCommitsController' => 'applications/people/controller/PhabricatorPeopleProfileCommitsController.php', 'PhabricatorPeopleProfileCommitsController' => 'applications/people/controller/PhabricatorPeopleProfileCommitsController.php',
'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php',
'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php', 'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php',
'PhabricatorPeopleProfileImageWorkflow' => 'applications/people/management/PhabricatorPeopleProfileImageWorkflow.php',
'PhabricatorPeopleProfileManageController' => 'applications/people/controller/PhabricatorPeopleProfileManageController.php', 'PhabricatorPeopleProfileManageController' => 'applications/people/controller/PhabricatorPeopleProfileManageController.php',
'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php', 'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php',
'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php', 'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php',
@ -10332,6 +10333,8 @@ phutil_register_library_map(array(
'PhabricatorPeopleMailEngine' => 'Phobject', 'PhabricatorPeopleMailEngine' => 'Phobject',
'PhabricatorPeopleMailEngineException' => 'Exception', 'PhabricatorPeopleMailEngineException' => 'Exception',
'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleManagementEmpowerWorkflow' => 'PhabricatorPeopleManagementWorkflow',
'PhabricatorPeopleManagementEnableWorkflow' => 'PhabricatorPeopleManagementWorkflow',
'PhabricatorPeopleManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorPeopleManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorPeopleNewController' => 'PhabricatorPeopleController', 'PhabricatorPeopleNewController' => 'PhabricatorPeopleController',
'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorPeopleNoOwnerDatasource' => 'PhabricatorTypeaheadDatasource',
@ -10341,7 +10344,6 @@ phutil_register_library_map(array(
'PhabricatorPeopleProfileCommitsController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileCommitsController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileImageWorkflow' => 'PhabricatorPeopleManagementWorkflow',
'PhabricatorPeopleProfileManageController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfileManageController' => 'PhabricatorPeopleProfileController',
'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine',
'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController', 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController',

View file

@ -0,0 +1,44 @@
<?php
final class PhabricatorPeopleManagementEmpowerWorkflow
extends PhabricatorPeopleManagementWorkflow {
protected function didConstruct() {
$arguments = array_merge(
$this->getUserSelectionArguments(),
array());
$this
->setName('empower')
->setExamples('**empower** --user __username__')
->setSynopsis(pht('Turn a user account into an administrator account.'))
->setArguments($arguments);
}
public function execute(PhutilArgumentParser $args) {
$user = $this->selectUser($args);
$display_name = $user->getUsername();
if ($user->getIsAdmin()) {
throw new PhutilArgumentUsageException(
pht(
'User account "%s" is already an administrator. You can only '.
'empower accounts that are not yet administrators.',
$display_name));
}
$xactions = array();
$xactions[] = $user->getApplicationTransactionTemplate()
->setTransactionType(PhabricatorUserEmpowerTransaction::TRANSACTIONTYPE)
->setNewValue(true);
$this->applyTransactions($user, $xactions);
$this->logOkay(
pht('DONE'),
pht('Empowered user account "%s".', $display_name));
return 0;
}
}

View file

@ -0,0 +1,44 @@
<?php
final class PhabricatorPeopleManagementEnableWorkflow
extends PhabricatorPeopleManagementWorkflow {
protected function didConstruct() {
$arguments = array_merge(
$this->getUserSelectionArguments(),
array());
$this
->setName('enable')
->setExamples('**enable** --user __username__')
->setSynopsis(pht('Enable a disabled user account.'))
->setArguments($arguments);
}
public function execute(PhutilArgumentParser $args) {
$user = $this->selectUser($args);
$display_name = $user->getUsername();
if (!$user->getIsDisabled()) {
throw new PhutilArgumentUsageException(
pht(
'User account "%s" is not disabled. You can only enable accounts '.
'that are disabled.',
$display_name));
}
$xactions = array();
$xactions[] = $user->getApplicationTransactionTemplate()
->setTransactionType(PhabricatorUserDisableTransaction::TRANSACTIONTYPE)
->setNewValue(false);
$this->applyTransactions($user, $xactions);
$this->logOkay(
pht('DONE'),
pht('Enabled user account "%s".', $display_name));
return 0;
}
}

View file

@ -3,45 +3,55 @@
abstract class PhabricatorPeopleManagementWorkflow abstract class PhabricatorPeopleManagementWorkflow
extends PhabricatorManagementWorkflow { extends PhabricatorManagementWorkflow {
protected function buildIterator(PhutilArgumentParser $args) { final protected function getUserSelectionArguments() {
$usernames = $args->getArg('users'); return array(
array(
'name' => 'user',
'param' => 'username',
'help' => pht('User account to act on.'),
),
);
}
if ($args->getArg('all')) { final protected function selectUser(PhutilArgumentParser $argv) {
if ($usernames) { $username = $argv->getArg('user');
if (!strlen($username)) {
throw new PhutilArgumentUsageException( throw new PhutilArgumentUsageException(
pht( pht(
'Specify either a list of users or `%s`, but not both.', 'Select a user account to act on with "--user <username>".'));
'--all'));
}
return new LiskMigrationIterator(new PhabricatorUser());
} }
if ($usernames) { $user = id(new PhabricatorPeopleQuery())
return $this->loadUsersWithUsernames($usernames);
}
return null;
}
protected function loadUsersWithUsernames(array $usernames) {
$users = array();
foreach($usernames as $username) {
$query = id(new PhabricatorPeopleQuery())
->setViewer($this->getViewer()) ->setViewer($this->getViewer())
->withUsernames(array($username)) ->withUsernames(array($username))
->executeOne(); ->executeOne();
if (!$user) {
if (!$query) {
throw new PhutilArgumentUsageException( throw new PhutilArgumentUsageException(
pht( pht(
'"%s" is not a valid username.', 'No user with username "%s" exists.',
$username)); $username));
} }
$users[] = $query;
return $user;
} }
return $users; final protected function applyTransactions(
PhabricatorUser $user,
array $xactions) {
assert_instances_of($xactions, 'PhabricatorUserTransaction');
$viewer = $this->getViewer();
$application = id(new PhabricatorPeopleApplication())->getPHID();
$content_source = $this->newContentSource();
$editor = $user->getApplicationTransactionEditor()
->setActor($viewer)
->setActingAsPHID($application)
->setContentSource($content_source)
->setContinueOnMissingFields(true);
return $editor->applyTransactions($user, $xactions);
} }
} }

View file

@ -1,85 +0,0 @@
<?php
final class PhabricatorPeopleProfileImageWorkflow
extends PhabricatorPeopleManagementWorkflow {
protected function didConstruct() {
$this
->setName('profileimage')
->setExamples('**profileimage** --users __username__')
->setSynopsis(pht('Generate default profile images.'))
->setArguments(
array(
array(
'name' => 'all',
'help' => pht(
'Generate default profile images for all users.'),
),
array(
'name' => 'force',
'short' => 'f',
'help' => pht(
'Force a default profile image to be replaced.'),
),
array(
'name' => 'users',
'wildcard' => true,
),
));
}
public function execute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole();
$is_force = $args->getArg('force');
$is_all = $args->getArg('all');
$gd = function_exists('imagecreatefromstring');
if (!$gd) {
throw new PhutilArgumentUsageException(
pht(
'GD is not installed for php-cli. Aborting.'));
}
$iterator = $this->buildIterator($args);
if (!$iterator) {
throw new PhutilArgumentUsageException(
pht(
'Either specify a list of users to update, or use `%s` '.
'to update all users.',
'--all'));
}
$version = PhabricatorFilesComposeAvatarBuiltinFile::VERSION;
$generator = new PhabricatorFilesComposeAvatarBuiltinFile();
foreach ($iterator as $user) {
$username = $user->getUsername();
$default_phid = $user->getDefaultProfileImagePHID();
$gen_version = $user->getDefaultProfileImageVersion();
$generate = false;
if ($gen_version != $version) {
$generate = true;
}
if ($default_phid == null || $is_force || $generate) {
$console->writeOut(
"%s\n",
pht(
'Generating profile image for "%s".',
$username));
$generator->updateUser($user);
} else {
$console->writeOut(
"%s\n",
pht(
'Default profile image "%s" already set for "%s".',
$version,
$username));
}
}
}
}

View file

@ -0,0 +1,116 @@
@title User Guide: Unlocking Objects
@group userguide
Explains how to access locked or invisible objects and accounts.
Overview
========
Phabricator tries to make it difficult for users to lock themselves out of
things, but you can occasionally end up in situations where no one has access
to an object that you need access to.
For example, sometimes the only user who had edit permission for something has
left the organization, or you configured a "Phase of the Moon" policy rule and
the stars aren't currently aligned.
You can use various CLI tools to unlock objects and accounts if you need to
regain access.
Unlocking Accounts
==================
If you need to regain access to an object, the easiest approach is usually to
recover access to the account which owns it, then change the object policies
to be more open using the web UI.
For example, if an important task was accidentally locked so that only a user
who is currently on vacation can edit it, you can log in as that user and
change the edit policy to something more permissive.
To regain access to an account:
```
$ ./bin/auth recover <username>
```
If the account you're recovering access to has MFA or other session prompts,
use the `--force-full-session` to bypass them:
```
$ ./bin/auth recover <username> --force-full-session
```
In either case, the command will give you a link you a one-time link you can
use to access the account from the web UI. From there, you can open up objects
or change settings.
Unlocking MFA
=============
You can completely strip MFA from a user account with:
```
$ ./bin/auth strip --user <username> ...
```
For detailed help on managing and stripping MFA, see the instructions in
@{article:User Guide: Multi-Factor Authentication}
Unlocking Objects
=================
If you aren't sure who owns an object, or no user account has access to an
object, you can directly change object policies from the CLI:
```
$ ./bin/policy unlock <object> [--view ...] [--edit ...] [--owner ...]
```
To identify the object you want to unlock, you can specify an object name (like
`T123`) or a PHID as the `<object>` parameter.
Use the `--view` and `--edit` flags (and, for some objects, the `--owner`
flag) to specify new policies for the object.
For example, to make task `T123` editable by user `@alice`, run:
```
$ ./bin/policy unlock T123 --edit alice
```
Not every object has mutable view and edit policies, and not every object has
an owner, so each flag only works on some types of objects.
From here, you can log in to the web UI and change the relevant policies to
whatever you want to set them to.
No Enabled Users
================
If you accidentally disabled all administrator accounts, you can enable a
disabled account from the CLI like this:
```
$ ./bin/user enable --user <username>
```
From here, recover the account or log in normally.
No Administrators
=================
If you accidentally deleted all the administrator accounts, you can empower
a user as an administrator from the CLI like this:
```
$ ./bin/user empower --user <username>
```
This will upgrade the user account from a regular account to an administrator
account.