mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-28 23:01:44 +00:00
fix: process list patch values in http requests
This commit parses values from post request as well as always serializes values for the web interface
This commit is contained in:
@ -163,7 +163,7 @@
|
|||||||
const variableValueInput = document.createElement("input");
|
const variableValueInput = document.createElement("input");
|
||||||
variableValueInput.classList.add("form-control");
|
variableValueInput.classList.add("form-control");
|
||||||
variableValueInput.readOnly = true;
|
variableValueInput.readOnly = true;
|
||||||
variableValueInput.value = variable.value;
|
variableValueInput.value = JSON.stringify(variable.value);
|
||||||
|
|
||||||
const variableButtonRemove = document.createElement("button");
|
const variableButtonRemove = document.createElement("button");
|
||||||
variableButtonRemove.type = "button";
|
variableButtonRemove.type = "button";
|
||||||
|
@ -100,11 +100,11 @@ class PkgbuildPatch:
|
|||||||
return cls(**filter_json(dump, known_fields))
|
return cls(**filter_json(dump, known_fields))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, key: str | None, source: str) -> Self:
|
def parse(cls, key: str | None, source: str | list[str]) -> Self:
|
||||||
"""
|
"""
|
||||||
parse string value to the PKGBUILD patch value. This method simply takes string, tries to identify it as array
|
parse string value to the PKGBUILD patch value. This method simply takes string, tries to identify it as array
|
||||||
or just string and return the respective value. Functions are returned as is. Shell arrays and single values
|
or just string and return the respective value. Functions are returned as is. Shell arrays and single values
|
||||||
are returned without quotes
|
are returned without quotes. If source is ``list``, then value is returned as is
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key(str | None): variable key
|
key(str | None): variable key
|
||||||
@ -118,6 +118,9 @@ class PkgbuildPatch:
|
|||||||
case function if key is not None and key.endswith("()"):
|
case function if key is not None and key.endswith("()"):
|
||||||
# the key looks like a function, no further processing should be applied here
|
# the key looks like a function, no further processing should be applied here
|
||||||
return function
|
return function
|
||||||
|
case list():
|
||||||
|
# do not try to perform operations on the list, just return as is
|
||||||
|
return source
|
||||||
case shell_array if shell_array.startswith("(") and shell_array.endswith(")"):
|
case shell_array if shell_array.startswith("(") and shell_array.endswith(")"):
|
||||||
# the source value looks like shell array, remove brackets and parse with shlex
|
# the source value looks like shell array, remove brackets and parse with shlex
|
||||||
return shlex.split(shell_array[1:-1])
|
return shlex.split(shell_array[1:-1])
|
||||||
|
@ -101,6 +101,6 @@ class PatchesView(StatusViewGuard, BaseView):
|
|||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
raise HTTPBadRequest(reason=str(ex))
|
raise HTTPBadRequest(reason=str(ex))
|
||||||
|
|
||||||
self.service().package_patches_update(package_base, PkgbuildPatch(key, value))
|
self.service().package_patches_update(package_base, PkgbuildPatch.parse(key, value))
|
||||||
|
|
||||||
raise HTTPNoContent
|
raise HTTPNoContent
|
||||||
|
@ -68,7 +68,7 @@ class AddView(BaseView):
|
|||||||
try:
|
try:
|
||||||
data = await self.request.json()
|
data = await self.request.json()
|
||||||
packages = self.get_non_empty(lambda key: [package for package in data[key] if package], "packages")
|
packages = self.get_non_empty(lambda key: [package for package in data[key] if package], "packages")
|
||||||
patches = [PkgbuildPatch(patch["key"], patch.get("value", "")) for patch in data.get("patches", [])]
|
patches = [PkgbuildPatch.parse(patch["key"], patch.get("value", "")) for patch in data.get("patches", [])]
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
raise HTTPBadRequest(reason=str(ex))
|
raise HTTPBadRequest(reason=str(ex))
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class RequestView(BaseView):
|
|||||||
try:
|
try:
|
||||||
data = await self.request.json()
|
data = await self.request.json()
|
||||||
packages = self.get_non_empty(lambda key: [package for package in data[key] if package], "packages")
|
packages = self.get_non_empty(lambda key: [package for package in data[key] if package], "packages")
|
||||||
patches = [PkgbuildPatch(patch["key"], patch.get("value", "")) for patch in data.get("patches", [])]
|
patches = [PkgbuildPatch.parse(patch["key"], patch.get("value", "")) for patch in data.get("patches", [])]
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
raise HTTPBadRequest(reason=str(ex))
|
raise HTTPBadRequest(reason=str(ex))
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ def test_parse() -> None:
|
|||||||
assert PkgbuildPatch.parse("key", """("QU'OUTED" ARRAY VALUE)""").value == ["QU'OUTED", "ARRAY", "VALUE"]
|
assert PkgbuildPatch.parse("key", """("QU'OUTED" ARRAY VALUE)""").value == ["QU'OUTED", "ARRAY", "VALUE"]
|
||||||
assert PkgbuildPatch.parse("key()", """{ function with " quotes }""").value == """{ function with " quotes }"""
|
assert PkgbuildPatch.parse("key()", """{ function with " quotes }""").value == """{ function with " quotes }"""
|
||||||
assert PkgbuildPatch.parse("key", json.dumps(["array", "value"])).value == ["array", "value"]
|
assert PkgbuildPatch.parse("key", json.dumps(["array", "value"])).value == ["array", "value"]
|
||||||
|
assert PkgbuildPatch.parse("key", ["array", "value"]).value == ["array", "value"]
|
||||||
|
|
||||||
|
|
||||||
def test_quote() -> None:
|
def test_quote() -> None:
|
||||||
|
@ -82,6 +82,25 @@ async def test_post_full_diff(client: TestClient, package_ahriman: Package) -> N
|
|||||||
assert patches == [payload]
|
assert patches == [payload]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_post_array(client: TestClient, package_ahriman: Package) -> None:
|
||||||
|
"""
|
||||||
|
must create patch from list variable
|
||||||
|
"""
|
||||||
|
await client.post(f"/api/v1/packages/{package_ahriman.base}",
|
||||||
|
json={"status": BuildStatusEnum.Success.value, "package": package_ahriman.view()})
|
||||||
|
request_schema = pytest.helpers.schema_request(PatchesView.post)
|
||||||
|
|
||||||
|
payload = {"key": "k", "value": "(array value)"}
|
||||||
|
assert not request_schema.validate(payload)
|
||||||
|
response = await client.post(f"/api/v1/packages/{package_ahriman.base}/patches", json=payload)
|
||||||
|
assert response.status == 204
|
||||||
|
|
||||||
|
response = await client.get(f"/api/v1/packages/{package_ahriman.base}/patches")
|
||||||
|
patches = await response.json()
|
||||||
|
parsed = [PkgbuildPatch(patch["key"], patch["value"]) for patch in patches]
|
||||||
|
assert parsed == [PkgbuildPatch("k", ["array", "value"])]
|
||||||
|
|
||||||
|
|
||||||
async def test_post_exception(client: TestClient, package_ahriman: Package) -> None:
|
async def test_post_exception(client: TestClient, package_ahriman: Package) -> None:
|
||||||
"""
|
"""
|
||||||
must raise exception on invalid payload
|
must raise exception on invalid payload
|
||||||
|
Reference in New Issue
Block a user