GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Branch master (7a4ba9)
by Charles
04:15 queued 02:18
created

IPLoggerService::getIP()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
/**
3
 * Provides a central point via which code can log and review events.
4
 * Ideally this service should be injected using SilverStripe's injector.
5
 *
6
 * @package silverstripe-iplogger
7
 * @see https://docs.silverstripe.org/en/3.1/developer_guides/extending/injector/
8
 */
9
class IPLoggerService extends Object
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
10
{
11
    private static $rules = array();
0 ignored issues
show
Unused Code introduced by
The property $rules is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
12
13
    private static $delete_expired = false;
0 ignored issues
show
Unused Code introduced by
The property $delete_expired is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
14
    
15
    private static $dependencies = array(
0 ignored issues
show
Unused Code introduced by
The property $dependencies is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
16
        'loggerEntry' => '%$IPLoggerEntry',
17
        'banEntry'    => '%$IPBanEntry'
18
    );
19
20
    protected $rule = null;
21
22
    public function __construct()
23
    {
24
    }
25
26
    /**
27
     * Returns the IP address of the current client; relies on
28
     * {@link SS_HTTPRequest} to provide the IP address.
29
     *
30
     * @return string The current clients IP address
31
     */
32
    public function getIP()
33
    {
34
        $request = Controller::curr()->getRequest();
35
36
        return $request->getIP();
37
    }
38
39
    /**
40
     * Logs an event against a clients IP address.
41
     *
42
     * @param $event string The event being logged.
43
     */
44
    public function log($event)
45
    {
46
        $entry = $this->loggerEntry;
0 ignored issues
show
Bug introduced by
The property loggerEntry does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
47
48
        $entry->IP = $this->getIP();
49
        $entry->Event = $event;
50
51
        $entry->write();
52
    }
53
54
    /**
55
     * Get's an array of logs related to the clients IP and the supplied event.
56
     *
57
     * @param string $event The event
58
     * @return DataList A list of logged events
59
     */
60
    public function getEntries($event)
61
    {
62
        $entryClass = get_class($this->loggerEntry);
63
64
        //$this->pruneEntries($event);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
65
        
66
        $entries = $entryClass::get()->filter(
67
            array(
68
                'Event' => $event,
69
                'IP' => $this->getIP()
70
            )
71
        );
72
73
        return $entries;
74
    }
75
76
    /**
77
     * If a rule exists for a specific event; return it.
78
     *
79
     * Any rules found are checked for validity and an error thrown if incorrect.
80
     * Rules should be defined in .yml config files using the following format.
81
     *
82
     * <code>
83
     * IPLoggerService:
84
     *   rules:
85
     *     submit_contact_form:
86
     *       findtime: 60
87
     *       hits: 4
88
     *       bantime: 600
89
     * </code>
90
     *
91
     * @param string $event The event we want a rule for
92
     * @return array|null The rule array
93
     */
94
    public function getRule($event)
95
    {
96
        $config = $this->config();
97
98
        $rules = $config->get('rules');
99
100
        $rule = null;
101
        
102
        if (isset($rules[$event])) {
103
            $rule = $rules[$event];
104
            
105
            // If the rule for this event is malformed throw an Exception;
106
            if (!(isset($rule['bantime']) && isset($rule['findtime']) && isset($rule['hits']))) {
107
                throw new Exception(
108
                    'Rule must contain the keys bantime, findtime and hits.'
109
                );
110
            }
111
        }
112
113
        return $rule;
114
    }
115
116
    /**
117
     * Get a date x seconds ago.
118
     *
119
     * @param integer $seconds The number of seconds to subtract
120
     * @return DateTime
121
     */
122
    public function getPastDate($seconds)
123
    {
124
        $interval = new DateInterval('PT' . $seconds  . 'S');
125
        $interval->invert = 1;
126
127
        $pastDate = new DateTime();
128
        $pastDate->add($interval);
129
130
        return $pastDate;
131
    }
132
    
133
    public function pruneEntries($event)
134
    {
135
        $config = $this->config();
136
        
137
        $entryClass = get_class($this->loggerEntry);
138
139
        $rule = $this->getRule($event);
140
141
        if ($rule) {
142
            $entries = $entryClass::get()->filter(
143
                array(
144
                    'Created:LessThan' => $minTime,
0 ignored issues
show
Bug introduced by
The variable $minTime does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
145
                    'Event' => $minTime->format('c'),
146
                    'IP' => $this->getIP()
147
                )
148
            );
149
150
            if ($entries) {
151
                $deleteExpired = $config->get('delete_expired');
152
            
153
                foreach ($entries as $entry) {
154
                    if ($deleteExpired) {
155
                        $entry->delete();
156
                    } else {
157
                        $entry->Expired = true;
158
                    }
159
                }
160
            }
161
        }
162
    }
163
    
164
    /**
165
     * Checks if a specific client IP is allowed to perform an event
166
     *
167
     * First if there is no rule supplied for an event string, we assume
168
     * that user can perform this event as many times as needed and it should
169
     * be logged but not restricted.
170
     * Next a check if performed to see if a client IP has been banned from
171
     * performing an event.
172
     * Finally we calculate the total number of logs for an event and check
173
     * these are within the limits set by the rules. If they are not withing
174
     * the limit apply a ban.
175
     *
176
     * @param string $event The event to check
177
     * @return true|string Is the client allowd to perform $event
178
     */
179
    public function checkAllowed($event)
180
    {
181
        $rule = $this->getRule($event);
182
183
        // If no rule is set there must be no limit to how often an event can
184
        // happen.
185
        if (!$rule) {
186
            return true;
187
        }
188
189
        $maxDate = $this->getPastDate($rule['bantime'])->format('c');
190
        
191
        $banClass = get_class($this->banEntry);
0 ignored issues
show
Bug introduced by
The property banEntry does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
192
        $bans = $banClass::get()->filter(
193
            array(
194
                'Created:GreaterThan' => $maxDate,
195
                'Event'   => $event,
196
                'IP'      => $this->getIP()
197
            )
198
        );
199
200
        // Check if a ban exists.
201
        if ($bans->count() > 0) {
202
            return false;
203
        }
204
205
        $maxDate = $this->getPastDate($rule['findtime'])->format('c');
206
        
207
        $entries = $this->getEntries($event)->filter(
208
            array(
209
                'Created:GreaterThan' => $maxDate
210
            )
211
        );
212
213
        // If there are no log entries the client must not have triggered this
214
        // event before, so let it happen.
215
        if (!$entries) {
216
            return true;
217
        }
218
219
        // Check if the number of entries is greater than the number of hits
220
        // allowed in findtime.
221
        if ($entries->count() > $rule['hits']) {
222
            $banEntry = $this->banEntry;
223
            $banEntry->IP = $this->getIP();
224
            $banEntry->Event = $event;
225
            $banEntry->write();
226
227
            return false;
228
        }
229
230
        return true;
231
    }
232
}
233