cli.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <?php
  2. use dokuwiki\Extension\AuthPlugin;
  3. use splitbrain\phpcli\Options;
  4. use splitbrain\phpcli\TableFormatter;
  5. /**
  6. * Class cli_plugin_usermanager
  7. *
  8. * Command Line component for the usermanager
  9. *
  10. * @license GPL2
  11. * @author Karsten Kosmala <karsten.kosmala@gmail.com>
  12. */
  13. class cli_plugin_usermanager extends DokuWiki_CLI_Plugin
  14. {
  15. public function __construct()
  16. {
  17. parent::__construct();
  18. auth_setup();
  19. }
  20. /** @inheritdoc */
  21. protected function setup(Options $options)
  22. {
  23. // general setup
  24. $options->setHelp(
  25. "Manage users for this DokuWiki instance\n"
  26. );
  27. // list
  28. $options->registerCommand('list', 'List users');
  29. $options->registerOption('verbose', 'Show detailed user information', 'v', false, 'list');
  30. // add
  31. $options->registerCommand('add', 'Add an user to auth backend');
  32. $options->registerArgument('login', 'Username', true, 'add');
  33. $options->registerArgument('mail', 'Email address', true, 'add');
  34. $options->registerArgument('name', 'Full name', false, 'add');
  35. $options->registerArgument('groups', 'Groups to be added, comma-seperated', false, 'add');
  36. $options->registerArgument('password', 'Password to set', false, 'add');
  37. $options->registerOption('notify', 'Notify user', 'n', false, 'add');
  38. // delete
  39. $options->registerCommand('delete', 'Deletes user(s) from auth backend');
  40. $options->registerArgument('name', 'Username(s), comma-seperated', true, 'delete');
  41. // add to group
  42. $options->registerCommand('addtogroup', 'Add user to group(s)');
  43. $options->registerArgument('name', 'Username', true, 'addtogroup');
  44. $options->registerArgument('group', 'Group(s), comma-seperated', true, 'addtogroup');
  45. // remove from group
  46. $options->registerCommand('removefromgroup', 'Remove user from group(s)');
  47. $options->registerArgument('name', 'Username', true, 'removefromgroup');
  48. $options->registerArgument('group', 'Group(s), comma-separated', true, 'removefromgroup');
  49. }
  50. /** @inheritdoc */
  51. protected function main(Options $options)
  52. {
  53. /** @var AuthPlugin $auth */
  54. global $auth;
  55. if (!isset($auth)) {
  56. $this->error($this->getLang('noauth'));
  57. return 1;
  58. }
  59. switch ($options->getCmd()) {
  60. case 'list':
  61. $ret = $this->cmdList($options->getOpt('verbose'));
  62. break;
  63. case 'add':
  64. $ret = $this->cmdAdd($options->getOpt('notify'), $options->getArgs());
  65. break;
  66. case 'delete':
  67. $ret = $this->cmdDelete($options->getArgs());
  68. break;
  69. case 'addtogroup':
  70. $ret = $this->cmdAddToGroup($options->getArgs());
  71. break;
  72. case 'removefromgroup':
  73. $ret = $this->cmdRemoveFromGroup($options->getArgs());
  74. break;
  75. default:
  76. echo $options->help();
  77. $ret = 0;
  78. }
  79. exit($ret);
  80. }
  81. /**
  82. * @param bool $showdetails
  83. * @return int
  84. */
  85. protected function cmdList(bool $showdetails)
  86. {
  87. /** @var AuthPlugin $auth */
  88. global $auth;
  89. if (!$auth->canDo('getUsers')) {
  90. $this->error($this->getLang('nosupport'));
  91. return 1;
  92. } else {
  93. $this->listUsers($showdetails);
  94. }
  95. return 0;
  96. }
  97. /**
  98. * List the given users
  99. *
  100. * @param bool $details display details
  101. */
  102. protected function listUsers(bool $details = false)
  103. {
  104. /** @var AuthPlugin $auth */
  105. global $auth;
  106. $list = $auth->retrieveUsers();
  107. $tr = new TableFormatter($this->colors);
  108. foreach ($list as $username => $user) {
  109. $content = [$username];
  110. if ($details) {
  111. array_push($content, $user['name']);
  112. array_push($content, $user['mail']);
  113. array_push($content, implode(", ", $user['grps']));
  114. }
  115. echo $tr->format(
  116. [15, 25, 25, 15],
  117. $content
  118. );
  119. }
  120. }
  121. /**
  122. * Adds an user
  123. *
  124. * @param bool $notify display details
  125. * @param array $args
  126. * @return int
  127. */
  128. protected function cmdAdd(bool $notify, array $args)
  129. {
  130. /** @var AuthPlugin $auth */
  131. global $auth;
  132. if (!$auth->canDo('addUser')) {
  133. $this->error($this->getLang('nosupport'));
  134. return 1;
  135. }
  136. list($login, $mail, $name, $grps, $pass) = $args;
  137. $grps = array_filter(array_map('trim', explode(',', $grps)));
  138. if ($auth->canDo('modPass')) {
  139. if (empty($pass)) {
  140. if ($notify) {
  141. $pass = auth_pwgen($login);
  142. } else {
  143. $this->error($this->getLang('add_fail'));
  144. $this->error($this->getLang('addUser_error_missing_pass'));
  145. return 1;
  146. }
  147. }
  148. } else {
  149. if (!empty($pass)) {
  150. $this->error($this->getLang('add_fail'));
  151. $this->error($this->getLang('addUser_error_modPass_disabled'));
  152. return 1;
  153. }
  154. }
  155. if ($auth->triggerUserMod('create', array($login, $pass, $name, $mail, $grps))) {
  156. $this->success($this->getLang('add_ok'));
  157. } else {
  158. $this->printErrorMessages();
  159. $this->error($this->getLang('add_fail'));
  160. $this->error($this->getLang('addUser_error_create_event_failed'));
  161. return 1;
  162. }
  163. return 0;
  164. }
  165. /**
  166. * Deletes users
  167. * @param array $args
  168. * @return int
  169. */
  170. protected function cmdDelete(array $args)
  171. {
  172. /** @var AuthPlugin $auth */
  173. global $auth;
  174. if (!$auth->canDo('delUser')) {
  175. $this->error($this->getLang('nosupport'));
  176. return 1;
  177. }
  178. $users = explode(',', $args[0]);
  179. $count = $auth->triggerUserMod('delete', array($users));
  180. if (!($count == count($users))) {
  181. $this->printErrorMessages();
  182. $part1 = str_replace('%d', $count, $this->getLang('delete_ok'));
  183. $part2 = str_replace('%d', (count($users) - $count), $this->getLang('delete_fail'));
  184. $this->error("$part1, $part2");
  185. return 1;
  186. }
  187. return 0;
  188. }
  189. /**
  190. * Adds an user to group(s)
  191. *
  192. * @param array $args
  193. * @return int
  194. */
  195. protected function cmdAddToGroup(array $args)
  196. {
  197. /** @var AuthPlugin $auth */
  198. global $auth;
  199. list($name, $newgrps) = $args;
  200. $newgrps = array_filter(array_map('trim', explode(',', $newgrps)));
  201. $oldinfo = $auth->getUserData($name);
  202. $changes = array();
  203. if (!empty($newgrps) && $auth->canDo('modGroups')) {
  204. $changes['grps'] = $oldinfo['grps'];
  205. foreach ($newgrps as $group) {
  206. if (!in_array($group, $oldinfo['grps'])) {
  207. array_push($changes['grps'], $group);
  208. }
  209. }
  210. }
  211. if (!empty(array_diff($changes['grps'], $oldinfo['grps']))) {
  212. if ($auth->triggerUserMod('modify', array($name, $changes))) {
  213. $this->success($this->getLang('update_ok'));
  214. } else {
  215. $this->printErrorMessages();
  216. $this->error($this->getLang('update_fail'));
  217. return 1;
  218. }
  219. }
  220. return 0;
  221. }
  222. /**
  223. * Removes an user from group(s)
  224. *
  225. * @param array $args
  226. * @return int
  227. */
  228. protected function cmdRemoveFromGroup(array $args)
  229. {
  230. /** @var AuthPlugin $auth */
  231. global $auth;
  232. list($name, $grps) = $args;
  233. $grps = array_filter(array_map('trim', explode(',', $grps)));
  234. $oldinfo = $auth->getUserData($name);
  235. $changes = array();
  236. if (!empty($grps) && $auth->canDo('modGroups')) {
  237. $changes['grps'] = $oldinfo['grps'];
  238. foreach ($grps as $group) {
  239. if (($pos = array_search($group, $changes['grps'])) == !false) {
  240. unset($changes['grps'][$pos]);
  241. }
  242. }
  243. }
  244. if (!empty(array_diff($oldinfo['grps'], $changes['grps']))) {
  245. if ($auth->triggerUserMod('modify', array($name, $changes))) {
  246. $this->success($this->getLang('update_ok'));
  247. } else {
  248. $this->printErrorMessages();
  249. $this->error($this->getLang('update_fail'));
  250. return 1;
  251. }
  252. }
  253. return 0;
  254. }
  255. /**
  256. * Plugins triggered during user modification may cause failures and output messages via
  257. * DokuWiki's msg() function
  258. */
  259. protected function printErrorMessages()
  260. {
  261. global $MSG;
  262. if (isset($MSG)) {
  263. foreach ($MSG as $msg) {
  264. if ($msg['lvl'] === 'error') $this->error($msg['msg']);
  265. }
  266. }
  267. }
  268. }