17faa86faSKarsten Kosmala<?php 27faa86faSKarsten Kosmala 38553d24dSAndreas Gohruse dokuwiki\Extension\CLIPlugin; 444c2bd91SAndreas Gohruse dokuwiki\Extension\AuthPlugin; 544c2bd91SAndreas Gohruse splitbrain\phpcli\Options; 67faa86faSKarsten Kosmalause splitbrain\phpcli\TableFormatter; 77faa86faSKarsten Kosmala 87faa86faSKarsten Kosmala/** 97faa86faSKarsten Kosmala * Class cli_plugin_usermanager 107faa86faSKarsten Kosmala * 117faa86faSKarsten Kosmala * Command Line component for the usermanager 127faa86faSKarsten Kosmala * 137faa86faSKarsten Kosmala * @license GPL2 147faa86faSKarsten Kosmala * @author Karsten Kosmala <karsten.kosmala@gmail.com> 157faa86faSKarsten Kosmala */ 168553d24dSAndreas Gohrclass cli_plugin_usermanager extends CLIPlugin 177faa86faSKarsten Kosmala{ 187faa86faSKarsten Kosmala 197faa86faSKarsten Kosmala /** @inheritdoc */ 2044c2bd91SAndreas Gohr protected function setup(Options $options) 217faa86faSKarsten Kosmala { 227faa86faSKarsten Kosmala // general setup 237faa86faSKarsten Kosmala $options->setHelp( 24ae26f74eSKarsten Kosmala "Manage users for this DokuWiki instance\n" 257faa86faSKarsten Kosmala ); 267faa86faSKarsten Kosmala 277faa86faSKarsten Kosmala // list 287faa86faSKarsten Kosmala $options->registerCommand('list', 'List users'); 297faa86faSKarsten Kosmala $options->registerOption('verbose', 'Show detailed user information', 'v', false, 'list'); 307faa86faSKarsten Kosmala 317faa86faSKarsten Kosmala // add 327faa86faSKarsten Kosmala $options->registerCommand('add', 'Add an user to auth backend'); 334fe4fe89SAndreas Gohr $options->registerArgument('login', 'Username', true, 'add'); 342bf5aa0cSKarsten Kosmala $options->registerArgument('mail', 'Email address', true, 'add'); 354fe4fe89SAndreas Gohr $options->registerArgument('name', 'Full name', false, 'add'); 363dc79ed8SAndreas Gohr $options->registerArgument('groups', 'Groups to be added, comma-seperated', false, 'add'); 373dc79ed8SAndreas Gohr $options->registerArgument('password', 'Password to set', false, 'add'); 382bf5aa0cSKarsten Kosmala $options->registerOption('notify', 'Notify user', 'n', false, 'add'); 397faa86faSKarsten Kosmala 407faa86faSKarsten Kosmala // delete 4144c2bd91SAndreas Gohr $options->registerCommand('delete', 'Deletes user(s) from auth backend'); 42ae26f74eSKarsten Kosmala $options->registerArgument('name', 'Username(s), comma-seperated', true, 'delete'); 43ae26f74eSKarsten Kosmala 44ae26f74eSKarsten Kosmala // add to group 45ae26f74eSKarsten Kosmala $options->registerCommand('addtogroup', 'Add user to group(s)'); 462bf5aa0cSKarsten Kosmala $options->registerArgument('name', 'Username', true, 'addtogroup'); 47ae26f74eSKarsten Kosmala $options->registerArgument('group', 'Group(s), comma-seperated', true, 'addtogroup'); 48ae26f74eSKarsten Kosmala 49ae26f74eSKarsten Kosmala // remove from group 50ae26f74eSKarsten Kosmala $options->registerCommand('removefromgroup', 'Remove user from group(s)'); 512bf5aa0cSKarsten Kosmala $options->registerArgument('name', 'Username', true, 'removefromgroup'); 5244c2bd91SAndreas Gohr $options->registerArgument('group', 'Group(s), comma-separated', true, 'removefromgroup'); 537faa86faSKarsten Kosmala } 547faa86faSKarsten Kosmala 557faa86faSKarsten Kosmala /** @inheritdoc */ 5644c2bd91SAndreas Gohr protected function main(Options $options) 577faa86faSKarsten Kosmala { 58*4c1ed9daSAndreas Gohr auth_setup(); 59*4c1ed9daSAndreas Gohr 60e56df874SAndreas Gohr /** @var AuthPlugin $auth */ 61e56df874SAndreas Gohr global $auth; 62e56df874SAndreas Gohr 636547cfc7SGerrit Uitslag if (!$auth instanceof AuthPlugin) { 64e56df874SAndreas Gohr $this->error($this->getLang('noauth')); 65e56df874SAndreas Gohr return 1; 66e56df874SAndreas Gohr } 67e56df874SAndreas Gohr 687faa86faSKarsten Kosmala switch ($options->getCmd()) { 697faa86faSKarsten Kosmala case 'list': 707faa86faSKarsten Kosmala $ret = $this->cmdList($options->getOpt('verbose')); 717faa86faSKarsten Kosmala break; 727faa86faSKarsten Kosmala case 'add': 737faa86faSKarsten Kosmala $ret = $this->cmdAdd($options->getOpt('notify'), $options->getArgs()); 747faa86faSKarsten Kosmala break; 757faa86faSKarsten Kosmala case 'delete': 767faa86faSKarsten Kosmala $ret = $this->cmdDelete($options->getArgs()); 777faa86faSKarsten Kosmala break; 78ae26f74eSKarsten Kosmala case 'addtogroup': 79ae26f74eSKarsten Kosmala $ret = $this->cmdAddToGroup($options->getArgs()); 80ae26f74eSKarsten Kosmala break; 81ae26f74eSKarsten Kosmala case 'removefromgroup': 82ae26f74eSKarsten Kosmala $ret = $this->cmdRemoveFromGroup($options->getArgs()); 83ae26f74eSKarsten Kosmala break; 847faa86faSKarsten Kosmala 857faa86faSKarsten Kosmala default: 867faa86faSKarsten Kosmala echo $options->help(); 877faa86faSKarsten Kosmala $ret = 0; 887faa86faSKarsten Kosmala } 897faa86faSKarsten Kosmala 907faa86faSKarsten Kosmala exit($ret); 917faa86faSKarsten Kosmala } 927faa86faSKarsten Kosmala 937faa86faSKarsten Kosmala /** 947faa86faSKarsten Kosmala * @param bool $showdetails 957faa86faSKarsten Kosmala * @return int 967faa86faSKarsten Kosmala */ 97ae26f74eSKarsten Kosmala protected function cmdList(bool $showdetails) 987faa86faSKarsten Kosmala { 9944c2bd91SAndreas Gohr /** @var AuthPlugin $auth */ 100ae26f74eSKarsten Kosmala global $auth; 1017faa86faSKarsten Kosmala 102e56df874SAndreas Gohr if (!$auth->canDo('getUsers')) { 103ae26f74eSKarsten Kosmala $this->error($this->getLang('nosupport')); 104ae26f74eSKarsten Kosmala return 1; 105ae26f74eSKarsten Kosmala } else { 106ae26f74eSKarsten Kosmala $this->listUsers($showdetails); 107ae26f74eSKarsten Kosmala } 1087faa86faSKarsten Kosmala 1097faa86faSKarsten Kosmala return 0; 1107faa86faSKarsten Kosmala } 1117faa86faSKarsten Kosmala 1127faa86faSKarsten Kosmala /** 1137faa86faSKarsten Kosmala * List the given users 1147faa86faSKarsten Kosmala * 1157faa86faSKarsten Kosmala * @param bool $details display details 1167faa86faSKarsten Kosmala */ 11744c2bd91SAndreas Gohr protected function listUsers(bool $details = false) 1187faa86faSKarsten Kosmala { 11944c2bd91SAndreas Gohr /** @var AuthPlugin $auth */ 120ae26f74eSKarsten Kosmala global $auth; 121ae26f74eSKarsten Kosmala $list = $auth->retrieveUsers(); 122ae26f74eSKarsten Kosmala 1237faa86faSKarsten Kosmala $tr = new TableFormatter($this->colors); 1247faa86faSKarsten Kosmala 1257faa86faSKarsten Kosmala foreach ($list as $username => $user) { 1267faa86faSKarsten Kosmala $content = [$username]; 1277faa86faSKarsten Kosmala if ($details) { 12854cc7aa4SAndreas Gohr $content[] = $user['name']; 12954cc7aa4SAndreas Gohr $content[] = $user['mail']; 13054cc7aa4SAndreas Gohr $content[] = implode(", ", $user['grps']); 1317faa86faSKarsten Kosmala } 1327faa86faSKarsten Kosmala echo $tr->format( 1337faa86faSKarsten Kosmala [15, 25, 25, 15], 1347faa86faSKarsten Kosmala $content 1357faa86faSKarsten Kosmala ); 1367faa86faSKarsten Kosmala } 1377faa86faSKarsten Kosmala } 1387faa86faSKarsten Kosmala 139ae26f74eSKarsten Kosmala /** 140ae26f74eSKarsten Kosmala * Adds an user 141ae26f74eSKarsten Kosmala * 142ae26f74eSKarsten Kosmala * @param bool $notify display details 143ae26f74eSKarsten Kosmala * @param array $args 144ae26f74eSKarsten Kosmala * @return int 145ae26f74eSKarsten Kosmala */ 1467faa86faSKarsten Kosmala protected function cmdAdd(bool $notify, array $args) 1477faa86faSKarsten Kosmala { 14844c2bd91SAndreas Gohr /** @var AuthPlugin $auth */ 149ae26f74eSKarsten Kosmala global $auth; 1507faa86faSKarsten Kosmala 151ae26f74eSKarsten Kosmala if (!$auth->canDo('addUser')) { 152ae26f74eSKarsten Kosmala $this->error($this->getLang('nosupport')); 153ae26f74eSKarsten Kosmala return 1; 154ae26f74eSKarsten Kosmala } 1557faa86faSKarsten Kosmala 15654cc7aa4SAndreas Gohr [$login, $mail, $name, $grps, $pass] = $args; 157ae26f74eSKarsten Kosmala $grps = array_filter(array_map('trim', explode(',', $grps))); 158ae26f74eSKarsten Kosmala 159ae26f74eSKarsten Kosmala if ($auth->canDo('modPass')) { 1607faa86faSKarsten Kosmala if (empty($pass)) { 1617faa86faSKarsten Kosmala if ($notify) { 1624fe4fe89SAndreas Gohr $pass = auth_pwgen($login); 1637faa86faSKarsten Kosmala } else { 164ae26f74eSKarsten Kosmala $this->error($this->getLang('add_fail')); 165ae26f74eSKarsten Kosmala $this->error($this->getLang('addUser_error_missing_pass')); 166ae26f74eSKarsten Kosmala return 1; 1677faa86faSKarsten Kosmala } 1687faa86faSKarsten Kosmala } 16954cc7aa4SAndreas Gohr } elseif (!empty($pass)) { 170ae26f74eSKarsten Kosmala $this->error($this->getLang('add_fail')); 171ae26f74eSKarsten Kosmala $this->error($this->getLang('addUser_error_modPass_disabled')); 172ae26f74eSKarsten Kosmala return 1; 1737faa86faSKarsten Kosmala } 1747faa86faSKarsten Kosmala 17554cc7aa4SAndreas Gohr if ($auth->triggerUserMod('create', [$login, $pass, $name, $mail, $grps])) { 1761a88e283SAndreas Gohr $this->success($this->getLang('add_ok')); 1771a88e283SAndreas Gohr } else { 17880fb44d9SAndreas Gohr $this->printErrorMessages(); 179ae26f74eSKarsten Kosmala $this->error($this->getLang('add_fail')); 180ae26f74eSKarsten Kosmala $this->error($this->getLang('addUser_error_create_event_failed')); 181ae26f74eSKarsten Kosmala return 1; 1827faa86faSKarsten Kosmala } 1837faa86faSKarsten Kosmala 1847faa86faSKarsten Kosmala return 0; 1857faa86faSKarsten Kosmala } 1867faa86faSKarsten Kosmala 187ae26f74eSKarsten Kosmala /** 188ae26f74eSKarsten Kosmala * Deletes users 189ae26f74eSKarsten Kosmala * @param array $args 190ae26f74eSKarsten Kosmala * @return int 191ae26f74eSKarsten Kosmala */ 1927faa86faSKarsten Kosmala protected function cmdDelete(array $args) 1937faa86faSKarsten Kosmala { 19444c2bd91SAndreas Gohr /** @var AuthPlugin $auth */ 195ae26f74eSKarsten Kosmala global $auth; 1967faa86faSKarsten Kosmala 197ae26f74eSKarsten Kosmala if (!$auth->canDo('delUser')) { 198ae26f74eSKarsten Kosmala $this->error($this->getLang('nosupport')); 199ae26f74eSKarsten Kosmala return 1; 200ae26f74eSKarsten Kosmala } 201ae26f74eSKarsten Kosmala 202ae26f74eSKarsten Kosmala $users = explode(',', $args[0]); 20354cc7aa4SAndreas Gohr $count = $auth->triggerUserMod('delete', [$users]); 2047faa86faSKarsten Kosmala 20554cc7aa4SAndreas Gohr if ($count != count($users)) { 20680fb44d9SAndreas Gohr $this->printErrorMessages(); 207ae26f74eSKarsten Kosmala $part1 = str_replace('%d', $count, $this->getLang('delete_ok')); 208ae26f74eSKarsten Kosmala $part2 = str_replace('%d', (count($users) - $count), $this->getLang('delete_fail')); 2097faa86faSKarsten Kosmala $this->error("$part1, $part2"); 210ae26f74eSKarsten Kosmala return 1; 211ae26f74eSKarsten Kosmala } 212ae26f74eSKarsten Kosmala 213ae26f74eSKarsten Kosmala return 0; 214ae26f74eSKarsten Kosmala } 215ae26f74eSKarsten Kosmala 216ae26f74eSKarsten Kosmala /** 217ae26f74eSKarsten Kosmala * Adds an user to group(s) 218ae26f74eSKarsten Kosmala * 219ae26f74eSKarsten Kosmala * @param array $args 220ae26f74eSKarsten Kosmala * @return int 221ae26f74eSKarsten Kosmala */ 222ae26f74eSKarsten Kosmala protected function cmdAddToGroup(array $args) 223ae26f74eSKarsten Kosmala { 22444c2bd91SAndreas Gohr /** @var AuthPlugin $auth */ 225ae26f74eSKarsten Kosmala global $auth; 226ae26f74eSKarsten Kosmala 22754cc7aa4SAndreas Gohr [$name, $newgrps] = $args; 228ae26f74eSKarsten Kosmala $newgrps = array_filter(array_map('trim', explode(',', $newgrps))); 229ae26f74eSKarsten Kosmala $oldinfo = $auth->getUserData($name); 23054cc7aa4SAndreas Gohr $changes = []; 231ae26f74eSKarsten Kosmala 23254cc7aa4SAndreas Gohr if ($newgrps !== [] && $auth->canDo('modGroups')) { 233ae26f74eSKarsten Kosmala $changes['grps'] = $oldinfo['grps']; 234ae26f74eSKarsten Kosmala foreach ($newgrps as $group) { 235ae26f74eSKarsten Kosmala if (!in_array($group, $oldinfo['grps'])) { 23654cc7aa4SAndreas Gohr $changes['grps'][] = $group; 237ae26f74eSKarsten Kosmala } 238ae26f74eSKarsten Kosmala } 239ae26f74eSKarsten Kosmala } 240ae26f74eSKarsten Kosmala 241ae26f74eSKarsten Kosmala if (!empty(array_diff($changes['grps'], $oldinfo['grps']))) { 24254cc7aa4SAndreas Gohr if ($auth->triggerUserMod('modify', [$name, $changes])) { 2431a88e283SAndreas Gohr $this->success($this->getLang('update_ok')); 244ae26f74eSKarsten Kosmala } else { 24580fb44d9SAndreas Gohr $this->printErrorMessages(); 246ae26f74eSKarsten Kosmala $this->error($this->getLang('update_fail')); 247ae26f74eSKarsten Kosmala return 1; 248ae26f74eSKarsten Kosmala } 249ae26f74eSKarsten Kosmala } 250ae26f74eSKarsten Kosmala 251ae26f74eSKarsten Kosmala return 0; 252ae26f74eSKarsten Kosmala } 253ae26f74eSKarsten Kosmala 254ae26f74eSKarsten Kosmala /** 255ae26f74eSKarsten Kosmala * Removes an user from group(s) 256ae26f74eSKarsten Kosmala * 257ae26f74eSKarsten Kosmala * @param array $args 258ae26f74eSKarsten Kosmala * @return int 259ae26f74eSKarsten Kosmala */ 260ae26f74eSKarsten Kosmala protected function cmdRemoveFromGroup(array $args) 261ae26f74eSKarsten Kosmala { 26244c2bd91SAndreas Gohr /** @var AuthPlugin $auth */ 263ae26f74eSKarsten Kosmala global $auth; 264ae26f74eSKarsten Kosmala 26554cc7aa4SAndreas Gohr [$name, $grps] = $args; 266ae26f74eSKarsten Kosmala $grps = array_filter(array_map('trim', explode(',', $grps))); 267ae26f74eSKarsten Kosmala $oldinfo = $auth->getUserData($name); 26854cc7aa4SAndreas Gohr $changes = []; 269ae26f74eSKarsten Kosmala 27054cc7aa4SAndreas Gohr if ($grps !== [] && $auth->canDo('modGroups')) { 271ae26f74eSKarsten Kosmala $changes['grps'] = $oldinfo['grps']; 272ae26f74eSKarsten Kosmala foreach ($grps as $group) { 273ae26f74eSKarsten Kosmala if (($pos = array_search($group, $changes['grps'])) == !false) { 274ae26f74eSKarsten Kosmala unset($changes['grps'][$pos]); 275ae26f74eSKarsten Kosmala } 276ae26f74eSKarsten Kosmala } 277ae26f74eSKarsten Kosmala } 278ae26f74eSKarsten Kosmala 279ae26f74eSKarsten Kosmala if (!empty(array_diff($oldinfo['grps'], $changes['grps']))) { 28054cc7aa4SAndreas Gohr if ($auth->triggerUserMod('modify', [$name, $changes])) { 2811a88e283SAndreas Gohr $this->success($this->getLang('update_ok')); 282ae26f74eSKarsten Kosmala } else { 28380fb44d9SAndreas Gohr $this->printErrorMessages(); 284ae26f74eSKarsten Kosmala $this->error($this->getLang('update_fail')); 285ae26f74eSKarsten Kosmala return 1; 286ae26f74eSKarsten Kosmala } 2877faa86faSKarsten Kosmala } 2887faa86faSKarsten Kosmala 2897faa86faSKarsten Kosmala return 0; 2907faa86faSKarsten Kosmala } 29180fb44d9SAndreas Gohr 29280fb44d9SAndreas Gohr /** 29380fb44d9SAndreas Gohr * Plugins triggered during user modification may cause failures and output messages via 29480fb44d9SAndreas Gohr * DokuWiki's msg() function 29580fb44d9SAndreas Gohr */ 2963dc79ed8SAndreas Gohr protected function printErrorMessages() 2973dc79ed8SAndreas Gohr { 29880fb44d9SAndreas Gohr global $MSG; 2993dc79ed8SAndreas Gohr if (isset($MSG)) { 3003dc79ed8SAndreas Gohr foreach ($MSG as $msg) { 30180fb44d9SAndreas Gohr if ($msg['lvl'] === 'error') $this->error($msg['msg']); 30280fb44d9SAndreas Gohr } 30380fb44d9SAndreas Gohr } 3047faa86faSKarsten Kosmala } 3053dc79ed8SAndreas Gohr} 306