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

SchemaGenerator   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 101
rs 10
c 0
b 0
f 0
wmc 8

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getSchema() 0 20 1
A getRegisteredMethods() 0 16 2
A getAvailableMethods() 0 25 3
A getDefaultMethod() 0 4 2
1
<?php
2
3
namespace SilverStripe\MFA\Service;
4
5
use SilverStripe\Core\Extensible;
6
use SilverStripe\Core\Injector\Injectable;
7
use SilverStripe\MFA\Extension\MemberExtension;
8
use SilverStripe\Security\Member;
9
10
/**
11
 * Generates a multi-factor authentication frontend app schema from the given request
12
 */
13
class SchemaGenerator
14
{
15
    use Extensible;
16
    use Injectable;
17
18
    /**
19
     * Gets the schema data for the multi factor authentication app, using the current Member as context
20
     *
21
     * @param Member&MemberExtension $member
22
     * @return array
23
     */
24
    public function getSchema(Member $member)
25
    {
26
        $enforcementManager = EnforcementManager::singleton();
27
28
        $registeredMethods = $this->getRegisteredMethods($member);
29
30
        // Skip registration details if the user has already registered this method
31
        $exclude = array_column($registeredMethods, 'urlSegment');
32
33
        $schema = [
34
            'registeredMethods' => $registeredMethods,
35
            'availableMethods' => $this->getAvailableMethods($exclude),
36
            'defaultMethod' => $this->getDefaultMethod($member),
37
            'canSkip' => $enforcementManager->canSkipMFA($member),
38
            'shouldRedirect' => $enforcementManager->shouldRedirectToMFA($member),
39
        ];
40
41
        $this->extend('updateSchema', $schema);
42
43
        return $schema;
44
    }
45
46
    /**
47
     * Get a list of methods registered to the user
48
     *
49
     * @param Member&MemberExtension $member
50
     * @return array[]
51
     */
52
    protected function getRegisteredMethods(Member $member)
53
    {
54
        $registeredMethods = $member->RegisteredMFAMethods();
55
56
        // Generate a map of URL Segments to 'lead in labels', which are used to describe the method in the login UI
57
        $registeredMethodDetails = [];
58
        foreach ($registeredMethods as $registeredMethod) {
59
            $method = $registeredMethod->getMethod();
60
61
            $registeredMethodDetails[] = [
62
                'urlSegment' => $method->getURLSegment(),
63
                'leadInLabel' => $method->getLoginHandler()->getLeadInLabel()
64
            ];
65
        }
66
67
        return $registeredMethodDetails;
68
    }
69
70
    /**
71
     * Get details in a list for all available methods, optionally excluding those with urlSegments provided in
72
     * $exclude
73
     *
74
     * @param array $exclude
75
     * @return array[]
76
     */
77
    protected function getAvailableMethods(array $exclude = [])
78
    {
79
        // Prepare an array to hold details for methods available to register
80
        $availableMethods = [];
81
82
        // Get all methods enabled on the site
83
        $allMethods = MethodRegistry::singleton()->getMethods();
84
85
        // Compile details for methods that aren't already registered to the user
86
        foreach ($allMethods as $method) {
87
            if (in_array($method->getURLSegment(), $exclude)) {
88
                continue;
89
            }
90
91
            $registerHandler = $method->getRegisterHandler();
92
93
            $availableMethods[] = [
94
                'urlSegment' => $method->getURLSegment(),
95
                'name' => $registerHandler->getName(),
96
                'description' => $registerHandler->getDescription(),
97
                'supportLink' => $registerHandler->getSupportLink(),
98
            ];
99
        }
100
101
        return $availableMethods;
102
    }
103
104
    /**
105
     * Get the URL Segment for the configured default method on the current member, or null if none is configured
106
     *
107
     * @param Member&MemberExtension $member
108
     * @return string|null
109
     */
110
    protected function getDefaultMethod(Member $member)
111
    {
112
        $defaultMethod = $member->DefaultRegisteredMethod;
113
        return $defaultMethod ? $defaultMethod->getMethod()->getURLSegment() : null;
114
    }
115
}
116