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