1<?php 2 3use dokuwiki\Form\Form; 4use dokuwiki\plugin\twofactor\Manager; 5use dokuwiki\plugin\twofactor\MenuItem; 6use dokuwiki\plugin\twofactor\Provider; 7 8/** 9 * DokuWiki Plugin twofactor (Action Component) 10 * 11 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 12 */ 13class action_plugin_twofactor_profile extends \dokuwiki\Extension\ActionPlugin 14{ 15 /** @var Manager */ 16 protected $manager; 17 18 /** 19 * Constructor 20 */ 21 public function __construct() 22 { 23 $this->manager = Manager::getInstance(); 24 } 25 26 /** @inheritDoc */ 27 public function register(Doku_Event_Handler $controller) 28 { 29 if (!$this->manager->isReady()) return; 30 31 // Adds our twofactor profile to the user menu. 32 $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'handleUserMenuAssembly'); 33 34 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handlePreProcess'); 35 $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'handleUnknownAction'); 36 } 37 38 /** 39 * Add 2fa Menu Item 40 * 41 * @param Doku_Event $event 42 */ 43 public function handleUserMenuAssembly(Doku_Event $event) 44 { 45 global $INPUT; 46 // If this is not the user menu, then get out. 47 if ($event->data['view'] != 'user') return; 48 if (!$INPUT->server->has('REMOTE_USER')) return; 49 50 // Create the new menu item 51 $menuitem = new MenuItem($this->getLang('btn_twofactor_profile')); 52 53 // Find index of existing Profile menu item. 54 for ($index = 0; $index > count($event->data['items']); $index++) { 55 if ($event->data['items'][$index]->getType() === 'profile') { 56 break; 57 } 58 } 59 array_splice($event->data['items'], $index + 1, 0, [$menuitem]); 60 } 61 62 /** 63 * Check permissions to call the 2fa profile 64 * 65 * @param Doku_Event $event 66 */ 67 public function handlePreProcess(Doku_Event $event) 68 { 69 if ($event->data != 'twofactor_profile') return; 70 71 // We will be handling this action's permissions here. 72 $event->preventDefault(); 73 $event->stopPropagation(); 74 75 // If not logged into the main auth plugin then send there. 76 global $INPUT; 77 global $ID; 78 79 if (!$INPUT->server->has('REMOTE_USER')) { 80 $event->result = false; 81 send_redirect(wl($ID, array('do' => 'login'), true, '&')); 82 return; 83 } 84 85 $this->handleProfile(); 86 } 87 88 /** 89 * @param Doku_Event $event 90 */ 91 public function handleUnknownAction(Doku_Event $event) 92 { 93 if ($event->data != 'twofactor_profile') return; 94 95 $event->preventDefault(); 96 $event->stopPropagation(); 97 $this->printProfile(); 98 } 99 100 /** 101 * Handle POSTs for provider forms 102 */ 103 protected function handleProfile() 104 { 105 global $INPUT; 106 if (!$INPUT->has('provider')) return; 107 $user = $INPUT->server->str('REMOTE_USER'); 108 109 $class = 'helper_plugin_' . $INPUT->str('provider'); 110 /** @var Provider $provider */ 111 $provider = new $class($user); 112 113 if (!checkSecurityToken()) return; 114 115 if (!$provider->isConfigured()) { 116 $provider->handleProfileForm(); 117 } elseif ($INPUT->has('2fa_delete')) { 118 $provider->reset(); 119 $this->manager->getUserDefaultProvider(); // resets the default to the next available 120 } elseif ($INPUT->has('2fa_default')) { 121 $this->manager->setUserDefaultProvider($provider); 122 } 123 } 124 125 /** 126 * Handles the profile form rendering. Displays user manageable settings. 127 */ 128 protected function printProfile() 129 { 130 global $lang; 131 132 echo $this->locale_xhtml('profile'); 133 134 // default provider selection 135 $userproviders = $this->manager->getUserProviders(); 136 $default = $this->manager->getUserDefaultProvider(); 137 if (count($userproviders)) { 138 $form = new Form(['method' => 'POST']); 139 $form->addFieldsetOpen('Default Provider'); 140 foreach ($userproviders as $provider) { 141 $form->addRadioButton('provider', $provider->getLabel()) 142 ->val($provider->getProviderID()) 143 ->attr('checked', $provider->getProviderID() === $default->getProviderID()); 144 } 145 $form->addButton('2fa_default', $lang['btn_save'])->attr('submit'); 146 $form->addFieldsetClose(); 147 echo $form->toHTML(); 148 } 149 150 // iterate over all providers 151 $providers = $this->manager->getAllProviders(); 152 foreach ($providers as $provider) { 153 $form = new dokuwiki\Form\Form(['method' => 'POST']); 154 $form->setHiddenField('do', 'twofactor_profile'); 155 $form->setHiddenField('provider', $provider->getProviderID()); 156 $form->addFieldsetOpen($provider->getLabel()); 157 $provider->renderProfileForm($form); 158 if (!$provider->isConfigured()) { 159 $form->addButton('2fa_submit', $lang['btn_save'])->attr('submit'); 160 } else { 161 $form->addButton('2fa_delete', $lang['btn_delete'])->attr('submit'); 162 } 163 $form->addFieldsetClose(); 164 echo $form->toHTML(); 165 } 166 } 167} 168 169