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

MemberMFAExtension::currentUserCanViewMFAConfig()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
namespace SilverStripe\MFA\Extension;
3
4
use SilverStripe\Forms\FieldList;
5
use SilverStripe\MFA\FormField\RegisteredMFAMethodListField;
6
use SilverStripe\MFA\Method\MethodInterface;
7
use SilverStripe\MFA\Model\RegisteredMethod;
8
use SilverStripe\ORM\DataExtension;
9
use SilverStripe\ORM\HasManyList;
10
use SilverStripe\Security\Member;
11
use SilverStripe\Security\Permission;
12
use SilverStripe\Security\PermissionProvider;
13
use SilverStripe\Security\Security;
14
15
/**
16
 * Extend Member to add relationship to registered methods and track some specific preferences
17
 *
18
 * @method RegisteredMethod[]|HasManyList RegisteredMFAMethods
19
 * @property MethodInterface DefaultRegisteredMethod
20
 * @property string DefaultRegisteredMethodID
21
 * @property bool HasSkippedMFARegistration
22
 * @property Member|MemberMFAExtension owner
23
 */
24
class MemberMFAExtension extends DataExtension implements PermissionProvider
25
{
26
    const MFA_ADMINISTER_REGISTERED_METHODS = 'MFA_ADMINISTER_REGISTERED_METHODS';
27
28
    private static $has_many = [
0 ignored issues
show
introduced by
The private property $has_many is not used, and could be removed.
Loading history...
29
        'RegisteredMFAMethods' => RegisteredMethod::class,
30
    ];
31
32
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
33
        'DefaultRegisteredMethodID' => 'Int',
34
        'HasSkippedMFARegistration' => 'Boolean',
35
    ];
36
37
    /**
38
     * Accessor for the `DefaultRegisteredMethod` property
39
     *
40
     * This is replicating the usual functionality of a has_one relation but does it like this so we can ensure the same
41
     * instance of the MethodInterface is provided regardless if you access it through the has_one or the has_many.
42
     *
43
     * @return MethodInterface
44
     */
45
    public function getDefaultRegisteredMethod()
46
    {
47
        return $this->owner->RegisteredMFAMethods()->byId($this->owner->DefaultRegisteredMethodID);
0 ignored issues
show
Bug introduced by
It seems like $this->owner->DefaultRegisteredMethodID can also be of type string; however, parameter $id of SilverStripe\ORM\DataList::byID() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

47
        return $this->owner->RegisteredMFAMethods()->byId(/** @scrutinizer ignore-type */ $this->owner->DefaultRegisteredMethodID);
Loading history...
Bug Best Practice introduced by
The expression return $this->owner->Reg...aultRegisteredMethodID) returns the type SilverStripe\ORM\DataObject which is incompatible with the documented return type SilverStripe\MFA\Method\MethodInterface.
Loading history...
48
    }
49
50
    public function updateCMSFields(FieldList $fields)
51
    {
52
        $fields->removeByName(['DefaultRegisteredMethodID', 'HasSkippedMFARegistration', 'RegisteredMFAMethods']);
53
54
        if (!$this->currentUserCanViewMFAConfig()) {
55
            return $fields;
56
        }
57
58
        $fields->addFieldToTab(
59
            'Root.Main',
60
            $methodListField = RegisteredMFAMethodListField::create(
61
                'MFASettings',
62
                _t(__CLASS__ . '.MFA_SETTINGS_FIELD_LABEL', 'Multi Factor Authentication settings (MFA)'),
63
                $this->owner
64
            )
65
        );
66
67
        if (!$this->currentUserCanEditMFAConfig()) {
68
            $methodListField->setReadonly(true);
69
        }
70
71
        return $fields;
72
    }
73
74
    /**
75
     * Determines whether the logged in user has sufficient permission to see the MFA config for this Member.
76
     *
77
     * @return bool
78
     */
79
    public function currentUserCanViewMFAConfig()
80
    {
81
        return (Permission::check(self::MFA_ADMINISTER_REGISTERED_METHODS)
82
            || $this->currentUserCanEditMFAConfig());
83
    }
84
85
    /**
86
     * Determines whether the logged in user has sufficient permission to modify the MFA config for this Member.
87
     * Note that this is different from being able to _reset_ the config (which administrators can do).
88
     *
89
     * @return bool
90
     */
91
    public function currentUserCanEditMFAConfig()
92
    {
93
        return (Security::getCurrentUser() && Security::getCurrentUser()->ID === $this->owner->ID);
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist on SilverStripe\MFA\Extension\MemberMFAExtension. Did you maybe forget to declare it?
Loading history...
94
    }
95
96
    /**
97
     * Provides the MFA view/reset permission for selection in the permission list in the CMS.
98
     *
99
     * @return array
100
     */
101
    public function providePermissions()
102
    {
103
        $label = _t(
104
            __CLASS__ . '.MFA_PERMISSION_LABEL',
105
            'View/reset MFA configuration for other members'
106
        );
107
108
        $category = _t(
109
            'SilverStripe\\Security\\Permission.PERMISSIONS_CATEGORY',
110
            'Roles and access permissions'
111
        );
112
113
        $description = _t(
114
            __CLASS__ . '.MFA_PERMISSION_DESCRIPTION',
115
            'Ability to view and reset registered MFA methods for other members.'
116
            . ' Requires the "Access to \'Security\' section" permission.'
117
        );
118
119
        return [
120
            self::MFA_ADMINISTER_REGISTERED_METHODS => [
121
                'name' => $label,
122
                'category' => $category,
123
                'help' => $description,
124
                'sort' => 200,
125
            ],
126
        ];
127
    }
128
}
129