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));
}
+2
View File
@@ -10,11 +10,13 @@ $action = $data['action'] ?? '';
$data['items'] = json_decode($data['items'] ?? '[]', true) ?: [];
if (!in_array($action, ['create', 'update'], true)) {
http_response_code(400);
$answer['message'] = 'Unknown action';
exit(json_encode($answer));
}
if (empty($data['items'])) {
http_response_code(400);
$answer['message'] = 'At least one item is required';
exit(json_encode($answer));
}
@@ -7,8 +7,13 @@ try {
$quotation = new QuotationManager($pdo2, $company_id);
$answer['output'] = $quotation->getStats();
$answer['success'] = 1;
} catch (PDOException $e) {
error_log('[' . basename(__FILE__) . '] ' . $e->getMessage());
$answer['message'] = 'Database error, please try again.';
http_response_code(500);
} catch (Exception $e) {
$answer['message'] = $e->getMessage();
http_response_code(400);
}
exit(json_encode($answer));
@@ -9,6 +9,7 @@ $id = (int)($data['id'] ?? 0);
$action = $data['action_type'] ?? '';
if (!$id || !$action) {
http_response_code(400);
$answer['message'] = 'ID and action are required.';
exit(json_encode($answer));
}