xref: /plugin/twofactor/admin.php (revision 588e565967b906a9bb7f7b0b6269187a14ad7120)
1163ac707SMichael Wilmes<?php
2f62d0e33SAndreas Gohr
3f62d0e33SAndreas Gohruse dokuwiki\Form\Form;
4f62d0e33SAndreas Gohruse dokuwiki\plugin\twofactor\Manager;
56d69ca71SAndreas Gohruse dokuwiki\plugin\twofactor\Settings;
6f62d0e33SAndreas Gohr
7f62d0e33SAndreas Gohr/**
8163ac707SMichael Wilmes *  Twofactor Manager
9163ac707SMichael Wilmes *
10bbe22a6aSAndreas Gohr *  Allows to reset a user's twofactor data
11163ac707SMichael Wilmes */
12d0a31016SAndreas Gohrclass admin_plugin_twofactor extends DokuWiki_Admin_Plugin
13d0a31016SAndreas Gohr{
143571ccfcSAndreas Gohr    /** @var array currently active filters */
153571ccfcSAndreas Gohr    protected $filter = [];
163571ccfcSAndreas Gohr    /** @var int index of first user to be displayed */
173571ccfcSAndreas Gohr    protected $start = 0;
183571ccfcSAndreas Gohr    /** @var int number of users to list on one page */
193571ccfcSAndreas Gohr    protected $pagesize = 20;
203571ccfcSAndreas Gohr    /** @var Manager */
21bbe22a6aSAndreas Gohr    protected $manager;
22bbe22a6aSAndreas Gohr
23163ac707SMichael Wilmes    /**
24163ac707SMichael Wilmes     * Constructor
25163ac707SMichael Wilmes     */
26d0a31016SAndreas Gohr    public function __construct()
27d0a31016SAndreas Gohr    {
28bbe22a6aSAndreas Gohr        $this->manager = Manager::getInstance();
29bbe22a6aSAndreas Gohr        if (!$this->manager->isReady()) return;
30bbe22a6aSAndreas Gohr
31bbe22a6aSAndreas Gohr        global $INPUT;
32bbe22a6aSAndreas Gohr
33bbe22a6aSAndreas Gohr        $this->filter = $INPUT->arr('filter');
34bbe22a6aSAndreas Gohr        $this->start = $INPUT->int('start');
35163ac707SMichael Wilmes    }
362cc41bddSMichael Wilmes
37f62d0e33SAndreas Gohr    /** @inheritdoc */
38d0a31016SAndreas Gohr    public function handle()
39d0a31016SAndreas Gohr    {
40bbe22a6aSAndreas Gohr        global $INPUT;
41bbe22a6aSAndreas Gohr
42bbe22a6aSAndreas Gohr        if ($INPUT->has('reset') && checkSecurityToken()) {
43bbe22a6aSAndreas Gohr            $userdel = $INPUT->extract('reset')->str('reset');
44bbe22a6aSAndreas Gohr            if ($userdel == $INPUT->server->str('REMOTE_USER')) {
45bbe22a6aSAndreas Gohr                msg($this->lang['reset_not_self'], -1);
46bbe22a6aSAndreas Gohr                return;
47b71db9c8SMichael Wilmes            }
48bbe22a6aSAndreas Gohr            foreach ($this->manager->getAllProviders() as $providerID => $provider) {
496d69ca71SAndreas Gohr                (new Settings($providerID, $userdel))->purge();
50163ac707SMichael Wilmes            }
516d69ca71SAndreas Gohr            (new Settings('twofactor', $userdel))->purge();
52163ac707SMichael Wilmes        }
53*588e5659SAndreas Gohr
54*588e5659SAndreas Gohr        // when a search is initiated, roll back to first page
55*588e5659SAndreas Gohr        if ($INPUT->has('search')) {
56*588e5659SAndreas Gohr            $this->start = 0;
57*588e5659SAndreas Gohr        }
58163ac707SMichael Wilmes    }
59163ac707SMichael Wilmes
603571ccfcSAndreas Gohr    /** @inheritdoc */
61d0a31016SAndreas Gohr    public function html()
62d0a31016SAndreas Gohr    {
63f62d0e33SAndreas Gohr        echo $this->locale_xhtml('admin');
64bbe22a6aSAndreas Gohr        if (!$this->manager->isReady()) {
65bbe22a6aSAndreas Gohr            return true;
66bbe22a6aSAndreas Gohr        }
67f62d0e33SAndreas Gohr
686ce592efSAndreas Gohr        $users = $this->getUserData($this->filter);
696ce592efSAndreas Gohr        $usercount = count($users);
706ce592efSAndreas Gohr        $users = $this->applyPagination($users, $this->start, $this->pagesize);
716ce592efSAndreas Gohr
72bbe22a6aSAndreas Gohr        $form = new Form(['method' => 'POST', 'class' => 'plugin_twofactor_admin']);
73f62d0e33SAndreas Gohr        $form->setHiddenField('do', 'admin');
74f62d0e33SAndreas Gohr        $form->setHiddenField('page', 'twofactor');
75f62d0e33SAndreas Gohr        $form->setHiddenField('start', $this->start);
76f62d0e33SAndreas Gohr
77f62d0e33SAndreas Gohr        $form->addTagOpen('div')->addClass('table');
78f62d0e33SAndreas Gohr        $form->addTagOpen('table')->addClass('inline');
79f62d0e33SAndreas Gohr        $form = $this->addTableHead($form);
80f62d0e33SAndreas Gohr
81f62d0e33SAndreas Gohr        $form->addTagOpen('tbody');
82f62d0e33SAndreas Gohr        foreach ($users as $user => $userinfo) {
83f62d0e33SAndreas Gohr            $form = $this->addTableUser($form, $user, $userinfo);
84f62d0e33SAndreas Gohr        }
85f62d0e33SAndreas Gohr        $form->addTagClose('tbody');
86f62d0e33SAndreas Gohr
87bbe22a6aSAndreas Gohr        $form->addTagOpen('tfooter');
88bbe22a6aSAndreas Gohr        $form = $this->addTablePagination($form, $usercount, $this->start, $this->pagesize);
89bbe22a6aSAndreas Gohr        $form->addTagClose('tfooter');
90bbe22a6aSAndreas Gohr
91f62d0e33SAndreas Gohr        $form->addTagClose('table');
92f62d0e33SAndreas Gohr        $form->addTagClose('div');
93f62d0e33SAndreas Gohr
94f62d0e33SAndreas Gohr        echo $form->toHTML();
95f62d0e33SAndreas Gohr
96b71db9c8SMichael Wilmes        return true;
97b71db9c8SMichael Wilmes    }
98b71db9c8SMichael Wilmes
99163ac707SMichael Wilmes    /**
100f62d0e33SAndreas Gohr     * Add the table headers to the table in the given form
101f62d0e33SAndreas Gohr     * @param Form $form
102f62d0e33SAndreas Gohr     * @return Form
103163ac707SMichael Wilmes     */
104f62d0e33SAndreas Gohr    protected function addTableHead(Form $form)
105f62d0e33SAndreas Gohr    {
106f62d0e33SAndreas Gohr        $form->addTagOpen('thead');
107f62d0e33SAndreas Gohr
108f62d0e33SAndreas Gohr        // header
109f62d0e33SAndreas Gohr        $form->addTagOpen('tr');
110f62d0e33SAndreas Gohr        $form->addTagOpen('th');
111f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('user_id'));
112f62d0e33SAndreas Gohr        $form->addTagClose('th');
113f62d0e33SAndreas Gohr        $form->addTagOpen('th');
114f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('user_name'));
115f62d0e33SAndreas Gohr        $form->addTagClose('th');
116f62d0e33SAndreas Gohr        $form->addTagOpen('th');
117f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('user_mail'));
118f62d0e33SAndreas Gohr        $form->addTagClose('th');
119f62d0e33SAndreas Gohr        $form->addTagOpen('th');
120f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('action'));
121f62d0e33SAndreas Gohr        $form->addTagClose('th');
122f62d0e33SAndreas Gohr        $form->addTagClose('tr');
123f62d0e33SAndreas Gohr
124f62d0e33SAndreas Gohr        // filter
125f62d0e33SAndreas Gohr        $form->addTagOpen('tr');
126f62d0e33SAndreas Gohr        $form->addTagOpen('th');
127bbe22a6aSAndreas Gohr        $form->addTextInput('filter[user]');
128f62d0e33SAndreas Gohr        $form->addTagClose('th');
129f62d0e33SAndreas Gohr        $form->addTagOpen('th');
130bbe22a6aSAndreas Gohr        $form->addTextInput('filter[name]');
131f62d0e33SAndreas Gohr        $form->addTagClose('th');
132f62d0e33SAndreas Gohr        $form->addTagOpen('th');
133bbe22a6aSAndreas Gohr        $form->addTextInput('filter[mail]');
134f62d0e33SAndreas Gohr        $form->addTagClose('th');
135f62d0e33SAndreas Gohr        $form->addTagOpen('th');
136*588e5659SAndreas Gohr        $form->addButton('search', $this->getLang('search'))->attr('type', 'submit');
137f62d0e33SAndreas Gohr        $form->addTagClose('th');
138f62d0e33SAndreas Gohr        $form->addTagClose('tr');
139f62d0e33SAndreas Gohr
140f62d0e33SAndreas Gohr        $form->addTagClose('thead');
141f62d0e33SAndreas Gohr        return $form;
142163ac707SMichael Wilmes    }
143163ac707SMichael Wilmes
144f62d0e33SAndreas Gohr    /**
145f62d0e33SAndreas Gohr     * Add
146f62d0e33SAndreas Gohr     *
147f62d0e33SAndreas Gohr     * @param Form $form
148f62d0e33SAndreas Gohr     * @param $user
149f62d0e33SAndreas Gohr     * @param $userinfo
150f62d0e33SAndreas Gohr     * @return Form
151f62d0e33SAndreas Gohr     */
152f62d0e33SAndreas Gohr    protected function addTableUser(Form $form, $user, $userinfo)
153f62d0e33SAndreas Gohr    {
154f62d0e33SAndreas Gohr        $form->addTagOpen('tr');
155f62d0e33SAndreas Gohr        $form->addTagOpen('td');
156f62d0e33SAndreas Gohr        $form->addHTML(hsc($user));
157f62d0e33SAndreas Gohr        $form->addTagClose('td');
158f62d0e33SAndreas Gohr        $form->addTagOpen('td');
159f62d0e33SAndreas Gohr        $form->addHTML(hsc($userinfo['name']));
160f62d0e33SAndreas Gohr        $form->addTagClose('td');
161f62d0e33SAndreas Gohr        $form->addTagOpen('td');
162f62d0e33SAndreas Gohr        $form->addHTML(hsc($userinfo['mail']));
163f62d0e33SAndreas Gohr        $form->addTagClose('td');
164f62d0e33SAndreas Gohr        $form->addTagOpen('td');
165bbe22a6aSAndreas Gohr        $form->addButton('reset[' . $user . ']', $this->getLang('reset'))
166bbe22a6aSAndreas Gohr             ->attr('type', 'submit')
167bbe22a6aSAndreas Gohr             ->addClass('twofactor_resetconfirm');
168f62d0e33SAndreas Gohr        $form->addTagClose('td');
169f62d0e33SAndreas Gohr        $form->addTagClose('tr');
170f62d0e33SAndreas Gohr        return $form;
171163ac707SMichael Wilmes    }
172163ac707SMichael Wilmes
173f62d0e33SAndreas Gohr    /**
174bbe22a6aSAndreas Gohr     * Add the pagination buttons to the form
175163ac707SMichael Wilmes     *
176bbe22a6aSAndreas Gohr     * @param Form $form
177bbe22a6aSAndreas Gohr     * @param int $usercount
178bbe22a6aSAndreas Gohr     * @param int $start
179bbe22a6aSAndreas Gohr     * @param int $pagesize
180bbe22a6aSAndreas Gohr     * @return Form
181163ac707SMichael Wilmes     */
182bbe22a6aSAndreas Gohr    protected function addTablePagination(Form $form, $usercount, $start, $pagesize)
183d0a31016SAndreas Gohr    {
184bbe22a6aSAndreas Gohr        $form->addTagOpen('tr');
185bbe22a6aSAndreas Gohr        $form->addTagOpen('td')->attr('colspan', '4');
186bbe22a6aSAndreas Gohr        $form->addTagOpen('div')->addClass('pagination');
187163ac707SMichael Wilmes
188bbe22a6aSAndreas Gohr        // start
189bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('start'))->val('0');
190bbe22a6aSAndreas Gohr        if ($start <= 0) $btn->attr('disabled', 'disabled');
191163ac707SMichael Wilmes
192bbe22a6aSAndreas Gohr        // prev
193bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('prev'))->val($start - $pagesize);
194bbe22a6aSAndreas Gohr        if ($start - $pagesize < 0) $btn->attr('disabled', 'disabled');
195bbe22a6aSAndreas Gohr
196bbe22a6aSAndreas Gohr        // next
197bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('next'))->val($start + $pagesize);
198bbe22a6aSAndreas Gohr        if ($start + $pagesize >= $usercount) $btn->attr('disabled', 'disabled');
199bbe22a6aSAndreas Gohr
200bbe22a6aSAndreas Gohr        // last
201bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('last'))->val($usercount - $pagesize);
202bbe22a6aSAndreas Gohr        if ($usercount - $pagesize <= 0) $btn->attr('disabled', 'disabled');
203bbe22a6aSAndreas Gohr        if ($usercount - $pagesize == $start) $btn->attr('disabled', 'disabled');
204bbe22a6aSAndreas Gohr
205bbe22a6aSAndreas Gohr        $form->addTagClose('div');
206bbe22a6aSAndreas Gohr        $form->addTagClose('td');
207bbe22a6aSAndreas Gohr        $form->addTagClose('tr');
208bbe22a6aSAndreas Gohr
209bbe22a6aSAndreas Gohr        return $form;
210163ac707SMichael Wilmes    }
211163ac707SMichael Wilmes
212163ac707SMichael Wilmes    /**
213bbe22a6aSAndreas Gohr     * Get the filtered users that have a twofactor provider set
214163ac707SMichael Wilmes     *
215bbe22a6aSAndreas Gohr     * @param array $filter
216163ac707SMichael Wilmes     * @return array
217163ac707SMichael Wilmes     */
218bbe22a6aSAndreas Gohr    protected function getUserData($filter)
219d0a31016SAndreas Gohr    {
2206d69ca71SAndreas Gohr        $users = Settings::findUsers('twofactor');
221bbe22a6aSAndreas Gohr        return $this->applyFilter($users, $filter);
222163ac707SMichael Wilmes    }
223163ac707SMichael Wilmes
224163ac707SMichael Wilmes    /**
225bbe22a6aSAndreas Gohr     * Apply the given filters and return user details
226163ac707SMichael Wilmes     *
227bbe22a6aSAndreas Gohr     * @param string[] $users simple list of user names
228bbe22a6aSAndreas Gohr     * @param array $filter
229bbe22a6aSAndreas Gohr     * @return array (user => userdata)
230163ac707SMichael Wilmes     */
231bbe22a6aSAndreas Gohr    protected function applyFilter($users, $filter)
232d0a31016SAndreas Gohr    {
233bbe22a6aSAndreas Gohr        global $auth;
234bbe22a6aSAndreas Gohr        $filtered = [];
235163ac707SMichael Wilmes
236bbe22a6aSAndreas Gohr        $hasFilter = (bool)array_filter(array_values($filter));
237bbe22a6aSAndreas Gohr        foreach ($users as $user) {
238bbe22a6aSAndreas Gohr            $userdata = $auth->getUserData($user);
239bbe22a6aSAndreas Gohr            if (!$userdata) continue;
240bbe22a6aSAndreas Gohr            $userdata['user'] = $user;
241bbe22a6aSAndreas Gohr            if ($hasFilter) {
242bbe22a6aSAndreas Gohr                foreach ($filter as $key => $value) {
243db15b76eSAndreas Gohr                    $q = preg_quote($value, '/');
244db15b76eSAndreas Gohr                    if ($value && preg_match("/$q/iu", $userdata[$key])) {
245bbe22a6aSAndreas Gohr                        $filtered[$user] = $userdata;
246bbe22a6aSAndreas Gohr                        continue 2;
247bbe22a6aSAndreas Gohr                    }
248bbe22a6aSAndreas Gohr                }
249163ac707SMichael Wilmes            } else {
250bbe22a6aSAndreas Gohr                $filtered[$user] = $userdata;
251bbe22a6aSAndreas Gohr            }
252bbe22a6aSAndreas Gohr        }
253bbe22a6aSAndreas Gohr        return $filtered;
254163ac707SMichael Wilmes    }
255163ac707SMichael Wilmes
256bbe22a6aSAndreas Gohr    /**
257bbe22a6aSAndreas Gohr     * Get the current page of users
258bbe22a6aSAndreas Gohr     *
259bbe22a6aSAndreas Gohr     * @param array $users
260bbe22a6aSAndreas Gohr     * @param int $start
261bbe22a6aSAndreas Gohr     * @param int $pagesize
262bbe22a6aSAndreas Gohr     * @return array
263bbe22a6aSAndreas Gohr     */
264bbe22a6aSAndreas Gohr    protected function applyPagination($users, $start, $pagesize)
265bbe22a6aSAndreas Gohr    {
266bbe22a6aSAndreas Gohr        return array_slice($users, $start, $pagesize, true);
267163ac707SMichael Wilmes    }
268163ac707SMichael Wilmes
269163ac707SMichael Wilmes}
270