feat(auth): enforce strict branch scoping for branch-assigned HR and staff accounts
- Introduce authBranchId() helper to resolve assigned branch while allowing company admin/superadmin cross-branch oversight - Restrict branch, department, and employee listings and mutations to assigned branch for branch-scoped accounts - Scope attendance records, biometric logs, leave applications/balances, payslips, shifts, and announcements by assigned branch - Add comprehensive automated feature tests in BranchScopedAccessTest to prevent branch cross-visibility regression
This commit is contained in:
@@ -23,6 +23,7 @@ class LeaveApplicationController extends Controller
|
||||
$isSelfServiceOnly = !$canManageAny && !$canManageBranch;
|
||||
$isMyLeavesView = $request->boolean('my_leaves') || $isSelfServiceOnly;
|
||||
|
||||
$scopedBranchId = authBranchId();
|
||||
$query = LeaveApplication::with(['employee.employee', 'leaveType', 'leavePolicy', 'approver', 'creator']);
|
||||
|
||||
if ($isMyLeavesView) {
|
||||
@@ -30,6 +31,11 @@ class LeaveApplicationController extends Controller
|
||||
$q->where('employee_id', $user->id)
|
||||
->orWhere('created_by', $user->id);
|
||||
});
|
||||
} elseif ($scopedBranchId) {
|
||||
$query->whereIn('created_by', getCompanyAndUsersId())
|
||||
->whereHas('employee.employee', function ($eq) use ($scopedBranchId) {
|
||||
$eq->where('branch_id', $scopedBranchId);
|
||||
});
|
||||
} elseif ($canManageAny) {
|
||||
$query->whereIn('created_by', getCompanyAndUsersId());
|
||||
} elseif ($canManageBranch) {
|
||||
@@ -120,8 +126,11 @@ class LeaveApplicationController extends Controller
|
||||
{
|
||||
$user = Auth::user();
|
||||
$employeeQuery = Employee::whereIn('created_by', getCompanyAndUsersId());
|
||||
$scopedBranchId = authBranchId();
|
||||
|
||||
if (!$user->can('manage-any-leave-applications')) {
|
||||
if ($scopedBranchId) {
|
||||
$employeeQuery->where('branch_id', $scopedBranchId);
|
||||
} elseif (!$user->can('manage-any-leave-applications')) {
|
||||
if ($user->can('manage-leave-applications')) {
|
||||
$branchId = $user->branch_id ?? $user->employee?->branch_id ?? null;
|
||||
if ($branchId) {
|
||||
@@ -350,11 +359,19 @@ class LeaveApplicationController extends Controller
|
||||
'manager_comments' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$leaveApplication = LeaveApplication::where('id', $leaveApplicationId)
|
||||
$leaveApplication = LeaveApplication::with('employee.employee')->where('id', $leaveApplicationId)
|
||||
->whereIn('created_by', getCompanyAndUsersId())
|
||||
->first();
|
||||
|
||||
if ($leaveApplication) {
|
||||
$scopedBranchId = authBranchId();
|
||||
if ($scopedBranchId) {
|
||||
$applicantBranchId = $leaveApplication->employee?->employee?->branch_id;
|
||||
if ($applicantBranchId && (int)$applicantBranchId !== (int)$scopedBranchId) {
|
||||
return redirect()->back()->with('error', __('Permission Denied. You cannot manage leave applications outside your branch.'));
|
||||
}
|
||||
}
|
||||
|
||||
// If the leave belongs to the currently logged in user, require manage-own-leave-applications permission
|
||||
if ($leaveApplication->employee_id == Auth::id()) {
|
||||
if (!Auth::user()->can('manage-own-leave-applications')) {
|
||||
@@ -415,10 +432,16 @@ class LeaveApplicationController extends Controller
|
||||
public function export()
|
||||
{
|
||||
if (Auth::user()->can('export-leave-applications')) {
|
||||
$scopedBranchId = authBranchId();
|
||||
try {
|
||||
$leaveApplications = LeaveApplication::with(['employee.employee', 'leaveType', 'approver'])
|
||||
->where(function ($q) {
|
||||
if (Auth::user()->can('manage-any-leave-applications')) {
|
||||
->where(function ($q) use ($scopedBranchId) {
|
||||
if ($scopedBranchId) {
|
||||
$q->whereIn('created_by', getCompanyAndUsersId())
|
||||
->whereHas('employee.employee', function ($eq) use ($scopedBranchId) {
|
||||
$eq->where('branch_id', $scopedBranchId);
|
||||
});
|
||||
} elseif (Auth::user()->can('manage-any-leave-applications')) {
|
||||
$q->whereIn('created_by', getCompanyAndUsersId());
|
||||
} elseif (Auth::user()->can('manage-leave-applications')) {
|
||||
$branchId = Auth::user()->branch_id ?? Auth::user()->employee?->branch_id ?? null;
|
||||
|
||||
Reference in New Issue
Block a user