feat: Implement permission gate for appointment and billing controllers
- Added PermissionGateTrait to manage access control for AppointmentPlanController and BillingController. - Introduced denyUnlessGrantedForPlanning method in AppointmentPlanController to handle specific permission checks for planning appointments. - Updated existing methods in both controllers to utilize the new permission checks. - Refactored ResourcePermissionTrait to use PermissionGateTrait for cleaner permission management. - Added tests to ensure proper permission enforcement across different scenarios, including cross-tenant access restrictions for staff.
This commit is contained in:
@@ -52,7 +52,15 @@ class SecretaryAppointmentScopeTest extends ApiTestCase
|
||||
$this->assertSame(1, $body['meta']['totalRecords']);
|
||||
}
|
||||
|
||||
public function testSecretaryWithNoAssignmentSeesNothing(): void
|
||||
/**
|
||||
* منشیِ بدون رابطهٔ فعال دیگر لیست خالی نمیگیرد، ۴۰۳ میگیرد.
|
||||
*
|
||||
* تا ۲۰۲۶-۰۸-۰۷ این مسیر گِیت مجوز نداشت و پاسخ خالی از فیلترِ خودِ کوئری
|
||||
* میآمد. با گِیتِ `appointments.view` (یافتهٔ ۸ آدیت)، `SecretaryAccessChecker`
|
||||
* برای منشیِ بیرابطه `can()=false` میدهد — همان رفتار fail-closed مستندِ
|
||||
* `SecretaryPermissionChecker`. «خالیِ خاموش» با «اجازه نداری» یکی نیست.
|
||||
*/
|
||||
public function testSecretaryWithNoAssignmentIsDenied(): void
|
||||
{
|
||||
$owner = $this->createUser(['ROLE_CLINIC']);
|
||||
$clinic = new Clinic($owner);
|
||||
@@ -73,7 +81,7 @@ class SecretaryAppointmentScopeTest extends ApiTestCase
|
||||
|
||||
$body = $this->authJson('GET', '/api/v1/my/appointments', $secretaryUser);
|
||||
|
||||
// بدون رابطهی فعال → resolveSecretaryFilter=null → لیست خالی
|
||||
$this->assertSame(0, $body['meta']['totalRecords']);
|
||||
$this->assertSame(403, $this->responseCode());
|
||||
$this->assertSame('ERR_FORBIDDEN_001', $body['errors'][0]['code']);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user