From 396d71c4a5fe31d94933007ef81c7f92e2f61a8f Mon Sep 17 00:00:00 2001 From: notCharles Date: Mon, 11 May 2026 06:38:53 -0400 Subject: [PATCH] Updates + stan --- .../ActivityLogs/ActivityLogResource.php | 7 +- app/Observers/AdminActivityObserver.php | 87 +++++++++++++++++-- app/Providers/AppServiceProvider.php | 4 + lang/en/activity.php | 30 +++++++ 4 files changed, 118 insertions(+), 10 deletions(-) diff --git a/app/Filament/Admin/Resources/ActivityLogs/ActivityLogResource.php b/app/Filament/Admin/Resources/ActivityLogs/ActivityLogResource.php index a17947164..6a2477644 100644 --- a/app/Filament/Admin/Resources/ActivityLogs/ActivityLogResource.php +++ b/app/Filament/Admin/Resources/ActivityLogs/ActivityLogResource.php @@ -9,6 +9,7 @@ use App\Traits\Filament\CanCustomizePages; use BackedEnum; use Filament\Resources\Pages\PageRegistration; use Filament\Resources\Resource; +use Illuminate\Database\Eloquent\Model; class ActivityLogResource extends Resource { @@ -45,17 +46,17 @@ class ActivityLogResource extends Resource return false; } - public static function canEdit($record): bool + public static function canEdit(Model $record): bool { return false; } - public static function canDelete($record): bool + public static function canDelete(Model $record): bool { return false; } - public static function canView($record): bool + public static function canView(Model $record): bool { return false; } diff --git a/app/Observers/AdminActivityObserver.php b/app/Observers/AdminActivityObserver.php index 3250ed16e..5a48a345b 100644 --- a/app/Observers/AdminActivityObserver.php +++ b/app/Observers/AdminActivityObserver.php @@ -5,6 +5,7 @@ namespace App\Observers; use App\Facades\Activity; use App\Models\Egg; use App\Models\Node; +use App\Models\Role; use App\Models\Server; use App\Models\User; use Filament\Facades\Filament; @@ -33,6 +34,8 @@ class AdminActivityObserver * @param string $event The event name (e.g. 'admin:user.create') * @param Model $model The model being acted upon * @param array $properties Additional properties to log + * + * @throws \Throwable */ private function log(string $event, Model $model, array $properties = []): void { @@ -47,10 +50,10 @@ class AdminActivityObserver // Deduplicate identical events for the same record within a single request. $key = $event . ':' . get_class($model) . ':' . $model->getKey(); - if (isset(static::$logged[$key])) { + if (isset(self::$logged[$key])) { return; } - static::$logged[$key] = true; + self::$logged[$key] = true; $log = Activity::event($event) ->actor($actor) @@ -62,7 +65,6 @@ class AdminActivityObserver $log->log(); } - // ------------------------------------------------------------------------- // User events // ------------------------------------------------------------------------- @@ -74,7 +76,13 @@ class AdminActivityObserver public function userUpdated(User $user): void { - $this->log('admin:user.update', $user, ['name' => $user->username]); + $changedFields = $this->changedFieldsFor($user); + + $this->log('admin:user.update', $user, [ + 'name' => empty($changedFields) ? $user->username : sprintf('%s (%s)', $user->username, implode(', ', $changedFields)), + 'count' => count($changedFields), + 'changes' => implode(', ', $changedFields), + ]); } public function userDeleted(User $user): void @@ -93,7 +101,13 @@ class AdminActivityObserver public function serverUpdated(Server $server): void { - $this->log('admin:server.update', $server, ['name' => $server->name]); + $changedFields = $this->changedFieldsFor($server); + + $this->log('admin:server.update', $server, [ + 'name' => empty($changedFields) ? $server->name : sprintf('%s (%s)', $server->name, implode(', ', $changedFields)), + 'count' => count($changedFields), + 'changes' => implode(', ', $changedFields), + ]); } public function serverDeleted(Server $server): void @@ -112,7 +126,13 @@ class AdminActivityObserver public function nodeUpdated(Node $node): void { - $this->log('admin:node.update', $node, ['name' => $node->name]); + $changedFields = $this->changedFieldsFor($node); + + $this->log('admin:node.update', $node, [ + 'name' => empty($changedFields) ? $node->name : sprintf('%s (%s)', $node->name, implode(', ', $changedFields)), + 'count' => count($changedFields), + 'changes' => implode(', ', $changedFields), + ]); } public function nodeDeleted(Node $node): void @@ -131,11 +151,64 @@ class AdminActivityObserver public function eggUpdated(Egg $egg): void { - $this->log('admin:egg.update', $egg, ['name' => $egg->name]); + $changedFields = $this->changedFieldsFor($egg); + + $this->log('admin:egg.update', $egg, [ + 'name' => empty($changedFields) ? $egg->name : sprintf('%s (%s)', $egg->name, implode(', ', $changedFields)), + 'count' => count($changedFields), + 'changes' => implode(', ', $changedFields), + ]); } public function eggDeleted(Egg $egg): void { $this->log('admin:egg.delete', $egg, ['name' => $egg->name]); } + + // ------------------------------------------------------------------------- + // Role events + // ------------------------------------------------------------------------- + + public function roleCreated(Role $role): void + { + $this->log('admin:role.create', $role, ['name' => $role->name]); + } + + public function roleUpdated(Role $role): void + { + $changedFields = $this->changedFieldsFor($role); + + $this->log('admin:role.update', $role, [ + 'name' => empty($changedFields) ? $role->name : sprintf('%s (%s)', $role->name, implode(', ', $changedFields)), + 'count' => count($changedFields), + 'changes' => implode(', ', $changedFields), + ]); + } + + public function roleDeleted(Role $role): void + { + $this->log('admin:role.delete', $role, ['name' => $role->name]); + } + + // ------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------- + + /** + * Returns the sorted list of attribute names that changed on the given model, + * excluding internal timestamps. + * + * @return string[] + */ + private function changedFieldsFor(Model $model): array + { + $fields = collect(array_keys($model->getChanges())) + ->reject(fn (string $field) => $field === 'updated_at') + ->values() + ->all(); + + sort($fields); + + return $fields; + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index d50ed5820..7fa11df89 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -18,6 +18,7 @@ use App\Models\Database; use App\Models\Egg; use App\Models\EggVariable; use App\Models\Node; +use App\Models\Role; use App\Models\Schedule; use App\Models\Server; use App\Models\Task; @@ -123,6 +124,9 @@ class AppServiceProvider extends ServiceProvider Egg::created(fn (Egg $egg) => $observer->eggCreated($egg)); Egg::updated(fn (Egg $egg) => $observer->eggUpdated($egg)); Egg::deleted(fn (Egg $egg) => $observer->eggDeleted($egg)); + Role::created(fn (Role $role) => $observer->roleCreated($role)); + Role::updated(fn (Role $role) => $observer->roleUpdated($role)); + Role::deleted(fn (Role $role) => $observer->roleDeleted($role)); Gate::before(fn (User $user, $ability) => $user->isRootAdmin() ? true : null); diff --git a/lang/en/activity.php b/lang/en/activity.php index 4667ff5f8..7baf18594 100644 --- a/lang/en/activity.php +++ b/lang/en/activity.php @@ -125,4 +125,34 @@ return [ ], 'crashed' => 'Server crashed', ], + 'admin' => [ + 'settings' => [ + 'update' => 'Updated panel settings (:count): :settings', + ], + 'user' => [ + 'create' => 'Created user :name', + 'update' => 'Updated user :name', + 'delete' => 'Deleted user :name', + ], + 'server' => [ + 'create' => 'Created server :name', + 'update' => 'Updated server :name', + 'delete' => 'Deleted server :name', + ], + 'node' => [ + 'create' => 'Created node :name', + 'update' => 'Updated node :name', + 'delete' => 'Deleted node :name', + ], + 'egg' => [ + 'create' => 'Created egg :name', + 'update' => 'Updated egg :name', + 'delete' => 'Deleted egg :name', + ], + 'role' => [ + 'create' => 'Created role :name', + 'update' => 'Updated role :name', + 'delete' => 'Deleted role :name', + ], + ], ];