diff --git a/app/Exports/PermissionExport.php b/app/Exports/PermissionExport.php index 598e4b3..0050c25 100644 --- a/app/Exports/PermissionExport.php +++ b/app/Exports/PermissionExport.php @@ -21,7 +21,8 @@ class PermissionExport implements WithColumnFormatting, WithHeadings, FromCollec } public function map($row): array{ - $role = $row->roles->pluck('name')->toArray(); + // Convert the array to a collection before using pluck + $role = collect($row->roles)->pluck('name')->toArray(); return [ $row->id, $row->name, diff --git a/app/Http/Controllers/PermissionsController.php b/app/Http/Controllers/PermissionsController.php index c55aa2f..81f5f1d 100644 --- a/app/Http/Controllers/PermissionsController.php +++ b/app/Http/Controllers/PermissionsController.php @@ -25,6 +25,16 @@ */ public $user; + /** + * UsersController constructor. + * + * Initializes the user property with the authenticated user. + */ + public function __construct() + { + $this->user = Auth::guard('web')->user(); + } + /** * Display a listing of the resource. * @@ -34,8 +44,8 @@ public function index() { // Check if the authenticated user has the required permission to view permissions - if (is_null($this->user) || !$this->user->can('permissions.view')) { - //abort(403, 'Sorry! You are not allowed to view permissions.'); + if (is_null($this->user) || !$this->user->can('usermanagement.read')) { + abort(403, 'Sorry! You are not allowed to view permissions.'); } // Return the view for displaying the permissions @@ -53,8 +63,8 @@ public function store(PermissionRequest $request) { // Check if the authenticated user has the required permission to store permissions - if (is_null($this->user) || !$this->user->can('permissions.store')) { - //abort(403, 'Sorry! You are not allowed to store permissions.'); + if (is_null($this->user) || !$this->user->can('usermanagement.store')) { + abort(403, 'Sorry! You are not allowed to store permissions.'); } $validate = $request->validated(); @@ -97,24 +107,14 @@ public function create() { // Check if the authenticated user has the required permission to create permissions - if (is_null($this->user) || !$this->user->can('permissions.create')) { - //abort(403, 'Sorry! You are not allowed to create permissions.'); + if (is_null($this->user) || !$this->user->can('usermanagement.create')) { + abort(403, 'Sorry! You are not allowed to create permissions.'); } // Return the view for creating a new role return view('usermanagement::permissions.create'); } - public function show($id){ - // Check if the authenticated user has the required permission to view permissions - if (is_null($this->user) ||!$this->user->can('permissions.view')) { - //abort(403, 'Sorry! You are not allowed to view permissions.'); - } - - // Return the view for editing the role - return view('usermanagement::permissions.create'); - } - /** * Show the form for editing the specified resource. * @@ -126,8 +126,8 @@ public function edit($id) { // Check if the authenticated user has the required permission to edit permissions - if (is_null($this->user) || !$this->user->can('permissions.edit')) { - //abort(403, 'Sorry! You are not allowed to edit permissions.'); + if (is_null($this->user) || !$this->user->can('usermanagement.edit')) { + abort(403, 'Sorry! You are not allowed to edit permissions.'); } $permission = PermissionGroup::find($id); @@ -150,8 +150,8 @@ public function update(PermissionRequest $request, $id) { // Check if the authenticated user has the required permission to update permissions - if (is_null($this->user) || !$this->user->can('permissions.update')) { - //abort(403, 'Sorry! You are not allowed to update permissions.'); + if (is_null($this->user) || !$this->user->can('usermanagement.update')) { + abort(403, 'Sorry! You are not allowed to update permissions.'); } $validated = $request->validated(); @@ -202,8 +202,8 @@ public function destroy($id) { // Check if the authenticated user has the required permission to delete permissions - if (is_null($this->user) || !$this->user->can('permissions.delete')) { - //abort(403, 'Sorry! You are not allowed to delete permissions.'); + if (is_null($this->user) || !$this->user->can('usermanagement.delete')) { + abort(403, 'Sorry! You are not allowed to delete permissions.'); } $permission = PermissionGroup::find($id); @@ -214,7 +214,7 @@ } // Redirect back to the permissions index with a success message - echo json_encode(['message' => 'Permission deleted successfully.', 'success' => true]); + return response()->json(['message' => 'Permission deleted successfully.','success' => true]); } /** @@ -228,7 +228,7 @@ public function restore($id) { // Check if the authenticated user has the required permission to restore permissions - if (is_null($this->user) || !$this->user->can('permissions.restore')) { + if (is_null($this->user) || !$this->user->can('usermanagement.restore')) { abort(403, 'Sorry! You are not allowed to restore permissions.'); } @@ -257,8 +257,8 @@ */ public function dataForDatatables(Request $request) { - if (is_null($this->user) || !$this->user->can('permissions.view')) { - //abort(403, 'Sorry! You are not allowed to view users.'); + if (is_null($this->user) || !$this->user->can('usermanagement.read')) { + abort(403, 'Sorry! You are not allowed to view users.'); } // Retrieve data from the database diff --git a/app/Models/Permission.php b/app/Models/Permission.php index d66e52b..21e419a 100644 --- a/app/Models/Permission.php +++ b/app/Models/Permission.php @@ -2,13 +2,14 @@ namespace Modules\Usermanagement\Models; - use Spatie\Activitylog\LogOptions; +use Illuminate\Database\Eloquent\SoftDeletes; +use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\LogsActivity; use Spatie\Permission\Models\Permission as SpatiePermission; class Permission extends SpatiePermission { - use LogsActivity; + use LogsActivity, SoftDeletes; /** * Retrieve the activity log options for this permission. diff --git a/app/Models/PermissionGroup.php b/app/Models/PermissionGroup.php index ccea056..267e83a 100644 --- a/app/Models/PermissionGroup.php +++ b/app/Models/PermissionGroup.php @@ -12,6 +12,17 @@ 'slug' ]; + protected static function boot() + { + parent::boot(); + + static::creating(function ($model) { + if (!$model->slug) { + $model->slug = \Str::slug($model->name); + } + }); + } + /** * Retrieves all permissions associated with a given permission group ID. * diff --git a/resources/views/permissions/index.blade.php b/resources/views/permissions/index.blade.php index 55acb2b..52dccad 100644 --- a/resources/views/permissions/index.blade.php +++ b/resources/views/permissions/index.blade.php @@ -19,29 +19,7 @@ -
- - - +
Export to Excel Add Permission diff --git a/tests/Feature/PermissionsControllerTest.php b/tests/Feature/PermissionsControllerTest.php new file mode 100644 index 0000000..7fe11fc --- /dev/null +++ b/tests/Feature/PermissionsControllerTest.php @@ -0,0 +1,474 @@ +adminRole = Role::create([ + 'name' => 'Admin', + 'guard_name' => 'web' + ]); + + // Create a permission group for usermanagement permissions + $usermanagementGroup = PermissionGroup::create(['name' => 'Usermanagement']); + + // Create permissions + $permissions = [ + 'usermanagement.create', + 'usermanagement.read', + 'usermanagement.update', + 'usermanagement.delete', + 'usermanagement.export', + 'usermanagement.store', + 'usermanagement.edit', + 'usermanagement.view', + 'usermanagement.restore' + ]; + + foreach ($permissions as $permission) { + Permission::create([ + 'name' => $permission, + 'guard_name' => 'web', + 'permission_group_id' => $usermanagementGroup->id + ]); + } + + // Assign permissions to admin role + $this->adminRole->givePermissionTo($permissions); + + // Create user with admin role + $this->user = User::create([ + 'name' => 'Admin User', + 'email' => 'admin@example.com', + 'password' => bcrypt('password') + ]); + + $this->user->assignRole($this->adminRole); + + // Create a test permission group + $this->permissionGroup = PermissionGroup::create(['name' => 'Test Group']); + } + + /** + * Test user with permission can view permissions index. + */ + public function test_user_with_permission_can_view_permissions_index(): void + { + $this->actingAs($this->user); + + $response = $this->get(route('users.permissions.index')); + + $response->assertStatus(200); + $response->assertViewIs('usermanagement::permissions.index'); + } + + /** + * Test user without permission cannot view permissions index. + */ + public function test_user_without_permission_cannot_view_permissions_index(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user@example.com', + 'password' => bcrypt('password') + ]); + + $this->actingAs($user); + + $response = $this->get(route('users.permissions.index')); + + $response->assertStatus(403); + } + + /** + * Test user with permission can create permission. + */ + public function test_user_with_permission_can_create_permission(): void + { + $this->actingAs($this->user); + + $response = $this->get(route('users.permissions.create')); + + $response->assertStatus(200); + $response->assertViewIs('usermanagement::permissions.create'); + } + + /** + * Test user without permission cannot create permission. + */ + public function test_user_without_permission_cannot_create_permission(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user2@example.com', + 'password' => bcrypt('password') + ]); + + $this->actingAs($user); + + $response = $this->get(route('users.permissions.create')); + + $response->assertStatus(403); + } + + /** + * Test user with permission can store permission. + */ + public function test_user_with_permission_can_store_permission(): void + { + $this->actingAs($this->user); + + $data = [ + 'name' => 'TestPermission' + ]; + + $response = $this->post(route('users.permissions.store'), $data); + + $response->assertRedirect(route('users.permissions.index')); + $response->assertSessionHas('success'); + $this->assertDatabaseHas('permission_groups', ['name' => 'TestPermission']); + + // Check if all the required permissions were created + $this->assertDatabaseHas('permissions', ['name' => 'testpermission.create']); + $this->assertDatabaseHas('permissions', ['name' => 'testpermission.read']); + $this->assertDatabaseHas('permissions', ['name' => 'testpermission.update']); + $this->assertDatabaseHas('permissions', ['name' => 'testpermission.delete']); + $this->assertDatabaseHas('permissions', ['name' => 'testpermission.export']); + $this->assertDatabaseHas('permissions', ['name' => 'testpermission.authorize']); + $this->assertDatabaseHas('permissions', ['name' => 'testpermission.report']); + } + + /** + * Test user without permission cannot store permission. + */ + public function test_user_without_permission_cannot_store_permission(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user3@example.com', + 'password' => bcrypt('password') + ]); + + $this->actingAs($user); + + $data = [ + 'name' => 'TestPermission2' + ]; + + $response = $this->post(route('users.permissions.store'), $data); + + $response->assertStatus(403); + $this->assertDatabaseMissing('permission_groups', ['name' => 'TestPermission2']); + } + + /** + * Test user with permission can edit permission. + */ + public function test_user_with_permission_can_edit_permission(): void + { + $this->actingAs($this->user); + + $response = $this->get(route('users.permissions.edit', $this->permissionGroup->id)); + + $response->assertStatus(200); + $response->assertViewIs('usermanagement::permissions.create'); + $response->assertViewHas('permission', $this->permissionGroup); + } + + /** + * Test user without permission cannot edit permission. + */ + public function test_user_without_permission_cannot_edit_permission(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user4@example.com', + 'password' => bcrypt('password') + ]); + + $this->actingAs($user); + + $response = $this->get(route('users.permissions.edit', $this->permissionGroup->id)); + + $response->assertStatus(403); + } + + /** + * Test user with permission can update permission. + */ + public function test_user_with_permission_can_update_permission(): void + { + $this->actingAs($this->user); + + // Create permissions for the test group + $permissions = [ + 'test group.create', + 'test group.read', + 'test group.update', + 'test group.delete', + 'test group.export', + 'test group.authorize', + 'test group.report' + ]; + + foreach ($permissions as $permission) { + Permission::create([ + 'name' => $permission, + 'guard_name' => 'web', + 'permission_group_id' => $this->permissionGroup->id + ]); + } + + $data = [ + 'name' => 'Updated Group' + ]; + + $response = $this->put(route('users.permissions.update', $this->permissionGroup->id), $data); + + $response->assertRedirect(route('users.permissions.index')); + $response->assertSessionHas('success'); + $this->assertDatabaseHas('permission_groups', [ + 'id' => $this->permissionGroup->id, + 'name' => 'Updated Group' + ]); + + // Check if all the permissions were updated + $this->assertDatabaseHas('permissions', ['name' => 'updated group.create']); + $this->assertDatabaseHas('permissions', ['name' => 'updated group.read']); + $this->assertDatabaseHas('permissions', ['name' => 'updated group.update']); + $this->assertDatabaseHas('permissions', ['name' => 'updated group.delete']); + $this->assertDatabaseHas('permissions', ['name' => 'updated group.export']); + $this->assertDatabaseHas('permissions', ['name' => 'updated group.authorize']); + $this->assertDatabaseHas('permissions', ['name' => 'updated group.report']); + } + + /** + * Test user without permission cannot update permission. + */ + public function test_user_without_permission_cannot_update_permission(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user5@example.com', + 'password' => bcrypt('password') + ]); + + $this->actingAs($user); + + $data = [ + 'name' => 'Should Not Update' + ]; + + $response = $this->put(route('users.permissions.update', $this->permissionGroup->id), $data); + + $response->assertStatus(403); + $this->assertDatabaseMissing('permission_groups', [ + 'id' => $this->permissionGroup->id, + 'name' => 'Should Not Update' + ]); + } + + /** + * Test user with permission can delete permission. + */ + public function test_user_with_permission_can_delete_permission(): void + { + $this->actingAs($this->user); + + $response = $this->delete(route('users.permissions.destroy', $this->permissionGroup->id)); + + $response->assertJson([ + 'message' => 'Permission deleted successfully.', + 'success' => true + ]); + + $this->assertSoftDeleted('permission_groups', ['id' => $this->permissionGroup->id]); + } + + /** + * Test user without permission cannot delete permission. + */ + public function test_user_without_permission_cannot_delete_permission(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user6@example.com', + 'password' => bcrypt('password') + ]); + + $this->actingAs($user); + + $response = $this->delete(route('users.permissions.destroy', $this->permissionGroup->id)); + + $response->assertStatus(403); + $this->assertDatabaseHas('permission_groups', ['id' => $this->permissionGroup->id, 'deleted_at' => null]); + } + + /** + * Test user with permission can restore permission. + */ + public function test_user_with_permission_can_restore_permission(): void + { + $this->actingAs($this->user); + + // First delete the permission group + $this->permissionGroup->delete(); + $this->assertSoftDeleted('permission_groups', ['id' => $this->permissionGroup->id]); + + $response = $this->get(route('users.permissions.restore', $this->permissionGroup->id)); + + $response->assertRedirect(route('users.permissions.index')); + $response->assertSessionHas('success'); + $this->assertDatabaseHas('permission_groups', ['id' => $this->permissionGroup->id, 'deleted_at' => null]); + } + + /** + * Test user without permission cannot restore permission. + */ + public function test_user_without_permission_cannot_restore_permission(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user7@example.com', + 'password' => bcrypt('password') + ]); + + // First delete the permission group + $this->permissionGroup->delete(); + $this->assertSoftDeleted('permission_groups', ['id' => $this->permissionGroup->id]); + + $this->actingAs($user); + + $response = $this->get(route('users.permissions.restore', $this->permissionGroup->id)); + + $response->assertStatus(403); + $this->assertSoftDeleted('permission_groups', ['id' => $this->permissionGroup->id]); + } + + /** + * Test user with permission can access datatables data. + */ + public function test_user_with_permission_can_access_datatables_data(): void + { + $this->actingAs($this->user); + + $response = $this->getJson(route('users.permissions.datatables') . '?page=1&size=10'); + + $response->assertStatus(200); + $response->assertJsonStructure([ + 'draw', + 'recordsTotal', + 'recordsFiltered', + 'pageCount', + 'page', + 'totalCount', + 'data' + ]); + } + + /** + * Test user without permission cannot access datatables data. + */ + public function test_user_without_permission_cannot_access_datatables_data(): void + { + // Create user without permissions + $user = User::create([ + 'name' => 'Regular User', + 'email' => 'user8@example.com', + 'password' => bcrypt('password') + ]); + + $this->actingAs($user); + + $response = $this->getJson(route('users.permissions.datatables') . '?page=1&size=10'); + + $response->assertStatus(403); + } + + /** + * Test datatables search filters permissions correctly. + */ + public function test_datatables_search_filters_permissions_correctly(): void + { + $this->actingAs($this->user); + + // Create additional permission groups for testing search + PermissionGroup::create(['name' => 'SearchTest1']); + PermissionGroup::create(['name' => 'SearchTest2']); + PermissionGroup::create(['name' => 'DifferentName']); + + $response = $this->getJson(route('users.permissions.datatables') . '?page=1&size=10&search=SearchTest'); + + $response->assertStatus(200); + $response->assertJsonCount(2, 'data'); + $response->assertJsonPath('data.0.name', 'SearchTest1'); + $response->assertJsonPath('data.1.name', 'SearchTest2'); + } + + /** + * Test datatables sorting works correctly. + */ + public function test_datatables_sorting_works_correctly(): void + { + $this->actingAs($this->user); + + // Create additional permission groups for testing sorting + PermissionGroup::create(['name' => 'A-Group']); + PermissionGroup::create(['name' => 'Z-Group']); + + // Test ascending order + $response = $this->getJson(route('users.permissions.datatables') . '?page=1&size=10&sortField=name&sortOrder=asc'); + + $response->assertStatus(200); + $response->assertJsonPath('data.0.name', 'A-Group'); + + // Test descending order + $response = $this->getJson(route('users.permissions.datatables') . '?page=1&size=10&sortField=name&sortOrder=desc'); + + $response->assertStatus(200); + $response->assertJsonPath('data.0.name', 'Z-Group'); + } + + /** + * Test export functionality. + */ + public function test_export_functionality(): void + { + $this->actingAs($this->user); + + $response = $this->get(route('users.permissions.export')); + + $response->assertStatus(200); + $response->assertHeader('content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); + } +}