Skip to content

Commit 1c048cc

Browse files
committed
Fix listener to accept Filament event objects
- Change handle() signature to accept RecordCreated|RecordUpdated event objects instead of separate params (Laravel passes the event, not constructor args) - Use [REDACTED] placeholder instead of silently dropping sensitive fields - Expand redacted fields list with current_password, daemon_token, _token - Update tests to construct proper event objects
1 parent bdf8a91 commit 1c048cc

File tree

2 files changed

+41
-21
lines changed

2 files changed

+41
-21
lines changed

app/Listeners/AdminActivityListener.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,38 @@
44

55
use App\Facades\Activity;
66
use Filament\Facades\Filament;
7-
use Filament\Resources\Pages\Page;
8-
use Illuminate\Database\Eloquent\Model;
7+
use Filament\Resources\Events\RecordCreated;
8+
use Filament\Resources\Events\RecordUpdated;
99
use Illuminate\Support\Str;
1010

1111
class AdminActivityListener
1212
{
1313
protected const REDACTED_FIELDS = [
1414
'password',
1515
'password_confirmation',
16+
'current_password',
1617
'token',
1718
'secret',
1819
'api_key',
20+
'daemon_token',
21+
'_token',
1922
];
2023

21-
/** @param array<string, mixed> $data */
22-
public function handle(Model $record, array $data, Page $page): void
24+
public function handle(RecordCreated|RecordUpdated $event): void
2325
{
2426
if (Filament::getCurrentPanel()?->getId() !== 'admin') {
2527
return;
2628
}
2729

30+
$record = $event->getRecord();
31+
$page = $event->getPage();
32+
$data = $event->getData();
33+
2834
$resourceClass = $page::getResource();
2935
$modelClass = $resourceClass::getModel();
3036
$slug = Str::kebab(class_basename($modelClass));
3137

32-
$action = $page instanceof \Filament\Resources\Pages\CreateRecord ? 'create' : 'update';
38+
$action = $event instanceof RecordCreated ? 'create' : 'update';
3339

3440
$properties = $this->redactSensitiveFields($data);
3541

@@ -49,6 +55,8 @@ protected function redactSensitiveFields(array $data): array
4955

5056
foreach ($data as $key => $value) {
5157
if (in_array($key, self::REDACTED_FIELDS, true)) {
58+
$redacted[$key] = '[REDACTED]';
59+
5260
continue;
5361
}
5462

tests/Filament/Admin/AdminActivityListenerTest.php

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,25 @@
1010
use App\Models\Node;
1111
use App\Models\Role;
1212
use Filament\Facades\Filament;
13+
use Filament\Resources\Events\RecordCreated;
14+
use Filament\Resources\Events\RecordUpdated;
1315
use Illuminate\Support\Facades\Event;
1416

1517
function pageInstance(string $class): object
1618
{
1719
return (new ReflectionClass($class))->newInstanceWithoutConstructor();
1820
}
1921

22+
function createEvent(object $record, array $data, object $page): RecordCreated
23+
{
24+
return new RecordCreated($record, $data, $page);
25+
}
26+
27+
function updateEvent(object $record, array $data, object $page): RecordUpdated
28+
{
29+
return new RecordUpdated($record, $data, $page);
30+
}
31+
2032
beforeEach(function () {
2133
[$this->admin] = generateTestAccount([]);
2234
$this->admin = $this->admin->syncRoles(Role::getRootAdmin());
@@ -29,7 +41,7 @@ function pageInstance(string $class): object
2941
$egg = Egg::first();
3042

3143
$listener = new AdminActivityListener();
32-
$listener->handle($egg, ['name' => 'Test Egg'], pageInstance(CreateEgg::class));
44+
$listener->handle(createEvent($egg, ['name' => 'Test Egg'], pageInstance(CreateEgg::class)));
3345

3446
$this->assertActivityLogged('admin:egg.create');
3547
});
@@ -38,7 +50,7 @@ function pageInstance(string $class): object
3850
$egg = Egg::first();
3951

4052
$listener = new AdminActivityListener();
41-
$listener->handle($egg, ['name' => 'Updated Egg'], pageInstance(EditEgg::class));
53+
$listener->handle(updateEvent($egg, ['name' => 'Updated Egg'], pageInstance(EditEgg::class)));
4254

4355
$this->assertActivityLogged('admin:egg.update');
4456
});
@@ -47,7 +59,7 @@ function pageInstance(string $class): object
4759
$node = Node::first();
4860

4961
$listener = new AdminActivityListener();
50-
$listener->handle($node, ['name' => 'Test Node'], pageInstance(CreateNode::class));
62+
$listener->handle(createEvent($node, ['name' => 'Test Node'], pageInstance(CreateNode::class)));
5163

5264
$this->assertActivityLogged('admin:node.create');
5365
});
@@ -56,7 +68,7 @@ function pageInstance(string $class): object
5668
$node = Node::first();
5769

