fix(security): enforce doctor scope on POST my/appointment (H1)
createAppointment only checked the caller held an allowed role, then booked onto whatever doctor_uuid the request named — a doctor could book onto any other doctor's calendar, a clinic onto doctors outside it, a secretary outside their scope. Add canBookForDoctor(): doctor→own only, clinic→member doctors, secretary→active scope + appointments.create permission, admin→any. Regression: tests/Appointment/BookingScopeTest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Appointment;
|
||||
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
* POST /api/v1/my/appointment must enforce that the acting user is scoped to
|
||||
* the target doctor. A doctor having the ROLE_DOCTOR role is not enough — they
|
||||
* must not be able to book onto another doctor's calendar via doctor_uuid.
|
||||
*/
|
||||
class BookingScopeTest extends ApiTestCase
|
||||
{
|
||||
private function makeDoctor(): Doctor
|
||||
{
|
||||
$user = $this->createUser(['ROLE_USER', 'ROLE_DOCTOR']);
|
||||
$doctor = new Doctor($user, 'دکتر تست');
|
||||
$this->em->persist($doctor);
|
||||
$this->em->flush();
|
||||
|
||||
return $doctor;
|
||||
}
|
||||
|
||||
private function bookingBody(string $doctorUuid): array
|
||||
{
|
||||
$start = time() + 86_400;
|
||||
|
||||
return [
|
||||
'doctor_uuid' => $doctorUuid,
|
||||
'slot_start' => $start,
|
||||
'slot_end' => $start + 1_800,
|
||||
'patient_mobile' => '09120000000',
|
||||
'patient_name' => 'بیمار تست',
|
||||
];
|
||||
}
|
||||
|
||||
public function testDoctorCannotBookOntoAnotherDoctor(): void
|
||||
{
|
||||
$doctorA = $this->makeDoctor();
|
||||
$doctorB = $this->makeDoctor();
|
||||
|
||||
$this->authJson('POST', '/api/v1/my/appointment', $doctorA->getUser(), $this->bookingBody($doctorB->getUuid()));
|
||||
|
||||
$this->assertSame(403, $this->responseCode());
|
||||
}
|
||||
|
||||
public function testDoctorCanBookOntoOwnCalendar(): void
|
||||
{
|
||||
$doctorA = $this->makeDoctor();
|
||||
|
||||
$this->authJson('POST', '/api/v1/my/appointment', $doctorA->getUser(), $this->bookingBody($doctorA->getUuid()));
|
||||
|
||||
$this->assertSame(201, $this->responseCode());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user