diff --git a/app/Http/Controllers/Credit/AccountController.php b/app/Http/Controllers/Credit/AccountController.php index c5f8531..92a9e87 100644 --- a/app/Http/Controllers/Credit/AccountController.php +++ b/app/Http/Controllers/Credit/AccountController.php @@ -38,12 +38,24 @@ 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(); + 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..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 * 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..4a07210 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,7 +47,43 @@ 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('credit_log', function ($value) { + /** @var \App\Models\User|null */ + if (!($user = \auth()->user())) { + abort(401); + } + + $this->assertClientHasBrands($user); + + return CreditLog::where('id', \intval($value))->firstOrFail(); + }); Route::model('brand', Brand::class); Route::model('label', Label::class); Route::model('marker', Marker::class); @@ -74,6 +112,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/accounts/index.blade.php b/resources/views/accounts/index.blade.php index 6120874..562d76b 100644 --- a/resources/views/accounts/index.blade.php +++ b/resources/views/accounts/index.blade.php @@ -30,6 +30,7 @@ + @if(request()->brand)