xref: /dokuwiki/inc/Action/Resendpwd.php (revision 6723156fd9886ff7204e21fb8bf9240b9223b40f)
1f21dad39SAndreas Gohr<?php
2f21dad39SAndreas Gohr
3f21dad39SAndreas Gohrnamespace dokuwiki\Action;
4f21dad39SAndreas Gohr
5*6723156fSAndreas Gohruse dokuwiki\Ui\UserResendPwd;
6f21dad39SAndreas Gohruse dokuwiki\Action\Exception\ActionAbort;
7480336a3SAndreas Gohruse dokuwiki\Action\Exception\ActionDisabledException;
879a2d784SGerrit Uitslaguse dokuwiki\Extension\AuthPlugin;
9a838eeebSSatoshi Saharause dokuwiki\Ui;
10f21dad39SAndreas Gohr
11ab583a1bSAndreas Gohr/**
12ab583a1bSAndreas Gohr * Class Resendpwd
13ab583a1bSAndreas Gohr *
14ab583a1bSAndreas Gohr * Handle password recovery
15ab583a1bSAndreas Gohr *
16ab583a1bSAndreas Gohr * @package dokuwiki\Action
17ab583a1bSAndreas Gohr */
18a838eeebSSatoshi Saharaclass Resendpwd extends AbstractAclAction
19a838eeebSSatoshi Sahara{
20f21dad39SAndreas Gohr    /** @inheritdoc */
21a838eeebSSatoshi Sahara    public function minimumPermission()
22a838eeebSSatoshi Sahara    {
23f21dad39SAndreas Gohr        return AUTH_NONE;
24f21dad39SAndreas Gohr    }
25f21dad39SAndreas Gohr
26f21dad39SAndreas Gohr    /** @inheritdoc */
27a838eeebSSatoshi Sahara    public function checkPreconditions()
28a838eeebSSatoshi Sahara    {
29b2c9cd19SAndreas Gohr        parent::checkPreconditions();
30480336a3SAndreas Gohr
3179a2d784SGerrit Uitslag        /** @var AuthPlugin $auth */
32480336a3SAndreas Gohr        global $auth;
33480336a3SAndreas Gohr        global $conf;
34a838eeebSSatoshi Sahara        if (isset($conf['resendpasswd']) && !$conf['resendpasswd'])
35a838eeebSSatoshi Sahara            throw new ActionDisabledException(); //legacy option
36480336a3SAndreas Gohr        if (!$auth->canDo('modPass')) throw new ActionDisabledException();
37480336a3SAndreas Gohr    }
38480336a3SAndreas Gohr
39480336a3SAndreas Gohr    /** @inheritdoc */
40a838eeebSSatoshi Sahara    public function preProcess()
41a838eeebSSatoshi Sahara    {
42f21dad39SAndreas Gohr        if ($this->resendpwd()) {
43f21dad39SAndreas Gohr            throw new ActionAbort('login');
44f21dad39SAndreas Gohr        }
45f21dad39SAndreas Gohr    }
46f21dad39SAndreas Gohr
474347c5bbSAndreas Gohr    /** @inheritdoc */
48a838eeebSSatoshi Sahara    public function tplContent()
49a838eeebSSatoshi Sahara    {
50*6723156fSAndreas Gohr        (new UserResendPwd)->show();
514347c5bbSAndreas Gohr    }
524347c5bbSAndreas Gohr
53f21dad39SAndreas Gohr    /**
54f21dad39SAndreas Gohr     * Send a  new password
55f21dad39SAndreas Gohr     *
56f21dad39SAndreas Gohr     * This function handles both phases of the password reset:
57f21dad39SAndreas Gohr     *
58f21dad39SAndreas Gohr     *   - handling the first request of password reset
59f21dad39SAndreas Gohr     *   - validating the password reset auth token
60f21dad39SAndreas Gohr     *
61f21dad39SAndreas Gohr     * @author Benoit Chesneau <benoit@bchesneau.info>
62f21dad39SAndreas Gohr     * @author Chris Smith <chris@jalakai.co.uk>
63f21dad39SAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
64f21dad39SAndreas Gohr     * @fixme this should be split up into multiple methods
65f21dad39SAndreas Gohr     * @return bool true on success, false on any error
66f21dad39SAndreas Gohr     */
67a838eeebSSatoshi Sahara    protected function resendpwd()
68a838eeebSSatoshi Sahara    {
69f21dad39SAndreas Gohr        global $lang;
70f21dad39SAndreas Gohr        global $conf;
7179a2d784SGerrit Uitslag        /* @var AuthPlugin $auth */
72f21dad39SAndreas Gohr        global $auth;
73f21dad39SAndreas Gohr        global $INPUT;
74f21dad39SAndreas Gohr
75f21dad39SAndreas Gohr        if (!actionOK('resendpwd')) {
76f21dad39SAndreas Gohr            msg($lang['resendna'], -1);
77f21dad39SAndreas Gohr            return false;
78f21dad39SAndreas Gohr        }
79f21dad39SAndreas Gohr
80f21dad39SAndreas Gohr        $token = preg_replace('/[^a-f0-9]+/', '', $INPUT->str('pwauth'));
81f21dad39SAndreas Gohr
82f21dad39SAndreas Gohr        if ($token) {
83f21dad39SAndreas Gohr            // we're in token phase - get user info from token
84f21dad39SAndreas Gohr
852401f18dSSyntaxseed            $tfile = $conf['cachedir'] .'/'. $token[0] .'/'. $token . '.pwauth';
86f21dad39SAndreas Gohr            if (!file_exists($tfile)) {
87f21dad39SAndreas Gohr                msg($lang['resendpwdbadauth'], -1);
88f21dad39SAndreas Gohr                $INPUT->remove('pwauth');
89f21dad39SAndreas Gohr                return false;
90f21dad39SAndreas Gohr            }
91f21dad39SAndreas Gohr            // token is only valid for 3 days
92f21dad39SAndreas Gohr            if ((time() - filemtime($tfile)) > (3 * 60 * 60 * 24)) {
93f21dad39SAndreas Gohr                msg($lang['resendpwdbadauth'], -1);
94f21dad39SAndreas Gohr                $INPUT->remove('pwauth');
95f21dad39SAndreas Gohr                @unlink($tfile);
96f21dad39SAndreas Gohr                return false;
97f21dad39SAndreas Gohr            }
98f21dad39SAndreas Gohr
99f21dad39SAndreas Gohr            $user = io_readfile($tfile);
100f21dad39SAndreas Gohr            $userinfo = $auth->getUserData($user, $requireGroups = false);
101fd853d4aSfiwswe            if (empty($userinfo['mail'])) {
102f21dad39SAndreas Gohr                msg($lang['resendpwdnouser'], -1);
103f21dad39SAndreas Gohr                return false;
104f21dad39SAndreas Gohr            }
105f21dad39SAndreas Gohr
106f21dad39SAndreas Gohr            if (!$conf['autopasswd']) { // we let the user choose a password
107f21dad39SAndreas Gohr                $pass = $INPUT->str('pass');
108f21dad39SAndreas Gohr
109f21dad39SAndreas Gohr                // password given correctly?
110f21dad39SAndreas Gohr                if (!$pass) return false;
111f21dad39SAndreas Gohr                if ($pass != $INPUT->str('passchk')) {
112f21dad39SAndreas Gohr                    msg($lang['regbadpass'], -1);
113f21dad39SAndreas Gohr                    return false;
114f21dad39SAndreas Gohr                }
115f21dad39SAndreas Gohr
116f21dad39SAndreas Gohr                // change it
117*6723156fSAndreas Gohr                if (!$auth->triggerUserMod('modify', [$user, ['pass' => $pass]])) {
118f21dad39SAndreas Gohr                    msg($lang['proffail'], -1);
119f21dad39SAndreas Gohr                    return false;
120f21dad39SAndreas Gohr                }
121f21dad39SAndreas Gohr
122f21dad39SAndreas Gohr            } else { // autogenerate the password and send by mail
123f21dad39SAndreas Gohr
124f21dad39SAndreas Gohr                $pass = auth_pwgen($user);
125*6723156fSAndreas Gohr                if (!$auth->triggerUserMod('modify', [$user, ['pass' => $pass]])) {
126f21dad39SAndreas Gohr                    msg($lang['proffail'], -1);
127f21dad39SAndreas Gohr                    return false;
128f21dad39SAndreas Gohr                }
129f21dad39SAndreas Gohr
130f21dad39SAndreas Gohr                if (auth_sendPassword($user, $pass)) {
131f21dad39SAndreas Gohr                    msg($lang['resendpwdsuccess'], 1);
132f21dad39SAndreas Gohr                } else {
133f21dad39SAndreas Gohr                    msg($lang['regmailfail'], -1);
134f21dad39SAndreas Gohr                }
135f21dad39SAndreas Gohr            }
136f21dad39SAndreas Gohr
137f21dad39SAndreas Gohr            @unlink($tfile);
138f21dad39SAndreas Gohr            return true;
139f21dad39SAndreas Gohr
140f21dad39SAndreas Gohr        } else {
141f21dad39SAndreas Gohr            // we're in request phase
142f21dad39SAndreas Gohr
143f21dad39SAndreas Gohr            if (!$INPUT->post->bool('save')) return false;
144f21dad39SAndreas Gohr
145f21dad39SAndreas Gohr            if (!$INPUT->post->str('login')) {
146f21dad39SAndreas Gohr                msg($lang['resendpwdmissing'], -1);
147f21dad39SAndreas Gohr                return false;
148f21dad39SAndreas Gohr            } else {
149f21dad39SAndreas Gohr                $user = trim($auth->cleanUser($INPUT->post->str('login')));
150f21dad39SAndreas Gohr            }
151f21dad39SAndreas Gohr
152f21dad39SAndreas Gohr            $userinfo = $auth->getUserData($user, $requireGroups = false);
153fd853d4aSfiwswe            if (empty($userinfo['mail'])) {
154f21dad39SAndreas Gohr                msg($lang['resendpwdnouser'], -1);
155f21dad39SAndreas Gohr                return false;
156f21dad39SAndreas Gohr            }
157f21dad39SAndreas Gohr
158f21dad39SAndreas Gohr            // generate auth token
159f21dad39SAndreas Gohr            $token = md5(auth_randombytes(16)); // random secret
1602401f18dSSyntaxseed            $tfile = $conf['cachedir'] .'/'. $token[0] .'/'. $token .'.pwauth';
161*6723156fSAndreas Gohr            $url = wl('', ['do' => 'resendpwd', 'pwauth' => $token], true, '&');
162f21dad39SAndreas Gohr
163f21dad39SAndreas Gohr            io_saveFile($tfile, $user);
164f21dad39SAndreas Gohr
165f21dad39SAndreas Gohr            $text = rawLocale('pwconfirm');
166*6723156fSAndreas Gohr            $trep = [
167f21dad39SAndreas Gohr                'FULLNAME' => $userinfo['name'],
168f21dad39SAndreas Gohr                'LOGIN' => $user,
169f21dad39SAndreas Gohr                'CONFIRM' => $url
170*6723156fSAndreas Gohr            ];
171f21dad39SAndreas Gohr
172f21dad39SAndreas Gohr            $mail = new \Mailer();
173f21dad39SAndreas Gohr            $mail->to($userinfo['name'] .' <'. $userinfo['mail'] .'>');
174f21dad39SAndreas Gohr            $mail->subject($lang['regpwmail']);
175f21dad39SAndreas Gohr            $mail->setBody($text, $trep);
176f21dad39SAndreas Gohr            if ($mail->send()) {
177f21dad39SAndreas Gohr                msg($lang['resendpwdconfirm'], 1);
178f21dad39SAndreas Gohr            } else {
179f21dad39SAndreas Gohr                msg($lang['regmailfail'], -1);
180f21dad39SAndreas Gohr            }
181f21dad39SAndreas Gohr            return true;
182f21dad39SAndreas Gohr        }
183f21dad39SAndreas Gohr        // never reached
184f21dad39SAndreas Gohr    }
185f21dad39SAndreas Gohr
186f21dad39SAndreas Gohr}
187