Completed
Push — master ( 0e58f5...d2de37 )
by
unknown
13s
created

MemberExtension::getBackupcodes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Firesphere\BootstrapMFA\Extensions;
4
5
use DateTime;
6
use Firesphere\BootstrapMFA\Authenticators\BootstrapMFAAuthenticator;
7
use Firesphere\BootstrapMFA\Models\BackupCode;
8
use Firesphere\BootstrapMFA\Providers\BootstrapMFAProvider;
9
use SilverStripe\Control\Controller;
10
use SilverStripe\Core\Config\Config;
11
use SilverStripe\Core\Injector\Injector;
12
use SilverStripe\Forms\CheckboxField;
13
use SilverStripe\Forms\FieldList;
14
use SilverStripe\Forms\LiteralField;
15
use SilverStripe\Forms\Tab;
16
use SilverStripe\ORM\DataExtension;
17
use SilverStripe\ORM\DataList;
18
use SilverStripe\ORM\FieldType\DBDatetime;
19
use SilverStripe\Security\Member;
20
use SilverStripe\SiteConfig\SiteConfig;
21
22
/**
23
 * Class MemberExtension
24
 *
25
 * @package Firesphere\BootstrapMFA
26
 * @property Member|MemberExtension $owner
27
 * @property boolean $MFAEnabled
28
 * @property string $PrimaryMFA
29
 * @method DataList|BackupCode[] BackupCodes()
30
 */
31
class MemberExtension extends DataExtension
32
{
33
    /**
34
     * @var array
35
     */
36
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
37
        'MFAEnabled' => 'Boolean(false)',
38
        'PrimaryMFA' => 'Varchar(255)',
39
    ];
40
41
    /**
42
     * @var array
43
     */
44
    private static $has_many = [
0 ignored issues
show
introduced by
The private property $has_many is not used, and could be removed.
Loading history...
45
        'BackupCodes' => BackupCode::class
46
    ];
47
48
    /**
49
     * @var bool
50
     */
51
    public $updateMFA = false;
52
53
    /**
54
     * @param FieldList $fields
55
     */
56
    public function updateCMSFields(FieldList $fields)
57
    {
58
        // Force the updateMFA value of this field. This resolves that when it's checked and submitted
59
        // The checkbox stays checked.
60
        $this->updateMFA = false;
61
        $fields->removeByName(['BackupCodes', 'PrimaryMFA']);
62
        $session = Controller::curr()->getRequest()->getSession();
63
        $rootTabSet = $fields->fieldByName('Root');
64
        $field = LiteralField::create('tokens', $session->get('tokens'));
65
        // We need to push the tab for unit tests
66
        $tab = Tab::create(
67
            'MFA',
68
            _t(self::class . '.MFATAB', 'Multi Factor Authentication')
69
        );
70
        $rootTabSet->push(
71
            $tab
72
        );
73
        $fields->addFieldToTab(
74
            'Root.MFA',
75
            $enabled = CheckboxField::create('MFAEnabled', _t(self::class . '.MFAEnabled', 'MFA Enabled'))
76
        );
77
        $fields->addFieldToTab(
78
            'Root.MFA',
79
            CheckboxField::create('updateMFA', _t(self::class . '.RESETMFA', 'Reset MFA codes'))
80
        );
81
82
        if ($session->get('tokens')) {
83
            $fields->addFieldToTab('Root.MFA', $field);
84
            $session->clear('tokens');
85
        }
86
    }
87
88
    /**
89
     * Force enable MFA on the member if needed
90
     */
91
    public function onBeforeWrite()
92
    {
93
        if (!$this->owner->MFAEnabled && SiteConfig::current_site_config()->ForceMFA) {
94
            $this->owner->MFAEnabled = true;
95
            $this->owner->updateMFA = true;
96
        }
97
    }
98
99
    /**
100
     *
101
     * @throws \Psr\Container\NotFoundExceptionInterface
102
     */
103
    public function onAfterWrite()
104
    {
105
        parent::onAfterWrite();
106
        if ($this->owner->updateMFA) {
107
            $provider = Injector::inst()->get(BootstrapMFAProvider::class);
108
            $provider->setMember($this->owner);
109
            $provider->updateTokens();
110
        }
111
    }
112
113
    public function isInGracePeriod()
114
    {
115
        /** @var Member|MemberExtension $member */
116
        $member = $this->owner;
117
118
        // If MFA is enabled on the member, we're always using it
119
        if ($member->MFAEnabled) {
120
            return false;
121
        }
122
123
        /** @var SiteConfig|SiteConfigExtension $config */
124
        $config = SiteConfig::current_site_config();
125
        // If MFA is not enforced, we're in an endless grace period
126
        if ($config->ForceMFA === null) {
127
            return true;
128
        }
129
130
        // Default the grace start day
131
        $graceStartDay = ($member->Created > $config->ForceMFA) ? $member->Created : $config->ForceMFA;
0 ignored issues
show
Bug Best Practice introduced by
The property Created does not exist on Firesphere\BootstrapMFA\Extensions\MemberExtension. Did you maybe forget to declare it?
Loading history...
132
        $graceStartDay = new DateTime($graceStartDay);
133
134
        $gracePeriodInDays = Config::inst()->get(BootstrapMFAAuthenticator::class, 'grace_period');
135
136
        $nowDate = new DateTime(DBDatetime::now()->format(DBDatetime::ISO_DATE));
137
138
        $daysSinceGraceStart = $nowDate->diff($graceStartDay)->days;
139
140
        return $daysSinceGraceStart < $gracePeriodInDays;
141
    }
142
}
143