Skip to content

Commit 38c1555

Browse files
author
Andrey Helldar
authored
Merge pull request #2 from TheDragonCode/1.x
Added the ability to hide secret fields
2 parents 3fbdf08 + e99b471 commit 38c1555

File tree

9 files changed

+206
-32
lines changed

9 files changed

+206
-32
lines changed

config/http-logger.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,12 @@
66
'connection' => env('DB_CONNECTION'),
77

88
'table' => 'http_logs',
9+
10+
'hide' => [
11+
'authorization',
12+
'token',
13+
'access_token',
14+
'password',
15+
'password_confirmation',
16+
],
917
];

src/Casts/Hide.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DragonCode\LaravelHttpLogger\Casts;
6+
7+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
8+
use Illuminate\Support\Str;
9+
use JetBrains\PhpStorm\Pure;
10+
11+
class Hide implements CastsAttributes
12+
{
13+
protected string $mask = '*';
14+
15+
public function get($model, string $key, $value, array $attributes): array
16+
{
17+
return json_decode($value, true);
18+
}
19+
20+
public function set($model, string $key, $value, array $attributes): string
21+
{
22+
$value = $this->process((array) $value);
23+
24+
return json_encode($value);
25+
}
26+
27+
protected function process(array $values): array
28+
{
29+
foreach ($values as $k => &$val) {
30+
if (is_array($val)) {
31+
$val = $this->process($val);
32+
continue;
33+
}
34+
35+
if ($this->toHide($k)) {
36+
$val = $this->hide($val);
37+
}
38+
}
39+
40+
return $values;
41+
}
42+
43+
protected function toHide(mixed $key): bool
44+
{
45+
return in_array(Str::lower((string) $key), $this->hides(), true);
46+
}
47+
48+
#[Pure]
49+
protected function hide(mixed $value): string
50+
{
51+
$length = Str::length($value);
52+
53+
return str_pad('', $length, $this->mask);
54+
}
55+
56+
protected function hides(): array
57+
{
58+
return config('http-logger.hide', []);
59+
}
60+
}

src/Casts/HideHeader.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DragonCode\LaravelHttpLogger\Casts;
6+
7+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
8+
9+
class HideHeader extends Hide implements CastsAttributes
10+
{
11+
protected function process(array $values): array
12+
{
13+
foreach ($values as $key => &$value) {
14+
if ($this->toHide($key)) {
15+
$value = [$this->hide($value[0])];
16+
}
17+
}
18+
19+
return $values;
20+
}
21+
}

src/Models/HttpLog.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace DragonCode\LaravelHttpLogger\Models;
66

7+
use DragonCode\LaravelHttpLogger\Casts\Hide;
8+
use DragonCode\LaravelHttpLogger\Casts\HideHeader;
79
use DragonCode\LaravelHttpLogger\Casts\Method;
810
use DragonCode\LaravelHttpLogger\Concerns\HasTable;
911
use DragonCode\Support\Facades\Http\Builder;
@@ -32,9 +34,9 @@ class HttpLog extends Model
3234

3335
'port' => 'int',
3436

35-
'query' => 'json',
36-
'payload' => 'json',
37-
'headers' => 'json',
37+
'query' => Hide::class,
38+
'payload' => Hide::class,
39+
'headers' => HideHeader::class,
3840
];
3941

4042
public function __construct(array $attributes = [])

src/Services/Logger.php

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace DragonCode\LaravelHttpLogger\Services;
66

77
use DragonCode\LaravelHttpLogger\Models\HttpLog;
8+
use DragonCode\Support\Facades\Helpers\Arr;
89
use Illuminate\Http\Request;
910

1011
class Logger
@@ -19,23 +20,23 @@ public static function save(Request $request): void
1920
$request->getPort(),
2021
$request->path(),
2122
$request->query(),
22-
$request->all(),
23+
Arr::except($request->all(), array_keys($request->query())),
2324
$request->headers->all(),
2425
$request?->getClientIp() ?: $request?->ip()
2526
);
2627
}
2728

