ChangeUserStateCommand.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <?php
  2. /**
  3. * @package Grav\Plugin\Login
  4. *
  5. * @copyright Copyright (C) 2014 - 2017 RocketTheme, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Plugin\Console;
  9. use Grav\Common\Config\Config;
  10. use Grav\Common\Grav;
  11. use Grav\Console\ConsoleCommand;
  12. use Grav\Common\File\CompiledYamlFile;
  13. use Grav\Common\User\User;
  14. use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
  15. use Symfony\Component\Console\Input\InputOption;
  16. use Symfony\Component\Console\Helper\Helper;
  17. use Symfony\Component\Console\Question\ChoiceQuestion;
  18. use Symfony\Component\Console\Question\Question;
  19. /**
  20. * Class CleanCommand
  21. *
  22. * @package Grav\Console\Cli
  23. */
  24. class ChangeUserStateCommand extends ConsoleCommand
  25. {
  26. /**
  27. * @var array
  28. */
  29. protected $options = [];
  30. /**
  31. * Configure the command
  32. */
  33. protected function configure()
  34. {
  35. $this
  36. ->setName('toggle-user')
  37. ->setAliases(['disableuser', 'enableuser', 'toggleuser', 'change-user-state'])
  38. ->addOption(
  39. 'user',
  40. 'u',
  41. InputOption::VALUE_REQUIRED,
  42. 'The username'
  43. )
  44. ->addOption(
  45. 'state',
  46. 's',
  47. InputOption::VALUE_REQUIRED,
  48. 'The state of the account. Can be either `enabled` or `disabled`. [default: "enabled"]'
  49. )
  50. ->setDescription('Changes whether user can login or not')
  51. ->setHelp('The <info>toggle-user</info> sets a user\'s login status to enabled or disabled.')
  52. ;
  53. }
  54. /**
  55. * @return int|null|void
  56. */
  57. protected function serve()
  58. {
  59. $this->options = [
  60. 'user' => $this->input->getOption('user'),
  61. 'state' => $this->input->getOption('state')
  62. ];
  63. $this->validateOptions();
  64. $helper = $this->getHelper('question');
  65. $data = [];
  66. $this->output->writeln('<green>Setting User State</green>');
  67. $this->output->writeln('');
  68. if (!$this->options['user']) {
  69. // Get username and validate
  70. $question = new Question('Enter a <yellow>username</yellow>: ');
  71. $question->setValidator(function ($value) {
  72. return $this->validate('user', $value);
  73. });
  74. $username = $helper->ask($this->input, $this->output, $question);
  75. } else {
  76. $username = $this->options['user'];
  77. }
  78. if (!$this->options['state'] && !count(array_filter($this->options))) {
  79. // Choose State
  80. $question = new ChoiceQuestion(
  81. 'Please choose the <yellow>state</yellow> for the account:',
  82. array('enabled' => 'Enabled', 'disabled' => 'Disabled'),
  83. 'enabled'
  84. );
  85. $question->setErrorMessage('State %s is invalid.');
  86. $data['state'] = $helper->ask($this->input, $this->output, $question);
  87. } else {
  88. $data['state'] = $this->options['state'] ?: 'enabled';
  89. }
  90. // Lowercase the username for the filename
  91. $username = strtolower($username);
  92. /** @var UniformResourceLocator $locator */
  93. $locator = Grav::instance()['locator'];
  94. // Grab the account file and read in the information before setting the file (prevent setting erase)
  95. $oldUserFile = CompiledYamlFile::instance($locator->findResource('account://' . $username . YAML_EXT, true, true));
  96. $oldData = (array)$oldUserFile->content();
  97. //Set the state feild to new state
  98. $oldData['state'] = $data['state'];
  99. // Create user object and save it using oldData (with updated state)
  100. $user = new User($oldData);
  101. $file = CompiledYamlFile::instance($locator->findResource('account://' . $username . YAML_EXT, true, true));
  102. $user->file($file);
  103. $user->save();
  104. $this->output->writeln('');
  105. $this->output->writeln('<green>Success!</green> User <cyan>' . $username . '</cyan> state set to .' . $data['state']);
  106. }
  107. /**
  108. *
  109. */
  110. protected function validateOptions()
  111. {
  112. foreach (array_filter($this->options) as $type => $value) {
  113. $this->validate($type, $value);
  114. }
  115. }
  116. /**
  117. * @param $type
  118. * @param $value
  119. * @param string $extra
  120. *
  121. * @return mixed
  122. */
  123. protected function validate($type, $value, $extra = '')
  124. {
  125. /** @var Config $config */
  126. $config = Grav::instance()['config'];
  127. /** @var UniformResourceLocator $locator */
  128. $locator = Grav::instance()['locator'];
  129. $username_regex = '/' . $config->get('system.username_regex') . '/';
  130. switch ($type) {
  131. case 'user':
  132. if (!preg_match($username_regex, $value)) {
  133. throw new \RuntimeException('Username should be between 3 and 16 characters, including lowercase letters, numbers, underscores, and hyphens. Uppercase letters, spaces, and special characters are not allowed');
  134. }
  135. if (!file_exists($locator->findResource('account://' . $value . YAML_EXT))) {
  136. throw new \RuntimeException('Username "' . $value . '" does not exist, please pick another username');
  137. }
  138. break;
  139. case 'state':
  140. if ($value !== 'enabled' && $value !== 'disabled') {
  141. throw new \RuntimeException('State is not valid');
  142. }
  143. break;
  144. }
  145. return $value;
  146. }
  147. }