xref: /plugin/twofactor/admin.php (revision 3571ccfc1985141d01ac176ed8bf0c3a2c025a8a)
1<?php
2
3use dokuwiki\Form\Form;
4use dokuwiki\plugin\twofactor\Manager;
5use dokuwiki\plugin\twofactor\Settings;
6
7/**
8 *  Twofactor Manager
9 *
10 *  Allows to reset a user's twofactor data
11 */
12class admin_plugin_twofactor extends DokuWiki_Admin_Plugin
13{
14    /** @var array currently active filters */
15    protected $filter = [];
16    /** @var int index of first user to be displayed */
17    protected $start = 0;
18    /** @var int number of users to list on one page */
19    protected $pagesize = 20;
20    /** @var Manager */
21    protected $manager;
22
23    /**
24     * Constructor
25     */
26    public function __construct()
27    {
28        $this->manager = Manager::getInstance();
29        if (!$this->manager->isReady()) return;
30
31        global $INPUT;
32
33        $this->filter = $INPUT->arr('filter');
34        $this->start = $INPUT->int('start');
35    }
36
37    /** @inheritdoc */
38    public function handle()
39    {
40        global $INPUT;
41
42        if ($INPUT->has('reset') && checkSecurityToken()) {
43            $userdel = $INPUT->extract('reset')->str('reset');
44            if ($userdel == $INPUT->server->str('REMOTE_USER')) {
45                msg($this->lang['reset_not_self'], -1);
46                return;
47            }
48            foreach ($this->manager->getAllProviders() as $providerID => $provider) {
49                (new Settings($providerID, $userdel))->purge();
50            }
51            (new Settings('twofactor', $userdel))->purge();
52        }
53    }
54
55    /** @inheritdoc */
56    public function html()
57    {
58        echo $this->locale_xhtml('admin');
59        if (!$this->manager->isReady()) {
60            return true;
61        }
62
63        $users = $this->getUserData($this->filter);
64        $usercount = count($users);
65        $users = $this->applyPagination($users, $this->start, $this->pagesize);
66
67        $form = new Form(['method' => 'POST', 'class' => 'plugin_twofactor_admin']);
68        $form->setHiddenField('do', 'admin');
69        $form->setHiddenField('page', 'twofactor');
70        $form->setHiddenField('start', $this->start);
71
72        $form->addTagOpen('div')->addClass('table');
73        $form->addTagOpen('table')->addClass('inline');
74        $form = $this->addTableHead($form);
75
76        $form->addTagOpen('tbody');
77        foreach ($users as $user => $userinfo) {
78            $form = $this->addTableUser($form, $user, $userinfo);
79        }
80        $form->addTagClose('tbody');
81
82        $form->addTagOpen('tfooter');
83        $form = $this->addTablePagination($form, $usercount, $this->start, $this->pagesize);
84        $form->addTagClose('tfooter');
85
86        $form->addTagClose('table');
87        $form->addTagClose('div');
88
89        echo $form->toHTML();
90
91        return true;
92    }
93
94    /**
95     * Add the table headers to the table in the given form
96     * @param Form $form
97     * @return Form
98     */
99    protected function addTableHead(Form $form)
100    {
101        $form->addTagOpen('thead');
102
103        // header
104        $form->addTagOpen('tr');
105        $form->addTagOpen('th');
106        $form->addHTML($this->getLang('user_id'));
107        $form->addTagClose('th');
108        $form->addTagOpen('th');
109        $form->addHTML($this->getLang('user_name'));
110        $form->addTagClose('th');
111        $form->addTagOpen('th');
112        $form->addHTML($this->getLang('user_mail'));
113        $form->addTagClose('th');
114        $form->addTagOpen('th');
115        $form->addHTML($this->getLang('action'));
116        $form->addTagClose('th');
117        $form->addTagClose('tr');
118
119        // filter
120        $form->addTagOpen('tr');
121        $form->addTagOpen('th');
122        $form->addTextInput('filter[user]');
123        $form->addTagClose('th');
124        $form->addTagOpen('th');
125        $form->addTextInput('filter[name]');
126        $form->addTagClose('th');
127        $form->addTagOpen('th');
128        $form->addTextInput('filter[mail]');
129        $form->addTagClose('th');
130        $form->addTagOpen('th');
131        $form->addButton('', $this->getLang('search'))->attr('type', 'submit');
132        $form->addTagClose('th');
133        $form->addTagClose('tr');
134
135        $form->addTagClose('thead');
136        return $form;
137    }
138
139    /**
140     * Add
141     *
142     * @param Form $form
143     * @param $user
144     * @param $userinfo
145     * @return Form
146     */
147    protected function addTableUser(Form $form, $user, $userinfo)
148    {
149        $form->addTagOpen('tr');
150        $form->addTagOpen('td');
151        $form->addHTML(hsc($user));
152        $form->addTagClose('td');
153        $form->addTagOpen('td');
154        $form->addHTML(hsc($userinfo['name']));
155        $form->addTagClose('td');
156        $form->addTagOpen('td');
157        $form->addHTML(hsc($userinfo['mail']));
158        $form->addTagClose('td');
159        $form->addTagOpen('td');
160        $form->addButton('reset[' . $user . ']', $this->getLang('reset'))
161             ->attr('type', 'submit')
162             ->addClass('twofactor_resetconfirm');
163        $form->addTagClose('td');
164        $form->addTagClose('tr');
165        return $form;
166    }
167
168    /**
169     * Add the pagination buttons to the form
170     *
171     * @param Form $form
172     * @param int $usercount
173     * @param int $start
174     * @param int $pagesize
175     * @return Form
176     */
177    protected function addTablePagination(Form $form, $usercount, $start, $pagesize)
178    {
179        $form->addTagOpen('tr');
180        $form->addTagOpen('td')->attr('colspan', '4');
181        $form->addTagOpen('div')->addClass('pagination');
182
183        // start
184        $btn = $form->addButton('start', $this->getLang('start'))->val('0');
185        if ($start <= 0) $btn->attr('disabled', 'disabled');
186
187        // prev
188        $btn = $form->addButton('start', $this->getLang('prev'))->val($start - $pagesize);
189        if ($start - $pagesize < 0) $btn->attr('disabled', 'disabled');
190
191        // next
192        $btn = $form->addButton('start', $this->getLang('next'))->val($start + $pagesize);
193        if ($start + $pagesize >= $usercount) $btn->attr('disabled', 'disabled');
194
195        // last
196        $btn = $form->addButton('start', $this->getLang('last'))->val($usercount - $pagesize);
197        if ($usercount - $pagesize <= 0) $btn->attr('disabled', 'disabled');
198        if ($usercount - $pagesize == $start) $btn->attr('disabled', 'disabled');
199
200        $form->addTagClose('div');
201        $form->addTagClose('td');
202        $form->addTagClose('tr');
203
204        return $form;
205    }
206
207    /**
208     * Get the filtered users that have a twofactor provider set
209     *
210     * @param array $filter
211     * @return array
212     */
213    protected function getUserData($filter)
214    {
215        $users = Settings::findUsers('twofactor');
216        return $this->applyFilter($users, $filter);
217    }
218
219    /**
220     * Apply the given filters and return user details
221     *
222     * @param string[] $users simple list of user names
223     * @param array $filter
224     * @return array (user => userdata)
225     */
226    protected function applyFilter($users, $filter)
227    {
228        global $auth;
229        $filtered = [];
230
231        $hasFilter = (bool)array_filter(array_values($filter));
232        foreach ($users as $user) {
233            $userdata = $auth->getUserData($user);
234            if (!$userdata) continue;
235            $userdata['user'] = $user;
236            if ($hasFilter) {
237                foreach ($filter as $key => $value) {
238                    $q = preg_quote($value, '/');
239                    if ($value && preg_match("/$q/iu", $userdata[$key])) {
240                        $filtered[$user] = $userdata;
241                        continue 2;
242                    }
243                }
244            } else {
245                $filtered[$user] = $userdata;
246            }
247        }
248        return $filtered;
249    }
250
251    /**
252     * Get the current page of users
253     *
254     * @param array $users
255     * @param int $start
256     * @param int $pagesize
257     * @return array
258     */
259    protected function applyPagination($users, $start, $pagesize)
260    {
261        return array_slice($users, $start, $pagesize, true);
262    }
263
264}
265