Passed
Pull Request — master (#32)
by Robbie
01:51
created

EnforcementManager::isMFARequired()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 11
nc 4
nop 0
dl 0
loc 22
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\MFA\Service;
4
5
use SilverStripe\Core\Injector\Injectable;
6
use SilverStripe\MFA\Extension\MemberExtension;
7
use SilverStripe\ORM\FieldType\DBDate;
8
use SilverStripe\Security\Member;
9
use SilverStripe\SiteConfig\SiteConfig;
10
11
/**
12
 * The EnforcementManager class is responsible for making decisions regarding multi factor authentication app flow,
13
 * e.g. "is MFA required", "should we redirect to the MFA section", "can the user skip MFA registration" etc.
14
 */
15
class EnforcementManager
16
{
17
    use Injectable;
18
19
    /**
20
     * Whether the current member can skip the multi factor authentication registration process.
21
     *
22
     * This is determined by a combination of:
23
     *  - Whether MFA is required or optional
24
     *  - If MFA is required, whether there is a grace period
25
     *  - If MFA is required and there is a grace period, whether we're currently within that timeframe
26
     *
27
     * @param Member&MemberExtension $member
28
     * @return bool
29
     */
30
    public function canSkipMFA(Member $member)
31
    {
32
        if ($this->isMFARequired()) {
33
            return false;
34
        }
35
36
        // If they've already registered MFA methods we will not allow them to skip the authentication process
37
        $registeredMethods = $member->RegisteredMFAMethods();
38
        if ($registeredMethods->exists()) {
39
            return false;
40
        }
41
42
        // MFA is optional, or is required but might be within a grace period (see isMFARequired)
43
        return true;
44
    }
45
46
    /**
47
     * Whether the authentication process should redirect the user to multi factor authentication registration or
48
     * login.
49
     *
50
     * This is determined by a combination of:
51
     *  - Whether MFA is required or optional
52
     *  - Whether the user has registered MFA methods already
53
     *  - If the user doesn't have any registered MFA methods already, and MFA is optional, whether the user has opted
54
     *    to skip the registration process
55
     *
56
     * Note that in determining this, we ignore whether or not MFA is enabled for the site in general.
57
     *
58
     * @param Member&MemberExtension $member
59
     * @return bool
60
     */
61
    public function shouldRedirectToMFA(Member $member)
62
    {
63
        $isRequired = $this->isMFARequired();
64
        if ($isRequired) {
65
            return true;
66
        }
67
68
        $hasSkipped = $member->HasSkippedMFARegistration;
69
        if (!$hasSkipped) {
70
            return true;
71
        }
72
73
        return false;
74
    }
75
76
    /**
77
     * Whether multi factor authentication is required for site members. This also takes into account whether a
78
     * grace period is set and whether we're currently inside the window for it.
79
     *
80
     * Note that in determining this, we ignore whether or not MFA is enabled for the site in general.
81
     *
82
     * @return bool
83
     */
84
    public function isMFARequired()
85
    {
86
        $siteConfig = SiteConfig::current_site_config();
87
88
        $isRequired = $siteConfig->MFARequired;
89
        if (!$isRequired) {
90
            return false;
91
        }
92
93
        $gracePeriod = $siteConfig->MFAGracePeriodExpires;
94
        if ($isRequired && !$gracePeriod) {
95
            return true;
96
        }
97
98
        /** @var DBDate $gracePeriodDate */
99
        $gracePeriodDate = $siteConfig->dbObject('MFAGracePeriodExpires');
100
        if ($isRequired && $gracePeriodDate->InPast()) {
101
            return true;
102
        }
103
104
        // MFA is required, a grace period is set, and it's in the future
105
        return false;
106
    }
107
}
108