Enforce roles on admin endpoints and return real status codes

- users, SMTP and batch-lock endpoints are owner/admin only
- engines answer 400/403/404/409/500 instead of 200 with an error body;
  database errors no longer leak to the client
This commit is contained in:
Thanakorn
2026-09-24 14:53:40 +07:00
parent 73c680e844
commit 8705be0d1b
35 changed files with 131 additions and 4 deletions
@@ -10,6 +10,7 @@ $quotation_id = (int)($data['quotation_id'] ?? 0);
$convert_items = $data['convert_items'] ?? [];
if (!$quotation_id) {
http_response_code(400);
$answer['message'] = 'Quotation ID required.';
exit(json_encode($answer));
}
@@ -19,17 +20,20 @@ $qm = new QuotationManager($pdo2, $company_id);
// Load quotation — must be Accepted
$q = $qm->getById($quotation_id);
if (!$q || (int)$q['status'] !== 2) {
http_response_code(400);
$answer['message'] = 'Quotation not found or not in Accepted status.';
exit(json_encode($answer));
}
$qt_items = $q['items'];
if (empty($qt_items)) {
http_response_code(400);
$answer['message'] = 'Quotation has no items.';
exit(json_encode($answer));
}
if ((float)$q['total_remaining'] <= 0.000001) {
http_response_code(400);
$answer['message'] = 'Quotation is already fully converted.';
exit(json_encode($answer));
}
@@ -61,6 +65,7 @@ foreach ($convert_items as $ci) {
if ($qty <= 0) continue;
if (!isset($qt_by_id[$item_id])) {
http_response_code(400);
$answer['message'] = "Item #{$item_id} not found in this quotation.";
exit(json_encode($answer));
}
@@ -70,6 +75,7 @@ foreach ($convert_items as $ci) {
if ($qty - $remaining > 0.000001) {
$name = $qi['product_name'] ?: $qi['product_sku'];
http_response_code(400);
$answer['message'] = "Cannot convert {$qty} for \"{$name}\": only {$remaining} remaining.";
exit(json_encode($answer));
}
@@ -95,6 +101,7 @@ foreach ($convert_items as $ci) {
}
if (empty($ord_items)) {
http_response_code(400);
$answer['message'] = 'No valid items to convert.';
exit(json_encode($answer));
}