From eac0a3eda3ee7a2ea9548a4b0d271e2793929504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Cmit=20Tun=C3=A7?= Date: Tue, 30 Sep 2025 00:50:43 -0300 Subject: [PATCH] Add user management functionality: Implemented UserActions for editing and changing passwords, created UserPolicy for authorization checks, and integrated AuthServiceProvider for policy registration. Updated Filament configuration to utilize new user actions and adjusted localization for user-related actions. Enhanced .gitignore and CSS files for better organization. --- .gitignore | 1 + .../Resources/Users/Tables/UserActions.php | 52 +++++++++ app/Policies/UserPolicy.php | 105 ++++++++++++++++++ app/Providers/AuthServiceProvider.php | 38 +++++++ app/Providers/Filament/AdminPanelProvider.php | 2 +- bootstrap/providers.php | 1 + config/filament-shield.php | 2 +- config/filament-users.php | 2 +- public/css/app/citrus.css | 4 +- resources/css/app.css | 1 + resources/css/citrus.css | 1 + resources/js/app.js | 1 + resources/js/bootstrap.js | 1 + vite.config.js | 1 + 14 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 app/Filament/Admin/Resources/Users/Tables/UserActions.php create mode 100644 app/Policies/UserPolicy.php create mode 100644 app/Providers/AuthServiceProvider.php diff --git a/.gitignore b/.gitignore index 8b76ec0..f1e90bb 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ Homestead.json Homestead.yaml Thumbs.db + diff --git a/app/Filament/Admin/Resources/Users/Tables/UserActions.php b/app/Filament/Admin/Resources/Users/Tables/UserActions.php new file mode 100644 index 0000000..1b6b343 --- /dev/null +++ b/app/Filament/Admin/Resources/Users/Tables/UserActions.php @@ -0,0 +1,52 @@ +visible(fn () => Auth::user()?->can('Update:User')), + + Action::make('change_password') + ->label(__('filament-users::user.resource.change_password')) + ->icon('heroicon-o-key') + ->color('warning') + ->form([ + TextInput::make('password') + ->label(__('filament-users::user.resource.password')) + ->password() + ->required() + ->confirmed(), + TextInput::make('password_confirmation') + ->label(__('filament-users::user.resource.password_confirmation')) + ->password() + ->required(), + ]) + ->action(function ($record, array $data) { + $record->update([ + 'password' => Hash::make($data['password']), + ]); + + Notification::make() + ->title(__('filament-users::user.resource.change_password_success')) + ->success() + ->send(); + }) + ->visible(fn () => Auth::user()?->can('Update:User')), + + DeleteAction::make() + ->visible(fn () => Auth::user()?->can('Delete:User')), + ]; + } +} diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php new file mode 100644 index 0000000..2e9ab73 --- /dev/null +++ b/app/Policies/UserPolicy.php @@ -0,0 +1,105 @@ +can('ViewAny:User'); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, User $model): bool + { + return $user->can('View:User'); + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->can('Create:User'); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, User $model): bool + { + return $user->can('Update:User'); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, User $model): bool + { + return $user->can('Delete:User'); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, User $model): bool + { + return $user->can('Restore:User'); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, User $model): bool + { + return $user->can('ForceDelete:User'); + } + + /** + * Determine whether the user can delete any models. + */ + public function deleteAny(User $user): bool + { + return $user->can('DeleteAny:User'); + } + + /** + * Determine whether the user can restore any models. + */ + public function restoreAny(User $user): bool + { + return $user->can('RestoreAny:User'); + } + + /** + * Determine whether the user can permanently delete any models. + */ + public function forceDeleteAny(User $user): bool + { + return $user->can('ForceDeleteAny:User'); + } + + /** + * Determine whether the user can replicate the model. + */ + public function replicate(User $user, User $model): bool + { + return $user->can('Replicate:User'); + } + + /** + * Determine whether the user can reorder models. + */ + public function reorder(User $user): bool + { + return $user->can('Reorder:User'); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php new file mode 100644 index 0000000..89c03aa --- /dev/null +++ b/app/Providers/AuthServiceProvider.php @@ -0,0 +1,38 @@ + + */ + protected $policies = [ + User::class => UserPolicy::class, + Role::class => RolePolicy::class, + ]; + + /** + * Register services. + */ + public function register(): void + { + // + } + + /** + * Bootstrap services. + */ + public function boot(): void + { + $this->registerPolicies(); + } +} diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index fa371ca..e1e55fe 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -39,6 +39,7 @@ class AdminPanelProvider extends PanelProvider Dashboard::class, ]) ->discoverWidgets(in: app_path('Filament/Admin/Widgets'), for: 'App\Filament\Admin\Widgets') + ->plugin(\TomatoPHP\FilamentUsers\FilamentUsersPlugin::make()) ->plugin(FilamentShieldPlugin::make()) ->widgets([ AccountWidget::class, @@ -58,7 +59,6 @@ class AdminPanelProvider extends PanelProvider ->authMiddleware([ Authenticate::class, ]) - ->plugin(\TomatoPHP\FilamentUsers\FilamentUsersPlugin::make()) ->login() ->assets([ \Filament\Support\Assets\Css::make('citrus', resource_path('css/citrus.css')), diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 22744d1..0842610 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -2,5 +2,6 @@ return [ App\Providers\AppServiceProvider::class, + App\Providers\AuthServiceProvider::class, App\Providers\Filament\AdminPanelProvider::class, ]; diff --git a/config/filament-shield.php b/config/filament-shield.php index 5731ee5..78bb257 100644 --- a/config/filament-shield.php +++ b/config/filament-shield.php @@ -179,7 +179,7 @@ return [ ], ], 'exclude' => [ - // + // TomatoPHP Users resource'u exclude etmeyin, permission kontrolü yapması için ], ], diff --git a/config/filament-users.php b/config/filament-users.php index 2428a87..62f28dc 100644 --- a/config/filament-users.php +++ b/config/filament-users.php @@ -141,7 +141,7 @@ return [ 'table' => [ 'class' => \TomatoPHP\FilamentUsers\Filament\Resources\Users\Tables\UsersTable::class, 'filters' => \TomatoPHP\FilamentUsers\Filament\Resources\Users\Tables\UserFilters::class, - 'actions' => \TomatoPHP\FilamentUsers\Filament\Resources\Users\Tables\UserActions::class, + 'actions' => \App\Filament\Admin\Resources\Users\Tables\UserActions::class, 'bulkActions' => \TomatoPHP\FilamentUsers\Filament\Resources\Users\Tables\UserBulkActions::class, ], 'form' => [ diff --git a/public/css/app/citrus.css b/public/css/app/citrus.css index 115d0c3..17f6ae9 100644 --- a/public/css/app/citrus.css +++ b/public/css/app/citrus.css @@ -3,7 +3,9 @@ height: 6rem !important; width: auto !important; } - +.fi-topbar-start .fi-logo { + height: 2.5rem !important; +} /* Login sayfası brand logo boyutu */ .fi-brand-logo { height: 6rem !important; diff --git a/resources/css/app.css b/resources/css/app.css index d16e2b5..1f42c6c 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -10,3 +10,4 @@ 'Segoe UI Symbol', 'Noto Color Emoji'; } + diff --git a/resources/css/citrus.css b/resources/css/citrus.css index 115d0c3..1ac5e99 100644 --- a/resources/css/citrus.css +++ b/resources/css/citrus.css @@ -4,6 +4,7 @@ width: auto !important; } + /* Login sayfası brand logo boyutu */ .fi-brand-logo { height: 6rem !important; diff --git a/resources/js/app.js b/resources/js/app.js index 401533a..29f5ccf 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,2 +1,3 @@ import './bootstrap'; + diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index 9a4ae1b..3ab907d 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -3,3 +3,4 @@ window.axios = axios; window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; + diff --git a/vite.config.js b/vite.config.js index 6bc1814..2f8aefa 100644 --- a/vite.config.js +++ b/vite.config.js @@ -12,3 +12,4 @@ export default defineConfig({ ], }); +