From 6f27b3b652a0c2ce9ae59002e6e7f949c23742a9 Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Fri, 9 Jun 2023 23:39:30 +0530 Subject: [PATCH 01/41] Roles interface with add role --- .../Controllers/Dashboard/RolesController.php | 68 +++++++ resources/app/pages/Roles.vue | 171 ++++++++++++++++++ routes/web.php | 7 +- 3 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/Dashboard/RolesController.php create mode 100644 resources/app/pages/Roles.vue diff --git a/app/Http/Controllers/Dashboard/RolesController.php b/app/Http/Controllers/Dashboard/RolesController.php new file mode 100644 index 0000000..5e20728 --- /dev/null +++ b/app/Http/Controllers/Dashboard/RolesController.php @@ -0,0 +1,68 @@ + [] + ] + ); + } + public function store(Request $request) + { + // Validate the request input + $validator = Validator::make($request->all(), [ + 'name' => 'required|string', + 'display_name' => 'required|string', + 'description' => 'required|string', + ]); + + if ($validator->fails()) { + return response()->json($validator->errors(), 422); + } + + // Create a new Role object and save it to the database + $role = new Role(); + $role->name = $request->name; + $role->display_name = $request->display_name; + $role->description = $request->description; + $role->save(); + + // Return a success response with the new role object + return response()->json($role, 201); + } + public function getRoles() + { + // Get all roles from the database + // $roles = Role::all(); + $roles = Role::with('permissions')->get(); + // Get the permissions associated with each role + + + // Embed the permissions into the roles + +// foreach ($roles as $role) { +// $role->permissions = $role->permissions; +// } + + + // Return all roles as a JSON response + return response()->json($roles); + } +} diff --git a/resources/app/pages/Roles.vue b/resources/app/pages/Roles.vue new file mode 100644 index 0000000..1289391 --- /dev/null +++ b/resources/app/pages/Roles.vue @@ -0,0 +1,171 @@ + + diff --git a/routes/web.php b/routes/web.php index fcb27a9..0486d80 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Auth\ResetPasswordController; use App\Http\Controllers\Dashboard\Calendar\CalendarController; use App\Http\Controllers\Dashboard\DashboardController; +use App\Http\Controllers\Dashboard\RolesController; use App\Http\Controllers\Dashboard\Facility\FacilityController; use App\Http\Controllers\Dashboard\FlowBoardController; use App\Http\Controllers\Dashboard\Patient\PatientAppointmentController; @@ -109,7 +110,9 @@ function () { // ======== Calendar routes ======== Route::get('calendar', [CalendarController::class, 'index'])->name('calendar'); - + Route::get('/roles', [RolesController::class, 'index']); + Route::post('/roles', [RolesController::class, 'store']); + Route::get('/allRoles', [RolesController::class, 'getRoles']); // ======== Users related routes ======== Route::resource('users', UserController::class)->names([ 'index' => 'users.index', @@ -214,3 +217,5 @@ function () { }); }); }); + + From 6bc448aed5ac324c72a18801255906f54d0c667b Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Fri, 16 Jun 2023 21:38:33 +0530 Subject: [PATCH 02/41] =?UTF-8?q?=F0=9F=90=9B=20Minor=20fixes:=20used=20zi?= =?UTF-8?q?ggy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Dashboard/RolesController.php | 13 ++------ app/Http/Requests/CreateRoleRequest.php | 32 +++++++++++++++++++ resources/app/pages/Roles.vue | 4 +-- routes/web.php | 6 ++-- 4 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 app/Http/Requests/CreateRoleRequest.php diff --git a/app/Http/Controllers/Dashboard/RolesController.php b/app/Http/Controllers/Dashboard/RolesController.php index 5e20728..0a218a9 100644 --- a/app/Http/Controllers/Dashboard/RolesController.php +++ b/app/Http/Controllers/Dashboard/RolesController.php @@ -7,6 +7,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; use App\Http\Controllers\Controller; +use App\Http\Requests\CreateRoleRequest; use Inertia\Inertia; use Inertia\Response; class RolesController extends Controller @@ -24,18 +25,8 @@ public function index(): Response ] ); } - public function store(Request $request) + public function store(CreateRoleRequest $request) { - // Validate the request input - $validator = Validator::make($request->all(), [ - 'name' => 'required|string', - 'display_name' => 'required|string', - 'description' => 'required|string', - ]); - - if ($validator->fails()) { - return response()->json($validator->errors(), 422); - } // Create a new Role object and save it to the database $role = new Role(); diff --git a/app/Http/Requests/CreateRoleRequest.php b/app/Http/Requests/CreateRoleRequest.php new file mode 100644 index 0000000..f715d8f --- /dev/null +++ b/app/Http/Requests/CreateRoleRequest.php @@ -0,0 +1,32 @@ + + */ + public function rules() + { + return [ + 'name' => 'required|string', + 'display_name' => 'required|string', + 'description' => 'required|string', + ]; + } +} diff --git a/resources/app/pages/Roles.vue b/resources/app/pages/Roles.vue index 1289391..f889d61 100644 --- a/resources/app/pages/Roles.vue +++ b/resources/app/pages/Roles.vue @@ -130,13 +130,13 @@ export default { }, methods: { getRoles() { - axios.get("/dashboard/allRoles").then((response) => { + axios.get(this.route("dashboard.roles.all")).then((response) => { this.roles = response.data; }); }, addRole() { axios - .post("/dashboard/roles", { + .post(this.route("dashboard.roles.store"), { name: this.name, display_name: this.display_name, description: this.description, diff --git a/routes/web.php b/routes/web.php index 0486d80..464bfff 100644 --- a/routes/web.php +++ b/routes/web.php @@ -110,9 +110,9 @@ function () { // ======== Calendar routes ======== Route::get('calendar', [CalendarController::class, 'index'])->name('calendar'); - Route::get('/roles', [RolesController::class, 'index']); - Route::post('/roles', [RolesController::class, 'store']); - Route::get('/allRoles', [RolesController::class, 'getRoles']); + Route::get('/roles', [RolesController::class, 'index'])->name('roles.index'); + Route::post('/roles', [RolesController::class, 'store'])->name('roles.store'); + Route::get('/all-roles', [RolesController::class, 'getRoles'])->name('roles.all'); // ======== Users related routes ======== Route::resource('users', UserController::class)->names([ 'index' => 'users.index', From e4281e456f7f3aff57eabefa58b1128f8bad5d1c Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Fri, 16 Jun 2023 23:10:52 +0530 Subject: [PATCH 03/41] Added Laratrust Seeder for Roles --- config/laratrust_seeder.php | 141 +++++++++++++++++++++++++++ database/seeders/DatabaseSeeder.php | 3 + database/seeders/LaratrustSeeder.php | 103 +++++++++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 config/laratrust_seeder.php create mode 100644 database/seeders/LaratrustSeeder.php diff --git a/config/laratrust_seeder.php b/config/laratrust_seeder.php new file mode 100644 index 0000000..4c8ddba --- /dev/null +++ b/config/laratrust_seeder.php @@ -0,0 +1,141 @@ + false, + + /** + * Control if all the laratrust tables should be truncated before running the seeder. + */ + 'truncate_tables' => true, + + 'roles_structure' => [ + 'superadministrator' => [ + 'calendar' => 'c,r,u,d', + 'flow-board' => 'c,r,u,d', + 'patient' => 'c,r,u,d', + 'fees' => 'c,r,u,d', + 'inventory' => 'c,r,u,d', + 'procedures' => 'c,r,u,d', + 'administration' => 'c,r,u,d', + 'reports' => 'c,r,u,d', + 'misc' => 'c,r,u,d', + 'popups' => 'c,r,u,d', + 'qa-measures' => 'c,r,u,d', + 'help' => 'c,r,u,d', + ], + 'administrators' => [ + 'calendar' => 'c,r,u,d', + 'flow-board' => 'c,r,u,d', + 'patient' => 'c,r,u,d', + 'fees' => 'c,r,u,d', + 'inventory' => 'c,r,u,d', + 'procedures' => 'c,r,u,d', + 'administration' => 'c,r', + 'reports' => 'c,r,u,d', + 'misc' => 'c,r,u,d', + 'popups' => 'c,r,u,d', + 'qa-measures' => 'c,r,u,d', + 'help' => 'r', + ], + 'lh-user' => [ + 'calendar' => 'r', + 'patient' => 'r', + 'fees' => 'r', + 'inventory' => 'r', + 'procedures' => 'r', + 'administration' => 'r', + 'reports' => 'r', + 'misc' => 'r', + 'popups' => 'r', + 'qa-measures' => 'r', + 'help' => 'r', + ], + 'accounting' => [ + 'Calendar' => 'r', + 'patient' => 'r', + 'fees' => 'c,r,u,d', + 'inventory' => 'r', + 'procedures' => 'r', + 'administration' => 'r,u', + 'reports' => 'c,r,u,d', + 'misc' => 'r,u', + 'popups' => 'r,u', + 'qa-measures' => 'r,u', + 'help' => 'r', + ], + 'clinicians' => [ + 'calendar' => 'c,r,u,d', + 'patient' => 'c,r,u,d', + 'fees' => 'c,r,u,d', + 'inventory' => 'r,u', + 'procedures' => 'r,u', + 'administration' => 'r,u', + 'reports' => 'r,u', + 'misc' => 'r,u', + 'popups' => 'r,u', + 'qa-measures' => 'r,u', + 'help' => 'r', + ], + 'emergency_login' => [ + 'calendar' => 'r', + 'patient' => 'c,r,u,d', + 'fees' => 'r', + 'inventory' => 'r', + 'procedures' => 'r', + 'administration' => 'r', + 'reports' => 'r', + 'misc' => 'r', + 'popups' => 'r', + 'qa-measures' => 'r', + 'help' => 'r', + ], + 'front_office' => [ + 'calendar' => 'r,u', + 'patient' => 'r,u', + 'fees' => 'r,u', + 'inventory' => 'r', + 'procedures' => 'r', + 'administration' => 'r', + 'reports' => 'r', + 'misc' => 'r', + 'popups' => 'r', + 'qa-measures' => 'r', + 'help' => 'r', + ], + 'physicians' => [ + 'calendar' => 'c,r,u,d', + 'patient' => 'c,r,u,d', + 'fees' => 'r,u', + 'inventory' => 'r', + 'procedures' => 'c,r,u,d', + 'administration' => 'c,r', + 'reports' => 'c,r,u,d', + 'misc' => 'c,r,u,d', + 'popups' => 'c,r,u,d', + 'qa-measures' => 'c,r,u,d', + 'help' => 'r', + ], + 'super_student' => [ + 'calendar' => 'r,u', + 'patient' => 'r,u', + 'fees' => 'r', + 'inventory' => 'r', + 'procedures' => 'r,u', + 'administration' => 'r,u', + 'reports' => 'r,u', + 'misc' => 'r,u', + 'popups' => 'r,u', + 'qa-measures' => 'r,u', + 'help' => 'r', + ], + ], + 'permissions_map' => [ + 'c' => 'create', + 'r' => 'read', + 'u' => 'update', + 'd' => 'delete' + ] + ]; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 9536bd2..60e407b 100755 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -42,6 +42,7 @@ public function truncateAndSeedData() DB::table($name)->truncate(); } Schema::enableForeignKeyConstraints(); + $this->seedData(); $this->complete(); } @@ -58,8 +59,10 @@ public function seedData() if (count($continents) < 1) { Artisan::call('world:init'); } + $this->call(CurrencySeeder::class); $this->call(UserTableSeeder::class); + $this->call(LaratrustSeeder::class); $this->call(AddressTableSeeder::class); $this->call(ContactTableSeeder::class); $this->call(FacilityTableSeeder::class); diff --git a/database/seeders/LaratrustSeeder.php b/database/seeders/LaratrustSeeder.php new file mode 100644 index 0000000..a85ffd4 --- /dev/null +++ b/database/seeders/LaratrustSeeder.php @@ -0,0 +1,103 @@ +truncateLaratrustTables(); + + $config = Config::get('laratrust_seeder.roles_structure'); + + if ($config === null) { + $this->command->error("The configuration has not been published. Did you run `php artisan vendor:publish --tag=\"laratrust-seeder\"`"); + $this->command->line(''); + return false; + } + + $mapPermission = collect(config('laratrust_seeder.permissions_map')); + + foreach ($config as $key => $modules) { + + // Create a new role + $role = \App\Models\Role::firstOrCreate([ + 'name' => $key, + 'display_name' => ucwords(str_replace('_', ' ', $key)), + 'description' => ucwords(str_replace('_', ' ', $key)) + ]); + $permissions = []; + + $this->command->info('Creating Role '. strtoupper($key)); + + // Reading role permission modules + foreach ($modules as $module => $value) { + + foreach (explode(',', $value) as $p => $perm) { + + $permissionValue = $mapPermission->get($perm); + + $permissions[] = \App\Models\Permission::firstOrCreate([ + 'name' => $module . '-' . $permissionValue, + 'display_name' => ucfirst($permissionValue) . ' ' . ucfirst($module), + 'description' => ucfirst($permissionValue) . ' ' . ucfirst($module), + ])->id; + + $this->command->info('Creating Permission to '.$permissionValue.' for '. $module); + } + } + + // Attach all permissions to the role + $role->permissions()->sync($permissions); + + if (Config::get('laratrust_seeder.create_users')) { + $this->command->info("Creating '{$key}' user"); + // Create default user for each role + $user = \App\Models\User::create([ + 'name' => ucwords(str_replace('_', ' ', $key)), + 'email' => $key.'@app.com', + 'password' => bcrypt('password') + ]); + $user->attachRole($role); + } + + } + } + + /** + * Truncates all the laratrust tables and the users table + * + * @return void + */ + public function truncateLaratrustTables() + { + $this->command->info('Truncating User, Role and Permission tables'); + Schema::disableForeignKeyConstraints(); + + DB::table('permission_role')->truncate(); + DB::table('permission_user')->truncate(); + DB::table('role_user')->truncate(); + + if (Config::get('laratrust_seeder.truncate_tables')) { + DB::table('roles')->truncate(); + DB::table('permissions')->truncate(); + + if (Config::get('laratrust_seeder.create_users')) { + $usersTable = (new \App\Models\User)->getTable(); + DB::table($usersTable)->truncate(); + } + } + + Schema::enableForeignKeyConstraints(); + } +} From a819002c70ccb44f82d8f16f9317004444a8918f Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Tue, 20 Jun 2023 23:01:30 +0530 Subject: [PATCH 04/41] Minor updates --- .../Controllers/Dashboard/RolesController.php | 16 +--------------- config/laratrust_seeder.php | 2 +- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/app/Http/Controllers/Dashboard/RolesController.php b/app/Http/Controllers/Dashboard/RolesController.php index 0a218a9..cca11cf 100644 --- a/app/Http/Controllers/Dashboard/RolesController.php +++ b/app/Http/Controllers/Dashboard/RolesController.php @@ -28,32 +28,18 @@ public function index(): Response public function store(CreateRoleRequest $request) { - // Create a new Role object and save it to the database $role = new Role(); $role->name = $request->name; $role->display_name = $request->display_name; $role->description = $request->description; $role->save(); - - // Return a success response with the new role object return response()->json($role, 201); } public function getRoles() { - // Get all roles from the database - // $roles = Role::all(); - $roles = Role::with('permissions')->get(); - // Get the permissions associated with each role - - - // Embed the permissions into the roles - -// foreach ($roles as $role) { -// $role->permissions = $role->permissions; -// } + $roles = Role::with('permissions')->get(); - // Return all roles as a JSON response return response()->json($roles); } } diff --git a/config/laratrust_seeder.php b/config/laratrust_seeder.php index 4c8ddba..958ef18 100644 --- a/config/laratrust_seeder.php +++ b/config/laratrust_seeder.php @@ -40,7 +40,7 @@ 'qa-measures' => 'c,r,u,d', 'help' => 'r', ], - 'lh-user' => [ + 'users' => [ 'calendar' => 'r', 'patient' => 'r', 'fees' => 'r', From 51ec886798e8cc9bdf617456131e8544d9096573 Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Sun, 25 Jun 2023 00:51:12 +0530 Subject: [PATCH 05/41] Role UI update and Permission Data fetched in form --- .../Dashboard/PermissionController.php | 19 +++ resources/app/pages/Roles.vue | 141 +++++++++++------- routes/web.php | 3 + 3 files changed, 107 insertions(+), 56 deletions(-) create mode 100644 app/Http/Controllers/Dashboard/PermissionController.php diff --git a/app/Http/Controllers/Dashboard/PermissionController.php b/app/Http/Controllers/Dashboard/PermissionController.php new file mode 100644 index 0000000..34450ef --- /dev/null +++ b/app/Http/Controllers/Dashboard/PermissionController.php @@ -0,0 +1,19 @@ +json($permissions); + } +} diff --git a/resources/app/pages/Roles.vue b/resources/app/pages/Roles.vue index f889d61..cb346a4 100644 --- a/resources/app/pages/Roles.vue +++ b/resources/app/pages/Roles.vue @@ -1,6 +1,6 @@ @@ -213,15 +209,17 @@ export default { return { role_dropdown: null, default_facility_dropdown: false, - userForm: { + userForm: this.$inertia.form({ username: "", - password: "", - confirmPassword: "", + email: "", suffix: "", - full_name: "", + first_name: "", + middle_name: "", + last_name: "", dea_number: "", tax_id: "", npi: "", + job_description: "", provider_type: "", default_warehouse: "", taxonomy: "", @@ -229,7 +227,7 @@ export default { additional_details: "", default_facility: "", role: "", - }, + }), errors: { username: "", full_name: "", @@ -260,7 +258,18 @@ export default { this.roleOptions = response.data; }); }, - addUser() {}, + addUser() { + console.log(this.userForm); + this.userForm.post(this.route("dashboard.users.store")); + }, + selectDefaultFacility(facility) { + this.userForm.default_facility = facility.name; + this.default_facility_dropdown = false; + }, + selectRole(role) { + this.userForm.role = role.name; + this.role_dropdown = false; + }, toggleRoleList() { this.role_dropdown = !this.role_dropdown; }, diff --git a/resources/views/emails/testMail.blade.php b/resources/views/emails/testMail.blade.php new file mode 100644 index 0000000..0e72a93 --- /dev/null +++ b/resources/views/emails/testMail.blade.php @@ -0,0 +1,15 @@ + + + + + + Document + + +

{{$mailData['title']}}

+ +

Helllo,{{$mailData['username']}}
You have been invited to Librehealth as a {{$mailData['role']}} for the facility: {{$mailData['facility']}}
Please click the linke bellow and activate you account

+ Click here to activate your account + + + diff --git a/routes/web.php b/routes/web.php index ece53c5..628276d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,6 +19,7 @@ use App\Http\Controllers\Installer\InstallerFilePermissionController; use App\Http\Controllers\Installer\InstallerRequirementsController; use App\Http\Controllers\LocaleController; +use App\Http\Controllers\MailController; use App\Http\Controllers\PagesController; use Illuminate\Support\Facades\Route; @@ -91,6 +92,7 @@ /* ================================= LH EHR PORTAL Routes ================================= */ + Route::group( [ 'as' => 'dashboard.', @@ -129,6 +131,8 @@ function () { 'update' => 'users.update', 'destroy' => 'users.destroy', ]); + Route::post('/add-user', [UserController::class, 'store'])->name('users.add'); + Route::get('users/load/data', [UserController::class, 'getUserData']) ->name('users.load.data'); @@ -202,7 +206,12 @@ function () { ); } ); + /* ================================= + LH EHR New User Routes + ================================= */ + Route::get('/add-password', [UserController::class, 'AddPassword'])->name('users.confirm'); + Route::post('/verify-user', [UserController::class, 'verifyUser'])->name('users.verify'); /* ================================= LH EHR ADMIN Routes From 4621bfabc7ef58d041e949e7f67a7f910b9543a0 Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Fri, 21 Jul 2023 06:21:51 +0530 Subject: [PATCH 16/41] Added a default value for token expiry --- database/migrations/2017_06_14_000000_create_users_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2017_06_14_000000_create_users_table.php b/database/migrations/2017_06_14_000000_create_users_table.php index 626aaeb..45923c6 100755 --- a/database/migrations/2017_06_14_000000_create_users_table.php +++ b/database/migrations/2017_06_14_000000_create_users_table.php @@ -34,7 +34,7 @@ public function up() $table->string('facility')->nullable(); $table->text('additional_details')->nullable(); $table->string('token')->nullable()->comment('Token'); - $table->timestamp('token_expiry')->comment('Token Expiry'); + $table->timestamp('token_expiry')->default(now())->comment('Token Expiry'); // Miscellaneous properties From 3e3a4dde4bb1cd4af465744e9e3a6bb5aa711ee8 Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Wed, 26 Jul 2023 05:51:24 +0530 Subject: [PATCH 17/41] User Invitation Updated --- .../Controllers/UserInvitationController.php | 74 +++++++++ app/Invite.php | 149 +++++++++++++++++ app/Models/UserInvitation.php | 18 ++ app/Models/UsersInvited.php | 18 ++ ...7_25_201028_create_users_invited_table.php | 55 ++++++ ...5_201052_create_user_invitations_table.php | 36 ++++ resources/app/pages/AddPassword.vue | 156 +++++++++++++----- resources/app/pages/AddUsers.vue | 2 +- routes/web.php | 12 +- 9 files changed, 474 insertions(+), 46 deletions(-) create mode 100644 app/Http/Controllers/UserInvitationController.php create mode 100644 app/Invite.php create mode 100644 app/Models/UserInvitation.php create mode 100644 app/Models/UsersInvited.php create mode 100644 database/migrations/2023_07_25_201028_create_users_invited_table.php create mode 100644 database/migrations/2023_07_25_201052_create_user_invitations_table.php diff --git a/app/Http/Controllers/UserInvitationController.php b/app/Http/Controllers/UserInvitationController.php new file mode 100644 index 0000000..9533e37 --- /dev/null +++ b/app/Http/Controllers/UserInvitationController.php @@ -0,0 +1,74 @@ + $request->username, + 'email' => $request->email, + 'first_name' => $request->first_name, + 'middle_name' => $request->middle_name, + 'last_name' => $request->last_name, + 'federal_tax_id' => $request->tax_id, + 'federal_drug_id' => $request->dea_number, + 'npi' => $request->npi, + 'suffix' => $request->suffix, + 'taxonomy' => $request->taxonomy, + 'info' => $request->job_description, + 'access_control' => $request->role, + 'warehouse' => $request->default_warehouse, + 'facility'=> $request->default_facility, + 'provider_type' => $request->provider_type, + 'license' => $request->license_number, + 'additional_details' => $request->additional_details, + ]; + + + + Invite::send($userData, $request->email); + return Inertia::location(route('dashboard.users.index')); + } + + public function acceptInvite(Request $request) + { + $code = $request->code; + $password = bcrypt($request->password); + $success=Invite::accept($code, $password); + if($success){ + return Inertia::location(route('login')); + }else{ + return Redirect::back()->with(['error' => 'Something went wrong']); + } + + } + + public function rejectInvite(Request $request) + { + $code = $request->code; + $success=Invite::reject($code); + if($success){ + return response()->json(['status' => 'success']); + }else{ + return Redirect::back()->with(['error' => 'Something went wrong']); + } + + } + + public function invitationStatus(Request $request) + { + $code = $request->code; + $status = Invite::status($code); + return response()->json(['status' => $status]); + + } + +} diff --git a/app/Invite.php b/app/Invite.php new file mode 100644 index 0000000..e3a966c --- /dev/null +++ b/app/Invite.php @@ -0,0 +1,149 @@ + $userInvited->id, + 'email' => $email, + 'code' => $code, + 'status' => 'pending', + 'valid_till' => now()->addDays(7), // Invitation valid for 7 days + ]); + + // Send the invitation email + $url = URL::temporarySignedRoute( + 'users.confirm', + now()->addDays(7), + ['username' => $userData['username'],'code'=>$code] + ); + $mailData = [ + 'title' => 'User Invitation Mail', + 'url'=> $url, + 'facility' => $userData['facility'], + 'role'=> $userData['access_control'], + 'username' => $userData['username'], + + ]; + Mail::to($userData['email'])->send(new InvitationMail($mailData)); + if($invitation->save()){ + return Inertia::location(route('dashboard.users.index')); + }else{ + return Redirect::back()->with(['error' => 'Something went wrong']); + } + } + + public static function accept($code, $password) + { + // Find the invitation by code + $invitation = UserInvitation::where('code', $code)->first(); + + if (!$invitation || $invitation->valid_till < now() || $invitation->status != 'pending') { + return false; // Invalid invitation code or invitation expired or invitation already accepted/rejected + } + + // Create the new user in the real users table + $invitedUser=UsersInvited::find($invitation->for_user); + + $user = User::create([ + 'username' => $invitedUser->username, + 'email' => $invitedUser->email, + 'password' =>$password, + 'first_name' => $invitedUser->first_name, + 'middle_name' => $invitedUser->middle_name, + 'last_name' => $invitedUser->last_name, + 'federal_tax_id' => $invitedUser->federal_tax_id, + 'federal_drug_id' => $invitedUser->federal_drug_id, + 'npi' => $invitedUser->npi, + 'suffix' => $invitedUser->suffix, + 'taxonomy' => $invitedUser->taxonomy, + 'info' => $invitedUser->info, + 'access_control' => $invitedUser->access_control, + 'warehouse' => $invitedUser->warehouse, + 'facility'=> $invitedUser->facility, + 'provider_type' => $invitedUser->provider_type, + 'license' => $invitedUser->license, + ]); + $role = Role::where('name', '=', $invitedUser->access_control)->first(); + $permissions=$role->permissions; + $user->attachRole($role); + foreach ($permissions as $permission) { + $user->attachPermission($permission); + } + $invitation->update([ + 'status' => 'accepted', + ]); + $invitation->save(); + if($user->save()){ + return true; + } + + return false; //if any error occurs + } + + public static function reject($code) + { + // Find the invitation by code + $invitation = UserInvitation::where('code', $code)->first(); + + if (!$invitation) { + return false; // Invalid invitation code + } + + // Update the invitation status + $invitation->update([ + 'status' => 'rejected', + ]); + + $invitation->save(); + return true; // Invitation rejected successfully + } + + public static function isExpired($code) + { + // Find the invitation by code + $invitation = UserInvitation::where('code', $code)->first(); + if($invitation->valid_till < now()){ + $invitation->update([ + 'status' => 'expired', + ]); + $invitation->save(); + return true; + } + return false; + } + + public static function status($code) + { + // Find the invitation by code + $invitation = UserInvitation::where('code', $code)->first(); + + if (!$invitation) { + return 'invalid'; // Invalid invitation code + } + + return $invitation->status; + } +} diff --git a/app/Models/UserInvitation.php b/app/Models/UserInvitation.php new file mode 100644 index 0000000..3a9f03e --- /dev/null +++ b/app/Models/UserInvitation.php @@ -0,0 +1,18 @@ +belongsTo(UsersInvited::class, 'for_user'); + } +} diff --git a/app/Models/UsersInvited.php b/app/Models/UsersInvited.php new file mode 100644 index 0000000..f9bc8ba --- /dev/null +++ b/app/Models/UsersInvited.php @@ -0,0 +1,18 @@ +bigIncrements('id'); + $table->string('first_name')->comment('User First Name.'); + $table->string('middle_name')->nullable()->comment('User Middle Name.'); + $table->string('last_name')->comment('User Last Name.'); + $table->string('username')->unique(); + $table->string('email')->unique()->nullable(); + $table->string('license')->nullable(); + $table->string('provider_type')->nullable(); + $table->string('warehouse')->nullable(); + $table->string('facility')->nullable(); + + + // Miscellaneous properties + $table->string('suffix')->comment('User Suffix e.g Dr, PHD, Mr, Mrs'); + $table->string('federal_tax_id')->unique()->comment('Federal Tax ID'); + $table->string('federal_drug_id')->unique()->comment('Federal Drug ID. DEA Number'); + $table->string('taxonomy')->comment('Taxonomy'); + $table->bigInteger('npi')->comment('National Provider Identifier.')->default(0); + $table->longText('info')->nullable()->comment('About/Biography/Job Description'); + $table->string('access_control') + ->comment('Access Control of user. Viz Accounting, Administrators, Clinicians, etc.'); + + // remember tokens and timestamps + $table->softDeletes(); + $table->rememberToken()->comment('Remember me token'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('users_invited'); + } +}; diff --git a/database/migrations/2023_07_25_201052_create_user_invitations_table.php b/database/migrations/2023_07_25_201052_create_user_invitations_table.php new file mode 100644 index 0000000..08d8d88 --- /dev/null +++ b/database/migrations/2023_07_25_201052_create_user_invitations_table.php @@ -0,0 +1,36 @@ +id(); + $table->foreignId('for_user')->constrained('users_invited'); + $table->string('email'); + $table->string('code')->unique(); + $table->string('status')->default('pending'); + $table->timestamp('valid_till')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('user_invitations'); + } +}; diff --git a/resources/app/pages/AddPassword.vue b/resources/app/pages/AddPassword.vue index 74fabe6..be06e79 100644 --- a/resources/app/pages/AddPassword.vue +++ b/resources/app/pages/AddPassword.vue @@ -3,50 +3,79 @@
-

Add Password

-
-
- +
+ +
+

+ Invitation {{ message }} +

-
- -
-
- +
+
+ +

+ Accept Invitation +

+ +
+ +
- - +
+ +
+ +

+ Add Password +

+
+
+ +
+ +
+ +
+
+ +
+
+
diff --git a/resources/app/pages/AddUsers.vue b/resources/app/pages/AddUsers.vue index eb9b665..7672a94 100644 --- a/resources/app/pages/AddUsers.vue +++ b/resources/app/pages/AddUsers.vue @@ -260,7 +260,7 @@ export default { }, addUser() { console.log(this.userForm); - this.userForm.post(this.route("dashboard.users.store")); + this.userForm.post(this.route("dashboard.users.add")); }, selectDefaultFacility(facility) { this.userForm.default_facility = facility.name; diff --git a/routes/web.php b/routes/web.php index 628276d..3f6c6b4 100644 --- a/routes/web.php +++ b/routes/web.php @@ -20,7 +20,9 @@ use App\Http\Controllers\Installer\InstallerRequirementsController; use App\Http\Controllers\LocaleController; use App\Http\Controllers\MailController; +use App\Http\Controllers\MailSendingController; use App\Http\Controllers\PagesController; +use App\Http\Controllers\UserInvitationController; use Illuminate\Support\Facades\Route; /* @@ -110,6 +112,7 @@ function () { // ======== Flow Board routes ======== Route::get('flow-board', [FlowBoardController::class, 'index'])->name('flow_board'); + Route::get('mail', [MailSendingController::class, 'sendWelcomeEmail'])->name('mail'); // ======== Calendar routes ======== Route::get('calendar', [CalendarController::class, 'index'])->name('calendar'); @@ -131,7 +134,7 @@ function () { 'update' => 'users.update', 'destroy' => 'users.destroy', ]); - Route::post('/add-user', [UserController::class, 'store'])->name('users.add'); + Route::post('/add-user', [UserInvitationController::class, 'sendInvite'])->name('users.add'); Route::get('users/load/data', [UserController::class, 'getUserData']) ->name('users.load.data'); @@ -209,9 +212,12 @@ function () { /* ================================= LH EHR New User Routes ================================= */ - Route::get('/add-password', [UserController::class, 'AddPassword'])->name('users.confirm'); - Route::post('/verify-user', [UserController::class, 'verifyUser'])->name('users.verify'); + // User Invitation Routes + Route::post('/check-invitation-status', + [UserInvitationController::class, 'invitationStatus'])->name('invitation.status'); + Route::post('/accept-invite', [UserInvitationController::class, 'acceptInvite'])->name('invitation.accept'); + Route::post('/reject-invite', [UserInvitationController::class, 'rejectInvite'])->name('invitation.reject'); /* ================================= LH EHR ADMIN Routes From 037543c55ddf287a52cf6232c26cb8023f0037fa Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Wed, 26 Jul 2023 21:03:08 +0530 Subject: [PATCH 18/41] Table Updates --- .../Controllers/UserInvitationController.php | 15 +-- app/Invite.php | 92 +++++++++---------- app/Models/Invitation.php | 18 ++++ app/Models/User.php | 2 +- app/Models/UserInvitation.php | 18 ---- app/Models/UsersInvited.php | 18 ---- .../2017_06_14_000000_create_users_table.php | 4 +- ...7_25_201028_create_users_invited_table.php | 55 ----------- ...07_25_201052_create_invitations_table.php} | 8 +- resources/app/pages/AddPassword.vue | 16 ++-- routes/web.php | 2 - 11 files changed, 86 insertions(+), 162 deletions(-) create mode 100644 app/Models/Invitation.php delete mode 100644 app/Models/UserInvitation.php delete mode 100644 app/Models/UsersInvited.php delete mode 100644 database/migrations/2023_07_25_201028_create_users_invited_table.php rename database/migrations/{2023_07_25_201052_create_user_invitations_table.php => 2023_07_25_201052_create_invitations_table.php} (71%) diff --git a/app/Http/Controllers/UserInvitationController.php b/app/Http/Controllers/UserInvitationController.php index 9533e37..79bbfaa 100644 --- a/app/Http/Controllers/UserInvitationController.php +++ b/app/Http/Controllers/UserInvitationController.php @@ -6,14 +6,17 @@ use Illuminate\Http\Request; use Inertia\Inertia; use Redirect; +use Str; class UserInvitationController extends Controller { public function sendInvite(Request $request) { + $temporaryPassword = Str::random(10); $userData=[ 'username' => $request->username, + 'password'=> bcrypt($temporaryPassword), 'email' => $request->email, 'first_name' => $request->first_name, 'middle_name' => $request->middle_name, @@ -40,9 +43,9 @@ public function sendInvite(Request $request) public function acceptInvite(Request $request) { - $code = $request->code; + $token = $request->token; $password = bcrypt($request->password); - $success=Invite::accept($code, $password); + $success=Invite::accept($token, $password); if($success){ return Inertia::location(route('login')); }else{ @@ -53,8 +56,8 @@ public function acceptInvite(Request $request) public function rejectInvite(Request $request) { - $code = $request->code; - $success=Invite::reject($code); + $token = $request->token; + $success=Invite::reject($token); if($success){ return response()->json(['status' => 'success']); }else{ @@ -65,8 +68,8 @@ public function rejectInvite(Request $request) public function invitationStatus(Request $request) { - $code = $request->code; - $status = Invite::status($code); + $token = $request->token; + $status = Invite::status($token); return response()->json(['status' => $status]); } diff --git a/app/Invite.php b/app/Invite.php index e3a966c..e6607cc 100644 --- a/app/Invite.php +++ b/app/Invite.php @@ -2,11 +2,9 @@ namespace App; use App\Mail\InvitationMail; -use App\Mail\UserInvitationMail; use App\Models\Role; use App\Models\User; -use App\Models\UsersInvited; -use App\Models\UserInvitation; +use App\Models\Invitation; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Str; use Inertia\Inertia; @@ -20,15 +18,15 @@ public static function send($userData, $email,) // Save the invitation data in the users_invited table - $userInvited = UsersInvited::create($userData); - // Generate a unique code for the invitation - $code = Str::random(10); + $userInvited = User::create($userData); + // Generate a unique token for the invitation + $token = Str::random(10); // Save the invitation data in the user_invitations table - $invitation=UserInvitation::create([ + $invitation=Invitation::create([ 'for_user' => $userInvited->id, 'email' => $email, - 'code' => $code, + 'token' => $token, 'status' => 'pending', 'valid_till' => now()->addDays(7), // Invitation valid for 7 days ]); @@ -37,7 +35,7 @@ public static function send($userData, $email,) $url = URL::temporarySignedRoute( 'users.confirm', now()->addDays(7), - ['username' => $userData['username'],'code'=>$code] + ['username' => $userData['username'],'token'=>$token] ); $mailData = [ 'title' => 'User Invitation Mail', @@ -55,93 +53,91 @@ public static function send($userData, $email,) } } - public static function accept($code, $password) + public static function accept($token, $password) { - // Find the invitation by code - $invitation = UserInvitation::where('code', $code)->first(); + // Find the invitation by token + $invitation = Invitation::where('token', $token)->first(); if (!$invitation || $invitation->valid_till < now() || $invitation->status != 'pending') { - return false; // Invalid invitation code or invitation expired or invitation already accepted/rejected + return false; // Invalid invitation token or invitation expired or invitation already accepted/rejected } // Create the new user in the real users table - $invitedUser=UsersInvited::find($invitation->for_user); - - $user = User::create([ - 'username' => $invitedUser->username, - 'email' => $invitedUser->email, - 'password' =>$password, - 'first_name' => $invitedUser->first_name, - 'middle_name' => $invitedUser->middle_name, - 'last_name' => $invitedUser->last_name, - 'federal_tax_id' => $invitedUser->federal_tax_id, - 'federal_drug_id' => $invitedUser->federal_drug_id, - 'npi' => $invitedUser->npi, - 'suffix' => $invitedUser->suffix, - 'taxonomy' => $invitedUser->taxonomy, - 'info' => $invitedUser->info, - 'access_control' => $invitedUser->access_control, - 'warehouse' => $invitedUser->warehouse, - 'facility'=> $invitedUser->facility, - 'provider_type' => $invitedUser->provider_type, - 'license' => $invitedUser->license, - ]); + $invitedUser=User::find($invitation->for_user); $role = Role::where('name', '=', $invitedUser->access_control)->first(); $permissions=$role->permissions; - $user->attachRole($role); + $invitedUser->attachRole($role); foreach ($permissions as $permission) { - $user->attachPermission($permission); + $invitedUser->attachPermission($permission); } $invitation->update([ 'status' => 'accepted', ]); + $invitedUser->update([ + 'password' => $password, + 'invitation' => 'accepted', + ]); $invitation->save(); - if($user->save()){ + if($invitedUser->save()){ return true; } return false; //if any error occurs } - public static function reject($code) + public static function reject($token) { - // Find the invitation by code - $invitation = UserInvitation::where('code', $code)->first(); + // Find the invitation by token + $invitation = Invitation::where('token', $token)->first(); if (!$invitation) { - return false; // Invalid invitation code + return false; // Invalid invitation token } + $invitedUser=User::where('id', $invitation->for_user)->first(); + if (!$invitedUser) { + return false; // Invalid invitation token + } + $invitedUser->update([ + 'invitation' => 'rejected', + ]); + $invitedUser->save(); // Update the invitation status $invitation->update([ 'status' => 'rejected', ]); $invitation->save(); + return true; // Invitation rejected successfully } - public static function isExpired($code) + public static function isExpired($token) { - // Find the invitation by code - $invitation = UserInvitation::where('code', $code)->first(); + // Find the invitation by token + $invitation = Invitation::where('token', $token)->first(); + $invitedUser=User::find($invitation->for_user); if($invitation->valid_till < now()){ $invitation->update([ 'status' => 'expired', ]); + $invitedUser->update([ + 'invitation' => 'expired', + ]); $invitation->save(); + $invitedUser->save(); return true; } return false; } - public static function status($code) + public static function status($token) { - // Find the invitation by code - $invitation = UserInvitation::where('code', $code)->first(); + // Find the invitation by token + $invitation = Invitation::where('token', $token)->first(); if (!$invitation) { - return 'invalid'; // Invalid invitation code + return 'invalid'; // Invalid invitation token } return $invitation->status; diff --git a/app/Models/Invitation.php b/app/Models/Invitation.php new file mode 100644 index 0000000..17069d6 --- /dev/null +++ b/app/Models/Invitation.php @@ -0,0 +1,18 @@ +belongsTo(User::class, 'for_user'); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index c5b7e74..894ec5f 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -31,7 +31,7 @@ class User extends Authenticatable */ protected $fillable = [ 'username', 'password','email', 'first_name', 'middle_name', 'last_name', 'federal_tax_id', - 'federal_drug_id', 'see_auth', 'npi', 'suffix', 'taxonomy','license','provider_type','warehouse','additional_details','calendar_ui', 'info', 'token', 'token_expiry','facility', + 'federal_drug_id', 'see_auth', 'npi', 'suffix', 'taxonomy','license','provider_type','warehouse','additional_details','calendar_ui', 'info','facility','invitation', 'new_crop_user_role', 'access_control', 'in_calendar', 'device_id', 'last_login_at', 'last_login_ip', 'created_at', 'updated_at', 'deleted_at' ]; diff --git a/app/Models/UserInvitation.php b/app/Models/UserInvitation.php deleted file mode 100644 index 3a9f03e..0000000 --- a/app/Models/UserInvitation.php +++ /dev/null @@ -1,18 +0,0 @@ -belongsTo(UsersInvited::class, 'for_user'); - } -} diff --git a/app/Models/UsersInvited.php b/app/Models/UsersInvited.php deleted file mode 100644 index f9bc8ba..0000000 --- a/app/Models/UsersInvited.php +++ /dev/null @@ -1,18 +0,0 @@ -string('warehouse')->nullable(); $table->string('facility')->nullable(); $table->text('additional_details')->nullable(); - $table->string('token')->nullable()->comment('Token'); - $table->timestamp('token_expiry')->default(now())->comment('Token Expiry'); + $table->string('invitation')->default('pending')->comment('Invitation Status'); + // Miscellaneous properties diff --git a/database/migrations/2023_07_25_201028_create_users_invited_table.php b/database/migrations/2023_07_25_201028_create_users_invited_table.php deleted file mode 100644 index 63f3303..0000000 --- a/database/migrations/2023_07_25_201028_create_users_invited_table.php +++ /dev/null @@ -1,55 +0,0 @@ -bigIncrements('id'); - $table->string('first_name')->comment('User First Name.'); - $table->string('middle_name')->nullable()->comment('User Middle Name.'); - $table->string('last_name')->comment('User Last Name.'); - $table->string('username')->unique(); - $table->string('email')->unique()->nullable(); - $table->string('license')->nullable(); - $table->string('provider_type')->nullable(); - $table->string('warehouse')->nullable(); - $table->string('facility')->nullable(); - - - // Miscellaneous properties - $table->string('suffix')->comment('User Suffix e.g Dr, PHD, Mr, Mrs'); - $table->string('federal_tax_id')->unique()->comment('Federal Tax ID'); - $table->string('federal_drug_id')->unique()->comment('Federal Drug ID. DEA Number'); - $table->string('taxonomy')->comment('Taxonomy'); - $table->bigInteger('npi')->comment('National Provider Identifier.')->default(0); - $table->longText('info')->nullable()->comment('About/Biography/Job Description'); - $table->string('access_control') - ->comment('Access Control of user. Viz Accounting, Administrators, Clinicians, etc.'); - - // remember tokens and timestamps - $table->softDeletes(); - $table->rememberToken()->comment('Remember me token'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('users_invited'); - } -}; diff --git a/database/migrations/2023_07_25_201052_create_user_invitations_table.php b/database/migrations/2023_07_25_201052_create_invitations_table.php similarity index 71% rename from database/migrations/2023_07_25_201052_create_user_invitations_table.php rename to database/migrations/2023_07_25_201052_create_invitations_table.php index 08d8d88..e13bb92 100644 --- a/database/migrations/2023_07_25_201052_create_user_invitations_table.php +++ b/database/migrations/2023_07_25_201052_create_invitations_table.php @@ -13,11 +13,11 @@ */ public function up() { - Schema::create('user_invitations', function (Blueprint $table) { + Schema::create('invitations', function (Blueprint $table) { $table->id(); - $table->foreignId('for_user')->constrained('users_invited'); + $table->foreignId('for_user')->constrained('users'); $table->string('email'); - $table->string('code')->unique(); + $table->string('token')->unique(); $table->string('status')->default('pending'); $table->timestamp('valid_till')->nullable(); $table->timestamps(); @@ -31,6 +31,6 @@ public function up() */ public function down() { - Schema::dropIfExists('user_invitations'); + Schema::dropIfExists('invitations'); } }; diff --git a/resources/app/pages/AddPassword.vue b/resources/app/pages/AddPassword.vue index be06e79..3b1b144 100644 --- a/resources/app/pages/AddPassword.vue +++ b/resources/app/pages/AddPassword.vue @@ -83,12 +83,12 @@ export default { }, data() { return { - code: null, + token: null, message: null, passwordForm: this.$inertia.form({ expires: null, username: null, - code: null, + token: null, password: null, }), showExpiredMessage: true, @@ -111,7 +111,7 @@ export default { rejectInvitation() { console.log("reject invitation"); axios - .post(this.route("invitation.reject"), { code: this.code }) + .post(this.route("invitation.reject"), { token: this.token }) .then((response) => { if (response.data.status == "success") { this.message = "Rejected"; @@ -121,9 +121,9 @@ export default { } }); }, - tokenExpired(code) { + tokenExpired(token) { axios - .post(this.route("invitation.status"), { code: code }) + .post(this.route("invitation.status"), { token: token }) .then((response) => { if (response.data.status != "pending") { this.message = response.data.status; @@ -142,11 +142,11 @@ export default { created() { this.passwordForm.username = this.route().params.username; - this.passwordForm.code = this.route().params.code; - this.code = this.route().params.code; + this.passwordForm.token = this.route().params.token; + this.token = this.route().params.token; this.passwordForm.expires = this.route().params.expires; this.$on("submit", this.addPassword); - this.tokenExpired(this.code); + this.tokenExpired(this.token); }, }; diff --git a/routes/web.php b/routes/web.php index 3f6c6b4..869c6ec 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,8 +19,6 @@ use App\Http\Controllers\Installer\InstallerFilePermissionController; use App\Http\Controllers\Installer\InstallerRequirementsController; use App\Http\Controllers\LocaleController; -use App\Http\Controllers\MailController; -use App\Http\Controllers\MailSendingController; use App\Http\Controllers\PagesController; use App\Http\Controllers\UserInvitationController; use Illuminate\Support\Facades\Route; From 97f0a3353a9a2e99bc7e2d7f48e2ec850aa4b867 Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Wed, 2 Aug 2023 03:49:37 +0530 Subject: [PATCH 19/41] Minor Updates --- .../Dashboard/User/UserController.php | 46 ++++---- .../Controllers/UserInvitationController.php | 78 ++++++++------ app/Invite.php | 57 +++++----- app/Models/Invitation.php | 7 +- app/Models/User.php | 4 +- .../2017_06_14_000000_create_users_table.php | 2 +- ..._07_25_201052_create_invitations_table.php | 3 +- resources/app/pages/AddPassword.vue | 100 +++++++++--------- routes/web.php | 13 +-- 9 files changed, 148 insertions(+), 162 deletions(-) diff --git a/app/Http/Controllers/Dashboard/User/UserController.php b/app/Http/Controllers/Dashboard/User/UserController.php index 98b6ec0..753c8d3 100644 --- a/app/Http/Controllers/Dashboard/User/UserController.php +++ b/app/Http/Controllers/Dashboard/User/UserController.php @@ -17,22 +17,13 @@ class UserController extends Controller { - public function index():Response + public function index(): Response { - /** - * Shows the role page - * @return Response - */ - return Inertia::render('AddUsers'); - } - public function AddPassword():Response - { - /** - * Shows the role page - * @return Response - */ - return Inertia::render('AddPassword'); - + /** + * Shows the role page + * @return Response + */ + return Inertia::render('AddUsers'); } /** * Show the form for creating a new resource. @@ -57,7 +48,7 @@ public function store(Request $request) $user = User::create([ 'username' => $request->username, 'email' => $request->email, - 'password' =>bcrypt($token), + 'password' => bcrypt($token), 'first_name' => $request->first_name, 'middle_name' => $request->middle_name, 'last_name' => $request->last_name, @@ -69,7 +60,7 @@ public function store(Request $request) 'info' => $request->job_description, 'access_control' => $request->role, 'warehouse' => $request->default_warehouse, - 'facility'=> $request->default_facility, + 'facility' => $request->default_facility, 'provider_type' => $request->provider_type, 'license' => $request->license_number, 'additional_details' => $request->additional_details, @@ -77,7 +68,7 @@ public function store(Request $request) 'token_expiry' => now()->addDays(7), ]); $role = Role::where('name', '=', $request->role)->first(); - $permissions=$role->permissions; + $permissions = $role->permissions; $user->attachRole($role); foreach ($permissions as $permission) { $user->attachPermission($permission); @@ -86,39 +77,38 @@ public function store(Request $request) $url = URL::temporarySignedRoute( 'users.confirm', now()->addDays(7), - ['username' => $user->username,'token'=>$token] + ['username' => $user->username, 'token' => $token] ); $mailData = [ 'title' => 'User Invitation Mail', - 'url'=> $url, + 'url' => $url, 'facility' => $request->default_facility, - 'role'=> $request->role, + 'role' => $request->role, 'username' => $request->username, ]; Mail::to($request->email)->send(new InvitationMail($mailData)); - if($user->save()){ + if ($user->save()) { return Inertia::location(route('dashboard.users.index')); - }else{ + } else { return Redirect::back()->with(['error' => 'Something went wrong']); } - } public function verifyUser(Request $request) { $user = User::where('username', '=', $request->username)->first(); - if($user->token_expiry < now()){ + if ($user->token_expiry < now()) { return Redirect::back()->with(['error' => 'Token Expired']); } - if($user->token == $request->token){ + if ($user->token == $request->token) { $user->password = bcrypt($request->password); $user->token = null; $user->save(); return Inertia::location(route('login')); - }else{ + } else { - return Redirect::back()->with(['error' => 'Token Mismatch']); + return Redirect::back()->with(['error' => 'Token Mismatch']); } } /** diff --git a/app/Http/Controllers/UserInvitationController.php b/app/Http/Controllers/UserInvitationController.php index 79bbfaa..04169df 100644 --- a/app/Http/Controllers/UserInvitationController.php +++ b/app/Http/Controllers/UserInvitationController.php @@ -3,20 +3,46 @@ namespace App\Http\Controllers; use App\Invite; +use App\Models\Invitation; use Illuminate\Http\Request; use Inertia\Inertia; use Redirect; +use Inertia\Response; use Str; class UserInvitationController extends Controller { + public function index($token): Response + { + /** + * Shows the role page + * @return Response + */ + $invite = Invitation::where('token', $token)->first(); + + //send a invalid token message if the invite is not found in the database. + if (!$invite) { + return Inertia::render('AddPassword', ['status' => 'invalid']); + } + + //masking the username part of the email. + $email = $invite->email; + [$username, $domain] = explode('@', $email); + $usernameLength = strlen($username); + $firstHalf = substr($username, 0, ceil($usernameLength / 2)); + $secondHalf = str_repeat('*', floor($usernameLength / 2)); + $maskedEmail = $firstHalf . $secondHalf . '@' . $domain; + + return Inertia::render('AddPassword', ['status' => $invite->status, 'email' => $maskedEmail]); + } + public function sendInvite(Request $request) { $temporaryPassword = Str::random(10); - $userData=[ + $userData = [ 'username' => $request->username, - 'password'=> bcrypt($temporaryPassword), + 'password' => bcrypt($temporaryPassword), 'email' => $request->email, 'first_name' => $request->first_name, 'middle_name' => $request->middle_name, @@ -29,7 +55,7 @@ public function sendInvite(Request $request) 'info' => $request->job_description, 'access_control' => $request->role, 'warehouse' => $request->default_warehouse, - 'facility'=> $request->default_facility, + 'facility' => $request->default_facility, 'provider_type' => $request->provider_type, 'license' => $request->license_number, 'additional_details' => $request->additional_details, @@ -41,37 +67,27 @@ public function sendInvite(Request $request) return Inertia::location(route('dashboard.users.index')); } - public function acceptInvite(Request $request) + //single controller for both accept and reject based on reject parameter + public function acceptOrRejectInvite(Request $request) { $token = $request->token; - $password = bcrypt($request->password); - $success=Invite::accept($token, $password); - if($success){ - return Inertia::location(route('login')); - }else{ - return Redirect::back()->with(['error' => 'Something went wrong']); - } - - } - public function rejectInvite(Request $request) - { - $token = $request->token; - $success=Invite::reject($token); - if($success){ - return response()->json(['status' => 'success']); - }else{ - return Redirect::back()->with(['error' => 'Something went wrong']); + $reject = $request->reject; + if ($reject) { + $success = Invite::reject($token); + if ($success) { + return Inertia::location(route('login')); + } else { + return Redirect::back()->with(['error' => 'Something went wrong']); + } + } else { + $password = bcrypt($request->password); + $success = Invite::accept($token, $password); + if ($success) { + return Inertia::location(route('login')); + } else { + return Redirect::back()->with(['error' => 'Something went wrong']); + } } - } - - public function invitationStatus(Request $request) - { - $token = $request->token; - $status = Invite::status($token); - return response()->json(['status' => $status]); - - } - } diff --git a/app/Invite.php b/app/Invite.php index e6607cc..8ccb2ed 100644 --- a/app/Invite.php +++ b/app/Invite.php @@ -1,4 +1,5 @@ $userInvited->id, + // Save the invitation data in the invitations table + $invitation = Invitation::create([ 'email' => $email, 'token' => $token, 'status' => 'pending', + 'facility' => $userData['facility'], 'valid_till' => now()->addDays(7), // Invitation valid for 7 days ]); // Send the invitation email - $url = URL::temporarySignedRoute( - 'users.confirm', - now()->addDays(7), - ['username' => $userData['username'],'token'=>$token] - ); + $url = url("/invitations/join/{$token}"); $mailData = [ 'title' => 'User Invitation Mail', - 'url'=> $url, + 'url' => $url, 'facility' => $userData['facility'], - 'role'=> $userData['access_control'], + 'role' => $userData['access_control'], 'username' => $userData['username'], ]; + Mail::to($userData['email'])->send(new InvitationMail($mailData)); - if($invitation->save()){ - return Inertia::location(route('dashboard.users.index')); - }else{ + + if ($invitation->save()) { + return Inertia::location(route('dashboard.users.index'), ['success' => 'Invitation sent successfully']); + } else { return Redirect::back()->with(['error' => 'Something went wrong']); } } @@ -63,22 +63,22 @@ public static function accept($token, $password) } // Create the new user in the real users table - $invitedUser=User::find($invitation->for_user); + $invitedUser = User::where('email', $invitation->email)->first(); $role = Role::where('name', '=', $invitedUser->access_control)->first(); - $permissions=$role->permissions; + $permissions = $role->permissions; $invitedUser->attachRole($role); foreach ($permissions as $permission) { $invitedUser->attachPermission($permission); } $invitation->update([ 'status' => 'accepted', + 'accepted_at' => now(), ]); $invitedUser->update([ 'password' => $password, - 'invitation' => 'accepted', ]); $invitation->save(); - if($invitedUser->save()){ + if ($invitedUser->save()) { return true; } @@ -93,15 +93,7 @@ public static function reject($token) if (!$invitation) { return false; // Invalid invitation token } - $invitedUser=User::where('id', $invitation->for_user)->first(); - if (!$invitedUser) { - return false; // Invalid invitation token - } - $invitedUser->update([ - 'invitation' => 'rejected', - ]); - $invitedUser->save(); // Update the invitation status $invitation->update([ 'status' => 'rejected', @@ -116,16 +108,15 @@ public static function isExpired($token) { // Find the invitation by token $invitation = Invitation::where('token', $token)->first(); - $invitedUser=User::find($invitation->for_user); - if($invitation->valid_till < now()){ + if (!$invitation) { + return true; + } + //checking invitation is expired or not based on valid_till + if ($invitation->valid_till < now()) { $invitation->update([ 'status' => 'expired', ]); - $invitedUser->update([ - 'invitation' => 'expired', - ]); $invitation->save(); - $invitedUser->save(); return true; } return false; @@ -135,10 +126,10 @@ public static function status($token) { // Find the invitation by token $invitation = Invitation::where('token', $token)->first(); - if (!$invitation) { return 'invalid'; // Invalid invitation token } + $expired = self::isExpired($token); return $invitation->status; } diff --git a/app/Models/Invitation.php b/app/Models/Invitation.php index 17069d6..c8610d5 100644 --- a/app/Models/Invitation.php +++ b/app/Models/Invitation.php @@ -9,10 +9,5 @@ class Invitation extends Model { use HasFactory; protected $table = 'invitations'; - protected $fillable = ['for_user', 'email', 'token', 'status', 'valid_till']; - - public function user() - { - return $this->belongsTo(User::class, 'for_user'); - } + protected $fillable = ['email', 'facility', 'token', 'status', 'valid_till', 'accepted_at']; } diff --git a/app/Models/User.php b/app/Models/User.php index 894ec5f..1777eb3 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -30,8 +30,8 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'username', 'password','email', 'first_name', 'middle_name', 'last_name', 'federal_tax_id', - 'federal_drug_id', 'see_auth', 'npi', 'suffix', 'taxonomy','license','provider_type','warehouse','additional_details','calendar_ui', 'info','facility','invitation', + 'username', 'password', 'email', 'first_name', 'middle_name', 'last_name', 'federal_tax_id', + 'federal_drug_id', 'see_auth', 'npi', 'suffix', 'taxonomy', 'license', 'provider_type', 'warehouse', 'additional_details', 'calendar_ui', 'info', 'facility', 'new_crop_user_role', 'access_control', 'in_calendar', 'device_id', 'last_login_at', 'last_login_ip', 'created_at', 'updated_at', 'deleted_at' ]; diff --git a/database/migrations/2017_06_14_000000_create_users_table.php b/database/migrations/2017_06_14_000000_create_users_table.php index 918c371..64d1845 100755 --- a/database/migrations/2017_06_14_000000_create_users_table.php +++ b/database/migrations/2017_06_14_000000_create_users_table.php @@ -33,7 +33,7 @@ public function up() $table->string('warehouse')->nullable(); $table->string('facility')->nullable(); $table->text('additional_details')->nullable(); - $table->string('invitation')->default('pending')->comment('Invitation Status'); + diff --git a/database/migrations/2023_07_25_201052_create_invitations_table.php b/database/migrations/2023_07_25_201052_create_invitations_table.php index e13bb92..2394591 100644 --- a/database/migrations/2023_07_25_201052_create_invitations_table.php +++ b/database/migrations/2023_07_25_201052_create_invitations_table.php @@ -15,10 +15,11 @@ public function up() { Schema::create('invitations', function (Blueprint $table) { $table->id(); - $table->foreignId('for_user')->constrained('users'); $table->string('email'); + $table->string('facility'); $table->string('token')->unique(); $table->string('status')->default('pending'); + $table->timestamp('accepted_at')->nullable(); $table->timestamp('valid_till')->nullable(); $table->timestamps(); }); diff --git a/resources/app/pages/AddPassword.vue b/resources/app/pages/AddPassword.vue index 3b1b144..dafc489 100644 --- a/resources/app/pages/AddPassword.vue +++ b/resources/app/pages/AddPassword.vue @@ -3,15 +3,15 @@
-
+

