xref: /plugin/twofactor/action/profile.php (revision 30625b49d43f35ae8dc732acccd71d5a391980ea)
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