Passed
Pull Request — master (#127)
by Garion
02:22
created

getMemberByAccountResetToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
namespace SilverStripe\MFA\Extension;
4
5
use SilverStripe\Forms\FieldList;
6
use SilverStripe\ORM\DataExtension;
7
use SilverStripe\ORM\DataObject;
8
use SilverStripe\ORM\FieldType\DBDatetime;
9
use SilverStripe\ORM\ValidationException;
10
use SilverStripe\Security\Member;
11
use SilverStripe\Security\PasswordEncryptor_NotFoundException;
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 owner
19
 */
20
class MemberResetExtension extends DataExtension
21
{
22
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
23
        'AccountResetHash' => 'Varchar(160)',
24
        'AccountResetExpired' => 'Datetime',
25
    ];
26
27
    public function updateCMSFields(FieldList $fields)
28
    {
29
        $fields->removeByName(['AccountResetHash', 'AccountResetExpired']);
30
31
        return $fields;
32
    }
33
34
    /**
35
     * Mirrors the implementation in Member::generateAutologinTokenAndStoreHash(),
36
     * but against the AccountReset fields.
37
     *
38
     * @return string
39
     */
40
    public function generateAccountResetTokenAndStoreHash(): string
41
    {
42
        $lifetime = $this->owner->config()->auto_login_token_lifetime;
43
        $generator = new RandomGenerator();
44
45
        do {
46
            $token = $generator->randomToken();
47
            $hash = $this->owner->encryptWithUserSettings($token);
48
        } while (DataObject::get_one(Member::class, [
49
            '"Member"."AccountResetHash"' => $hash,
50
        ]));
51
52
        $this->owner->AccountResetHash = $hash;
53
        $this->owner->AccountResetExpired = DBDatetime::create(
54
            DBDatetime::now()->getTimestamp() + $lifetime
55
        )->Rfc2822();
56
57
        $this->owner->write();
58
59
        return $token;
60
    }
61
62
    /**
63
     * Based on Member::validateAutoLoginToken() and Member::member_from_autologinhash().
64
     *
65
     * @param string $token
66
     * @return Member
67
     */
68
    public function getMemberByAccountResetToken(string $token): ?Member
69
    {
70
        $hash = $this->owner->encryptWithUserSettings($token);
71
72
        /** @var Member $member */
73
        $member = Member::get()->filter([
74
            'AutoLoginHash' => $hash,
75
            'AutoLoginExpired:GreaterThan' => DBDatetime::now()->getValue(),
76
        ])->first();
77
78
        return $member;
79
    }
80
}
81