1<?php
2
3use dokuwiki\Form\Form;
4use dokuwiki\plugin\twofactor\OtpField;
5use dokuwiki\plugin\twofactor\Provider;
6
7/**
8 * 2fa provider using an alternative email address
9 */
10class action_plugin_twofactoraltemail extends Provider
11{
12    /** @inheritdoc */
13    public function getLabel()
14    {
15        $label = $this->getLang('name');
16        $email = $this->settings->get('email');
17        if ($email) $label .= ': ' . $email;
18        return $label;
19    }
20
21    /** @inheritdoc */
22    public function isConfigured()
23    {
24        return $this->settings->get('email') &&
25            $this->settings->get('verified');
26
27    }
28
29    /** @inheritdoc */
30    public function renderProfileForm(Form $form)
31    {
32        $email = $this->settings->get('email');
33
34        if (!$email) {
35            $form->addHTML('<p>' . $this->getLang('intro') . '</p>');
36            $form->addTextInput('newemail', $this->getLang('email'))->attr('autocomplete', 'off');
37        } else {
38            $form->addHTML('<p>' . $this->getLang('verifynotice') . '</p>');
39            $form->addElement(new OtpField('verify'));
40        }
41
42        return $form;
43    }
44
45    /** @inheritdoc */
46    public function handleProfileForm()
47    {
48        global $INPUT;
49        global $USERINFO;
50
51        if ($INPUT->str('verify')) {
52            // verification code given, check the code
53            if ($this->checkCode($INPUT->str('verify'))) {
54                $this->settings->set('verified', true);
55            } else {
56                $this->settings->delete('email');
57            }
58        } elseif ($INPUT->str('newemail')) {
59            $newmail = $INPUT->str('newemail');
60            // check that it differs
61            if (strtolower($newmail) == strtolower($USERINFO['mail'])) {
62                msg($this->getLang('notsameemail'), -1);
63                return;
64            }
65
66            // new email has been, set init verification
67            $this->settings->set('email', $newmail);
68
69            try {
70                $this->initSecret();
71                $code = $this->generateCode();
72                $info = $this->transmitMessage($code);
73                msg(hsc($info), 1);
74            } catch (\Exception $e) {
75                msg(hsc($e->getMessage()), -1);
76                $this->settings->delete('email');
77            }
78        }
79    }
80
81    /** @inheritdoc */
82    public function getTolerance()
83    {
84        return $this->getConf('tolerance');
85    }
86
87    /** @inheritdoc */
88    public function transmitMessage($code)
89    {
90        $to = $this->settings->get('email');
91        if (!$to) throw new \Exception($this->getLang('codesentfail'));
92
93        // Create the email object.
94        $body = io_readFile($this->localFN('mail'));
95        $mail = new Mailer();
96        $mail->to($to);
97        $mail->subject($this->getLang('subject'));
98        $mail->setBody($body, ['CODE' => $code]);
99        $result = $mail->send();
100        if (!$result) throw new \Exception($this->getLang('codesentfail'));
101
102        return $this->getLang('codesent');
103    }
104}
105