feat(auth): enforce strict branch scoping for overtime requests, attendance regularizations, and 13th month pay
- Restrict overtime applications query, submission, approval, and attendance details to assigned branch - Restrict attendance regularization listing, statistics, and dropdowns to assigned branch - Restrict 13th month pay batch generation, historical runs, entry updates, approvals, and CSV exports to assigned branch - Add feature tests in BranchScopedAccessTest for overtime and 13th month isolation
This commit is contained in:
@@ -24,6 +24,14 @@ class OvertimeApplicationController extends Controller
|
||||
if (!in_array(Auth::user()->type, ['admin', 'hr', 'company'])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$scopedBranchId = authBranchId();
|
||||
if ($scopedBranchId) {
|
||||
$targetEmp = \App\Models\Employee::where('user_id', $userId)->first();
|
||||
if ($targetEmp && (int)$targetEmp->branch_id !== (int)$scopedBranchId) {
|
||||
abort(403, 'Unauthorized to view attendance details for an employee outside your assigned branch.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$record = AttendanceRecord::with('employee.user', 'employee.shift')
|
||||
@@ -85,19 +93,30 @@ class OvertimeApplicationController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$user = Auth::user();
|
||||
$scopedBranchId = authBranchId();
|
||||
|
||||
$query = OvertimeApplication::with('user.employee');
|
||||
|
||||
// If not admin/hr, only show own requests
|
||||
if (!in_array($user->type, ['admin', 'hr', 'company'])) {
|
||||
$query->where('user_id', $user->id);
|
||||
} elseif ($scopedBranchId) {
|
||||
$query->whereHas('user.employee', function($q) use ($scopedBranchId) {
|
||||
$q->where('branch_id', $scopedBranchId);
|
||||
});
|
||||
}
|
||||
|
||||
$applications = $query->orderBy('date', 'desc')->get();
|
||||
|
||||
$users = [];
|
||||
if (in_array($user->type, ['admin', 'hr', 'company'])) {
|
||||
$users = \App\Models\User::where('type', 'employee')->select('id', 'name')->get();
|
||||
$usersQuery = \App\Models\User::where('type', 'employee');
|
||||
if ($scopedBranchId) {
|
||||
$usersQuery->whereHas('employee', function($q) use ($scopedBranchId) {
|
||||
$q->where('branch_id', $scopedBranchId);
|
||||
});
|
||||
}
|
||||
$users = $usersQuery->select('id', 'name')->get();
|
||||
}
|
||||
|
||||
return Inertia::render('hr/overtime/index', [
|
||||
@@ -117,10 +136,17 @@ class OvertimeApplicationController extends Controller
|
||||
]);
|
||||
|
||||
$userId = Auth::id();
|
||||
$scopedBranchId = authBranchId();
|
||||
|
||||
// If an admin/hr specifies a user_id, use it.
|
||||
if ($request->has('user_id') && $request->user_id != Auth::id()) {
|
||||
if (in_array(Auth::user()->type, ['admin', 'hr', 'company'])) {
|
||||
if ($scopedBranchId) {
|
||||
$targetEmp = \App\Models\Employee::where('user_id', $request->user_id)->first();
|
||||
if ($targetEmp && (int)$targetEmp->branch_id !== (int)$scopedBranchId) {
|
||||
abort(403, 'Unauthorized to apply overtime for an employee outside your assigned branch.');
|
||||
}
|
||||
}
|
||||
$userId = $request->user_id;
|
||||
} else {
|
||||
abort(403, 'Unauthorized to apply overtime for another employee.');
|
||||
@@ -160,6 +186,14 @@ class OvertimeApplicationController extends Controller
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$scopedBranchId = authBranchId();
|
||||
if ($scopedBranchId) {
|
||||
$applicantEmp = $overtimeApplication->user?->employee;
|
||||
if ($applicantEmp && (int)$applicantEmp->branch_id !== (int)$scopedBranchId) {
|
||||
abort(403, 'Unauthorized to update overtime status for an employee outside your assigned branch.');
|
||||
}
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'status' => 'required|in:approved,rejected',
|
||||
'approved_hours' => 'nullable|required_if:status,approved|numeric|min:0',
|
||||
|
||||
Reference in New Issue
Block a user