xref: /plugin/twofactor/admin.php (revision bbe22a6a87dd9db724f864d111d35d715e39a4e1)
1163ac707SMichael Wilmes<?php
2f62d0e33SAndreas Gohr
3f62d0e33SAndreas Gohruse dokuwiki\Form\Form;
4f62d0e33SAndreas Gohruse dokuwiki\plugin\twofactor\Manager;
5f62d0e33SAndreas Gohr
6f62d0e33SAndreas Gohr/**
7163ac707SMichael Wilmes *  Twofactor Manager
8163ac707SMichael Wilmes *
9*bbe22a6aSAndreas Gohr *  Allows to reset a user's twofactor data
10163ac707SMichael Wilmes */
11d0a31016SAndreas Gohrclass admin_plugin_twofactor extends DokuWiki_Admin_Plugin
12d0a31016SAndreas Gohr{
13f62d0e33SAndreas Gohr    protected $userList = array();     // list of users with attributes
14f62d0e33SAndreas Gohr    protected $filter = array();   // user selection filter(s)
15f62d0e33SAndreas Gohr    protected $start = 0;          // index of first user to be displayed
16f62d0e33SAndreas Gohr    protected $last = 0;           // index of the last user to be displayed
17f62d0e33SAndreas Gohr    protected $pagesize = 20;      // number of users to list on one page
18f62d0e33SAndreas Gohr    protected $disabled = '';      // if disabled set to explanatory string
19f62d0e33SAndreas Gohr
20f62d0e33SAndreas Gohr    /** @var helper_plugin_attribute */
21f62d0e33SAndreas Gohr    protected $attribute;
22163ac707SMichael Wilmes
23*bbe22a6aSAndreas Gohr    protected $manager;
24*bbe22a6aSAndreas Gohr
25163ac707SMichael Wilmes    /**
26163ac707SMichael Wilmes     * Constructor
27163ac707SMichael Wilmes     */
28d0a31016SAndreas Gohr    public function __construct()
29d0a31016SAndreas Gohr    {
30*bbe22a6aSAndreas Gohr        $this->manager = Manager::getInstance();
31*bbe22a6aSAndreas Gohr        if (!$this->manager->isReady()) return;
32f62d0e33SAndreas Gohr        $this->attribute = plugin_load('helper', 'attribute');
33*bbe22a6aSAndreas Gohr
34*bbe22a6aSAndreas Gohr        global $INPUT;
35*bbe22a6aSAndreas Gohr
36*bbe22a6aSAndreas Gohr        $this->filter = $INPUT->arr('filter');
37*bbe22a6aSAndreas Gohr        $this->start = $INPUT->int('start');
38163ac707SMichael Wilmes    }
392cc41bddSMichael Wilmes
40f62d0e33SAndreas Gohr    /** @inheritdoc */
41d0a31016SAndreas Gohr    public function handle()
42d0a31016SAndreas Gohr    {
43*bbe22a6aSAndreas Gohr        global $INPUT;
44*bbe22a6aSAndreas Gohr
45*bbe22a6aSAndreas Gohr        if ($INPUT->has('reset') && checkSecurityToken()) {
46*bbe22a6aSAndreas Gohr            $userdel = $INPUT->extract('reset')->str('reset');
47*bbe22a6aSAndreas Gohr            if ($userdel == $INPUT->server->str('REMOTE_USER')) {
48*bbe22a6aSAndreas Gohr                msg($this->lang['reset_not_self'], -1);
49*bbe22a6aSAndreas Gohr                return;
50b71db9c8SMichael Wilmes            }
51*bbe22a6aSAndreas Gohr            foreach ($this->manager->getAllProviders() as $providerID => $provider) {
52*bbe22a6aSAndreas Gohr                $this->attribute->purge($providerID, $userdel);
53163ac707SMichael Wilmes            }
54*bbe22a6aSAndreas Gohr            $this->attribute->purge('twofactor', $userdel);
55163ac707SMichael Wilmes        }
56163ac707SMichael Wilmes    }
57163ac707SMichael Wilmes
58163ac707SMichael Wilmes    /**
59163ac707SMichael Wilmes     * Output appropriate html
60163ac707SMichael Wilmes     *
61163ac707SMichael Wilmes     * @return bool
62163ac707SMichael Wilmes     */
63d0a31016SAndreas Gohr    public function html()
64d0a31016SAndreas Gohr    {
65*bbe22a6aSAndreas Gohr        $users = $this->getUserData($this->filter);
66*bbe22a6aSAndreas Gohr        $usercount = count($users);
67*bbe22a6aSAndreas Gohr        $users = $this->applyPagination($users, $this->start, $this->pagesize);
68163ac707SMichael Wilmes
69f62d0e33SAndreas Gohr        echo $this->locale_xhtml('admin');
70*bbe22a6aSAndreas Gohr        if (!$this->manager->isReady()) {
71*bbe22a6aSAndreas Gohr            return true;
72*bbe22a6aSAndreas Gohr        }
73f62d0e33SAndreas Gohr
74*bbe22a6aSAndreas Gohr        $form = new Form(['method' => 'POST', 'class' => 'plugin_twofactor_admin']);
75f62d0e33SAndreas Gohr        $form->setHiddenField('do', 'admin');
76f62d0e33SAndreas Gohr        $form->setHiddenField('page', 'twofactor');
77f62d0e33SAndreas Gohr        $form->setHiddenField('start', $this->start);
78f62d0e33SAndreas Gohr
79f62d0e33SAndreas Gohr        $form->addTagOpen('div')->addClass('table');
80f62d0e33SAndreas Gohr        $form->addTagOpen('table')->addClass('inline');
81f62d0e33SAndreas Gohr        $form = $this->addTableHead($form);
82f62d0e33SAndreas Gohr
83f62d0e33SAndreas Gohr        $form->addTagOpen('tbody');
84f62d0e33SAndreas Gohr        foreach ($users as $user => $userinfo) {
85f62d0e33SAndreas Gohr            $form = $this->addTableUser($form, $user, $userinfo);
86f62d0e33SAndreas Gohr        }
87f62d0e33SAndreas Gohr        $form->addTagClose('tbody');
88f62d0e33SAndreas Gohr
89*bbe22a6aSAndreas Gohr        $form->addTagOpen('tfooter');
90*bbe22a6aSAndreas Gohr        $form = $this->addTablePagination($form, $usercount, $this->start, $this->pagesize);
91*bbe22a6aSAndreas Gohr        $form->addTagClose('tfooter');
92*bbe22a6aSAndreas Gohr
93f62d0e33SAndreas Gohr        $form->addTagClose('table');
94f62d0e33SAndreas Gohr        $form->addTagClose('div');
95f62d0e33SAndreas Gohr
96f62d0e33SAndreas Gohr        echo $form->toHTML();
97f62d0e33SAndreas Gohr
98b71db9c8SMichael Wilmes        return true;
99b71db9c8SMichael Wilmes    }
100b71db9c8SMichael Wilmes
101163ac707SMichael Wilmes    /**
102f62d0e33SAndreas Gohr     * Add the table headers to the table in the given form
103f62d0e33SAndreas Gohr     * @param Form $form
104f62d0e33SAndreas Gohr     * @return Form
105163ac707SMichael Wilmes     */
106f62d0e33SAndreas Gohr    protected function addTableHead(Form $form)
107f62d0e33SAndreas Gohr    {
108f62d0e33SAndreas Gohr        $form->addTagOpen('thead');
109f62d0e33SAndreas Gohr
110f62d0e33SAndreas Gohr        // header
111f62d0e33SAndreas Gohr        $form->addTagOpen('tr');
112f62d0e33SAndreas Gohr        $form->addTagOpen('th');
113f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('user_id'));
114f62d0e33SAndreas Gohr        $form->addTagClose('th');
115f62d0e33SAndreas Gohr        $form->addTagOpen('th');
116f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('user_name'));
117f62d0e33SAndreas Gohr        $form->addTagClose('th');
118f62d0e33SAndreas Gohr        $form->addTagOpen('th');
119f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('user_mail'));
120f62d0e33SAndreas Gohr        $form->addTagClose('th');
121f62d0e33SAndreas Gohr        $form->addTagOpen('th');
122f62d0e33SAndreas Gohr        $form->addHTML($this->getLang('action'));
123f62d0e33SAndreas Gohr        $form->addTagClose('th');
124f62d0e33SAndreas Gohr        $form->addTagClose('tr');
125f62d0e33SAndreas Gohr
126f62d0e33SAndreas Gohr        // filter
127f62d0e33SAndreas Gohr        $form->addTagOpen('tr');
128f62d0e33SAndreas Gohr        $form->addTagOpen('th');
129*bbe22a6aSAndreas Gohr        $form->addTextInput('filter[user]');
130f62d0e33SAndreas Gohr        $form->addTagClose('th');
131f62d0e33SAndreas Gohr        $form->addTagOpen('th');
132*bbe22a6aSAndreas Gohr        $form->addTextInput('filter[name]');
133f62d0e33SAndreas Gohr        $form->addTagClose('th');
134f62d0e33SAndreas Gohr        $form->addTagOpen('th');
135*bbe22a6aSAndreas Gohr        $form->addTextInput('filter[mail]');
136f62d0e33SAndreas Gohr        $form->addTagClose('th');
137f62d0e33SAndreas Gohr        $form->addTagOpen('th');
138f62d0e33SAndreas Gohr        $form->addButton('', $this->getLang('search'))->attr('type', 'submit');
139f62d0e33SAndreas Gohr        $form->addTagClose('th');
140f62d0e33SAndreas Gohr        $form->addTagClose('tr');
141f62d0e33SAndreas Gohr
142f62d0e33SAndreas Gohr        $form->addTagClose('thead');
143f62d0e33SAndreas Gohr        return $form;
144163ac707SMichael Wilmes    }
145163ac707SMichael Wilmes
146f62d0e33SAndreas Gohr    /**
147f62d0e33SAndreas Gohr     * Add
148f62d0e33SAndreas Gohr     *
149f62d0e33SAndreas Gohr     * @param Form $form
150f62d0e33SAndreas Gohr     * @param $user
151f62d0e33SAndreas Gohr     * @param $userinfo
152f62d0e33SAndreas Gohr     * @return Form
153f62d0e33SAndreas Gohr     */
154f62d0e33SAndreas Gohr    protected function addTableUser(Form $form, $user, $userinfo)
155f62d0e33SAndreas Gohr    {
156f62d0e33SAndreas Gohr        $form->addTagOpen('tr');
157f62d0e33SAndreas Gohr        $form->addTagOpen('td');
158f62d0e33SAndreas Gohr        $form->addHTML(hsc($user));
159f62d0e33SAndreas Gohr        $form->addTagClose('td');
160f62d0e33SAndreas Gohr        $form->addTagOpen('td');
161f62d0e33SAndreas Gohr        $form->addHTML(hsc($userinfo['name']));
162f62d0e33SAndreas Gohr        $form->addTagClose('td');
163f62d0e33SAndreas Gohr        $form->addTagOpen('td');
164f62d0e33SAndreas Gohr        $form->addHTML(hsc($userinfo['mail']));
165f62d0e33SAndreas Gohr        $form->addTagClose('td');
166f62d0e33SAndreas Gohr        $form->addTagOpen('td');
167*bbe22a6aSAndreas Gohr        $form->addButton('reset[' . $user . ']', $this->getLang('reset'))
168*bbe22a6aSAndreas Gohr             ->attr('type', 'submit')
169*bbe22a6aSAndreas Gohr             ->addClass('twofactor_resetconfirm');
170f62d0e33SAndreas Gohr        $form->addTagClose('td');
171f62d0e33SAndreas Gohr        $form->addTagClose('tr');
172f62d0e33SAndreas Gohr        return $form;
173163ac707SMichael Wilmes    }
174163ac707SMichael Wilmes
175f62d0e33SAndreas Gohr    /**
176*bbe22a6aSAndreas Gohr     * Add the pagination buttons to the form
177163ac707SMichael Wilmes     *
178*bbe22a6aSAndreas Gohr     * @param Form $form
179*bbe22a6aSAndreas Gohr     * @param int $usercount
180*bbe22a6aSAndreas Gohr     * @param int $start
181*bbe22a6aSAndreas Gohr     * @param int $pagesize
182*bbe22a6aSAndreas Gohr     * @return Form
183163ac707SMichael Wilmes     */
184*bbe22a6aSAndreas Gohr    protected function addTablePagination(Form $form, $usercount, $start, $pagesize)
185d0a31016SAndreas Gohr    {
186*bbe22a6aSAndreas Gohr        $form->addTagOpen('tr');
187*bbe22a6aSAndreas Gohr        $form->addTagOpen('td')->attr('colspan', '4');
188*bbe22a6aSAndreas Gohr        $form->addTagOpen('div')->addClass('pagination');
189163ac707SMichael Wilmes
190*bbe22a6aSAndreas Gohr        // start
191*bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('start'))->val('0');
192*bbe22a6aSAndreas Gohr        if ($start <= 0) $btn->attr('disabled', 'disabled');
193163ac707SMichael Wilmes
194*bbe22a6aSAndreas Gohr        // prev
195*bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('prev'))->val($start - $pagesize);
196*bbe22a6aSAndreas Gohr        if ($start - $pagesize < 0) $btn->attr('disabled', 'disabled');
197*bbe22a6aSAndreas Gohr
198*bbe22a6aSAndreas Gohr        // next
199*bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('next'))->val($start + $pagesize);
200*bbe22a6aSAndreas Gohr        if ($start + $pagesize >= $usercount) $btn->attr('disabled', 'disabled');
201*bbe22a6aSAndreas Gohr
202*bbe22a6aSAndreas Gohr        // last
203*bbe22a6aSAndreas Gohr        $btn = $form->addButton('start', $this->getLang('last'))->val($usercount - $pagesize);
204*bbe22a6aSAndreas Gohr        if ($usercount - $pagesize <= 0) $btn->attr('disabled', 'disabled');
205*bbe22a6aSAndreas Gohr        if ($usercount - $pagesize == $start) $btn->attr('disabled', 'disabled');
206*bbe22a6aSAndreas Gohr
207*bbe22a6aSAndreas Gohr        $form->addTagClose('div');
208*bbe22a6aSAndreas Gohr        $form->addTagClose('td');
209*bbe22a6aSAndreas Gohr        $form->addTagClose('tr');
210*bbe22a6aSAndreas Gohr
211*bbe22a6aSAndreas Gohr        return $form;
212163ac707SMichael Wilmes    }
213163ac707SMichael Wilmes
214163ac707SMichael Wilmes    /**
215*bbe22a6aSAndreas Gohr     * Get the filtered users that have a twofactor provider set
216163ac707SMichael Wilmes     *
217*bbe22a6aSAndreas Gohr     * @param array $filter
218163ac707SMichael Wilmes     * @return array
219163ac707SMichael Wilmes     */
220*bbe22a6aSAndreas Gohr    protected function getUserData($filter)
221d0a31016SAndreas Gohr    {
222*bbe22a6aSAndreas Gohr        $users = $this->attribute->enumerateUsers('twofactor');
223*bbe22a6aSAndreas Gohr        return $this->applyFilter($users, $filter);
224163ac707SMichael Wilmes    }
225163ac707SMichael Wilmes
226163ac707SMichael Wilmes    /**
227*bbe22a6aSAndreas Gohr     * Apply the given filters and return user details
228163ac707SMichael Wilmes     *
229*bbe22a6aSAndreas Gohr     * @param string[] $users simple list of user names
230*bbe22a6aSAndreas Gohr     * @param array $filter
231*bbe22a6aSAndreas Gohr     * @return array (user => userdata)
232163ac707SMichael Wilmes     */
233*bbe22a6aSAndreas Gohr    protected function applyFilter($users, $filter)
234d0a31016SAndreas Gohr    {
235*bbe22a6aSAndreas Gohr        global $auth;
236*bbe22a6aSAndreas Gohr        $filtered = [];
237163ac707SMichael Wilmes
238*bbe22a6aSAndreas Gohr        $hasFilter = (bool)array_filter(array_values($filter));
239*bbe22a6aSAndreas Gohr        foreach ($users as $user) {
240*bbe22a6aSAndreas Gohr            $userdata = $auth->getUserData($user);
241*bbe22a6aSAndreas Gohr            if (!$userdata) continue;
242*bbe22a6aSAndreas Gohr            $userdata['user'] = $user;
243*bbe22a6aSAndreas Gohr            if ($hasFilter) {
244*bbe22a6aSAndreas Gohr                foreach ($filter as $key => $value) {
245*bbe22a6aSAndreas Gohr                    if ($value && strstr($userdata[$key], $value)) {
246*bbe22a6aSAndreas Gohr                        $filtered[$user] = $userdata;
247*bbe22a6aSAndreas Gohr                        continue 2;
248*bbe22a6aSAndreas Gohr                    }
249*bbe22a6aSAndreas Gohr                }
250163ac707SMichael Wilmes            } else {
251*bbe22a6aSAndreas Gohr                $filtered[$user] = $userdata;
252*bbe22a6aSAndreas Gohr            }
253*bbe22a6aSAndreas Gohr        }
254*bbe22a6aSAndreas Gohr        return $filtered;
255163ac707SMichael Wilmes    }
256163ac707SMichael Wilmes
257*bbe22a6aSAndreas Gohr    /**
258*bbe22a6aSAndreas Gohr     * Get the current page of users
259*bbe22a6aSAndreas Gohr     *
260*bbe22a6aSAndreas Gohr     * @param array $users
261*bbe22a6aSAndreas Gohr     * @param int $start
262*bbe22a6aSAndreas Gohr     * @param int $pagesize
263*bbe22a6aSAndreas Gohr     * @return array
264*bbe22a6aSAndreas Gohr     */
265*bbe22a6aSAndreas Gohr    protected function applyPagination($users, $start, $pagesize)
266*bbe22a6aSAndreas Gohr    {
267*bbe22a6aSAndreas Gohr        return array_slice($users, $start, $pagesize, true);
268163ac707SMichael Wilmes    }
269163ac707SMichael Wilmes
270163ac707SMichael Wilmes}
271