From 877525b86c267d2e4e12aee6ba42aebbf1cee5b7 Mon Sep 17 00:00:00 2001 From: Hasin Hayder Date: Wed, 18 May 2022 01:08:07 +0600 Subject: [PATCH] Functional User Registration and Login with Roles and Abilities With Default Values from the Options table --- .gitignore | 2 + app/Http/Controllers/UserController.php | 138 ++++++++++++++++++ app/Http/Kernel.php | 7 +- app/Models/Option.php | 14 ++ app/Models/Role.php | 19 +++ app/Models/User.php | 5 + app/Models/UserRole.php | 14 ++ config/database.php | 2 +- ...2022_05_17_171951_create_options_table.php | 33 +++++ .../2022_05_17_181447_create_roles_table.php | 33 +++++ ...2_05_17_181456_create_user_roles_table.php | 33 +++++ database/seeders/DatabaseSeeder.php | 7 + database/seeders/OptionsSeeder.php | 27 ++++ database/seeders/RoleSeeder.php | 29 ++++ database/seeders/UserRoleSeeder.php | 29 ++++ database/seeders/UsersSeeder.php | 27 ++++ routes/api.php | 5 + 17 files changed, 420 insertions(+), 4 deletions(-) create mode 100644 app/Http/Controllers/UserController.php create mode 100644 app/Models/Option.php create mode 100644 app/Models/Role.php create mode 100644 app/Models/UserRole.php create mode 100644 database/migrations/2022_05_17_171951_create_options_table.php create mode 100644 database/migrations/2022_05_17_181447_create_roles_table.php create mode 100644 database/migrations/2022_05_17_181456_create_user_roles_table.php create mode 100644 database/seeders/OptionsSeeder.php create mode 100644 database/seeders/RoleSeeder.php create mode 100644 database/seeders/UserRoleSeeder.php create mode 100644 database/seeders/UsersSeeder.php diff --git a/.gitignore b/.gitignore index bc67a66..8e96c35 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ npm-debug.log yarn-error.log /.idea /.vscode +database.sqlite +.DS_Store diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..57fee50 --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,138 @@ +validate([ + 'email' => 'required|email', + 'password' => 'required', + 'name' => 'required' + ]); + + $user = User::where('email', $creds['email'])->first(); + if ($user) { + return response(['error' => 1, 'message' => 'user already exists'], 409); + } + + $user = User::create([ + 'email' => $creds['email'], + 'password' => Hash::make($creds['password']), + 'name' => $creds['email'] + ]); + + $default_user_role_id = Option::where('key', 'default_role_id')->first()->value; + UserRole::create([ + 'user_id'=>$user->id, + 'role_id'=>$default_user_role_id + ]); + + + return $user; + } + + /** + * Authenticate an user and dispatch token. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function login(Request $request) { + $creds = $request->validate([ + 'email' => 'required|email', + 'password' => 'required', + ]); + + $user = User::where('email', $creds['email'])->first(); + if (!$user || !Hash::check($request->password, $user->password)) { + return response(['error' => 1, 'message' => 'invalid credentials'], 401); + } + + if (Option::where('key', 'single_session')->first()->value == '1') { + $user->tokens()->delete(); + } + + + $roles = $user->roles()->get(); + $_roles = []; + foreach($roles as $role){ + $_roles[] = $role->slug; + } + + return $user->createToken('hydra-api-token',$_roles)->plainTextToken; + } + + /** + * Display the specified resource. + * + * @param \App\Models\User $user + * @return \Illuminate\Http\Response + */ + public function show(User $user) { + // + } + + /** + * Show the form for editing the specified resource. + * + * @param \App\Models\User $user + * @return \Illuminate\Http\Response + */ + public function edit(User $user) { + // + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param \App\Models\User $user + * @return \Illuminate\Http\Response + */ + public function update(Request $request, User $user) { + // + } + + /** + * Remove the specified resource from storage. + * + * @param \App\Models\User $user + * @return \Illuminate\Http\Response + */ + public function destroy(User $user) { + // + } + + +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index c3be254..0ebdbfa 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -4,8 +4,7 @@ namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; -class Kernel extends HttpKernel -{ +class Kernel extends HttpKernel { /** * The application's global HTTP middleware stack. * @@ -39,7 +38,7 @@ class Kernel extends HttpKernel ], 'api' => [ - // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, + \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], @@ -63,5 +62,7 @@ class Kernel extends HttpKernel 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class, + 'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class, ]; } diff --git a/app/Models/Option.php b/app/Models/Option.php new file mode 100644 index 0000000..d30babf --- /dev/null +++ b/app/Models/Option.php @@ -0,0 +1,14 @@ + 'datetime', ]; + + public function roles(){ + return $this->belongsToMany(Role::class,'user_roles'); + } } diff --git a/app/Models/UserRole.php b/app/Models/UserRole.php new file mode 100644 index 0000000..4554f75 --- /dev/null +++ b/app/Models/UserRole.php @@ -0,0 +1,14 @@ + [ 'driver' => 'sqlite', 'url' => env('DATABASE_URL'), - 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'database' => database_path(env('DB_DATABASE', 'database.sqlite')), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], diff --git a/database/migrations/2022_05_17_171951_create_options_table.php b/database/migrations/2022_05_17_171951_create_options_table.php new file mode 100644 index 0000000..43bcae8 --- /dev/null +++ b/database/migrations/2022_05_17_171951_create_options_table.php @@ -0,0 +1,33 @@ +id(); + $table->string('key'); + $table->string('value'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('options'); + } +}; diff --git a/database/migrations/2022_05_17_181447_create_roles_table.php b/database/migrations/2022_05_17_181447_create_roles_table.php new file mode 100644 index 0000000..ff43946 --- /dev/null +++ b/database/migrations/2022_05_17_181447_create_roles_table.php @@ -0,0 +1,33 @@ +id(); + $table->string('name'); + $table->string('slug')->index(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('roles'); + } +}; diff --git a/database/migrations/2022_05_17_181456_create_user_roles_table.php b/database/migrations/2022_05_17_181456_create_user_roles_table.php new file mode 100644 index 0000000..1744a86 --- /dev/null +++ b/database/migrations/2022_05_17_181456_create_user_roles_table.php @@ -0,0 +1,33 @@ +id(); + $table->foreignId('user_id')->constrained()->cascadeOnDelete(); + $table->foreignId('role_id')->constrained()->cascadeOnDelete(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('user_roles'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index c1c48a0..0cc3ee8 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -20,5 +20,12 @@ class DatabaseSeeder extends Seeder // 'name' => 'Test User', // 'email' => 'test@example.com', // ]); + $this->call([ + OptionsSeeder::class, + UsersSeeder::class, + RoleSeeder::class, + UserRoleSeeder::class + ]); + } } diff --git a/database/seeders/OptionsSeeder.php b/database/seeders/OptionsSeeder.php new file mode 100644 index 0000000..f3050f9 --- /dev/null +++ b/database/seeders/OptionsSeeder.php @@ -0,0 +1,27 @@ +truncate(); + Option::create([ + 'key' => 'single_session', + 'value' => '1' + ]); + Option::create([ + 'key' => 'default_role_id', + 'value' => '2' //user + ]); + } +} diff --git a/database/seeders/RoleSeeder.php b/database/seeders/RoleSeeder.php new file mode 100644 index 0000000..f78dd63 --- /dev/null +++ b/database/seeders/RoleSeeder.php @@ -0,0 +1,29 @@ +truncate(); + Role::insert( + [ + ['name' => 'Administrator', 'slug' => 'admin'], + ['name' => 'User', 'slug' => 'user'], + ['name' => 'Customer', 'slug' => 'customer'], + ['name' => 'Editor', 'slug' => 'editor'], + ['name' => 'All', 'slug' => '*'], + ['name' => 'Super Admin', 'slug' => 'super-admin'], + ] + ); + } +} diff --git a/database/seeders/UserRoleSeeder.php b/database/seeders/UserRoleSeeder.php new file mode 100644 index 0000000..5b43128 --- /dev/null +++ b/database/seeders/UserRoleSeeder.php @@ -0,0 +1,29 @@ +truncate(); + UserRole::create([ + 'user_id'=>1, + 'role_id'=>1 + ]); //admin + UserRole::create([ + 'user_id'=>1, + 'role_id'=>5 + ]);//all + } +} diff --git a/database/seeders/UsersSeeder.php b/database/seeders/UsersSeeder.php new file mode 100644 index 0000000..f9c359a --- /dev/null +++ b/database/seeders/UsersSeeder.php @@ -0,0 +1,27 @@ +truncate(); + User::create([ + 'email'=>'admin@example.com', + 'password'=>Hash::make('hydra'), + 'name'=>'Hydra Admin' + ]); + } +} diff --git a/routes/api.php b/routes/api.php index eb6fa48..cf1fe2d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,5 +1,6 @@ get('/user', function (Request $request) { return $request->user(); }); + +Route::apiResource('users',UserController::class)->except(['create','edit','show','update','destroy']); +Route::apiResource('users',UserController::class)->except(['store','index'])->middleware('auth:sanctum'); +Route::post('login',[UserController::class,'login']);