'Payroll Only Corp', 'contact_name' => 'Payroll Admin', 'email' => 'payrolladmin@payrollcorp.com', 'desired_subdomain' => 'payroll-only-tenant', 'employee_count' => 50, 'requested_features' => ['payroll', 'documents'], // Only Payroll & Documents selected 'email_verified_at' => now(), 'status' => 'approved', ]); $job = new ProvisionTenantJob($inquiry); $job->handle(); $tenant = Tenant::find('payroll-only-tenant'); $this->assertNotNull($tenant); // Check Central database storage (Single source of truth) $this->assertDatabaseHas('central_tenant_modules', [ 'tenant_id' => 'payroll-only-tenant', 'module_key' => 'payroll', 'enabled' => true, ]); $this->assertDatabaseHas('central_tenant_modules', [ 'tenant_id' => 'payroll-only-tenant', 'module_key' => 'attendance', 'enabled' => false, ]); // Check exact real Spatie permissions within tenant DB $tenant->run(function () { $user = \App\Models\User::where('email', 'payrolladmin@payrollcorp.com')->first(); $this->assertNotNull($user); // Selected module permissions must exist on user $userPermissions = $user->getAllPermissions()->pluck('name')->toArray(); $this->assertContains('manage-payrolls', $userPermissions); $this->assertContains('manage-hr-documents', $userPermissions); // Unselected module permissions must NOT exist on user $this->assertNotContains('manage-candidates', $userPermissions); $this->assertNotContains('manage-biometric-attendance', $userPermissions); }); } public function test_ensure_tenant_module_enabled_middleware_returns_403_for_disabled_module(): void { $inquiry = Inquiry::create([ 'company_name' => 'No Attendance Corp', 'contact_name' => 'Admin User', 'email' => 'admin@noattendance.com', 'desired_subdomain' => 'no-attendance-tenant', 'requested_features' => ['payroll'], 'email_verified_at' => now(), 'status' => 'approved', ]); $job = new ProvisionTenantJob($inquiry); $job->handle(); $middleware = new \App\Http\Middleware\EnsureTenantModuleEnabled(); // Simulate tenant context request $request = \Illuminate\Http\Request::create('/attendances', 'GET'); $request->headers->set('Accept', 'application/json'); $request->headers->set('X-Tenant', 'no-attendance-tenant'); $response = $middleware->handle($request, function () { return response()->json(['success' => true]); }, 'attendance'); $this->assertEquals(403, $response->getStatusCode()); } public function test_cannot_reprovision_active_tenant(): void { $user = \App\Models\User::factory()->create(['type' => 'company']); $role = \Spatie\Permission\Models\Role::findOrCreate('company', 'web'); $permission = \Spatie\Permission\Models\Permission::findOrCreate('manage-contacts', 'web'); $role->givePermissionTo($permission); $user->assignRole($role); Inquiry::create([ 'company_name' => 'Active Tenant Co', 'contact_name' => 'Active User', 'email' => 'active@tenant.com', 'desired_subdomain' => 'active-tenant-slug', 'status' => 'active', ]); $response = $this->actingAs($user) ->postJson('/contacts/provision-subdomain', [ 'company_name' => 'Active Tenant Co', 'contact_name' => 'Active User', 'email' => 'active@tenant.com', 'desired_subdomain' => 'active-tenant-slug', ]); $response->assertStatus(422) ->assertJson(['success' => false]); } }