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