From 868f4a9dfbd928f63ca7dee4c17b19fee693cc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 30 Jun 2022 17:51:15 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Ticket=20n=C2=B0=20962=20Fix=20unhandled=20?= =?UTF-8?q?case=20user=20is=20not=20admin=20on=20accounts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Credit/AccountController.php | 18 +++++++++++++++++- app/Models/User.php | 16 +++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Credit/AccountController.php b/app/Http/Controllers/Credit/AccountController.php index c5f8531..9cb2488 100644 --- a/app/Http/Controllers/Credit/AccountController.php +++ b/app/Http/Controllers/Credit/AccountController.php @@ -38,9 +38,25 @@ class AccountController extends Controller */ public function indexQuery(Builder $query): Builder { + /** @var \App\Models\User */ + $user = auth()->user(); + + + if (!$user->isAdmin()) { + $userBrands = $user->brands(); + if (!$userBrands->count()) { + \redirect()->route('ticket.index')->withErrors(['warning' => trans( + // phpcs:ignore Generic.Files.LineLength.TooLong + 'Pour utiliser cette fonctionnalité vous devez appartenir à une marque, merci d\'en faire la demande à :mail', + ['mail' => collect(config('mail.contactsList.serviceweb'))->implode(' ')] + )])->throwResponse(); + } + return $query->whereIn('brand_id', $userBrands->pluck('id')); + } + /** @var \App\Models\Brand|null $brand */ if (!($brand = request()->brand)) { - throw new \ErrorException('Cannot get brand'); + abort(404, 'Cannot get brand'); } return $query->where('brand_id', '=', $brand->id); diff --git a/app/Models/User.php b/app/Models/User.php index 6d7ab39..40c0bf7 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -49,7 +49,11 @@ class User extends Authenticatable */ protected $crudValueColumn = 'id'; - // stores unhashed pwd + /** + * stores unhashed pwd + * + * @var string|null + */ public $tmpPass = null; /** @@ -249,6 +253,16 @@ class User extends Authenticatable // * METHODS + /** + * get User brands + * + * @return \Illuminate\Database\Eloquent\Collection<\App\Models\Brand> + */ + public function brands() + { + return $this->sites->pluck('brand')->filter(); + } + /** * Send User creation confirm mail * From 259ad1ba1830a075e7d7aa251391ffc1531e16f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Fri, 1 Jul 2022 09:27:31 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Ticket=20n=C2=B0=20957=20Fix=20ticket=20wor?= =?UTF-8?q?ding=20archived=20condition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/views/ticket/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/ticket/index.blade.php b/resources/views/ticket/index.blade.php index c589a28..9a37670 100644 --- a/resources/views/ticket/index.blade.php +++ b/resources/views/ticket/index.blade.php @@ -11,7 +11,7 @@ $userPr = Auth::user()->sites ?? collect([]);
-

{{ __('Gestion des tickets') }} @if(request()->st) (Archivés) @endif

+

{{ __('Gestion des tickets') }} @if(Session::get('tickets.st') == App\Enums\TicketStatus::archived()->value) (Archivés) @endif

From 97b492b87c50594073881dc2e961ce5c07d759e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Fri, 1 Jul 2022 11:05:15 +0200 Subject: [PATCH 3/3] =?UTF-8?q?Ticket=20n=C2=B0=20928=20Definitely=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Credit/AccountController.php | 27 +++++++-- .../Credit/CreditLogController.php | 11 ++-- app/Models/User.php | 10 ++++ app/Policies/AccountPolicy.php | 2 +- app/Policies/CreditLogPolicy.php | 4 +- app/Policies/Rules/CreditAccountLogRules.php | 24 ++++++++ app/Providers/RouteServiceProvider.php | 55 ++++++++++++++++++- resources/views/credit_logs/index.blade.php | 10 ++++ resources/views/layout/nav.blade.php | 2 +- 9 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 app/Policies/Rules/CreditAccountLogRules.php diff --git a/app/Http/Controllers/Credit/AccountController.php b/app/Http/Controllers/Credit/AccountController.php index c5f8531..db2d358 100644 --- a/app/Http/Controllers/Credit/AccountController.php +++ b/app/Http/Controllers/Credit/AccountController.php @@ -38,12 +38,31 @@ class AccountController extends Controller */ public function indexQuery(Builder $query): Builder { - /** @var \App\Models\Brand|null $brand */ - if (!($brand = request()->brand)) { - throw new \ErrorException('Cannot get brand'); + /** @var \App\Models\User */ + $user = auth()->user(); + + if (!$user->isAdmin()) { + $userBrands = $user->brands(); + if (!$userBrands->count()) { + \redirect()->route('ticket.index')->withErrors(['warning' => trans( + // phpcs:ignore Generic.Files.LineLength.TooLong + 'Pour utiliser cette fonctionnalité vous devez appartenir à une marque, merci d\'en faire la demande à :mail', + ['mail' => collect(config('mail.contactsList.serviceweb'))->implode(' ')] + )])->throwResponse(); + } + return $query->whereHas('brand', function ($q) use ($userBrands) { + $q->whereIn('brand_id', $userBrands->pluck('id')); + }); } - return $query->where('brand_id', '=', $brand->id); + /** @var \App\Models\Brand|null $brand */ + if (!($brand = request()->brand)) { + abort(404, 'Cannot get brand'); + } + + return $query->whereHas('brand', function ($q) use ($brand) { + $q->where('id', $brand->id); + }); } /** diff --git a/app/Http/Controllers/Credit/CreditLogController.php b/app/Http/Controllers/Credit/CreditLogController.php index a3d60e7..1350eae 100644 --- a/app/Http/Controllers/Credit/CreditLogController.php +++ b/app/Http/Controllers/Credit/CreditLogController.php @@ -36,13 +36,14 @@ class CreditLogController extends Controller { $query->orderBy('created_at', 'DESC'); - /** @var \App\Models\Credit\Account|null $account */ - if (!($account = request()->account)) { - throw new \ErrorException('Cannot get account'); - } + /** @var \App\Models\User */ + $user = auth()->user(); + + /** @var \App\Models\Credit\Account $account */ + $account = request()->account; return $query->whereHas('account', function ($q) use ($account) { - $q->whereIn('id', $account->pluck('id')); + $q->where('id', '=', $account->id); }); } diff --git a/app/Models/User.php b/app/Models/User.php index 6d7ab39..fa0cf91 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -249,6 +249,16 @@ class User extends Authenticatable // * METHODS + /** + * get User brands + * + * @return \Illuminate\Database\Eloquent\Collection<\App\Models\Brand> + */ + public function brands() + { + return $this->sites->pluck('brand')->filter(); + } + /** * Send User creation confirm mail * diff --git a/app/Policies/AccountPolicy.php b/app/Policies/AccountPolicy.php index 882c03a..bc91f90 100644 --- a/app/Policies/AccountPolicy.php +++ b/app/Policies/AccountPolicy.php @@ -32,7 +32,7 @@ class AccountPolicy extends RootPolicy 'update' => URR::make('denyEveryOne'), 'create' => URR::make('userIsAdmin', $user), 'delete' => URR::make('userIsAdmin', $user), - 'credit' => URR::make('userIsAdmin', $user) + 'credit' => URR::make('allowEveryOne') ] ]; } diff --git a/app/Policies/CreditLogPolicy.php b/app/Policies/CreditLogPolicy.php index 99c90bf..b4cb3bc 100644 --- a/app/Policies/CreditLogPolicy.php +++ b/app/Policies/CreditLogPolicy.php @@ -3,7 +3,7 @@ namespace App\Policies; use App\Models\User; -use App\Policies\Rules\UserRoleRules as URR; +use App\Policies\Rules\CreditAccountLogRules; use Illuminate\Auth\Access\HandlesAuthorization; use Illuminate\Database\Eloquent\Model; use Kwaadpepper\CrudPolicies\Policies\RootPolicy; @@ -27,7 +27,7 @@ class CreditLogPolicy extends RootPolicy */ $this->policies = [ 'creditlog' => [ - 'viewAny' => URR::make('allowEveryOne') + 'viewAny' => CreditAccountLogRules::make('nonAdminUserHasBrands', $user, $model) ] ]; } diff --git a/app/Policies/Rules/CreditAccountLogRules.php b/app/Policies/Rules/CreditAccountLogRules.php new file mode 100644 index 0000000..3ee21cd --- /dev/null +++ b/app/Policies/Rules/CreditAccountLogRules.php @@ -0,0 +1,24 @@ +isAdmin() or $user->brands()->count() > 0; + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 52a25c4..30600af 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -4,6 +4,7 @@ namespace App\Providers; use App\Models\Brand; use App\Models\Credit\Account; +use App\Models\Credit\CreditLog; use App\Models\File; use App\Models\Label; use App\Models\Log; @@ -15,6 +16,7 @@ use App\Models\User; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Http\Request; +use Illuminate\Routing\Route as RoutingRoute; use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\Route; @@ -45,8 +47,35 @@ class RouteServiceProvider extends ServiceProvider ->namespace($this->namespace) ->group(base_path('routes/web.php')); }); - Route::model('account', Account::class); + Route::bind('account', function ($value, RoutingRoute $route) { + /** @var \App\Models\User|null */ + if (!($user = \auth()->user())) { + abort(401); + } + + $this->assertClientHasBrands($user); + + // * If route has brand parameter + /** @var \App\Models\Brand|null */ + if ($brand = $route->parameter('brand')) { + return Account::where('id', \intval($value))->whereHas('brand', function ($q) use ($brand) { + $q->where('id', $brand->id); + })->firstOrFail(); + } + return Account::where('id', \intval($value))->firstOrFail(); + }); + Route::bind('brand', function ($value) { + /** @var \App\Models\User|null */ + if (!($user = \auth()->user())) { + abort(401); + } + + $this->assertClientHasBrands($user); + + return Account::where('id', \intval($value))->firstOrFail(); + }); Route::model('brand', Brand::class); + Route::model('credit_log', CreditLog::class); Route::model('label', Label::class); Route::model('marker', Marker::class); Route::model('file', File::class); @@ -74,6 +103,30 @@ class RouteServiceProvider extends ServiceProvider }); } + /** + * Assert client user has brands + * or return to tickets.index with warning + * + * @param \App\Models\User $user + * @return void + */ + private function assertClientHasBrands(User $user): void + { + if (!$user->isAdmin()) { + $userBrandsAccounts = $user->brands()->each(function (Brand $brand) { + $brand->load('accounts'); + })->pluck('accounts')->flatten(); + + if (!$userBrandsAccounts->count()) { + \redirect()->route('ticket.index')->withErrors(['warning' => trans( + // phpcs:ignore Generic.Files.LineLength.TooLong + 'Pour utiliser cette fonctionnalité vous devez appartenir à une marque, merci d\'en faire la demande à :mail', + ['mail' => collect(config('mail.contactsList.serviceweb'))->implode(' ')] + )])->throwResponse(); + } + } + } + /** * * Register CSP report URI * diff --git a/resources/views/credit_logs/index.blade.php b/resources/views/credit_logs/index.blade.php index 5388c25..8ab243c 100644 --- a/resources/views/credit_logs/index.blade.php +++ b/resources/views/credit_logs/index.blade.php @@ -30,6 +30,16 @@
+ @if(request()->brand) +
+
+ {{ __('Marque')}} +
+
+ {{ optional(request()->brand)->name }} +
+
+ @endif
{{ __('Compte')}} diff --git a/resources/views/layout/nav.blade.php b/resources/views/layout/nav.blade.php index 5f936bb..79f9ff0 100644 --- a/resources/views/layout/nav.blade.php +++ b/resources/views/layout/nav.blade.php @@ -47,7 +47,7 @@ @if(!Auth::user()->isAdmin()) @can('viewAny', App\Models\Credit\Account::class) @endcan @endif