ChangePasswordCommand.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. /**
  3. * @package Grav\Plugin\Login
  4. *
  5. * @copyright Copyright (C) 2014 - 2021 RocketTheme, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Plugin\Console;
  9. use Grav\Common\User\Interfaces\UserCollectionInterface;
  10. use Grav\Console\ConsoleCommand;
  11. use Grav\Common\Grav;
  12. use Grav\Plugin\Login\Login;
  13. use Symfony\Component\Console\Input\InputOption;
  14. use Symfony\Component\Console\Helper\Helper;
  15. use Symfony\Component\Console\Question\Question;
  16. /**
  17. * Class CleanCommand
  18. *
  19. * @package Grav\Console\Cli
  20. */
  21. class ChangePasswordCommand extends ConsoleCommand
  22. {
  23. /** @var array */
  24. protected $options = [];
  25. /** @var Login */
  26. protected $login;
  27. /**
  28. * Configure the command
  29. */
  30. protected function configure()
  31. {
  32. $this
  33. ->setName('change-password')
  34. ->setAliases(['edit-password', 'newpass', 'changepass', 'passwd'])
  35. ->addOption(
  36. 'user',
  37. 'u',
  38. InputOption::VALUE_REQUIRED,
  39. 'The username'
  40. )
  41. ->addOption(
  42. 'password',
  43. 'p',
  44. InputOption::VALUE_REQUIRED,
  45. "The password. Note that this option is not recommended because the password will be visible by users listing the processes. You should also make sure the password respects Grav's password policy."
  46. )
  47. ->setDescription('Changes a User Password')
  48. ->setHelp('The <info>change-password</info> changes the password of the specified user. (User must exist)')
  49. ;
  50. }
  51. /**
  52. * @return int|null|void
  53. */
  54. protected function serve()
  55. {
  56. include __DIR__ . '/../vendor/autoload.php';
  57. $grav = Grav::instance();
  58. if (!isset($grav['login'])) {
  59. $grav['login'] = new Login($grav);
  60. }
  61. $this->login = $grav['login'];
  62. $this->options = [
  63. 'user' => $this->input->getOption('user'),
  64. 'password1' => $this->input->getOption('password')
  65. ];
  66. $this->validateOptions();
  67. $helper = $this->getHelper('question');
  68. $data = [];
  69. $this->output->writeln('<green>Changing User Password</green>');
  70. $this->output->writeln('');
  71. /** @var UserCollectionInterface $users */
  72. $users = $grav['accounts'];
  73. if (!$this->options['user']) {
  74. // Get username and validate
  75. $question = new Question('Enter a <yellow>username</yellow>: ');
  76. $question->setValidator(function ($value) use ($users) {
  77. $this->validate('user', $value);
  78. if (!$users->find($value, ['username'])->exists()) {
  79. throw new \RuntimeException('Username "' . $value . '" does not exist, please pick another username');
  80. };
  81. return $value;
  82. });
  83. $username = $helper->ask($this->input, $this->output, $question);
  84. } else {
  85. $username = $this->options['user'];
  86. }
  87. if (!$this->options['password1']) {
  88. // Get password and validate
  89. $password = $this->askForPassword($helper, 'Enter a <yellow>new password</yellow>: ', function ($password1) use ($helper) {
  90. $this->validate('password1', $password1);
  91. // Since input is hidden when prompting for passwords, the user is asked to repeat the password
  92. return $this->askForPassword($helper, 'Repeat the <yellow>password</yellow>: ', function ($password2) use ($password1) {
  93. return $this->validate('password2', $password2, $password1);
  94. });
  95. });
  96. $data['password'] = $password;
  97. } else {
  98. $data['password'] = $this->options['password1'];
  99. }
  100. $user = $users->load($username);
  101. if (!$user->exists()) {
  102. $this->output->writeln('<red>Failure</red> User <cyan>' . $username . '</cyan> does not exist!');
  103. exit();
  104. }
  105. //Set the password field to new password
  106. $user->set('password', $data['password']);
  107. $user->save();
  108. $this->invalidateCache();
  109. $this->output->writeln('');
  110. $this->output->writeln('<green>Success!</green> User <cyan>' . $username . '\'s</cyan> password changed.');
  111. }
  112. /**
  113. *
  114. */
  115. protected function validateOptions()
  116. {
  117. foreach (array_filter($this->options) as $type => $value) {
  118. $this->validate($type, $value);
  119. }
  120. }
  121. /**
  122. * @param string $type
  123. * @param mixed $value
  124. * @param string $extra
  125. *
  126. * @return string
  127. */
  128. protected function validate($type, $value, $extra = '')
  129. {
  130. return $this->login->validateField($type, $value, $extra);
  131. }
  132. /**
  133. * Get password and validate.
  134. *
  135. * @param Helper $helper
  136. * @param string $question
  137. * @param callable $validator
  138. *
  139. * @return string
  140. */
  141. protected function askForPassword(Helper $helper, $question, callable $validator)
  142. {
  143. $question = new Question($question);
  144. $question->setValidator($validator);
  145. $question->setHidden(true);
  146. $question->setHiddenFallback(true);
  147. return $helper->ask($this->input, $this->output, $question);
  148. }
  149. }