fix: reject nested project write values
This commit is contained in:
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from collections.abc import Set as AbstractSet
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, Mapping, Sequence
|
from typing import Any, Callable, Mapping, Sequence
|
||||||
|
|
||||||
@@ -95,8 +96,7 @@ class NbClient:
|
|||||||
values: Mapping[str, Any],
|
values: Mapping[str, Any],
|
||||||
whitelist: Sequence[str],
|
whitelist: Sequence[str],
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
if not values:
|
self._validate_scalar_values(values)
|
||||||
raise ValueError("values must not be empty")
|
|
||||||
command = self._resource_command("create", resource)
|
command = self._resource_command("create", resource)
|
||||||
self._append_json(command, "--values", values)
|
self._append_json(command, "--values", values)
|
||||||
self._append_repeated(command, "--whitelist", whitelist)
|
self._append_repeated(command, "--whitelist", whitelist)
|
||||||
@@ -109,8 +109,7 @@ class NbClient:
|
|||||||
values: Mapping[str, Any],
|
values: Mapping[str, Any],
|
||||||
whitelist: Sequence[str],
|
whitelist: Sequence[str],
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
if not values:
|
self._validate_scalar_values(values)
|
||||||
raise ValueError("values must not be empty")
|
|
||||||
command = self._resource_command("update", resource)
|
command = self._resource_command("update", resource)
|
||||||
self._append_json_or_scalar(command, "--filter-by-tk", record_id)
|
self._append_json_or_scalar(command, "--filter-by-tk", record_id)
|
||||||
self._append_json(command, "--values", values)
|
self._append_json(command, "--values", values)
|
||||||
@@ -301,3 +300,11 @@ class NbClient:
|
|||||||
if value is None or value == "":
|
if value is None or value == "":
|
||||||
return
|
return
|
||||||
command.extend([flag, str(value)])
|
command.extend([flag, str(value)])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_scalar_values(values: Mapping[str, Any]) -> None:
|
||||||
|
if not values:
|
||||||
|
raise ValueError("values must not be empty")
|
||||||
|
for field, value in values.items():
|
||||||
|
if isinstance(value, (Mapping, list, AbstractSet, tuple)):
|
||||||
|
raise ValueError(f"values[{field!r}] must be scalar")
|
||||||
|
|||||||
@@ -132,6 +132,31 @@ class NbClientTests(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(commands, [])
|
self.assertEqual(commands, [])
|
||||||
|
|
||||||
|
def test_record_writes_reject_nested_values_without_running_command(self) -> None:
|
||||||
|
commands: list[list[str]] = []
|
||||||
|
|
||||||
|
def runner(cmd, **kwargs):
|
||||||
|
commands.append(cmd)
|
||||||
|
return subprocess.CompletedProcess(cmd, 0, stdout='{"data":{}}', stderr="")
|
||||||
|
|
||||||
|
client = NbClient(env_name="nb-mcp", runner=runner)
|
||||||
|
nested_values = [
|
||||||
|
{"client": {"id": 3}},
|
||||||
|
{"client_ids": [3]},
|
||||||
|
{"client_ids": {3}},
|
||||||
|
{"client_ids": (3,)},
|
||||||
|
]
|
||||||
|
|
||||||
|
for values in nested_values:
|
||||||
|
with self.subTest(operation="create", values=values):
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
client.create_record("t_projects", values, list(values))
|
||||||
|
with self.subTest(operation="update", values=values):
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
client.update_record("t_projects", 7, values, list(values))
|
||||||
|
|
||||||
|
self.assertEqual(commands, [])
|
||||||
|
|
||||||
def test_list_collection_fields_uses_data_modeling_command(self) -> None:
|
def test_list_collection_fields_uses_data_modeling_command(self) -> None:
|
||||||
commands: list[list[str]] = []
|
commands: list[list[str]] = []
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user