Issues (102)

src/Extension/AccountReset/MemberExtension.php (1 issue)

Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SilverStripe\MFA\Extension\AccountReset;
6
7
use SilverStripe\Forms\FieldList;
8
use SilverStripe\ORM\DataExtension;
9
use SilverStripe\ORM\DataObject;
10
use SilverStripe\ORM\FieldType\DBDatetime;
11
use SilverStripe\Security\Member;
12
use SilverStripe\Security\RandomGenerator;
13
14
/**
15
 * Provides DB columns / methods for account resets on Members
16
 *
17
 * @package SilverStripe\MFA\Extension
18
 * @property Member&MemberExtension owner
19
 * @property string AccountResetHash
20
 * @property DBDatetime AccountResetExpired
21
 */
22
class MemberExtension extends DataExtension
23
{
24
    private static $db = [
0 ignored issues
show
The private property $db is not used, and could be removed.
Loading history...
25
        'AccountResetHash' => 'Varchar(160)',
26
        'AccountResetExpired' => 'Datetime',
27
    ];
28
29
    public function updateCMSFields(FieldList $fields)
30
    {
31
        $fields->removeByName(['AccountResetHash', 'AccountResetExpired']);
32
33
        return $fields;
34
    }
35
36
    /**
37
     * Mirrors the implementation in Member::generateAutologinTokenAndStoreHash(),
38
     * but against the AccountReset fields.
39
     *
40
     * @return string
41
     */
42
    public function generateAccountResetTokenAndStoreHash(): string
43
    {
44
        $lifetime = $this->owner->config()->auto_login_token_lifetime;
45
        $generator = new RandomGenerator();
46
47
        do {
48
            $token = $generator->randomToken();
49
            $hash = $this->owner->encryptWithUserSettings($token);
50
        } while (
51
            DataObject::get_one(Member::class, [
52
            '"Member"."AccountResetHash"' => $hash,
53
            ])
54
        );
55
56
        $this->owner->AccountResetHash = $hash;
57
        $this->owner->AccountResetExpired = DBDatetime::create()->setValue(
58
            DBDatetime::now()->getTimestamp() + $lifetime
59
        )->Rfc2822();
60
61
        $this->owner->write();
62
63
        return $token;
64
    }
65
66
    /**
67
     * Based on Member::validateAutoLoginToken() and Member::member_from_autologinhash().
68
     *
69
     * @param string $token
70
     * @return bool
71
     */
72
    public function verifyAccountResetToken(string $token): bool
73
    {
74
        if (!$this->owner->exists()) {
75
            return false;
76
        }
77
78
        $hash = $this->owner->encryptWithUserSettings($token);
79
80
        return (
81
            $this->owner->AccountResetHash === $hash &&
82
            $this->owner->AccountResetExpired >= DBDatetime::now()->getValue()
83
        );
84
    }
85
}
86