5870
$listener = new AdminActivityListener();
59-
$listener->handle($node, ['name' => 'Updated Node'], pageInstance(EditNode::class));
71+
$listener->handle(updateEvent($node, ['name' => 'Updated Node'], pageInstance(EditNode::class)));
6072

6173
$this->assertActivityLogged('admin:node.update');
6274
});
@@ -67,7 +79,7 @@ function pageInstance(string $class): object
6779
$egg = Egg::first();
6880

6981
$listener = new AdminActivityListener();
70-
$listener->handle($egg, ['name' => 'Test'], pageInstance(CreateEgg::class));
82+
$listener->handle(createEvent($egg, ['name' => 'Test'], pageInstance(CreateEgg::class)));
7183

7284
Event::assertNotDispatched(ActivityLogged::class);
7385
});
@@ -76,7 +88,7 @@ function pageInstance(string $class): object
7688
$egg = Egg::first();
7789

7890
$listener = new AdminActivityListener();
79-
$listener->handle($egg, ['name' => 'Test'], pageInstance(CreateEgg::class));
91+
$listener->handle(createEvent($egg, ['name' => 'Test'], pageInstance(CreateEgg::class)));
8092

8193
$this->assertActivityFor('admin:egg.create', $this->admin, $egg);
8294
});
@@ -94,17 +106,17 @@ function pageInstance(string $class): object
94106
];
95107

96108
$listener = new AdminActivityListener();
97-
$listener->handle($egg, $data, pageInstance(EditEgg::class));
109+
$listener->handle(updateEvent($egg, $data, pageInstance(EditEgg::class)));
98110

99111
Event::assertDispatched(ActivityLogged::class, function (ActivityLogged $event) {
100112
$properties = $event->model->properties;
101113

102114
expect($properties)->toHaveKey('name', 'Visible')
103-
->not->toHaveKey('password')
104-
->not->toHaveKey('password_confirmation')
105-
->not->toHaveKey('token')
106-
->not->toHaveKey('secret')
107-
->not->toHaveKey('api_key');
115+
->toHaveKey('password', '[REDACTED]')
116+
->toHaveKey('password_confirmation', '[REDACTED]')
117+
->toHaveKey('token', '[REDACTED]')
118+
->toHaveKey('secret', '[REDACTED]')
119+
->toHaveKey('api_key', '[REDACTED]');
108120

109121
return true;
110122
});
@@ -123,14 +135,14 @@ function pageInstance(string $class): object
123135
];
124136

125137
$listener = new AdminActivityListener();
126-
$listener->handle($egg, $data, pageInstance(EditEgg::class));
138+
$listener->handle(updateEvent($egg, $data, pageInstance(EditEgg::class)));
127139

128140
Event::assertDispatched(ActivityLogged::class, function (ActivityLogged $event) {
129141
$properties = $event->model->properties;
130142

131143
expect($properties['nested'])->toHaveKey('safe', 'value')
132-
->not->toHaveKey('password')
133-
->not->toHaveKey('token');
144+
->toHaveKey('password', '[REDACTED]')
145+
->toHaveKey('token', '[REDACTED]');
134146

135147
return true;
136148
});
@@ -140,7 +152,7 @@ function pageInstance(string $class): object
140152
$node = Node::first();
141153

142154
$listener = new AdminActivityListener();
143-
$listener->handle($node, ['name' => 'Test'], pageInstance(CreateNode::class));
155+
$listener->handle(createEvent($node, ['name' => 'Test'], pageInstance(CreateNode::class)));
144156

145157
$this->assertActivityLogged('admin:node.create');
146158
});

0 commit comments

Comments
 (0)