Skip to content

Commit 81a4284

Browse files
authored
Merge pull request #22 from crowdsecurity/new-lib-features
Lint pass
2 parents 8ab68b8 + 394dd30 commit 81a4284

19 files changed

+178
-326
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ $bouncerApiKey = 'YOUR_BOUNCER_API_KEY';
4949
/* Select the best cache adapter for your needs (Memcached, Redis, PhpFiles, ...) */
5050
$cacheAdapter = new Symfony\Component\Cache\Adapter\PhpFilesAdapter();
5151

52-
$bouncer = new CrowdSecBouncer\Bouncer();
53-
$bouncer->configure(['api_key'=> $bouncerApiKey], $cacheAdapter);
52+
$bouncer = new CrowdSecBouncer\Bouncer($cacheAdapter);
53+
$bouncer->configure(['api_key'=> $bouncerApiKey]);
5454

5555
$remediation = $bouncer->getRemediationForIp($blockedIp);// Return "ban", "captcha" or "bypass"
5656
```

docs/api/ApiCache.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,7 @@ public pullUpdates (void)
154154
Used in stream mode only.
155155

156156
Pull decisions updates from the API and update the cached remediations.
157-
Used for the stream mode when we have to update the remediations list.
158-
159-
TODO P2 test for overlapping decisions strategy (ex: max expires)
157+
Used for the stream mode when we have to update the remediations list.
160158

161159
**Parameters**
162160

docs/api/Bouncer.md

-50
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ The main Class of this package. This is the first entry point of any PHP Bouncer
1919
|[getCaptchaHtmlTemplate](#bouncergetcaptchahtmltemplate)|Returns a default "CrowdSec Captcha" HTML template to display to a web browser using a captchable IP.|
2020
|[getLogger](#bouncergetlogger)|Returns the logger instance.|
2121
|[getRemediationForIp](#bouncergetremediationforip)|Get the remediation for the specified IP. This method use the cache layer.|
22-
|[loadPaginatedBlocklistFromCache](#bouncerloadpaginatedblocklistfromcache)|Browse the remediations cache.|
23-
|[loadPaginatedLogs](#bouncerloadpaginatedlogs)|Browse the bouncer technical logs.|
2422
|[pruneCache](#bouncerprunecache)|This method prune the cache: it removes all the expired cache items.|
2523
|[refreshBlocklistCache](#bouncerrefreshblocklistcache)|Used in stream mode only.|
2624
|[warmBlocklistCacheUp](#bouncerwarmblocklistcacheup)|Used in stream mode only.|
@@ -247,54 +245,6 @@ the cache system will call the API to check if there is a decision.
247245
<hr />
248246

249247

250-
### Bouncer::loadPaginatedBlocklistFromCache
251-
252-
**Description**
253-
254-
```php
255-
public loadPaginatedBlocklistFromCache (void)
256-
```
257-
258-
Browse the remediations cache.
259-
260-
261-
262-
**Parameters**
263-
264-
`This function has no parameters.`
265-
266-
**Return Values**
267-
268-
`void`
269-
270-
271-
<hr />
272-
273-
274-
### Bouncer::loadPaginatedLogs
275-
276-
**Description**
277-
278-
```php
279-
public loadPaginatedLogs (void)
280-
```
281-
282-
Browse the bouncer technical logs.
283-
284-
285-
286-
**Parameters**
287-
288-
`This function has no parameters.`
289-
290-
**Return Values**
291-
292-
`void`
293-
294-
295-
<hr />
296-
297-
298248
### Bouncer::pruneCache
299249

300250
**Description**

docs/complete-guide.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -377,11 +377,11 @@ $fileHandler = new RotatingFileHandler(__DIR__.'/crowdsec.log', 0, Logger::WARNI
377377
$logger->pushHandler($fileHandler);
378378

379379
// Instanciate the bouncer
380-
$bouncer = new Bouncer($logger);
380+
$bouncer = new Bouncer($cacheAdapter, $logger);
381381
$bouncer->configure([
382382
'api_key' => getenv('BOUNCER_KEY'),
383383
'api_url' => 'http://crowdsec:8080'
384-
], $cacheAdapter
384+
]
385385
);
386386

387387
// Refresh the blocklist cache

docs/configuration-reference.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@
3030
'cache_expiration_for_bad_ip'=> '20',
3131
]
3232
$cacheAdapter = (...)
33-
$bouncer = new Bouncer();
34-
$bouncer->configure($config, $cacheAdapter);
33+
$bouncer = new Bouncer($cacheAdapter);
34+
$bouncer->configure($config);
3535
```

