feat: granular permissions, export backup, user/role management
- PermissionSeeder: 29 permissions with role mapping (admin/manager/staff) - Policies updated to use hasPermissionTo() instead of hasRole() - ExportBackup command: JSON per-table backup with chunk processing - UserResource: CRUD users with role assignment (admin only) - RoleResource: CRUD roles with permission assignment (admin only) - UserPolicy + RolePolicy: admin-only access control - ImportCskh: detailed skip logging with color in dry-run mode - Widgets: permission-based visibility checks - Tests: 8/8 pass (21 assertions)
This commit is contained in:
@@ -7,12 +7,27 @@ use App\Models\FeedbackAttachment;
|
||||
use App\Models\FeedbackChannel;
|
||||
use App\Models\User;
|
||||
use App\Services\ClosingService;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
|
||||
|
||||
// Create permissions
|
||||
Permission::firstOrCreate(['name' => 'close-ticket']);
|
||||
Permission::firstOrCreate(['name' => 'view-feedback']);
|
||||
Permission::firstOrCreate(['name' => 'create-feedback']);
|
||||
Permission::firstOrCreate(['name' => 'update-feedback']);
|
||||
Permission::firstOrCreate(['name' => 'add-interaction']);
|
||||
Permission::firstOrCreate(['name' => 'transfer-department']);
|
||||
});
|
||||
|
||||
// ─── Scenario 1: Staff cannot close ticket ───────────────────────────
|
||||
test('staff cannot close ticket - returns 403 forbidden', function () {
|
||||
\Spatie\Permission\Models\Role::create(['name' => 'staff']);
|
||||
$staffRole = Role::create(['name' => 'staff']);
|
||||
$staffRole->givePermissionTo(['view-feedback', 'create-feedback', 'update-feedback', 'add-interaction']);
|
||||
|
||||
$staff = User::factory()->create();
|
||||
$staff->assignRole('staff');
|
||||
@@ -45,7 +60,8 @@ test('staff cannot close ticket - returns 403 forbidden', function () {
|
||||
|
||||
// ─── Scenario 2: Manager cannot close without proof_of_resolution ────
|
||||
test('manager cannot close ticket without proof_of_resolution evidence', function () {
|
||||
\Spatie\Permission\Models\Role::create(['name' => 'manager']);
|
||||
$managerRole = Role::create(['name' => 'manager']);
|
||||
$managerRole->givePermissionTo(['close-ticket', 'view-feedback', 'create-feedback', 'update-feedback', 'transfer-department']);
|
||||
|
||||
$manager = User::factory()->create();
|
||||
$manager->assignRole('manager');
|
||||
@@ -81,7 +97,9 @@ test('manager cannot close ticket without proof_of_resolution evidence', functio
|
||||
// ─── Scenario 2b: Manager CAN close with proof_of_resolution ─────────
|
||||
test('manager can close ticket with proof_of_resolution evidence', function () {
|
||||
\Illuminate\Support\Facades\Notification::fake();
|
||||
\Spatie\Permission\Models\Role::create(['name' => 'manager']);
|
||||
|
||||
$managerRole = Role::create(['name' => 'manager']);
|
||||
$managerRole->givePermissionTo(['close-ticket', 'view-feedback', 'create-feedback', 'update-feedback', 'transfer-department']);
|
||||
|
||||
$manager = User::factory()->create();
|
||||
$manager->assignRole('manager');
|
||||
@@ -122,7 +140,8 @@ test('manager can close ticket with proof_of_resolution evidence', function () {
|
||||
|
||||
// ─── Scenario 2c: Manager cannot close ticket from other department ──
|
||||
test('manager cannot close ticket from department they do not manage', function () {
|
||||
\Spatie\Permission\Models\Role::create(['name' => 'manager']);
|
||||
$managerRole = Role::create(['name' => 'manager']);
|
||||
$managerRole->givePermissionTo(['close-ticket', 'view-feedback', 'create-feedback', 'update-feedback', 'transfer-department']);
|
||||
|
||||
$manager = User::factory()->create();
|
||||
$manager->assignRole('manager');
|
||||
|
||||
Reference in New Issue
Block a user