PageRenderTime 1315ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Shell/AdminShell.php

https://gitlab.com/vortexadventures/void
PHP | 181 lines | 155 code | 21 blank | 5 comment | 20 complexity | b8016f880dded0490730e1529e37a5f3 MD5 | raw file
  1. <?php
  2. namespace App\Shell;
  3. use App\Model\Entity\Player;
  4. use App\Utility\CheckConfig;
  5. use Cake\Controller\Component\AuthComponent;
  6. class AdminShell extends AppShell
  7. {
  8. public function checks()
  9. {
  10. $status = CheckConfig::installation();
  11. foreach($status as $msg => $ok) {
  12. if($ok) {
  13. $this->out($msg);
  14. continue;
  15. }
  16. $this->err($msg);
  17. }
  18. }
  19. public function auth($plin = null, $role = null)
  20. {
  21. if(isset($plin)) {
  22. return $this->authPlayer($plin, $role);
  23. }
  24. $this->loadModel('Players');
  25. $perms = $this->Players->find('list',
  26. [ 'valueField' => 'id'
  27. , 'groupField' => 'role'
  28. ])->toArray();
  29. foreach(array_reverse(Player::roleValues()) as $role) {
  30. $count = isset($perms[$role]) ? count($perms[$role]) : 0;
  31. $this->out(sprintf('<warning>%s</warning> (%d)', $role, $count));
  32. if($count == 0 || $count > 100) {
  33. continue;
  34. }
  35. foreach($perms[$role] as $plin) {
  36. $player = $this->Players->get($plin);
  37. $this->out(sprintf('<info>%4d</info> %s', $plin, $player->fullName));
  38. }
  39. }
  40. }
  41. private function authPlayer($plin, $role)
  42. {
  43. $this->loadModel('Players');
  44. $player = $this->Players->findById($plin)->first();
  45. if(is_null($player) || strcmp($player->id, $plin)) {
  46. $this->abort(sprintf('No player found with plin `%s`.', $plin));
  47. }
  48. if(isset($role)) {
  49. $this->Players->patchEntity($player, ['role' => $role]);
  50. $this->Players->save($player);
  51. $errors = $player->getErrors('role');
  52. if(!empty($errors)) {
  53. foreach($errors as $error) {
  54. $this->err($error);
  55. }
  56. return 1;
  57. }
  58. }
  59. $this->out(sprintf('<warning>%s</warning> <info>%d</info> %s', $player->role, $player->id, $player->fullName));
  60. }
  61. public function password($plin)
  62. {
  63. $this->loadModel('Players');
  64. $player = $this->Players->findById($plin)->first();
  65. if(is_null($player) || strcmp($player->id, $plin)) {
  66. $this->abort(sprintf('No player found with plin `%s`.', $plin));
  67. }
  68. $new_password = false;
  69. if($this->params['remove']) {
  70. $new_password = NULL;
  71. $msg = 'Password removed';
  72. } else {
  73. $new_password = $this->prompt_silent();
  74. $msg = 'Password set';
  75. if(empty($new_password)) {
  76. $new_password = false;
  77. }
  78. }
  79. if($new_password === false) {
  80. $msg = 'Password unchanged';
  81. } else {
  82. $player->password = $new_password;
  83. $this->Players->save($player);
  84. $errors = $player->getErrors('password');
  85. if(!empty($errors)) {
  86. foreach($errors as $error) {
  87. $this->err($error);
  88. }
  89. return 1;
  90. }
  91. }
  92. $this->out(sprintf('<info>%4d</info> %s: <warning>%s</warning>', $player->id, $player->fullName, $msg));
  93. }
  94. public function getOptionParser()
  95. {
  96. $parser = parent::getOptionParser();
  97. $parser->setDescription(['Admin operations'])
  98. ->addSubcommand('checks',
  99. [ 'help' => 'Run application configuration and setup checks.'
  100. ])
  101. ->addSubcommand('auth',
  102. [ 'help' => 'Show/modify user authorizations.'
  103. , 'parser' =>
  104. [ 'arguments' =>
  105. [ 'plin' =>
  106. [ 'help' => '<plin> of the player to view/modify.'
  107. , 'required' => false
  108. ]
  109. , 'role' =>
  110. [ 'help' => 'The new authorization role to assign to player <plin>.'
  111. , 'required' => false
  112. , 'choice' => Player::roleValues()
  113. ] ] ] ])
  114. ->addSubcommand('password',
  115. [ 'help' => 'Set/remove user password.'
  116. , 'parser' =>
  117. [ 'options' =>
  118. [ 'remove' =>
  119. [ 'help' => 'Remove password instead of setting it.'
  120. , 'required' => false
  121. , 'boolean' => true
  122. ] ]
  123. , 'arguments' =>
  124. [ 'plin' =>
  125. [ 'help' => '<plin> of the player to view/modify.'
  126. , 'required' => true
  127. ] ] ] ])
  128. ->removeOption('verbose');
  129. foreach($parser->subcommands() as $sub) {
  130. $sub = $sub->parser();
  131. if(!$sub) continue;
  132. $sub->removeOption('verbose');
  133. }
  134. return $parser;
  135. }
  136. /**
  137. * Interactively prompts for input without echoing to the terminal.
  138. * Requires a bash shell or Windows and won't work with
  139. * safe_mode settings (Uses `shell_exec`)
  140. */
  141. private function prompt_silent($prompt = "Enter Password:")
  142. {
  143. if (preg_match('/^win/i', PHP_OS)) {
  144. $vbscript = sys_get_temp_dir() . 'prompt_password.vbs';
  145. file_put_contents(
  146. $vbscript, 'wscript.echo(InputBox("'
  147. . addslashes($prompt)
  148. . '", "", "password here"))');
  149. $command = "cscript //nologo " . escapeshellarg($vbscript);
  150. $password = rtrim(shell_exec($command));
  151. unlink($vbscript);
  152. return $password;
  153. } else {
  154. $this->out('<question>'.$prompt.'</question>');
  155. $command = "/usr/bin/env bash -c 'read -s -p \"\" mypassword && echo \$mypassword'";
  156. $password = rtrim(shell_exec($command));
  157. return $password;
  158. }
  159. }
  160. }