138 lines
4.5 KiB
PHP
138 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use App\Models\DropOffPoint;
|
|
use App\Models\Dumpsite;
|
|
use App\Models\Route;
|
|
use App\Models\CollectionTeam;
|
|
use App\Models\Trip;
|
|
use App\Models\Truck;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
|
|
class LguTenantIsolationTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
protected $seed = true;
|
|
|
|
protected Tenant $lguA;
|
|
protected Tenant $lguB;
|
|
protected User $adminA;
|
|
protected User $adminB;
|
|
protected User $superAdmin;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->seed([\Database\Seeders\SamplePsgcSeeder::class]);
|
|
|
|
$this->lguA = $this->defaultTenant;
|
|
$this->lguB = Tenant::factory()->create(['code' => 'LGU-B', 'name' => 'LGU B']);
|
|
|
|
$this->adminA = User::factory()->create([
|
|
'tenant_id' => $this->lguA->id,
|
|
'role' => User::ROLE_ADMIN,
|
|
]);
|
|
|
|
$this->adminB = User::factory()->create([
|
|
'tenant_id' => $this->lguB->id,
|
|
'role' => User::ROLE_ADMIN,
|
|
]);
|
|
|
|
$this->superAdmin = User::factory()->create([
|
|
'tenant_id' => null,
|
|
'role' => User::ROLE_SUPER_ADMIN,
|
|
]);
|
|
}
|
|
|
|
public function test_lgu_a_can_create_and_view_own_entities()
|
|
{
|
|
$this->actingAs($this->adminA);
|
|
$this->withHeaders(['X-Tenant-Code' => $this->lguA->code]);
|
|
|
|
$city = \App\Models\CityMunicipality::first();
|
|
$barangay = \App\Models\Barangay::first();
|
|
|
|
$dumpsiteResponse = $this->postJson('/api/v1/admin/dumpsites', [
|
|
'name' => 'LGU A Dumpsite',
|
|
'code' => 'DS-01',
|
|
'address_line' => '123 Test St',
|
|
'city_municipality_id' => $city->id,
|
|
'lat' => 14.0,
|
|
'lng' => 121.0,
|
|
'status' => 'active'
|
|
]);
|
|
$dumpsiteResponse->assertCreated();
|
|
|
|
// Create Drop-off Point
|
|
$dopResponse = $this->postJson('/api/v1/admin/drop-off-points', [
|
|
'name' => 'LGU A DOP',
|
|
'code' => 'DOP-01',
|
|
'address_line' => '456 Test Ave',
|
|
'barangay_id' => $barangay->id,
|
|
'lat' => 14.1,
|
|
'lng' => 121.1,
|
|
'status' => 'active'
|
|
]);
|
|
$dopResponse->assertCreated();
|
|
|
|
// Create Team
|
|
$teamResponse = $this->postJson('/api/v1/admin/teams', [
|
|
'name' => 'LGU A Team',
|
|
'status' => 'active'
|
|
]);
|
|
$teamResponse->assertCreated();
|
|
}
|
|
|
|
public function test_lgu_b_cannot_access_lgu_a_entities()
|
|
{
|
|
// Seed LGU A data
|
|
$dumpsiteA = Dumpsite::factory()->create(['tenant_id' => $this->lguA->id]);
|
|
$dopA = DropOffPoint::factory()->create(['tenant_id' => $this->lguA->id]);
|
|
|
|
$teamA = new CollectionTeam(['name' => 'Team A', 'status' => 'active']);
|
|
$teamA->tenant_id = $this->lguA->id;
|
|
$teamA->save();
|
|
|
|
$routeA = new Route(['name' => 'Route A', 'code' => 'RTA-01', 'geojson' => []]);
|
|
$routeA->tenant_id = $this->lguA->id;
|
|
$routeA->save();
|
|
|
|
// Act as LGU B Admin
|
|
$this->actingAs($this->adminB);
|
|
$this->withHeaders(['X-Tenant-Code' => $this->lguB->code]);
|
|
|
|
// 1. List Endpoints Should Not Contain LGU A Data
|
|
$this->getJson('/api/v1/admin/dumpsites')->assertJsonMissing(['id' => $dumpsiteA->id]);
|
|
$this->getJson('/api/v1/admin/drop-off-points')->assertJsonMissing(['id' => $dopA->id]);
|
|
$this->getJson('/api/v1/admin/teams')->assertJsonMissing(['id' => $teamA->id]);
|
|
$this->getJson('/api/v1/admin/routes')->assertJsonMissing(['id' => $routeA->id]);
|
|
|
|
// 2. Direct Access Should Fail (404/403)
|
|
$this->getJson("/api/v1/admin/routes/{$routeA->id}")->assertStatus(404);
|
|
|
|
// 3. API Tampering: Attempt to create a trip for LGU B using LGU A's Route
|
|
$truckB = new Truck(['plate_number' => 'ABC-1234', 'capacity_tons' => 5]);
|
|
$truckB->tenant_id = $this->lguB->id;
|
|
$truckB->save();
|
|
|
|
$teamB = new CollectionTeam(['name' => 'Team B', 'status' => 'active']);
|
|
$teamB->tenant_id = $this->lguB->id;
|
|
$teamB->save();
|
|
|
|
$response = $this->postJson('/api/v1/admin/trips', [
|
|
'route_id' => $routeA->id,
|
|
'truck_id' => $truckB->id,
|
|
'collection_team_id' => $teamB->id,
|
|
'scheduled_date' => now()->format('Y-m-d'),
|
|
]);
|
|
|
|
// Validation should fail because route_id doesn't belong to LGU B
|
|
$response->assertStatus(422);
|
|
}
|
|
}
|