feat: Implement secretary permissions enforcement across multiple resources
- Added SecretaryAccessChecker to manage resource access for secretaries. - Integrated permission checks for payments, inventory, and tags in relevant controllers. - Updated PaymentController and PaymentMethodController to enforce secretary permissions. - Enhanced TenantTagController to check permissions for tag management actions. - Introduced tests for secretary resource enforcement, ensuring proper access control. - Updated DoctorSecretary entity to include inventory and tags permissions. - Created a comprehensive audit document for secretary permissions coverage and enforcement. - Fixed potential crashes in SecretaryDashboard when rendering without doctor data.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Secretary;
|
||||
|
||||
use App\Auth\Entity\UserActiveContext;
|
||||
use App\Clinic\Entity\Clinic;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use App\Secretary\Entity\DoctorSecretary;
|
||||
use App\Tests\ApiTestCase;
|
||||
|
||||
/**
|
||||
* A secretary's per-resource permission JSON (DoctorSecretary.permission) must be
|
||||
* enforced by the API, not only for appointments. Resources the secretary was not
|
||||
* granted return 403; granted ones pass.
|
||||
*/
|
||||
class SecretaryResourceEnforcementTest extends ApiTestCase
|
||||
{
|
||||
private function makeClinicSecretary(): array
|
||||
{
|
||||
$owner = $this->createUser(['ROLE_CLINIC']);
|
||||
$clinic = new Clinic($owner);
|
||||
$this->em->persist($clinic);
|
||||
|
||||
$doctor = new Doctor($this->createUser(['ROLE_DOCTOR']), 'دکتر تست');
|
||||
$this->em->persist($doctor);
|
||||
$clinic->getDoctors()->add($doctor);
|
||||
|
||||
$secretary = $this->createUser(['ROLE_SECRETARY']);
|
||||
$rel = new DoctorSecretary($doctor, $secretary, DoctorSecretary::OWNER_CLINIC, $clinic);
|
||||
$this->em->persist($rel);
|
||||
$this->em->persist(new UserActiveContext($secretary, $clinic->getUuid()));
|
||||
|
||||
return [$secretary, $rel];
|
||||
}
|
||||
|
||||
public function testInventoryDeniedByDefault(): void
|
||||
{
|
||||
// DEFAULT_PERMISSIONS: inventory.* = false
|
||||
[$secretary] = $this->makeClinicSecretary();
|
||||
$this->em->flush();
|
||||
|
||||
$this->authJson('GET', '/api/v1/inventory-items', $secretary);
|
||||
$this->assertSame(403, $this->responseCode());
|
||||
}
|
||||
|
||||
public function testInventoryAllowedWhenGranted(): void
|
||||
{
|
||||
[$secretary, $rel] = $this->makeClinicSecretary();
|
||||
$rel->mergePermissions(['resources' => ['inventory' => ['view' => true]]]);
|
||||
$this->em->flush();
|
||||
|
||||
$this->authJson('GET', '/api/v1/inventory-items', $secretary);
|
||||
$this->assertSame(200, $this->responseCode());
|
||||
}
|
||||
|
||||
public function testPatientCreateDeniedByDefault(): void
|
||||
{
|
||||
// DEFAULT_PERMISSIONS: patients.create = false (view is true)
|
||||
[$secretary] = $this->makeClinicSecretary();
|
||||
$this->em->flush();
|
||||
|
||||
$this->authJson('POST', '/api/v1/patient', $secretary, ['name' => 'x']);
|
||||
$this->assertSame(403, $this->responseCode());
|
||||
}
|
||||
|
||||
public function testInventoryCreateDeniedButViewGranted(): void
|
||||
{
|
||||
[$secretary, $rel] = $this->makeClinicSecretary();
|
||||
$rel->mergePermissions(['resources' => ['inventory' => ['view' => true, 'create' => false]]]);
|
||||
$this->em->flush();
|
||||
|
||||
// مشاهده مجاز
|
||||
$this->authJson('GET', '/api/v1/inventory-items', $secretary);
|
||||
$this->assertSame(200, $this->responseCode());
|
||||
|
||||
// ایجاد ممنوع
|
||||
$this->authJson('POST', '/api/v1/inventory-item', $secretary, ['name' => 'گاز استریل']);
|
||||
$this->assertSame(403, $this->responseCode());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user