updateproduct.php 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. <?php
  2. /**
  3. * dashboard/client-settings/updateproduct.php
  4. *
  5. * AJAX handler — updates a single cell in fertiliser_specifications.
  6. * Requires authentication + CSRF token.
  7. * Column name is validated against a strict whitelist to prevent injection.
  8. */
  9. require_once __DIR__ . '/../../config/database.php';
  10. require_once __DIR__ . '/../../lib/auth.php';
  11. require_once __DIR__ . '/../../lib/csrf.php';
  12. if (session_status() === PHP_SESSION_NONE) {
  13. session_start();
  14. }
  15. header('Content-Type: application/json');
  16. if (!isLoggedIn()) {
  17. http_response_code(401);
  18. echo json_encode(['error' => 'Unauthorised']);
  19. exit;
  20. }
  21. if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  22. http_response_code(405);
  23. echo json_encode(['error' => 'Method not allowed']);
  24. exit;
  25. }
  26. // CSRF check
  27. if (!verifyCsrfToken($_POST['csrf_token'] ?? '')) {
  28. http_response_code(403);
  29. echo json_encode(['error' => 'Invalid CSRF token']);
  30. exit;
  31. }
  32. // Whitelist of updatable columns — never allow id or modx_user_id
  33. $allowedColumns = ['n', 'p', 'k', 'Na', 'Ca', 'Mg', 'B', 'Zn', 'Cu', 'Mn', 'Fe', 'Co', 'Mo', 'name', 'chemical'];
  34. $column = $_POST['column'] ?? '';
  35. $id = (int) ($_POST['id'] ?? 0);
  36. $editval = $_POST['editval'] ?? '';
  37. if (!in_array($column, $allowedColumns, true)) {
  38. http_response_code(400);
  39. echo json_encode(['error' => 'Invalid column']);
  40. exit;
  41. }
  42. if ($id <= 0) {
  43. http_response_code(400);
  44. echo json_encode(['error' => 'Invalid record ID']);
  45. exit;
  46. }
  47. // Validate the value is numeric for nutrient columns
  48. $numericColumns = ['n', 'p', 'k', 'Na', 'Ca', 'Mg', 'B', 'Zn', 'Cu', 'Mn', 'Fe', 'Co', 'Mo'];
  49. if (in_array($column, $numericColumns, true) && $editval !== '' && !is_numeric($editval)) {
  50. http_response_code(400);
  51. echo json_encode(['error' => 'Value must be numeric']);
  52. exit;
  53. }
  54. // Verify the record belongs to the current user
  55. try {
  56. $pdo = getDBConnection();
  57. $userId = getCurrentUserId();
  58. $check = $pdo->prepare(
  59. 'SELECT id FROM fertiliser_specifications WHERE id = ? AND modx_user_id = ? LIMIT 1'
  60. );
  61. $check->execute([$id, $userId]);
  62. if (!$check->fetch()) {
  63. http_response_code(403);
  64. echo json_encode(['error' => 'Record not found or access denied']);
  65. exit;
  66. }
  67. // Column name is from whitelist — safe to interpolate as identifier
  68. $stmt = $pdo->prepare("UPDATE fertiliser_specifications SET `{$column}` = ? WHERE id = ?");
  69. $stmt->execute([$editval === '' ? null : $editval, $id]);
  70. echo json_encode(['success' => true]);
  71. } catch (PDOException $e) {
  72. error_log('updateproduct.php DB error: ' . $e->getMessage());
  73. http_response_code(500);
  74. echo json_encode(['error' => 'Database error']);
  75. }