docs/contribute.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,23 @@ Full details here: https://github.com/github/super-linter/blob/master/docs/run-l
5353
docker-compose run --rm app vendor/bin/phpdoc-md
5454
```
5555

56-
## The git workflow we use
56+
### Git workflow cheat sheet
5757

5858
We use the git workflow [Github Flow](https://guides.github.com/introduction/flow/).
5959

60-
### Cheatsheet
61-
6260
#### New feature
6361

6462
```bash
65-
git checkout -b new-feature # the name is not important now.
63+
git checkout -b <basic-name> # the name is not important now, you can type "new-features"
6664
git commit # as mush as necessary.
67-
git branch -m <name-of-the-branch> # to rename the branch to what has really be done
68-
git push -u origin <name-of-the-branch>
65+
docker-compose run --rm app vendor/bin/phpdoc-md # regenerate php doc
66+
git branch -m <name-of-the-branch> # to rename the branch to what has really be done.
67+
git push origin :<basic-name> && git push origin <name-of-the-branch> # Only if already pushed
6968
gh pr create --fill
7069
```
7170

71+
After the merge, don't forget to delete to branch.
72+
7273
#### New release
7374

7475
```bash

examples/clear-cache.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
$logger->pushHandler($fileHandler);
4040

4141
// Instanciate the bouncer
42-
$bouncer = new Bouncer($logger);
43-
$bouncer->configure(['api_key' => $bouncerApiKey, 'api_url' => $apiUrl], $cacheAdapter);
42+
$bouncer = new Bouncer($cacheAdapter, $logger);
43+
$bouncer->configure(['api_key' => $bouncerApiKey, 'api_url' => $apiUrl]);
4444

4545
// Clear the cache.
4646
$bouncer->clearCache();

examples/live-mode/full-example-live-mode.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
$logger->pushHandler($fileHandler);
4242

4343
// Instanciate the bouncer
44-
$bouncer = new Bouncer($logger);
44+
$bouncer = new Bouncer($cacheAdapter, $logger);
4545
$bouncer->configure([
4646
'api_key' => $bouncerApiKey,
4747
'api_url' => $apiUrl,
@@ -51,7 +51,7 @@
5151
'max_remediation_level' => 'ban',
5252
'cache_expiration_for_clean_ip' => 2,
5353
'cache_expiration_for_bad_ip' => 30
54-
], $cacheAdapter,);
54+
]);
5555

5656
// Ask remediation to LAPI
5757
$remediation = $bouncer->getRemediationForIp($requestedIp);

src/ApiCache.php

+15-36
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ class ApiCache
4343
/** @var bool */
4444
private $warmedUp;
4545

46-
public function __construct(ApiClient $apiClient = null, LoggerInterface $logger)
46+
public function __construct(LoggerInterface $logger, ApiClient $apiClient = null, AbstractAdapter $adapter = null)
4747
{
4848
$this->logger = $logger;
4949
$this->apiClient = $apiClient ?: new ApiClient($logger);
50+
$this->adapter = $adapter ?: new FilesystemAdapter();
5051
}
5152

