CRM/backend/tests/Feature/CoreCrmAuthorizationTest.php

119 خطوط
4.9 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\Attachment;
use App\Models\Company;
use App\Models\Contact;
use App\Models\ContactPhone;
use App\Models\Deal;
use App\Models\Lead;
use App\Models\Team;
use App\Models\User;
use Database\Seeders\RolePermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class CoreCrmAuthorizationTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$this->seed(RolePermissionSeeder::class);
}
public function test_agent_cannot_access_core_records_owned_by_another_agent(): void
{
$agent = $this->user('agent');
$otherAgent = $this->user('agent');
$lead = $this->lead($otherAgent);
$company = Company::create(['name' => 'Private Company', 'owner_id' => $otherAgent->id, 'created_by' => $otherAgent->id]);
$deal = Deal::create(['title' => 'Private Deal', 'owner_id' => $otherAgent->id, 'lead_id' => $lead->id, 'created_by' => $otherAgent->id]);
$contact = Contact::create(['name' => 'Private Contact', 'lead_id' => $lead->id, 'company_id' => $company->id, 'created_by' => $otherAgent->id]);
ContactPhone::create(['contact_id' => $contact->id, 'phone' => '09120000002', 'type' => 'mobile', 'status' => 'active']);
$attachment = Attachment::create([
'attachable_type' => Company::class,
'attachable_id' => $company->id,
'uploaded_by' => $otherAgent->id,
'original_name' => 'private.pdf',
'path' => 'attachments/private.pdf',
'mime_type' => 'application/pdf',
'size' => 10,
]);
$this->actingAs($agent)->getJson("/api/companies/{$company->id}")->assertForbidden();
$this->actingAs($agent)->getJson("/api/deals/{$deal->id}")->assertForbidden();
$this->actingAs($agent)->putJson("/api/contacts/{$contact->id}", ['name' => 'Tampered'])->assertForbidden();
$this->actingAs($agent)->postJson('/api/notes', [
'entity_type' => 'lead',
'entity_id' => $lead->id,
'content' => 'Unauthorized note',
])->assertForbidden();
$this->actingAs($agent)->getJson("/api/timeline?entity_type=lead&entity_id={$lead->id}")->assertForbidden();
$this->actingAs($agent)->getJson("/api/attachments?entity_type=company&entity_id={$company->id}")->assertForbidden();
$this->actingAs($agent)->getJson("/api/attachments/{$attachment->id}/download")->assertForbidden();
$contacts = $this->actingAs($agent)->getJson('/api/contacts')->assertOk();
$this->assertNotContains($contact->id, collect($contacts->json('data'))->pluck('id')->all());
}
public function test_duplicate_check_does_not_disclose_out_of_scope_lead(): void
{
$agent = $this->user('agent');
$otherAgent = $this->user('agent');
$lead = $this->lead($otherAgent, ['phone' => '09125556677', 'company' => 'Hidden Corp']);
$response = $this->actingAs($agent)->postJson('/api/duplicates/check', [
'entity_type' => 'lead',
'phone' => '09125556677',
])->assertOk();
$this->assertNotContains($lead->id, collect($response->json('data'))->pluck('id')->all());
}
public function test_supervisor_can_access_team_records_but_not_other_teams(): void
{
$supervisor = $this->user('supervisor');
$teamAgent = $this->user('agent');
$otherAgent = $this->user('agent');
$team = Team::create(['name' => 'Own Team', 'supervisor_id' => $supervisor->id, 'is_active' => true]);
$otherTeam = Team::create(['name' => 'Other Team', 'is_active' => true]);
$supervisor->teams()->attach($team);
$teamAgent->teams()->attach($team);
$otherAgent->teams()->attach($otherTeam);
$teamLead = $this->lead($teamAgent, ['team_id' => $team->id]);
$otherLead = $this->lead($otherAgent, ['team_id' => $otherTeam->id]);
$this->actingAs($supervisor)->getJson("/api/leads/{$teamLead->id}")->assertOk();
$this->actingAs($supervisor)->getJson("/api/leads/{$otherLead->id}")->assertForbidden();
$this->actingAs($supervisor)->postJson('/api/notes', [
'entity_type' => 'lead',
'entity_id' => $otherLead->id,
'content' => 'Unauthorized supervisor note',
])->assertForbidden();
}
private function user(string $role): User
{
$user = User::factory()->create(['is_active' => true]);
$user->assignRole($role);
return $user;
}
private function lead(User $agent, array $attributes = []): Lead
{
return Lead::create(array_merge([
'company' => 'Scoped Company',
'first_name' => 'Ali',
'last_name' => 'Karimi',
'phone' => fake()->unique()->numerify('021########'),
'assigned_to' => $agent->id,
'is_unassigned' => false,
], $attributes));
}
}