- Invitation {{ message }} + Invitation {{ status }}. Please Contact Admin.

-
+

Accept Invitation @@ -33,22 +33,17 @@

-
+

Add Password

-
- -
+

+ This invitation is for + {{ email }}. Add a password to login into the account. +

+
+ +
+

+ Password and Confirm Password must match. +

@@ -205,6 +205,9 @@ diff --git a/routes/web.php b/routes/web.php index c3c4387..65569d9 100644 --- a/routes/web.php +++ b/routes/web.php @@ -217,6 +217,7 @@ function () { Route::get('/invitations/join/{token}', [InvitationController::class, 'index'])->name('invitation.get'); Route::post('/invitations/accept', [InvitationController::class, 'acceptOrRejectInvite'])->name('invitation.accept'); + Route::get('/invitations', [InvitationController::class, 'getInvitations'])->name('invitation.fetch'); /* ================================= From 811dd08ff9b601424641c960eefb95d8105f901e Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Wed, 9 Aug 2023 20:50:42 +0530 Subject: [PATCH 23/41] Proper Folder Structure Update --- .../Controllers/Dashboard/RolesController.php | 55 ++++++++++--------- .../Dashboard/User/SetupAccount.php | 2 +- app/Http/Controllers/InvitationController.php | 6 +- .../app/pages/{ => AccessControl}/Roles.vue | 2 +- .../{ => AccessControl}/RolesDetails.vue | 2 +- .../app/pages/{ => Users}/AddPassword.vue | 5 +- resources/app/pages/{ => Users}/AddUsers.vue | 2 + .../app/pages/{ => Users}/Invitations.vue | 2 + 8 files changed, 42 insertions(+), 34 deletions(-) rename resources/app/pages/{ => AccessControl}/Roles.vue (99%) rename resources/app/pages/{ => AccessControl}/RolesDetails.vue (98%) rename resources/app/pages/{ => Users}/AddPassword.vue (97%) rename resources/app/pages/{ => Users}/AddUsers.vue (99%) rename resources/app/pages/{ => Users}/Invitations.vue (98%) diff --git a/app/Http/Controllers/Dashboard/RolesController.php b/app/Http/Controllers/Dashboard/RolesController.php index 096450f..0ab7464 100644 --- a/app/Http/Controllers/Dashboard/RolesController.php +++ b/app/Http/Controllers/Dashboard/RolesController.php @@ -16,19 +16,21 @@ class RolesController extends Controller { public function index(): Response { - /** - * Shows the role page - * @return Response - */ - return Inertia::render('Roles',['roles' => []] + /** + * Shows the role page + * @return Response + */ + return Inertia::render( + 'AccessControl/Roles', + ['roles' => []] ); } public function details($roleId): Response { - /** - * Shows the role page - * @return Response - */ + /** + * Shows the role page + * @return Response + */ $role = Role::with('permissions')->where('id', $roleId)->first(); $users = $role->users()->get(); $temp = [ @@ -39,9 +41,10 @@ public function details($roleId): Response 'permissions' => $role->permissions, 'users' => $users, ]; - return Inertia::render('RolesDetails',['roleDetails' => $temp] + return Inertia::render( + 'AccessControl/RolesDetails', + ['roleDetails' => $temp] ); - } public function store(CreateRoleRequest $request) { @@ -54,29 +57,29 @@ public function store(CreateRoleRequest $request) $role->permissions()->attach([$permission['id']]); } $role->save(); - if($role->save()){ + if ($role->save()) { return Inertia::location(route('dashboard.roles.index')); - }else{ + } else { return Redirect::back()->with(['error' => 'Something went wrong']); } } public function getRoles() { - $result=[]; + $result = []; $roles = Role::with('permissions')->get(); foreach ($roles as $role) { - $users = $role->users()->get(); - $temp = [ - 'id' => $role->id, - 'name' => $role->name, - 'display_name' => $role->display_name, - 'description' => $role->description, - 'permissions' => $role->permissions, - 'users' => $users, - ]; - array_push($result, $temp); - } + $users = $role->users()->get(); + $temp = [ + 'id' => $role->id, + 'name' => $role->name, + 'display_name' => $role->display_name, + 'description' => $role->description, + 'permissions' => $role->permissions, + 'users' => $users, + ]; + array_push($result, $temp); + } - return response()->json($result, 200); + return response()->json($result, 200); } } diff --git a/app/Http/Controllers/Dashboard/User/SetupAccount.php b/app/Http/Controllers/Dashboard/User/SetupAccount.php index 5c100c9..1cace8c 100644 --- a/app/Http/Controllers/Dashboard/User/SetupAccount.php +++ b/app/Http/Controllers/Dashboard/User/SetupAccount.php @@ -14,6 +14,6 @@ public function index() { $facilities = Facility::pluck('name', 'id'); - return Inertia::render('AddUsers', ['facilities' => $facilities]); + return Inertia::render('Users/AddUsers', ['facilities' => $facilities]); } } diff --git a/app/Http/Controllers/InvitationController.php b/app/Http/Controllers/InvitationController.php index 262b5d9..a0a6e5b 100644 --- a/app/Http/Controllers/InvitationController.php +++ b/app/Http/Controllers/InvitationController.php @@ -19,7 +19,7 @@ public function showInvitations(): Response $facilities = Facility::pluck('name', 'id'); - return Inertia::render('Invitations', ['facilities' => $facilities]); + return Inertia::render('Users/Invitations', ['facilities' => $facilities]); } @@ -55,7 +55,7 @@ public function index($token): Response //send a invalid token message if the invite is not found in the database. if (!$invite) { - return Inertia::render('AddPassword', ['status' => 'invalid']); + return Inertia::render('Users/AddPassword', ['status' => 'invalid']); } //masking the username part of the email. @@ -65,7 +65,7 @@ public function index($token): Response $usernameLength = strlen($username); $maskedEmail = Str::mask($email, '*', - ($emailLength - $usernameLength / 2), $usernameLength / 2); - return Inertia::render('AddPassword', ['status' => $invite->status, 'email' => $maskedEmail]); + return Inertia::render('Users/AddPassword', ['status' => $invite->status, 'email' => $maskedEmail]); } public function sendInvite(Request $request) diff --git a/resources/app/pages/Roles.vue b/resources/app/pages/AccessControl/Roles.vue similarity index 99% rename from resources/app/pages/Roles.vue rename to resources/app/pages/AccessControl/Roles.vue index 5a44320..6b43eb9 100644 --- a/resources/app/pages/Roles.vue +++ b/resources/app/pages/AccessControl/Roles.vue @@ -184,7 +184,7 @@
+ + diff --git a/routes/web.php b/routes/web.php index 65569d9..e54cd63 100644 --- a/routes/web.php +++ b/routes/web.php @@ -137,9 +137,10 @@ function () { Route::get('/add-user', [SetupAccount::class, 'index'])->name('users.invite'); Route::post('/add-user', [InvitationController::class, 'sendInvite'])->name('users.add'); Route::get('/invitations', [InvitationController::class, 'showInvitations'])->name('user.invitations'); + Route::get('/users/profile/{userId}', [UserController::class, 'profile'])->name('users.profile'); + + - Route::get('users/load/data', [UserController::class, 'getUserData']) - ->name('users.load.data'); // ======== Facility related routes ======== Route::resource('facilities', FacilityController::class)->names([ From 9b4261fb8d32ff291beab4a4469b803ad02fd3ce Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Tue, 15 Aug 2023 02:56:23 +0530 Subject: [PATCH 25/41] Edit Profile Functionality --- .../Dashboard/User/UserController.php | 58 +++- resources/app/pages/Users/EditUser.vue | 276 ++++++++++++++++++ resources/app/pages/Users/UserProfile.vue | 22 +- routes/web.php | 4 +- 4 files changed, 353 insertions(+), 7 deletions(-) create mode 100644 resources/app/pages/Users/EditUser.vue diff --git a/app/Http/Controllers/Dashboard/User/UserController.php b/app/Http/Controllers/Dashboard/User/UserController.php index 44b83e2..201365f 100644 --- a/app/Http/Controllers/Dashboard/User/UserController.php +++ b/app/Http/Controllers/Dashboard/User/UserController.php @@ -4,6 +4,7 @@ use App\Http\Controllers\Controller; use App\Mail\InvitationMail; +use App\Models\Facilities\Facility; use App\Models\Invitation; use App\Models\Role; use App\Models\User; @@ -69,15 +70,27 @@ public function profile($userId): Response return Inertia::render('Users/UserProfile', ['userData' => $user]); } + public function showEditPage($userId): Response + { + /** + * Shows the user edit page + * @return Response + */ + $user = User::where('id', $userId)->first(); + $facilities = Facility::pluck('name', 'id'); + + return Inertia::render('Users/EditUser', ['userData' => $user, 'facilities' => $facilities]); + } + + /** * Show the form for editing the specified resource. * * @param int $id * @return Response */ - public function edit($id) + public function edit() { - // } /** @@ -87,9 +100,48 @@ public function edit($id) * @param int $id * @return Response */ - public function update(Request $request, $id) + public function update(Request $request, $userId) { // + + + // + // Get the existing user data + $user = User::findOrFail($userId); + + // Update user data + $user->username = $request->username; + $user->email = $request->email; + $user->first_name = $request->first_name; + $user->middle_name = $request->middle_name; + $user->last_name = $request->last_name; + $user->federal_tax_id = $request->tax_id; + $user->federal_drug_id = $request->dea_number; + $user->npi = $request->npi; + $user->suffix = $request->suffix; + $user->taxonomy = $request->taxonomy; + $user->info = $request->job_description; + $user->warehouse = $request->default_warehouse; + $user->facility = $request->default_facility; + $user->provider_type = $request->provider_type; + $user->license = $request->license_number; + $user->additional_details = $request->additional_details; + + $user->save(); + //update the roles if role is changed + if ($user->access_control != $request->role) { + $user->roles()->detach(); + $user->permissions()->detach(); + $user->access_control = $request->role; + $role = Role::where('name', '=', $request->role)->first(); + $permissions = $role->permissions; + $user->attachRole($role); + foreach ($permissions as $permission) { + $user->attachPermission($permission); + } + } + $user->save(); + return Inertia::location(route('dashboard.users.edit', ['userId' => $user->id])); } /** diff --git a/resources/app/pages/Users/EditUser.vue b/resources/app/pages/Users/EditUser.vue new file mode 100644 index 0000000..afa118c --- /dev/null +++ b/resources/app/pages/Users/EditUser.vue @@ -0,0 +1,276 @@ + + diff --git a/resources/app/pages/Users/UserProfile.vue b/resources/app/pages/Users/UserProfile.vue index 39cd974..2433093 100644 --- a/resources/app/pages/Users/UserProfile.vue +++ b/resources/app/pages/Users/UserProfile.vue @@ -1,8 +1,16 @@ diff --git a/resources/app/shared/includes/Header.vue b/resources/app/shared/includes/Header.vue index accf735..a12ff4b 100644 --- a/resources/app/shared/includes/Header.vue +++ b/resources/app/shared/includes/Header.vue @@ -11,20 +11,7 @@ :href="route('dashboard.index')" class="p-1 mx-2 border-transparent text-gray-400 rounded-full hover:text-white bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700" > - - - +
- -
-
-
- {{ $t("menu.patient_client") }}: - None -
-
-
- Logo + class="flex flex-wrap sm:flex-row justify-between text-base py-2 px-4 mb-2 sm:mb-0" + > +
+
+ {{ $t("menu.patient_client") }}: + None
-
-
- {{ $t("menu.patient_client") }}: - - - {{ - $page.props.ehr_patient.patient - .first_name - }} - {{ - $page.props.ehr_patient.patient - .last_name - }} - ({{ - $page.props.ehr_patient.patient.pid - }}) - - +
+
+ Logo
-
- {{ - $t("forms.date_of_birth") - }}:  - {{ - $page.props.ehr_patient.patient - .date_of_birth - }} -    - {{ $t("forms.age") }}:  - {{ - $page.props.ehr_patient.patient.age - }} +
+
+ {{ $t("menu.patient_client") }}: + + + {{ + $page.props.ehr_patient.patient + .first_name + }} + {{ + $page.props.ehr_patient.patient + .last_name + }} + ({{ + $page.props.ehr_patient.patient + .pid + }}) + + +
+
+ {{ + $t("forms.date_of_birth") + }}:  + {{ + $page.props.ehr_patient.patient + .date_of_birth + }} +    + {{ $t("forms.age") }}:  + {{ + $page.props.ehr_patient.patient.age + }} +
+ + Clear +
- - Clear -
-
-
-
+
- {{ $t("general.selected_encounter") }}: - None -
-
- {{ $t("general.selected_encounter") }}: - 2020-11-18 -
- + {{ + $t("general.selected_encounter") + }}: + None +
+
+ {{ + $t("general.selected_encounter") + }}: + 2020-11-18 + +
+ +
-
-
- From 047b2dc711b4bb6986901f59c657ff2175532389 Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Fri, 2 Jun 2023 22:57:11 +0530 Subject: [PATCH 38/41] Added L2 submenus for small devices --- resources/app/shared/includes/Header.vue | 1921 +++++++++++++++++++--- 1 file changed, 1719 insertions(+), 202 deletions(-) diff --git a/resources/app/shared/includes/Header.vue b/resources/app/shared/includes/Header.vue index 3b7cb70..7dde9e2 100644 --- a/resources/app/shared/includes/Header.vue +++ b/resources/app/shared/includes/Header.vue @@ -276,72 +276,542 @@
  • - Visits - + +
  • - Records - + +
  • +
  • - Visit Forms - + +
  • - Imports - + +
  • @@ -1020,22 +1490,208 @@
  • - - Other - + Other + + +
  • @@ -1065,132 +1721,971 @@ class="hidden py-2 space-y-2 ml-2" >
  • - Clients - + +
  • - Visits - + +
  • - Financial - + +
  • - Inventory - + +
  • - Procedures - + +
  • - Insurance - + +
  • - Blank Forms - + +
  • - Services - + +
  • @@ -1373,22 +2868,44 @@
  • - - Utilities - + Utilities + + +
  • Date: Sat, 26 Aug 2023 23:05:37 +0530 Subject: [PATCH 39/41] access controlled routes --- resources/app/shared/includes/Header.vue | 70 ++++++++++++++++-------- routes/web.php | 50 +++++++++-------- 2 files changed, 72 insertions(+), 48 deletions(-) diff --git a/resources/app/shared/includes/Header.vue b/resources/app/shared/includes/Header.vue index 7dde9e2..a2a2b5e 100644 --- a/resources/app/shared/includes/Header.vue +++ b/resources/app/shared/includes/Header.vue @@ -29,12 +29,7 @@ - - +
      -
    • +
    • @@ -1272,6 +1267,24 @@ > Facilities +
    • +
    • + + Invitations +
    • Facilities + + Invitations Lists { const $targetEl = document.getElementById("drawer-navigation"); const drawer = new Drawer($targetEl); - drawer.init(); + }); diff --git a/routes/web.php b/routes/web.php index 832ffa8..e62e324 100644 --- a/routes/web.php +++ b/routes/web.php @@ -98,7 +98,6 @@ [ 'as' => 'dashboard.', 'prefix' => 'dashboard', - 'middleware' => ['role:super_admin|admin|user'], 'namespace' => '\\', ], function () { @@ -109,29 +108,32 @@ function () { Route::get('settings', [DashboardController::class, 'settings'])->name('settings'); // ======== Flow Board routes ======== - Route::get('flow-board', [FlowBoardController::class, 'index'])->name('flow_board'); + Route::get('flow-board',[FlowBoardController::class, 'index'])->name('flow_board')->middleware('permission:flow-board-read'); Route::get('mail', [MailSendingController::class, 'sendWelcomeEmail'])->name('mail'); // ======== Calendar routes ======== - Route::get('calendar', [CalendarController::class, 'index'])->name('calendar'); - - // ======== Roles & Permissions Routes ======== - Route::get('/roles', [RolesController::class, 'index'])->name('roles.index'); - Route::get('/roles/{rolesId}', [RolesController::class, 'details'])->name('roles.details'); - Route::post('/roles', [RolesController::class, 'store'])->name('roles.store'); - Route::get('/all-roles', [RolesController::class, 'getRoles'])->name('roles.all'); - Route::get('/all-permissions', [PermissionController::class, 'getPermissions'])->name('permissions.all'); - - // ======== Users related routes ======== - Route::resource('users', UserController::class)->names([ - 'index' => 'users.index', - 'create' => 'users.create', - 'edit' => 'users.edit', - 'update' => 'users.update', - 'show' => 'users.show', - 'destroy' => 'users.destroy', - ]); + Route::get('calendar', [CalendarController::class, 'index'])->name('calendar')->middleware('permission:calendar-read'); + + Route::middleware(['role:super_admin|admin'])->group(function () { + Route::get('/roles', [RolesController::class, 'index'])->name('roles.index'); + Route::get('/roles/{rolesId}', [RolesController::class, 'details'])->name('roles.details'); + Route::post('/roles', [RolesController::class, 'store'])->name('roles.store'); + Route::get('/all-roles', [RolesController::class, 'getRoles'])->name('roles.all'); + Route::get('/all-permissions', [PermissionController::class, 'getPermissions'])->name('permissions.all'); + + + // ======== Users related routes ======== + Route::resource('users', UserController::class)->names([ + 'index' => 'users.index', + 'create' => 'users.create', + 'edit' => 'users.edit', + 'update' => 'users.update', + 'show' => 'users.show', + 'destroy' => 'users.destroy', + ]); + + }); // ======== Facility related routes ======== Route::resource('facilities', FacilityController::class)->names([ @@ -142,7 +144,7 @@ function () { 'edit' => 'facilities.edit', 'update' => 'facilities.update', 'destroy' => 'facilities.destroy', - ]); + ])->middleware('permission:facility-read'); // ======== Patient related routes ======== Route::resource('patients', PatientController::class)->names([ @@ -153,7 +155,7 @@ function () { 'edit' => 'patients.edit', 'update' => 'patients.update', 'destroy' => 'patients.destroy', - ]); + ])->middleware('permission:patient-read'); Route::get('patients/load/data', [PatientController::class, 'getPatientData']) ->name('patients.load.data'); @@ -162,8 +164,8 @@ function () { 'as' => 'patients.', 'prefix' => 'patients', 'namespace' => '\\', - // TODO (add a middleware for selected patients) - 'middleware' => 'select.patient', + + 'middleware' => ['select.patient', 'permission:patient-read'] ], function () { Route::get('select/{pid}', [PatientController::class, 'selectPatient']) From 43743612fc2070542d4bd8acd139e97380d7c14f Mon Sep 17 00:00:00 2001 From: chaitak-gorai Date: Sun, 27 Aug 2023 00:30:26 +0530 Subject: [PATCH 40/41] Users datatable --- .../Dashboard/User/UserController.php | 26 ++- app/Http/Controllers/InvitationController.php | 10 ++ resources/app/pages/Users/Index.vue | 162 ++++++++++++++++++ resources/app/pages/Users/Invitations.vue | 2 +- resources/app/shared/includes/Header.vue | 8 +- routes/web.php | 8 +- 6 files changed, 208 insertions(+), 8 deletions(-) create mode 100644 resources/app/pages/Users/Index.vue diff --git a/app/Http/Controllers/Dashboard/User/UserController.php b/app/Http/Controllers/Dashboard/User/UserController.php index c2c9f88..f11a2aa 100644 --- a/app/Http/Controllers/Dashboard/User/UserController.php +++ b/app/Http/Controllers/Dashboard/User/UserController.php @@ -12,6 +12,7 @@ use Illuminate\Http\Request; use Inertia\Response; use Inertia\Inertia; +use JamesDordoy\LaravelVueDatatable\Http\Resources\DataTableCollectionResource; use Mail; use Redirect; use Str; @@ -28,7 +29,30 @@ public function index() */ $facilities = Facility::pluck('name', 'id'); - return Inertia::render('Users/Invitations', ['facilities' => $facilities]); + return Inertia::render('Users/Index', ['facilities' => $facilities]); + } + + //URL for datatable for users + public function getUsers(Request $request) + { + $length = $request->input('length', 10); + $sortBy = $request->input('column'); + $orderBy = $request->input('dir'); + $facility = $request->input('facility'); + + + //get User + $query = User::query(); + + $query->orderBy($sortBy, $orderBy); + + if ($facility != null) { + $query->where('facility', $facility); + } + + $data = $query->paginate($length); + + return new DataTableCollectionResource($data); } /** * Show the form for creating a new resource. diff --git a/app/Http/Controllers/InvitationController.php b/app/Http/Controllers/InvitationController.php index f61dfcd..a2edaf2 100644 --- a/app/Http/Controllers/InvitationController.php +++ b/app/Http/Controllers/InvitationController.php @@ -15,6 +15,16 @@ class InvitationController extends Controller { + public function show() + { + /** + * Shows the Users/Invitations page + * @return Response + */ + $facilities = Facility::pluck('name', 'id'); + + return Inertia::render('Users/Invitations', ['facilities' => $facilities]); + } //URL for datatable for invitations public function getInvitations(Request $request) { diff --git a/resources/app/pages/Users/Index.vue b/resources/app/pages/Users/Index.vue new file mode 100644 index 0000000..1bcf287 --- /dev/null +++ b/resources/app/pages/Users/Index.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/resources/app/pages/Users/Invitations.vue b/resources/app/pages/Users/Invitations.vue index fc3cd9f..b1a227f 100644 --- a/resources/app/pages/Users/Invitations.vue +++ b/resources/app/pages/Users/Invitations.vue @@ -147,7 +147,7 @@ export default { }, }, mounted() { - this.url = route("invitation.fetch"); + this.url = route("dashboard.invitations.fetch"); }, }; diff --git a/resources/app/shared/includes/Header.vue b/resources/app/shared/includes/Header.vue index a2a2b5e..24b91a7 100644 --- a/resources/app/shared/includes/Header.vue +++ b/resources/app/shared/includes/Header.vue @@ -1272,7 +1272,7 @@ @@ -37,7 +38,9 @@
    @@ -70,6 +73,7 @@
    @@ -111,6 +119,7 @@
    @@ -118,18 +127,21 @@
    +

    {{ errors.default_facility }}

    +
    +

    {{ errors.role }}

    +
    + + + +
    +