xref: /plugin/twofactor/action/resendpwd.php (revision c8525a2117e724dfae4ab9910e06d5d95c6ff6ea)
1*c8525a21SAndreas Gohr<?php
2*c8525a21SAndreas Gohr
3*c8525a21SAndreas Gohruse dokuwiki\plugin\twofactor\Manager;
4*c8525a21SAndreas Gohr
5*c8525a21SAndreas Gohr/**
6*c8525a21SAndreas Gohr * DokuWiki Plugin twofactor (Action Component)
7*c8525a21SAndreas Gohr *
8*c8525a21SAndreas Gohr * This adds 2fa handling to the resendpwd action. It will interrupt the normal, first step of the
9*c8525a21SAndreas Gohr * flow and insert our own 2fa form, initialized with the user provided in the reset form. When the user
10*c8525a21SAndreas Gohr * has successfully authenticated, the normal flow will continue. All within the do?do=resendpwd action.
11*c8525a21SAndreas Gohr *
12*c8525a21SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
13*c8525a21SAndreas Gohr * @author  Andreas Gohr <dokuwiki@cosmocode.de>
14*c8525a21SAndreas Gohr */
15*c8525a21SAndreas Gohrclass action_plugin_twofactor_resendpwd extends \dokuwiki\Extension\ActionPlugin
16*c8525a21SAndreas Gohr{
17*c8525a21SAndreas Gohr    /** @inheritDoc */
18*c8525a21SAndreas Gohr    public function register(Doku_Event_Handler $controller)
19*c8525a21SAndreas Gohr    {
20*c8525a21SAndreas Gohr        $controller->register_hook(
21*c8525a21SAndreas Gohr            'ACTION_ACT_PREPROCESS',
22*c8525a21SAndreas Gohr            'BEFORE',
23*c8525a21SAndreas Gohr            $this,
24*c8525a21SAndreas Gohr            'handleActionPreProcess',
25*c8525a21SAndreas Gohr            null,
26*c8525a21SAndreas Gohr            Manager::EVENT_PRIORITY - 1
27*c8525a21SAndreas Gohr        );
28*c8525a21SAndreas Gohr
29*c8525a21SAndreas Gohr        $controller->register_hook(
30*c8525a21SAndreas Gohr            'TPL_ACT_UNKNOWN',
31*c8525a21SAndreas Gohr            'BEFORE',
32*c8525a21SAndreas Gohr            $this,
33*c8525a21SAndreas Gohr            'handleTplActUnknown',
34*c8525a21SAndreas Gohr            null,
35*c8525a21SAndreas Gohr            Manager::EVENT_PRIORITY - 1
36*c8525a21SAndreas Gohr        );
37*c8525a21SAndreas Gohr    }
38*c8525a21SAndreas Gohr
39*c8525a21SAndreas Gohr    /**
40*c8525a21SAndreas Gohr     * Event handler for ACTION_ACT_PREPROCESS
41*c8525a21SAndreas Gohr     *
42*c8525a21SAndreas Gohr     * @see https://www.dokuwiki.org/devel:events:ACTION_ACT_PREPROCESS
43*c8525a21SAndreas Gohr     * @param Doku_Event $event Event object
44*c8525a21SAndreas Gohr     * @param mixed $param optional parameter passed when event was registered
45*c8525a21SAndreas Gohr     * @return void
46*c8525a21SAndreas Gohr     */
47*c8525a21SAndreas Gohr    public function handleActionPreProcess(Doku_Event $event, $param)
48*c8525a21SAndreas Gohr    {
49*c8525a21SAndreas Gohr        if ($event->data !== 'resendpwd') return;
50*c8525a21SAndreas Gohr
51*c8525a21SAndreas Gohr        global $INPUT;
52*c8525a21SAndreas Gohr        if ($INPUT->has('pwauth')) return; // we're already in token phase, don't interrupt
53*c8525a21SAndreas Gohr        if (!$INPUT->str('login')) return; // no user given yet, don't interrupt
54*c8525a21SAndreas Gohr
55*c8525a21SAndreas Gohr        $user = $INPUT->str('login');
56*c8525a21SAndreas Gohr        $manager = Manager::getInstance();
57*c8525a21SAndreas Gohr        $manager->setUser($user);
58*c8525a21SAndreas Gohr
59*c8525a21SAndreas Gohr        if (!$manager->isReady()) return; // no 2fa setup, don't interrupt
60*c8525a21SAndreas Gohr        if (!count($manager->getUserProviders())) return; // no 2fa for this user, don't interrupt
61*c8525a21SAndreas Gohr
62*c8525a21SAndreas Gohr        $code = $INPUT->post->str('2fa_code');
63*c8525a21SAndreas Gohr        $providerID = $INPUT->post->str('2fa_provider');
64*c8525a21SAndreas Gohr        if ($code && $manager->verifyCode($code, $providerID)) {
65*c8525a21SAndreas Gohr            // all is good, don't interrupt
66*c8525a21SAndreas Gohr            Manager::destroyInstance(); // remove our instance so login.php can create a new one
67*c8525a21SAndreas Gohr            return;
68*c8525a21SAndreas Gohr        }
69*c8525a21SAndreas Gohr
70*c8525a21SAndreas Gohr        // we're still here, so we need to interrupt
71*c8525a21SAndreas Gohr        $event->preventDefault();
72*c8525a21SAndreas Gohr        $event->stopPropagation();
73*c8525a21SAndreas Gohr
74*c8525a21SAndreas Gohr        // next, we will overwrite the resendpwd form with our own in TPL_ACT_UNKNOWN
75*c8525a21SAndreas Gohr    }
76*c8525a21SAndreas Gohr
77*c8525a21SAndreas Gohr    /**
78*c8525a21SAndreas Gohr     * Event handler for TPL_ACT_UNKNOWN
79*c8525a21SAndreas Gohr     *
80*c8525a21SAndreas Gohr     * This is executed only when we prevented the default action in handleActionPreProcess()
81*c8525a21SAndreas Gohr     *
82*c8525a21SAndreas Gohr     * @see https://www.dokuwiki.org/devel:events:TPL_ACT_UNKNOWN
83*c8525a21SAndreas Gohr     * @param Doku_Event $event Event object
84*c8525a21SAndreas Gohr     * @param mixed $param optional parameter passed when event was registered
85*c8525a21SAndreas Gohr     * @return void
86*c8525a21SAndreas Gohr     */
87*c8525a21SAndreas Gohr    public function handleTplActUnknown(Doku_Event $event, $param)
88*c8525a21SAndreas Gohr    {
89*c8525a21SAndreas Gohr        if ($event->data !== 'resendpwd') return;
90*c8525a21SAndreas Gohr        $event->stopPropagation();
91*c8525a21SAndreas Gohr        $event->preventDefault();
92*c8525a21SAndreas Gohr
93*c8525a21SAndreas Gohr        global $INPUT;
94*c8525a21SAndreas Gohr
95*c8525a21SAndreas Gohr        $providerID = $INPUT->post->str('2fa_provider');
96*c8525a21SAndreas Gohr
97*c8525a21SAndreas Gohr        $manager = Manager::getInstance();
98*c8525a21SAndreas Gohr        $form = $manager->getCodeForm($providerID);
99*c8525a21SAndreas Gohr
100*c8525a21SAndreas Gohr        // overwrite form defaults, to redo the resendpwd action but with the code supplied
101*c8525a21SAndreas Gohr        $form->setHiddenField('do', 'resendpwd');
102*c8525a21SAndreas Gohr        $form->setHiddenField('login', $INPUT->str('login'));
103*c8525a21SAndreas Gohr        $form->setHiddenField('save', 1);
104*c8525a21SAndreas Gohr
105*c8525a21SAndreas Gohr
106*c8525a21SAndreas Gohr        echo '<div class="plugin_twofactor_login">';
107*c8525a21SAndreas Gohr        echo inlineSVG(__DIR__ . '/../admin.svg');
108*c8525a21SAndreas Gohr        echo $this->locale_xhtml('resendpwd');
109*c8525a21SAndreas Gohr        echo $form->toHTML();
110*c8525a21SAndreas Gohr        echo '</div>';
111*c8525a21SAndreas Gohr    }
112*c8525a21SAndreas Gohr}
113*c8525a21SAndreas Gohr
114