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