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

MemberResetExtension   A

Complexity

Total Complexity 4

Size/Duplication

Total Lines 60
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 4
eloc 23
dl 0
loc 60
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A generateAccountResetTokenAndStoreHash() 0 18 2
A updateCMSFields() 0 5 1
A getMemberByAccountResetToken() 0 11 1
1
<?php
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
     * @throws PasswordEncryptor_NotFoundException
40
     * @throws ValidationException
41
     */
42
    public function generateAccountResetTokenAndStoreHash(): string
43
    {
44
        $lifetime = $this->owner->config()->auto_login_token_lifetime;
45
46
        do {
47
            $generator = new RandomGenerator();
48
            $token = $generator->randomToken();
49
            $hash = $this->owner->encryptWithUserSettings($token);
50
        } while (DataObject::get_one(Member::class, [
51
            '"Member"."AccountResetHash"' => $hash,
52
        ]));
53
54
        $this->owner->AccountResetHash = $hash;
55
        $this->owner->AccountResetExpired = date('Y-m-d H:i:s', time() + $lifetime);
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
     * @throws PasswordEncryptor_NotFoundException
68
     */
69
    public function getMemberByAccountResetToken(string $token): ?Member
70
    {
71
        $hash = $this->owner->encryptWithUserSettings($token);
72
73
        /** @var Member $member */
74
        $member = Member::get()->filter([
75
            'AutoLoginHash' => $hash,
76
            'AutoLoginExpired:GreaterThan' => DBDatetime::now()->getValue(),
77
        ])->first();
78
79
        return $member;
80
    }
81
}
82