From 24b2825b31ea2361ab953e748204dedf447ef535 Mon Sep 17 00:00:00 2001 From: Ollama Date: Mon, 16 Mar 2026 18:24:40 +0000 Subject: [PATCH] Fix: Restrict employee selection in expenses and receivings forms Users without the 'employees' permission can no longer impersonate other employees when creating or editing expenses and receivings. The employee field is now restricted to the current user for new records and shows the stored employee for existing records. Changes: - Expenses controller: Add permission check in getView() and postSave() - Receivings controller: Add permission check in getEdit() and postSave() - Form views: Conditionally display dropdown or read-only field Fixes #3616 --- app/Controllers/Expenses.php | 49 +++++++++++++++++++++++++--------- app/Controllers/Receivings.php | 29 +++++++++++++++++--- app/Views/expenses/form.php | 7 ++++- app/Views/receivings/form.php | 8 +++++- 4 files changed, 74 insertions(+), 19 deletions(-) diff --git a/app/Controllers/Expenses.php b/app/Controllers/Expenses.php index d1fcb3f16..d36d474a9 100644 --- a/app/Controllers/Expenses.php +++ b/app/Controllers/Expenses.php @@ -93,16 +93,27 @@ class Expenses extends Secure_Controller { $data = []; // TODO: Duplicated code - $data['employees'] = []; - foreach ($this->employee->get_all()->getResult() as $employee) { - foreach (get_object_vars($employee) as $property => $value) { - $employee->$property = $value; - } - - $data['employees'][$employee->person_id] = $employee->first_name . ' ' . $employee->last_name; - } - $data['expenses_info'] = $this->expense->get_info($expense_id); + $expense_id = $data['expenses_info']->expense_id; + + $current_employee_id = $this->employee->get_logged_in_employee_info()->person_id; + $can_assign_employee = $this->employee->has_grant('employees', $current_employee_id); + + $data['employees'] = []; + if ($can_assign_employee) { + foreach ($this->employee->get_all()->getResult() as $employee) { + foreach (get_object_vars($employee) as $property => $value) { + $employee->$property = $value; + } + + $data['employees'][$employee->person_id] = $employee->first_name . ' ' . $employee->last_name; + } + } else { + $stored_employee_id = $expense_id == NEW_ENTRY ? $current_employee_id : $data['expenses_info']->employee_id; + $stored_employee = $this->employee->get_info($stored_employee_id); + $data['employees'][$stored_employee_id] = $stored_employee->first_name . ' ' . $stored_employee->last_name; + } + $data['can_assign_employee'] = $can_assign_employee; $expense_categories = []; foreach ($this->expense_category->get_all(0, 0, true)->getResultArray() as $row) { @@ -110,11 +121,9 @@ class Expenses extends Secure_Controller } $data['expense_categories'] = $expense_categories; - $expense_id = $data['expenses_info']->expense_id; - if ($expense_id == NEW_ENTRY) { $data['expenses_info']->date = date('Y-m-d H:i:s'); - $data['expenses_info']->employee_id = $this->employee->get_logged_in_employee_info()->person_id; + $data['expenses_info']->employee_id = $current_employee_id; } $data['payments'] = []; @@ -155,6 +164,20 @@ class Expenses extends Secure_Controller $date_formatter = date_create_from_format($config['dateformat'] . ' ' . $config['timeformat'], $newdate); + $current_employee_id = $this->employee->get_logged_in_employee_info()->person_id; + $submitted_employee_id = $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT); + + if (!$this->employee->has_grant('employees', $current_employee_id)) { + if ($expense_id == NEW_ENTRY) { + $employee_id = $current_employee_id; + } else { + $existing_expense = $this->expense->get_info($expense_id); + $employee_id = $existing_expense->employee_id; + } + } else { + $employee_id = $submitted_employee_id; + } + $expense_data = [ 'date' => $date_formatter->format('Y-m-d H:i:s'), 'supplier_id' => $this->request->getPost('supplier_id') == '' ? null : $this->request->getPost('supplier_id', FILTER_SANITIZE_NUMBER_INT), @@ -164,7 +187,7 @@ class Expenses extends Secure_Controller 'payment_type' => $this->request->getPost('payment_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'expense_category_id' => $this->request->getPost('expense_category_id', FILTER_SANITIZE_NUMBER_INT), 'description' => $this->request->getPost('description', FILTER_SANITIZE_FULL_SPECIAL_CHARS), - 'employee_id' => $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT), + 'employee_id' => $employee_id, 'deleted' => $this->request->getPost('deleted') != null ]; diff --git a/app/Controllers/Receivings.php b/app/Controllers/Receivings.php index 52f0169ac..1294bd152 100644 --- a/app/Controllers/Receivings.php +++ b/app/Controllers/Receivings.php @@ -241,15 +241,26 @@ class Receivings extends Secure_Controller $data['suppliers'][$supplier->person_id] = $supplier->first_name . ' ' . $supplier->last_name; } + $receiving_info = $this->receiving->get_info($receiving_id)->getRowArray(); + + $current_employee_id = $this->employee->get_logged_in_employee_info()->person_id; + $can_assign_employee = $this->employee->has_grant('employees', $current_employee_id); + $data['employees'] = []; - foreach ($this->employee->get_all()->getResult() as $employee) { - $data['employees'][$employee->person_id] = $employee->first_name . ' ' . $employee->last_name; + if ($can_assign_employee) { + foreach ($this->employee->get_all()->getResult() as $employee) { + $data['employees'][$employee->person_id] = $employee->first_name . ' ' . $employee->last_name; + } + } else { + $stored_employee_id = $receiving_info['employee_id']; + $stored_employee = $this->employee->get_info($stored_employee_id); + $data['employees'][$stored_employee_id] = $stored_employee->first_name . ' ' . $stored_employee->last_name; } - $receiving_info = $this->receiving->get_info($receiving_id)->getRowArray(); $data['selected_supplier_name'] = !empty($receiving_info['supplier_id']) ? $receiving_info['company_name'] : ''; $data['selected_supplier_id'] = $receiving_info['supplier_id']; $data['receiving_info'] = $receiving_info; + $data['can_assign_employee'] = $can_assign_employee; return view('receivings/form', $data); } @@ -491,10 +502,20 @@ class Receivings extends Secure_Controller $date_formatter = date_create_from_format($this->config['dateformat'] . ' ' . $this->config['timeformat'], $newdate); $receiving_time = $date_formatter->format('Y-m-d H:i:s'); + $current_employee_id = $this->employee->get_logged_in_employee_info()->person_id; + $submitted_employee_id = $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT); + + if (!$this->employee->has_grant('employees', $current_employee_id)) { + $existing_receiving = $this->receiving->get_info($receiving_id)->getRowArray(); + $employee_id = $existing_receiving['employee_id']; + } else { + $employee_id = $submitted_employee_id; + } + $receiving_data = [ 'receiving_time' => $receiving_time, 'supplier_id' => $this->request->getPost('supplier_id') ? $this->request->getPost('supplier_id', FILTER_SANITIZE_NUMBER_INT) : null, - 'employee_id' => $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT), + 'employee_id' => $employee_id, 'comment' => $this->request->getPost('comment', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'reference' => $this->request->getPost('reference') != '' ? $this->request->getPost('reference', FILTER_SANITIZE_FULL_SPECIAL_CHARS) : null ]; diff --git a/app/Views/expenses/form.php b/app/Views/expenses/form.php index 2fc89f99e..8169cc8a9 100644 --- a/app/Views/expenses/form.php +++ b/app/Views/expenses/form.php @@ -126,7 +126,12 @@
'control-label col-xs-3']) ?>
- employee_id, 'id="employee_id" class="form-control"') ?> + + employee_id, 'id="employee_id" class="form-control"') ?> + + employee_id) ?> + 'employee_name', 'value' => $employees[$expenses_info->employee_id] ?? '', 'class' => 'form-control', 'readonly' => 'readonly']) ?> +
diff --git a/app/Views/receivings/form.php b/app/Views/receivings/form.php index 927d9a530..561549171 100644 --- a/app/Views/receivings/form.php +++ b/app/Views/receivings/form.php @@ -5,6 +5,7 @@ * @var int $selected_supplier_id * @var array $employees * @var string $controller_name + * @var bool $can_assign_employee */ ?> @@ -50,7 +51,12 @@
'control-label col-xs-3']) ?>
- + + + + + 'employee_name', 'value' => $employees[$receiving_info['employee_id']] ?? '', 'class' => 'form-control input-sm', 'readonly' => 'readonly']) ?> +