From 2db3ca9d7e2386275405f32845ee654ffdb55c57 Mon Sep 17 00:00:00 2001 From: Ryan Scherler Date: Mon, 16 Mar 2020 14:52:58 -0700 Subject: [PATCH] Start integrating spatie / laravel-permission --- composer.json | 7 +- ...0000_add_is_super_admin_to_users_table.php | 43 ++++++++ ..._03_16_100000_create_permission_tables.php | 102 ++++++++++++++++++ src/AlpineServiceProvider.php | 17 +++ src/Http/Controllers/DashboardController.php | 20 ++++ src/Traits/AlpineUser.php | 26 ++++- src/routes/web.php | 4 +- 7 files changed, 208 insertions(+), 11 deletions(-) create mode 100644 database/migrations/2020_03_10_100000_add_is_super_admin_to_users_table.php create mode 100644 database/migrations/2020_03_16_100000_create_permission_tables.php create mode 100644 src/Http/Controllers/DashboardController.php diff --git a/composer.json b/composer.json index 3054efb9bd..d7f7a3a6cb 100644 --- a/composer.json +++ b/composer.json @@ -19,16 +19,13 @@ } ], "require": { - "php": "^7.2.5", + "doctrine/dbal": "^2.10.0", "graham-campbell/markdown": "^12.0", "laravel/ui": "^2.0", + "spatie/laravel-permission": "^3.11", "thomaswelton/laravel-gravatar": "~1.0", "watson/active": "^5.0" }, - "require-dev": { - "ext-pdo_sqlite": "*", - "doctrine/dbal": "^2.10.0" - }, "autoload": { "psr-4": { "Alpine\\": "src" diff --git a/database/migrations/2020_03_10_100000_add_is_super_admin_to_users_table.php b/database/migrations/2020_03_10_100000_add_is_super_admin_to_users_table.php new file mode 100644 index 0000000000..cf5cbaba6d --- /dev/null +++ b/database/migrations/2020_03_10_100000_add_is_super_admin_to_users_table.php @@ -0,0 +1,43 @@ +tableName, 'is_super_admin')) { + Schema::table($this->tableName, function (Blueprint $table) { + $table->boolean('is_super_admin')->default(0)->after('email'); + }); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + if (Schema::hasColumn($this->tableName, 'is_super_admin')) { + Schema::table($this->tableName, function (Blueprint $table) { + $table->dropColumn('is_super_admin'); + }); + } + } +} diff --git a/database/migrations/2020_03_16_100000_create_permission_tables.php b/database/migrations/2020_03_16_100000_create_permission_tables.php new file mode 100644 index 0000000000..e2a682edfc --- /dev/null +++ b/database/migrations/2020_03_16_100000_create_permission_tables.php @@ -0,0 +1,102 @@ +bigIncrements('id'); + $table->string('name'); + $table->string('guard_name'); + $table->timestamps(); + }); + + Schema::create($tableNames['roles'], function (Blueprint $table) { + $table->bigIncrements('id'); + $table->string('name'); + $table->string('guard_name'); + $table->timestamps(); + }); + + Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames) { + $table->unsignedBigInteger('permission_id'); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); + + $table->foreign('permission_id') + ->references('id') + ->on($tableNames['permissions']) + ->onDelete('cascade'); + + $table->primary(['permission_id', $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary'); + }); + + Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames) { + $table->unsignedBigInteger('role_id'); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); + + $table->foreign('role_id') + ->references('id') + ->on($tableNames['roles']) + ->onDelete('cascade'); + + $table->primary(['role_id', $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary'); + }); + + Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) { + $table->unsignedBigInteger('permission_id'); + $table->unsignedBigInteger('role_id'); + + $table->foreign('permission_id') + ->references('id') + ->on($tableNames['permissions']) + ->onDelete('cascade'); + + $table->foreign('role_id') + ->references('id') + ->on($tableNames['roles']) + ->onDelete('cascade'); + + $table->primary(['permission_id', 'role_id'], 'role_has_permissions_permission_id_role_id_primary'); + }); + + app('cache') + ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null) + ->forget(config('permission.cache.key')); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $tableNames = config('permission.table_names'); + + Schema::drop($tableNames['role_has_permissions']); + Schema::drop($tableNames['model_has_roles']); + Schema::drop($tableNames['model_has_permissions']); + Schema::drop($tableNames['roles']); + Schema::drop($tableNames['permissions']); + } +} \ No newline at end of file diff --git a/src/AlpineServiceProvider.php b/src/AlpineServiceProvider.php index fe92f619d7..7cce1119f4 100644 --- a/src/AlpineServiceProvider.php +++ b/src/AlpineServiceProvider.php @@ -6,6 +6,7 @@ use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Blade; +use Illuminate\Support\Facades\Gate; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Events\Dispatcher; @@ -46,6 +47,7 @@ class AlpineServiceProvider extends ServiceProvider */ public function boot() { + $this->handleAuth(); $this->handleCommands(); $this->handleEvents(); $this->handleMiddleware(); @@ -91,6 +93,21 @@ class AlpineServiceProvider extends ServiceProvider // $this->app->bind(ResourceContract::class, config('alpine.models.resource')); } + /** + * Register the package's auth. + * + * @return void + */ + protected function handleAuth() + { + // Implicitly grant "Super Admin" role all permissions + // This works in the app by using gate-related functions like auth()->user->can() and @can() + // @link https://docs.spatie.be/laravel-permission/v3/basic-usage/super-admin/ + Gate::before(function ($user, $ability) { + return $user->is_super_admin ? true : null; + }); + } + /** * Register the package's commands. * diff --git a/src/Http/Controllers/DashboardController.php b/src/Http/Controllers/DashboardController.php new file mode 100644 index 0000000000..a6c4eeef04 --- /dev/null +++ b/src/Http/Controllers/DashboardController.php @@ -0,0 +1,20 @@ +mergeFillable(['is_super_admin']); + $this->mergeCasts(['is_super_admin' => 'boolean']); + } + + /** + * Merge fillable attributes. + * + * @return void + */ + protected function mergeFillable(array $fillable) + { + $this->fillable(collect($this->fillable)->merge($fillable)->all()); + } + /** * Send the password reset notification. * @@ -28,5 +49,4 @@ trait AlpineUser { { $this->attributes['password'] = Hash::make($pass); } - } \ No newline at end of file diff --git a/src/routes/web.php b/src/routes/web.php index 0bfb17fe82..27ee815d97 100644 --- a/src/routes/web.php +++ b/src/routes/web.php @@ -40,8 +40,6 @@ Route::name('auth.')->namespace('Auth')->group(function () { // protected admin routes... Route::name('admin.')->middleware('auth.alpine')->group(function () { - Route::get('/', function () { - return view('alpine::dashboard'); - })->name('dashboard'); + Route::get('/', 'DashboardController')->name('dashboard'); }); \ No newline at end of file