2829
protected static function store(
29-
?string $name,
30-
string $method,
31-
string $scheme,
32-
string $host,
33-
int|string|null $port,
34-
string $path,
30+
?string $name,
31+
string $method,
32+
string $scheme,
33+
string $host,
34+
int|string|null $port,
35+
string $path,
3536
array|string|null $query,
36-
array $payload,
37-
array $headers,
38-
?string $ip
37+
array $payload,
38+
array $headers,
39+
?string $ip
3940
): void {
4041
HttpLog::create(compact(
4142
'name',

tests/Concerns/HasDatabase.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Concerns;
6+
7+
use DragonCode\LaravelHttpLogger\Models\HttpLog;
8+
9+
trait HasDatabase
10+
{
11+
protected function assertDatabaseLogsCount(int $count): void
12+
{
13+
$this->assertSame($count, HttpLog::query()->count());
14+
}
15+
16+
protected function assertDatabaseHasRecord(string $method, string $name, string $path, int $expected = 1): void
17+
{
18+
$count = HttpLog::where(compact('method', 'name', 'path'))->count();
19+
20+
$message = $method . ' ' . $path . ' ' . $name;
21+
22+
$this->assertSame($expected, $count, $message);
23+
}
24+
}

tests/HideTest.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests;
6+
7+
use DragonCode\LaravelHttpLogger\Models\HttpLog;
8+
9+
class HideTest extends TestCase
10+
{
11+
public function testLogging(): void
12+
{
13+
$method = 'POST';
14+
$name = 'api.pages.create';
15+
$path = 'api/pages';
16+
17+
$uri = $path . '?' . http_build_query([
18+
'foo' => 'Foo',
19+
'token' => 123,
20+
'access_token' => 456,
21+
]);
22+
23+
$this->assertDatabaseLogsCount(0);
24+
25+
$response = $this->post($uri, [
26+
'bar' => 'Bar',
27+
28+
'password' => 'q123456',
29+
'password_confirmation' => 'q123456',
30+
], [
31+
'Authorization' => 'Bearer QwErTy',
32+
]);
33+
34+
$response->assertNoContent();
35+
36+
$this->assertDatabaseLogsCount(1);
37+
$this->assertDatabaseHasRecord($method, $name, $path);
38+
39+
$log = HttpLog::where(compact('method', 'name'))->first();
40+
41+
$this->assertSame($method, $log->method);
42+
$this->assertSame($name, $log->name);
43+
$this->assertSame($path, $log->path);
44+
45+
$this->assertSame('http', $log->scheme);
46+
$this->assertSame('localhost', $log->host);
47+
$this->assertSame(80, $log->port);
48+
$this->assertSame('127.0.0.1', $log->ip);
49+
50+
$this->assertSame([
51+
'foo' => 'Foo',
52+
'token' => '***',
53+
'access_token' => '***',
54+
], $log->query);
55+
56+
$this->assertSame([
57+
'bar' => 'Bar',
58+
59+
'password' => '*******',
60+
'password_confirmation' => '*******',
61+
], $log->payload);
62+
63+
$this->assertSame([
64+
'host' => ['localhost'],
65+
'user-agent' => ['Symfony'],
66+
'accept' => ['text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'],
67+
'accept-language' => ['en-us,en;q=0.5'],
68+
'accept-charset' => ['ISO-8859-1,utf-8;q=0.7,*;q=0.7'],
69+
'authorization' => ['*************'],
70+
'content-type' => ['application/x-www-form-urlencoded'],
71+
], $log->headers);
72+
}
73+
}

tests/FeatureTest.php renamed to tests/MainTest.php

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
namespace Tests;
66

7-
use DragonCode\LaravelHttpLogger\Models\HttpLog;
87
use Illuminate\Support\Str;
98

10-
class FeatureTest extends TestCase
9+
class MainTest extends TestCase
1110
{
1211
public function testLogging()
1312
{
@@ -26,28 +25,12 @@ public function testLogging()
2625
$response->assertNoContent();
2726

2827
$this->assertDatabaseLogsCount(++$count);
29-
$this->assertDatabaseHasRecord($method, $name, $uri);
28+
$this->assertDatabaseHasRecord(Str::upper($method), $name, $uri);
3029
}
3130
}
3231

3332
public function testUnknownRoute()
3433
{
3534
$this->get('foo')->assertNotFound();
3635
}
37-
38-
protected function assertDatabaseLogsCount(int $count): void
39-
{
40-
$this->assertSame($count, HttpLog::query()->count());
41-
}
42-
43-
protected function assertDatabaseHasRecord(string $method, string $name, string $path, int $expected = 1): void
44-
{
45-
$method = Str::upper($method);
46-
47-
$count = HttpLog::where(compact('method', 'name', 'path'))->count();
48-
49-
$message = $method . ' ' . $path . ' ' . $name;
50-
51-
$this->assertSame($expected, $count, $message);
52-
}
5336
}

tests/TestCase.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
use Illuminate\Foundation\Testing\RefreshDatabase;
1010
use Illuminate\Routing\Router;
1111
use Orchestra\Testbench\TestCase as BaseTestCase;
12+
use Tests\Concerns\HasDatabase;
1213

1314
class TestCase extends BaseTestCase
1415
{
16+
use HasDatabase;
1517
use RefreshDatabase;
1618

1719
protected string $host = 'https://localhost';

0 commit comments

Comments
 (0)