5253
/**
5354
* Configure this instance.
5455
*/
5556
public function configure(
56-
?AbstractAdapter $adapter,
5757
bool $liveMode,
5858
string $apiUrl,
5959
int $timeout,
@@ -62,18 +62,16 @@ public function configure(
6262
int $cacheExpirationForCleanIp,
6363
int $cacheExpirationForBadIp
6464
): void {
65-
$adapter = $adapter ?: new FilesystemAdapter();
66-
$this->adapter = $adapter;
6765
$this->liveMode = $liveMode;
6866
$this->cacheExpirationForCleanIp = $cacheExpirationForCleanIp;
6967
$this->cacheExpirationForBadIp = $cacheExpirationForBadIp;
7068
$cacheConfigItem = $this->adapter->getItem('cacheConfig');
7169
$cacheConfig = $cacheConfigItem->get();
72-
$warmedUp = (is_array($cacheConfig) && isset($cacheConfig['warmed_up']) && $cacheConfig['warmed_up'] === true);
73-
$this->warmedUp = $warmedUp;
70+
$this->warmedUp = (is_array($cacheConfig) && isset($cacheConfig['warmed_up'])
71+
&& $cacheConfig['warmed_up'] === true);
7472
$this->logger->debug(null, [
7573
'type' => 'API_CACHE_INIT',
76-
'adapter' => get_class($adapter),
74+
'adapter' => get_class($this->adapter),
7775
'mode' => ($liveMode ? 'live' : 'stream'),
7876
'exp_clean_ips' => $cacheExpirationForCleanIp,
7977
'exp_bad_ips' => $cacheExpirationForBadIp,
@@ -174,21 +172,14 @@ private function removeDecisionFromRemediationItem(string $ip, int $decisionId):
174172

175173
/**
176174
* Parse "duration" entries returned from API to a number of seconds.
177-
*
178-
* TODO P3 Test parseDurationToSeconds
179-
* 9999h59m56.603445s
180-
* 10m33.3465483s
181-
* 33.3465483s
182-
* -285.876962ms
183-
* 33s'// should break!;
184175
*/
185176
private static function parseDurationToSeconds(string $duration): int
186177
{
187178
$re = '/(-?)(?:(?:(\d+)h)?(\d+)m)?(\d+).\d+(m?)s/m';
188179
preg_match($re, $duration, $matches);
189180
if (!count($matches)) {
190181
throw new BouncerException("Unable to parse the following duration: ${$duration}.");
191-
};
182+
}
192183
$seconds = 0;
193184
if (isset($matches[2])) {
194185
$seconds += ((int) $matches[2]) * 3600; // hours
@@ -206,17 +197,14 @@ private static function parseDurationToSeconds(string $duration): int
206197
$seconds *= -1;
207198
}
208199

209-
$seconds = (int)round($seconds);
210-
return $seconds;
200+
return (int)round($seconds);
211201
}
212202

213203

214204

215205
/**
216206
* Format a remediation item of a cache item.
217207
* This format use a minimal amount of data allowing less cache data consumption.
218-
*
219-
* TODO P3 test formatRemediationFromDecision
220208
*/
221209
private function formatRemediationFromDecision(?array $decision): array
222210
{
@@ -361,8 +349,6 @@ public function warmUp(): int
361349
* Pull decisions updates from the API and update the cached remediations.
362350
* Used for the stream mode when we have to update the remediations list.
363351
*
364-
* TODO P2 test for overlapping decisions strategy (ex: max expires)
365-
*
366352
* @return array number of deleted and new decisions.
367353
*
368354
*/
@@ -419,15 +405,12 @@ private function miss(string $ip): string
419405
private function hit(string $ip): string
420406
{
421407
$remediations = $this->adapter->getItem($ip)->get();
422-
// TODO P1 foreach $remediations, control if exp date is not expired.
423-
// If true, update cache item by removing this expired remediation.
424408

425409
// We apply array values first because keys are ids.
426410
$firstRemediation = array_values($remediations)[0];
427-
/** @var string */
428-
$firstRemediationString = $firstRemediation[0];
429411

430-
return $firstRemediationString;
412+
/** @var string */
413+
return $firstRemediation[0];
431414
}
432415

433416
/**
@@ -463,16 +446,12 @@ public function get(string $ip): string
463446

464447
public function prune(): bool
465448
{
466-
$isPrunable = ($this->adapter instanceof PruneableInterface);
467-
if (!$isPrunable) {
468-
throw new BouncerException("Cache Adapter" . get_class($this->adapter) . " is not prunable.");
449+
if ($this->adapter instanceof PruneableInterface) {
450+
$pruned = $this->adapter->prune();
451+
$this->logger->debug(null, ['type' => 'CACHE_PRUNED']);
452+
return $pruned;
469453
}
470-
/** @var PruneableInterface */
471-
$adapter = $this->adapter;
472-
$pruned = $adapter->prune();
473-
$this->logger->debug(null, ['type' => 'CACHE_PRUNED']);
474-
475-
// TODO P3 Prune remediation inside cache items.
476-
return $pruned;
454+
455+
throw new BouncerException("Cache Adapter" . get_class($this->adapter) . " is not prunable.");
477456
}
478457
}

src/ApiClient.php

+2-9
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,7 @@ public function configure(string $baseUri, int $timeout, string $userAgent, stri
5353
*/
5454
public function getFilteredDecisions(array $filter): array
5555
{
56-
// TODO P1 filter results for scope=ip or scope=range (we can't do anything with other scopes)
57-
$decisions = $this->restClient->request('/v1/decisions', $filter);
58-
$decisions = $decisions ?: [];
59-
60-
return $decisions;
56+
return $this->restClient->request('/v1/decisions', $filter) ?: [];
6157
}
6258

6359
/**
@@ -66,10 +62,7 @@ public function getFilteredDecisions(array $filter): array
6662
*/
6763
public function getStreamedDecisions(bool $startup = false): array
6864
{
69-
// TODO P1 filter results for scope=ip or scope=range (we can't do anything with other scopes)
7065
/** @var array */
71-
$decisionsDiff = $this->restClient->request('/v1/decisions/stream', $startup ? ['startup' => 'true'] : null);
72-
73-
return $decisionsDiff;
66+
return $this->restClient->request('/v1/decisions/stream', $startup ? ['startup' => 'true'] : null);
7467
}
7568
}

0 commit comments

Comments
 (0)