mirror of https://github.com/nucypher/nucypher.git
Remove functionality for post requests for JsonApiCondition i.e. only HTTPS GET is allowed.
Revert "inputs" parameter back to "parameters".pull/3560/head
parent
788eb6f3ec
commit
c46219f1ba
|
@ -5,7 +5,6 @@ from jsonpath_ng.exceptions import JsonPathLexerError, JsonPathParserError
|
|||
from jsonpath_ng.ext import parse
|
||||
from marshmallow import ValidationError, fields, post_load, validate, validates
|
||||
from marshmallow.fields import Field, Url
|
||||
from marshmallow.validate import OneOf
|
||||
|
||||
from nucypher.policy.conditions.base import ExecutionCall
|
||||
from nucypher.policy.conditions.context import (
|
||||
|
@ -44,14 +43,10 @@ class JSONPathField(Field):
|
|||
|
||||
class JsonApiCall(ExecutionCall):
|
||||
TIMEOUT = 5 # seconds
|
||||
HTTP_METHOD_GET = "get"
|
||||
HTTP_METHOD_POST = "post"
|
||||
ALLOWED_METHODS = {HTTP_METHOD_GET, HTTP_METHOD_POST}
|
||||
|
||||
class Schema(ExecutionCall.Schema):
|
||||
endpoint = Url(required=True, relative=False, schemes=["https"])
|
||||
method = fields.Str(required=True, validate=OneOf(["get", "post"]))
|
||||
inputs = fields.Dict(required=False, allow_none=True)
|
||||
parameters = fields.Dict(required=False, allow_none=True)
|
||||
query = JSONPathField(required=False, allow_none=True)
|
||||
authorization_token = fields.Str(required=False, allow_none=True)
|
||||
|
||||
|
@ -69,14 +64,12 @@ class JsonApiCall(ExecutionCall):
|
|||
def __init__(
|
||||
self,
|
||||
endpoint: str,
|
||||
method: Optional[str] = HTTP_METHOD_GET,
|
||||
inputs: Optional[dict] = None,
|
||||
parameters: Optional[dict] = None,
|
||||
query: Optional[str] = None,
|
||||
authorization_token: Optional[str] = None,
|
||||
):
|
||||
self.endpoint = endpoint
|
||||
self.method = method
|
||||
self.inputs = inputs or {}
|
||||
self.parameters = parameters or {}
|
||||
self.query = query
|
||||
self.authorization_token = authorization_token
|
||||
|
||||
|
@ -95,7 +88,7 @@ class JsonApiCall(ExecutionCall):
|
|||
"""Fetches data from the endpoint."""
|
||||
resolved_endpoint = resolve_any_context_variables(self.endpoint, **context)
|
||||
|
||||
resolved_inputs = resolve_any_context_variables(self.inputs, **context)
|
||||
resolved_parameters = resolve_any_context_variables(self.parameters, **context)
|
||||
|
||||
headers = None
|
||||
if self.authorization_token:
|
||||
|
@ -105,22 +98,12 @@ class JsonApiCall(ExecutionCall):
|
|||
headers = {"Authorization": f"Bearer {resolved_authorization_token}"}
|
||||
|
||||
try:
|
||||
|
||||
if self.method == self.HTTP_METHOD_GET:
|
||||
response = requests.get(
|
||||
resolved_endpoint,
|
||||
params=resolved_inputs,
|
||||
timeout=self.timeout,
|
||||
headers=headers,
|
||||
)
|
||||
else:
|
||||
response = requests.post(
|
||||
resolved_endpoint,
|
||||
data=resolved_inputs,
|
||||
timeout=self.timeout,
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
response = requests.get(
|
||||
resolved_endpoint,
|
||||
params=resolved_parameters,
|
||||
timeout=self.timeout,
|
||||
headers=headers,
|
||||
)
|
||||
response.raise_for_status()
|
||||
except requests.exceptions.HTTPError as http_error:
|
||||
self.logger.error(f"HTTP error occurred: {http_error}")
|
||||
|
@ -204,9 +187,8 @@ class JsonApiCondition(ExecutionCallAccessControlCondition):
|
|||
self,
|
||||
endpoint: str,
|
||||
return_value_test: ReturnValueTest,
|
||||
method: Optional[str] = JsonApiCall.HTTP_METHOD_GET,
|
||||
query: Optional[str] = None,
|
||||
inputs: Optional[dict] = None,
|
||||
parameters: Optional[dict] = None,
|
||||
authorization_token: Optional[str] = None,
|
||||
condition_type: str = ConditionType.JSONAPI.value,
|
||||
name: Optional[str] = None,
|
||||
|
@ -214,9 +196,8 @@ class JsonApiCondition(ExecutionCallAccessControlCondition):
|
|||
super().__init__(
|
||||
endpoint=endpoint,
|
||||
return_value_test=return_value_test,
|
||||
method=method,
|
||||
query=query,
|
||||
inputs=inputs,
|
||||
parameters=parameters,
|
||||
authorization_token=authorization_token,
|
||||
condition_type=condition_type,
|
||||
name=name,
|
||||
|
@ -226,17 +207,13 @@ class JsonApiCondition(ExecutionCallAccessControlCondition):
|
|||
def endpoint(self):
|
||||
return self.execution_call.endpoint
|
||||
|
||||
@property
|
||||
def method(self):
|
||||
return self.execution_call.method
|
||||
|
||||
@property
|
||||
def query(self):
|
||||
return self.execution_call.query
|
||||
|
||||
@property
|
||||
def inputs(self):
|
||||
return self.execution_call.inputs
|
||||
def parameters(self):
|
||||
return self.execution_call.parameters
|
||||
|
||||
@property
|
||||
def timeout(self):
|
||||
|
|
|
@ -70,11 +70,11 @@ def lingo_with_all_condition_types(get_random_checksum_address):
|
|||
# JSON API
|
||||
"conditionType": ConditionType.JSONAPI.value,
|
||||
"endpoint": "https://api.example.com/data",
|
||||
"method": "get",
|
||||
"inputs": {
|
||||
"parameters": {
|
||||
"ids": "ethereum",
|
||||
"vs_currencies": "usd",
|
||||
},
|
||||
"authorizationToken": ":authToken",
|
||||
"query": "$.store.book[0].price",
|
||||
"returnValueTest": {
|
||||
"comparator": "==",
|
||||
|
|
|
@ -10,7 +10,6 @@ from nucypher.policy.conditions.exceptions import (
|
|||
)
|
||||
from nucypher.policy.conditions.lingo import ConditionLingo, ReturnValueTest
|
||||
from nucypher.policy.conditions.offchain import (
|
||||
JsonApiCall,
|
||||
JsonApiCondition,
|
||||
JSONPathField,
|
||||
)
|
||||
|
@ -36,7 +35,6 @@ def test_jsonpath_field_invalid():
|
|||
def test_json_api_condition_initialization():
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
)
|
||||
|
@ -52,7 +50,6 @@ def test_json_api_condition_invalid_type():
|
|||
_ = JsonApiCondition(
|
||||
condition_type="INVALID_TYPE",
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
)
|
||||
|
@ -62,17 +59,6 @@ def test_https_enforcement():
|
|||
with pytest.raises(InvalidCondition, match="Not a valid URL"):
|
||||
_ = JsonApiCondition(
|
||||
endpoint="http://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
)
|
||||
|
||||
|
||||
def test_https_method_enforcement():
|
||||
with pytest.raises(InvalidCondition, match="Must be one of: get, post"):
|
||||
_ = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method="head",
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
)
|
||||
|
@ -82,7 +68,6 @@ def test_invalid_authorization_token():
|
|||
with pytest.raises(InvalidCondition, match="Invalid value for authorization token"):
|
||||
_ = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
authorization_token="1234", # doesn't make sense hardcoding the token
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
|
@ -96,7 +81,6 @@ def test_json_api_condition_with_primitive_response(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
return_value_test=ReturnValueTest("==", 1),
|
||||
)
|
||||
success, result = condition.verify()
|
||||
|
@ -110,7 +94,6 @@ def test_json_api_condition_fetch(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].title",
|
||||
return_value_test=ReturnValueTest("==", "'Test Title'"),
|
||||
)
|
||||
|
@ -126,7 +109,6 @@ def test_json_api_condition_fetch_failure(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 1),
|
||||
)
|
||||
|
@ -134,21 +116,19 @@ def test_json_api_condition_fetch_failure(mocker):
|
|||
condition.execution_call._fetch()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("method_name", JsonApiCall.ALLOWED_METHODS)
|
||||
def test_json_api_condition_verify(mocker, method_name):
|
||||
def test_json_api_condition_verify(mocker):
|
||||
mock_response = mocker.Mock(status_code=200)
|
||||
mock_response.json.return_value = {"store": {"book": [{"price": 1}]}}
|
||||
mocked_method = mocker.patch(f"requests.{method_name}", return_value=mock_response)
|
||||
mocked_method = mocker.patch("requests.get", return_value=mock_response)
|
||||
|
||||
inputs = {
|
||||
parameters = {
|
||||
"arg1": "val1",
|
||||
"arg2": "val2",
|
||||
}
|
||||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
inputs=inputs,
|
||||
method=method_name,
|
||||
parameters=parameters,
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 1),
|
||||
)
|
||||
|
@ -158,10 +138,7 @@ def test_json_api_condition_verify(mocker, method_name):
|
|||
|
||||
# check that appropriate kwarg used for respective http method
|
||||
assert mocked_method.call_count == 1
|
||||
if method_name == JsonApiCall.HTTP_METHOD_GET:
|
||||
assert mocked_method.call_args.kwargs["params"] == inputs
|
||||
else:
|
||||
assert mocked_method.call_args.kwargs["data"] == inputs
|
||||
assert mocked_method.call_args.kwargs["params"] == parameters
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -184,7 +161,6 @@ def test_json_api_condition_verify_strings(json_return, value_test, mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].text",
|
||||
return_value_test=ReturnValueTest("==", f"{value_test}"),
|
||||
)
|
||||
|
@ -200,7 +176,6 @@ def test_json_api_condition_verify_invalid_json(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 2),
|
||||
)
|
||||
|
@ -221,7 +196,6 @@ def test_non_json_response(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[0].price",
|
||||
return_value_test=ReturnValueTest("==", 18),
|
||||
)
|
||||
|
@ -242,8 +216,7 @@ def test_basic_json_api_condition_evaluation_with_parameters(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.coingecko.com/api/v3/simple/price",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
inputs={
|
||||
parameters={
|
||||
"ids": "ethereum",
|
||||
"vs_currencies": "usd",
|
||||
},
|
||||
|
@ -265,8 +238,7 @@ def test_json_api_condition_evaluation_with_auth_token(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.coingecko.com/api/v3/simple/price",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
inputs={
|
||||
parameters={
|
||||
"ids": "ethereum",
|
||||
"vs_currencies": "usd",
|
||||
},
|
||||
|
@ -296,8 +268,7 @@ def test_json_api_condition_evaluation_with_various_context_variables(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.coingecko.com/api/:version/simple/:endpointPath",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
inputs={
|
||||
parameters={
|
||||
"ids": "ethereum",
|
||||
"vs_currencies": ":vsCurrency",
|
||||
},
|
||||
|
@ -333,8 +304,7 @@ def test_json_api_condition_from_lingo_expression():
|
|||
lingo_dict = {
|
||||
"conditionType": "json-api",
|
||||
"endpoint": "https://api.example.com/data",
|
||||
"method": f"{JsonApiCall.HTTP_METHOD_GET}",
|
||||
"inputs": {
|
||||
"parameters": {
|
||||
"ids": "ethereum",
|
||||
"vs_currencies": "usd",
|
||||
},
|
||||
|
@ -358,8 +328,7 @@ def test_json_api_condition_from_lingo_expression_with_authorization():
|
|||
lingo_dict = {
|
||||
"conditionType": "json-api",
|
||||
"endpoint": "https://api.example.com/data",
|
||||
"method": f"{JsonApiCall.HTTP_METHOD_POST}",
|
||||
"inputs": {
|
||||
"parameters": {
|
||||
"ids": "ethereum",
|
||||
"vs_currencies": "usd",
|
||||
},
|
||||
|
@ -388,7 +357,6 @@ def test_ambiguous_json_path_multiple_results(mocker):
|
|||
|
||||
condition = JsonApiCondition(
|
||||
endpoint="https://api.example.com/data",
|
||||
method=JsonApiCall.HTTP_METHOD_GET,
|
||||
query="$.store.book[*].price",
|
||||
return_value_test=ReturnValueTest("==", 1),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue