diff --git a/app/Models/Policies/UserPolicy.php b/app/Models/Policies/UserPolicy.php index bc4ebff..949e6dc 100644 --- a/app/Models/Policies/UserPolicy.php +++ b/app/Models/Policies/UserPolicy.php @@ -10,6 +10,30 @@ class UserPolicy { use HandlesAuthorization; + /** + * Wholesalers can do anything. + * + * @param User $uo + * @param string $ability + * @return bool|null + */ + public function before(User $uo,string $ability): ?bool + { + return $uo->isWholesaler() ?: NULL; + } + + /** + * Can this user assume the role of the other user + * + * @param User $uo + * @param User $o + * @return bool + */ + public function assume(User $uo, User $o): bool + { + return $uo->isAdmin($o); + } + /** * Determine whether the user can view the user details. * @@ -22,69 +46,7 @@ class UserPolicy // If this is a service for an account managed by a user. return ($uo->id == $o->id) - // The user is the wholesaler - OR $uo->isWholesaler() - // The user has this as one of their accounts OR $uo->accounts->pluck('user')->pluck('id')->unique()->contains($o->id); } - - /** - * Determine whether the user can create services. - * - * @param User $uo - * @return bool - */ - public function create(User $uo): bool - { - return $uo->isWholesaler(); - } - - /** - * Determine whether the user can update the service. - * - * @param User $uo - * @param User $o - * @return bool - */ - public function update(User $uo, User $o): bool - { - return $uo->isWholesaler(); - } - - /** - * Determine whether the user can delete the service. - * - * @param User $uo - * @param User $o - * @return bool - */ - public function delete(User $uo, User $o): bool - { - return $uo->isWholesaler(); - } - - /** - * Determine whether the user can restore the service. - * - * @param User $uo - * @param User $o - * @return bool - */ - public function restore(User $uo, User $o): bool - { - return $uo->isWholesaler(); - } - - /** - * Determine whether the user can permanently delete the service. - * - * @param User $uo - * @param User $o - * @return bool - */ - public function forceDelete(User $uo, User $o): bool - { - return $uo->isWholesaler(); - } } \ No newline at end of file diff --git a/app/Models/User.php b/app/Models/User.php index 450e509..419e2f1 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -266,12 +266,12 @@ class User extends Authenticatable implements IDs /** * Determine if the user is an admin of the user with $id * - * @param $id + * @param User|null $user * @return bool */ - public function isAdmin($id): bool + public function isAdmin(User $user=NULL): bool { - return $id AND $this->isReseller() AND $this->accounts->pluck('user_id')->contains($id); + return $user->exists AND $this->isReseller() AND $this->accounts->pluck('user_id')->contains($user->id); } /** diff --git a/composer.json b/composer.json index 43c45c6..4b3689b 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "laravel/passport": "^10.1", "laravel/socialite": "^5.2", "laravel/ui": "^3.2", - "leenooks/laravel": "^9.0", + "leenooks/laravel": "^9.2.0", "leenooks/laravel-theme": "^v2.0.18", "nunomaduro/laravel-console-summary": "^1.8", "paypal/paypal-checkout-sdk": "^1.0", diff --git a/composer.lock b/composer.lock index d94f402..69c78c9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6b40a401e159479f114598fcfe5e71d0", + "content-hash": "c41aad3374358724adae9239e88f7a4f", "packages": [ { "name": "asm89/stack-cors", @@ -3296,11 +3296,11 @@ }, { "name": "leenooks/laravel", - "version": "9.1.6", + "version": "9.2.0", "source": { "type": "git", "url": "https://dev.leenooks.net/leenooks/laravel", - "reference": "2a8dd4fa2cbe00300800313c2ca6fed4f26cdc09" + "reference": "c9cd560b363a7c1dd4dbbdb349d4308151cdd210" }, "require": { "creativeorange/gravatar": "^1.0", @@ -3339,7 +3339,7 @@ "laravel", "leenooks" ], - "time": "2022-02-15T23:49:44+00:00" + "time": "2022-06-28T11:40:13+00:00" }, { "name": "leenooks/laravel-theme", @@ -5629,7 +5629,7 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -5676,7 +5676,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { @@ -5850,7 +5850,7 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", @@ -5909,7 +5909,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" }, "funding": [ { @@ -7218,16 +7218,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e517458f278c2131ca9f262f8fbaf01410f2c65c" + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e517458f278c2131ca9f262f8fbaf01410f2c65c", - "reference": "e517458f278c2131ca9f262f8fbaf01410f2c65c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", "shasum": "" }, "require": { @@ -7280,7 +7280,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" }, "funding": [ { @@ -7296,7 +7296,7 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:10:05+00:00" + "time": "2022-05-30T19:17:58+00:00" }, { "name": "symfony/string", @@ -7480,16 +7480,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.0.1", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "c4183fc3ef0f0510893cbeedc7718fb5cafc9ac9" + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/c4183fc3ef0f0510893cbeedc7718fb5cafc9ac9", - "reference": "c4183fc3ef0f0510893cbeedc7718fb5cafc9ac9", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", "shasum": "" }, "require": { @@ -7538,7 +7538,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.0.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" }, "funding": [ { @@ -7554,7 +7554,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-06-27T17:10:44+00:00" }, { "name": "symfony/var-dumper", diff --git a/routes/web.php b/routes/web.php index 0105ec0..1809711 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,6 @@ true, + 'logout' => true, + 'register' => false, + 'reset' => true, // for resetting passwords + 'confirm' => false, // for additional password confirmations + 'verify' => false, // for email verification +]); +Route::get('logout',[LoginController::class,'logout']) + ->name('logout-get'); // Account linking to OPENID host Route::group(['middleware'=>['theme:adminlte-be']],function() { @@ -36,66 +45,82 @@ Route::group(['middleware'=>['theme:adminlte-be']],function() { Route::get('auth/{socialProvider}/link',[SocialLoginController::class,'link']); Route::post('auth/{socialProvider}/linkcomplete',[SocialLoginController::class,'linkcomplete']); }); +// Return from user switch +Route::get('admin/switch/stop',[SwitchUserController::class,'switch_stop']) + ->middleware('auth') + ->name('switch.stop'); // Generic Image Renderer - Render images that we dont have with a generic image -Route::get('image/generic/{width}/{height}/{color}/{name?}',[MediaController::class,'image'])->name('image'); +Route::get('image/generic/{width}/{height}/{color}/{name?}',[MediaController::class,'image']) + ->name('image'); // Our Admin Routes - for wholesalers Route::group(['middleware'=>['theme:adminlte-be','auth','role:wholesaler'],'prefix'=>'a'],function() { // Site Setup Route::match(['get','post'],'setup',[AdminController::class,'setup']); + // Product Setup Route::match(['get'],'product',[ProductController::class,'home']); - Route::match(['get','post'],'product/details/{o?}',[ProductController::class,'details']); + Route::match(['get','post'],'product/details/{o?}',[ProductController::class,'details']) + ->where('o','[0-9]+'); + // Supplier Setup // @todo Move to Supplier Controller Route::match(['get'],'supplier',[AdminController::class,'supplier']); - Route::match(['get','post'],'supplier/details/{o?}',[AdminController::class,'supplier_addedit']); + Route::match(['get','post'],'supplier/details/{o?}',[AdminController::class,'supplier_addedit']) + ->where('o','[0-9]+'); + //Route::get('report/products','Wholesale\ReportController@products'); -// Route::get('service/{o}','AdminHomeController@service'); -// Route::post('service/{o}','AdminHomeController@service_update'); -// Route::get('report/products','Wholesale\ReportController@products'); + // Supplier Costs - @todo Move to supplier/cost route + Route::get('cost/{o}',[CostController::class,'home']) + ->where('o','[0-9]+'); - // Charges + // Charges - @todo This should probably go to resellers Route::match(['get','post'],'charge/addedit/{o?}',[AdminController::class,'charge_addedit']); Route::get('charge/unprocessed',[AdminController::class,'charge_unprocessed']); - // Payments + // Payments - @todo This should probably go to resellers Route::match(['get','post'],'payment/addedit/{o?}',[AdminController::class,'pay_addedit']); Route::get('payment/unapplied',[AdminController::class,'pay_unapplied']); + // Services + // @todo This should probably go to resellers - implement a change audit log first Route::post('service/edit/{o}',[ServiceController::class,'update']) - ->where('o','[0-9]+') - ->middleware('can:update,o'); - //Route::get('accounting/connect','AccountingController@connect'); + ->where('o','[0-9]+'); - Route::get('cost/{o}',[CostController::class,'home']) - ->where('o','[0-9]+') - ->middleware('can:view,o'); +//@deprecated +// Route::get('service/{o}','AdminHomeController@service'); +// Route::post('service/{o}','AdminHomeController@service_update'); +// Route::get('accounting/connect','AccountingController@connect'); }); -Route::get('admin/switch/stop',[LeenooksAdminController::class,'user_switch_stop'])->name('switch.user.start')->middleware('auth'); - // Our Reseller Routes Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix'=>'r'],function() { -// Route::get('supplier/index','SuppliersController@index'); -// Route::get('supplier/create','SuppliersController@create'); -// Route::post('supplier/store','SuppliersController@store'); - Route::get('switch/start/{id}',[LeenooksAdminController::class,'user_switch_start'])->name('switch.user.stop'); + // Enable user switch + Route::get('switch/start/{user}',[SwitchUserController::class,'switch_start']) + ->middleware('can:assume,user') + ->name('switch.start'); + // Reseller Reports Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix'=>'report'],function() { Route::get('domain',[ServiceController::class,'domain_list']); Route::get('email',[ServiceController::class,'email_list']); Route::get('hosting',[ServiceController::class,'hosting_list']); }); - // Charges on an account + // Charges Route::get('charges/{o}',[AdminController::class,'charge_pending_account']) + ->middleware('can:view,o') ->where('o','[0-9]+'); // Reseller API calls Route::post('service_change_charges/{o}',[ServiceController::class,'service_change_charges_display']) ->where('o','[0-9]+'); + +//@deprecated +// Route::get('supplier/index','SuppliersController@index'); +// Route::get('supplier/create','SuppliersController@create'); +// Route::post('supplier/store','SuppliersController@store'); }); // Our User Routes