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->getLang('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 // when a search is initiated, roll back to first page 55 if ($INPUT->has('search')) { 56 $this->start = 0; 57 } 58 } 59 60 /** @inheritdoc */ 61 public function html() 62 { 63 echo $this->locale_xhtml('admin'); 64 if (!$this->manager->isReady()) { 65 return true; 66 } 67 68 $users = $this->getUserData($this->filter); 69 $usercount = count($users); 70 $users = $this->applyPagination($users, $this->start, $this->pagesize); 71 72 $form = new Form(['method' => 'POST', 'class' => 'plugin_twofactor_admin']); 73 $form->setHiddenField('do', 'admin'); 74 $form->setHiddenField('page', 'twofactor'); 75 $form->setHiddenField('start', $this->start); 76 77 $form->addTagOpen('div')->addClass('table'); 78 $form->addTagOpen('table')->addClass('inline'); 79 $form = $this->addTableHead($form); 80 81 $form->addTagOpen('tbody'); 82 foreach ($users as $user => $userinfo) { 83 $form = $this->addTableUser($form, $user, $userinfo); 84 } 85 $form->addTagClose('tbody'); 86 87 $form->addTagOpen('tfooter'); 88 $form = $this->addTablePagination($form, $usercount, $this->start, $this->pagesize); 89 $form->addTagClose('tfooter'); 90 91 $form->addTagClose('table'); 92 $form->addTagClose('div'); 93 94 echo $form->toHTML(); 95 96 return true; 97 } 98 99 /** 100 * Add the table headers to the table in the given form 101 * @param Form $form 102 * @return Form 103 */ 104 protected function addTableHead(Form $form) 105 { 106 $form->addTagOpen('thead'); 107 108 // header 109 $form->addTagOpen('tr'); 110 $form->addTagOpen('th'); 111 $form->addHTML($this->getLang('user_id')); 112 $form->addTagClose('th'); 113 $form->addTagOpen('th'); 114 $form->addHTML($this->getLang('user_name')); 115 $form->addTagClose('th'); 116 $form->addTagOpen('th'); 117 $form->addHTML($this->getLang('user_mail')); 118 $form->addTagClose('th'); 119 $form->addTagOpen('th'); 120 $form->addHTML($this->getLang('action')); 121 $form->addTagClose('th'); 122 $form->addTagClose('tr'); 123 124 // filter 125 $form->addTagOpen('tr'); 126 $form->addTagOpen('th'); 127 $form->addTextInput('filter[user]'); 128 $form->addTagClose('th'); 129 $form->addTagOpen('th'); 130 $form->addTextInput('filter[name]'); 131 $form->addTagClose('th'); 132 $form->addTagOpen('th'); 133 $form->addTextInput('filter[mail]'); 134 $form->addTagClose('th'); 135 $form->addTagOpen('th'); 136 $form->addButton('search', $this->getLang('search'))->attr('type', 'submit'); 137 $form->addTagClose('th'); 138 $form->addTagClose('tr'); 139 140 $form->addTagClose('thead'); 141 return $form; 142 } 143 144 /** 145 * Add 146 * 147 * @param Form $form 148 * @param $user 149 * @param $userinfo 150 * @return Form 151 */ 152 protected function addTableUser(Form $form, $user, $userinfo) 153 { 154 $form->addTagOpen('tr'); 155 $form->addTagOpen('td'); 156 $form->addHTML(hsc($user)); 157 $form->addTagClose('td'); 158 $form->addTagOpen('td'); 159 $form->addHTML(hsc($userinfo['name'])); 160 $form->addTagClose('td'); 161 $form->addTagOpen('td'); 162 $form->addHTML(hsc($userinfo['mail'])); 163 $form->addTagClose('td'); 164 $form->addTagOpen('td'); 165 $form->addButton('reset[' . $user . ']', $this->getLang('reset')) 166 ->attr('type', 'submit') 167 ->addClass('twofactor_resetconfirm'); 168 $form->addTagClose('td'); 169 $form->addTagClose('tr'); 170 return $form; 171 } 172 173 /** 174 * Add the pagination buttons to the form 175 * 176 * @param Form $form 177 * @param int $usercount 178 * @param int $start 179 * @param int $pagesize 180 * @return Form 181 */ 182 protected function addTablePagination(Form $form, $usercount, $start, $pagesize) 183 { 184 $form->addTagOpen('tr'); 185 $form->addTagOpen('td')->attr('colspan', '4'); 186 $form->addTagOpen('div')->addClass('pagination'); 187 188 // start 189 $btn = $form->addButton('start', $this->getLang('start'))->val('0'); 190 if ($start <= 0) $btn->attr('disabled', 'disabled'); 191 192 // prev 193 $btn = $form->addButton('start', $this->getLang('prev'))->val($start - $pagesize); 194 if ($start - $pagesize < 0) $btn->attr('disabled', 'disabled'); 195 196 // next 197 $btn = $form->addButton('start', $this->getLang('next'))->val($start + $pagesize); 198 if ($start + $pagesize >= $usercount) $btn->attr('disabled', 'disabled'); 199 200 // last 201 $btn = $form->addButton('start', $this->getLang('last'))->val($usercount - $pagesize); 202 if ($usercount - $pagesize <= 0) $btn->attr('disabled', 'disabled'); 203 if ($usercount - $pagesize == $start) $btn->attr('disabled', 'disabled'); 204 205 $form->addTagClose('div'); 206 $form->addTagClose('td'); 207 $form->addTagClose('tr'); 208 209 return $form; 210 } 211 212 /** 213 * Get the filtered users that have a twofactor provider set 214 * 215 * @param array $filter 216 * @return array 217 */ 218 protected function getUserData($filter) 219 { 220 $users = Settings::findUsers('twofactor'); 221 return $this->applyFilter($users, $filter); 222 } 223 224 /** 225 * Apply the given filters and return user details 226 * 227 * @param string[] $users simple list of user names 228 * @param array $filter 229 * @return array (user => userdata) 230 */ 231 protected function applyFilter($users, $filter) 232 { 233 global $auth; 234 $filtered = []; 235 236 $hasFilter = (bool)array_filter(array_values($filter)); 237 foreach ($users as $user) { 238 $userdata = $auth->getUserData($user); 239 if (!$userdata) continue; 240 $userdata['user'] = $user; 241 if ($hasFilter) { 242 foreach ($filter as $key => $value) { 243 $q = preg_quote($value, '/'); 244 if ($value && preg_match("/$q/iu", $userdata[$key])) { 245 $filtered[$user] = $userdata; 246 continue 2; 247 } 248 } 249 } else { 250 $filtered[$user] = $userdata; 251 } 252 } 253 return $filtered; 254 } 255 256 /** 257 * Get the current page of users 258 * 259 * @param array $users 260 * @param int $start 261 * @param int $pagesize 262 * @return array 263 */ 264 protected function applyPagination($users, $start, $pagesize) 265 { 266 return array_slice($users, $start, $pagesize, true); 267 } 268 269} 270