Issues (98)

src/Model/HealthCheckProviderSecurity.php (19 issues)

1
<?php
2
3
namespace Sunnysideup\HealthCheckProvider\Model;
4
5
use SilverStripe\Forms\CheckboxField;
6
use SilverStripe\Forms\ReadonlyField;
7
use SilverStripe\ORM\DataObject;
8
use SilverStripe\Security\Member;
9
use SilverStripe\Security\Security;
10
11
class HealthCheckProviderSecurity extends DataObject
12
{
13
    #######################
14
    ### Names Section
15
    #######################
16
17
    private static $singular_name = 'Security Check';
0 ignored issues
show
The private property $singular_name is not used, and could be removed.
Loading history...
18
19
    private static $plural_name = 'Security Checks';
0 ignored issues
show
The private property $plural_name is not used, and could be removed.
Loading history...
20
21
    private static $table_name = 'HealthCheckProviderSecurity';
0 ignored issues
show
The private property $table_name is not used, and could be removed.
Loading history...
22
23
    #######################
24
    ### Model Section
25
    #######################
26
27
    private static $db = [
0 ignored issues
show
The private property $db is not used, and could be removed.
Loading history...
28
        'Secret' => 'Varchar(255)',
29
        'IpAddress' => 'Varchar(64)',
30
        'Allowed' => 'Boolean',
31
        'AllowAllData' => 'Boolean',
32
        'DefinitelyNotOk' => 'Boolean',
33
        'AccessCount' => 'Int',
34
    ];
35
36
    private static $has_one = [
0 ignored issues
show
The private property $has_one is not used, and could be removed.
Loading history...
37
        'Editor' => Member::class,
38
    ];
39
40
    #######################
41
    ### Further DB Field Details
42
    #######################
43
44
    private static $default_sort = [
0 ignored issues
show
The private property $default_sort is not used, and could be removed.
Loading history...
45
        'Allowed' => 'DESC',
46
        'Created' => 'DESC',
47
    ];
48
49
    #######################
50
    ### Field Names and Presentation Section
51
    #######################
52
53
    private static $field_labels = [
0 ignored issues
show
The private property $field_labels is not used, and could be removed.
Loading history...
54
        'Secret' => 'Api Key Provided by Retriever',
55
        'IpAddress' => 'IP Address of Retriever',
56
        'Allowed' => 'Allow this key from this IP address?',
57
        'Editor' => 'Report Editor',
58
        'EditorID' => 'Report Editor',
59
    ];
60
61
    private static $summary_fields = [
0 ignored issues
show
The private property $summary_fields is not used, and could be removed.
Loading history...
62
        'Created' => 'First Access',
63
        'Allowed.Nice' => 'Allow',
64
        'Editor.Title' => 'Editor',
65
        'Secret' => 'Api Key Provided',
66
        'IpAddress' => 'IP',
67
        'AccessCount' => 'Access Count',
68
    ];
69
70
    #######################
71
    ### Casting Section
72
    #######################
73
74
    private static $casting = [
0 ignored issues
show
The private property $casting is not used, and could be removed.
Loading history...
75
        'Title' => 'Varchar',
76
    ];
77
78
    public static function check(string $key, string $ip): bool
79
    {
80
        $obj = self::get_object_from_filter($key, $ip);
81
82
        return (bool) $obj->Allowed;
83
    }
84
85
    public static function get_editor_id(string $key, string $ip): int
86
    {
87
        $obj = self::get_object_from_filter($key, $ip);
88
89
        return (int) $obj->EditorID;
90
    }
91
92
    /**
93
     * casted variable
94
     */
95
    public function getTitle(): string
96
    {
97
        return 'Retrieval attempt from "' . $this->IpAddress . '" using "' . $this->Secret . '" as key';
98
    }
99
100
    #######################
101
    ### can Section
102
    #######################
103
104
    public function canCreate($member = null, $context = [])
105
    {
106
        return false;
107
    }
108
109
    public function canDelete($member = null)
110
    {
111
        return false;
112
    }
113
114
    public function canEdit($member = null)
115
    {
116
        return $this->DefinitelyNotOk ? false : parent::canEdit($member);
0 ignored issues
show
Bug Best Practice introduced by
The property DefinitelyNotOk does not exist on Sunnysideup\HealthCheckP...thCheckProviderSecurity. Since you implemented __get, consider adding a @property annotation.
Loading history...
117
    }
118
119
    #######################
120
    ### write Section
121
    #######################
122
123
    protected function onBeforeWrite()
124
    {
125
        parent::onBeforeWrite();
126
        if (! $this->EditorID) {
127
            $user = Security::getCurrentUser();
128
            if ($user) {
0 ignored issues
show
$user is of type SilverStripe\Security\Member, thus it always evaluated to true.
Loading history...
129
                $this->EditorID = Security::getCurrentUser()->ID;
0 ignored issues
show
Bug Best Practice introduced by
The property EditorID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
130
            }
131
        }
132
        if (! $this->Secret) {
133
            $this->Secret = 'Careful: no key set - ' . mt_rand(0, 9999999999999999);
0 ignored issues
show
Bug Best Practice introduced by
The property Secret does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
134
        }
135
        if (! $this->IpAddress) {
136
            $this->IpAddress = 'Careful: no IP Set';
0 ignored issues
show
Bug Best Practice introduced by
The property IpAddress does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
137
        }
138
        if ($this->DefinitelyNotOk) {
0 ignored issues
show
Bug Best Practice introduced by
The property DefinitelyNotOk does not exist on Sunnysideup\HealthCheckP...thCheckProviderSecurity. Since you implemented __get, consider adding a @property annotation.
Loading history...
139
            $this->Allowed = false;
0 ignored issues
show
Bug Best Practice introduced by
The property Allowed does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
140
        }
141
    }
142
143
    protected function onAfterWrite()
144
    {
145
        parent::onAfterWrite();
146
        if ($this->AllowAllData) {
0 ignored issues
show
Bug Best Practice introduced by
The property AllowAllData does not exist on Sunnysideup\HealthCheckP...thCheckProviderSecurity. Since you implemented __get, consider adding a @property annotation.
Loading history...
147
            $items = HealthCheckItemProvider::get()->filter(['Include' => false]);
148
            foreach ($items as $item) {
149
                $item->Include = true;
150
                $item->write();
151
            }
152
        }
153
    }
154
155
    #######################
156
    ### CMS Edit Section
157
    #######################
158
159
    public function getCMSFields()
160
    {
161
        $fields = parent::getCMSFields();
162
        $fields->addFieldsToTab(
163
            'Root.Main',
164
            [
165
                ReadonlyField::create('Secret', 'Secret Key'),
166
                ReadonlyField::create('IpAddress', 'IP'),
167
                ReadonlyField::create('AccessCount', 'Access Count'),
168
                CheckboxField::create('Allowed', 'Allow this IP with this Key?  If unsure, please double-check!')
169
                    ->setDescription('Make sure that you are OK with both the key and the IP address to ensure security.'),
170
                CheckboxField::create('DefinitelyNotOk', 'Check if you think this is a bad request')
171
                    ->setDescription('Careful, checking this will stop any future retrievals with this key and IP.'),
172
                CheckboxField::create('AllowAllData', 'Check this box to allow access to all for any IPs granted access')
173
                    ->setDescription('Carefully consider if you are ok with this'),
174
            ]
175
        );
176
177
        return $fields;
178
    }
179
180
    protected static function get_object_from_filter(string $key, string $ip): HealthCheckProviderSecurity
181
    {
182
        $filter = [
183
            'Secret' => $key,
184
            'IpAddress' => $ip,
185
        ];
186
187
        //we make sure we get the last one! Just in case there is more one.
188
        /** @var HealthCheckProviderSecurity|null $obj */
189
        $obj = HealthCheckProviderSecurity::get()->filter($filter)->last();
190
        if (! $obj) {
0 ignored issues
show
$obj is of type Sunnysideup\HealthCheckP...thCheckProviderSecurity, thus it always evaluated to true.
Loading history...
191
            $obj = HealthCheckProviderSecurity::create($filter);
192
        }
193
        ++$obj->AccessCount;
0 ignored issues
show
Bug Best Practice introduced by
The property AccessCount does not exist on Sunnysideup\HealthCheckP...thCheckProviderSecurity. Since you implemented __get, consider adding a @property annotation.
Loading history...
194
195
        $obj->write();
196
197
        return $obj;
198
    }
199
}
200