mirror of https://github.com/nucypher/nucypher.git
Ensure that the underlying marshmallow schema ValidationError is not propagated but gets reraised as InvalidConditionLingo.
parent
ff57ca1bc9
commit
c4b217e223
|
@ -3,9 +3,12 @@ from abc import ABC, abstractmethod
|
|||
from base64 import b64decode, b64encode
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
from marshmallow import Schema
|
||||
from marshmallow import Schema, ValidationError
|
||||
|
||||
from nucypher.policy.conditions.exceptions import InvalidCondition
|
||||
from nucypher.policy.conditions.exceptions import (
|
||||
InvalidCondition,
|
||||
InvalidConditionLingo,
|
||||
)
|
||||
|
||||
|
||||
class _Serializable:
|
||||
|
@ -62,3 +65,17 @@ class AccessControlCondition(_Serializable, ABC):
|
|||
errors = cls.Schema().validate(data=data)
|
||||
if errors:
|
||||
raise InvalidCondition(f"Invalid {cls.__name__}: {errors}")
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data) -> "_Serializable":
|
||||
try:
|
||||
return super().from_dict(data)
|
||||
except ValidationError as e:
|
||||
raise InvalidConditionLingo(f"Invalid condition grammar: {e}")
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, data) -> "_Serializable":
|
||||
try:
|
||||
return super().from_json(data)
|
||||
except ValidationError as e:
|
||||
raise InvalidConditionLingo(f"Invalid condition grammar: {e}")
|
||||
|
|
|
@ -3,7 +3,7 @@ import re
|
|||
from http import HTTPStatus
|
||||
from typing import Dict, NamedTuple, Optional, Tuple, Type, Union
|
||||
|
||||
from marshmallow import Schema, ValidationError, post_dump
|
||||
from marshmallow import Schema, post_dump
|
||||
from web3.providers import BaseProvider
|
||||
|
||||
from nucypher.policy.conditions.exceptions import (
|
||||
|
@ -135,14 +135,6 @@ def evaluate_condition_lingo(
|
|||
error = EvalError(
|
||||
"Decryption conditions not satisfied", HTTPStatus.FORBIDDEN
|
||||
)
|
||||
except ValidationError as e:
|
||||
# marshmallow Validation Error
|
||||
# TODO get this to always be InvalidConditionInfo/InvalidCondition
|
||||
# so that this block can be removed
|
||||
error = EvalError(
|
||||
f"Invalid condition grammar: {e}",
|
||||
HTTPStatus.BAD_REQUEST,
|
||||
)
|
||||
except ReturnValueEvaluationError as e:
|
||||
error = EvalError(
|
||||
f"Unable to evaluate return value: {e}",
|
||||
|
|
|
@ -46,8 +46,7 @@ def test_invalid_condition():
|
|||
}
|
||||
],
|
||||
}
|
||||
# TODO - see if I can customize this error
|
||||
with pytest.raises(ValidationError):
|
||||
with pytest.raises(InvalidConditionLingo):
|
||||
ConditionLingo.from_dict(invalid_operator_position_lingo)
|
||||
|
||||
|
||||
|
|
|
@ -69,6 +69,14 @@ def test_evaluate_condition_exception_cases(
|
|||
assert eval_error.status_code == expected_status_code
|
||||
|
||||
|
||||
def test_evaluate_condition_invalid_lingo():
|
||||
eval_error = evaluate_condition_lingo(
|
||||
condition_lingo={"dont_mind_me": "nothing_to_see_here"}
|
||||
) # provider and context default to empty dicts
|
||||
assert "Invalid condition grammar" in eval_error.message
|
||||
assert eval_error.status_code == HTTPStatus.BAD_REQUEST
|
||||
|
||||
|
||||
def test_evaluate_condition_eval_returns_false():
|
||||
condition_lingo = Mock()
|
||||
condition_lingo.eval.return_value = False
|
||||
|
@ -155,7 +163,7 @@ def test_condition_lingo_validation(compound_lingo):
|
|||
validate_condition_lingo(compound_lingo_dict)
|
||||
|
||||
invalid_operator_lingo = {
|
||||
"operator": "AND_OPERATOR",
|
||||
"operator": "AND_OPERATOR", # invalid operator
|
||||
"operands": [
|
||||
{
|
||||
"returnValueTest": {"value": 0, "comparator": ">"},
|
||||
|
@ -172,6 +180,6 @@ def test_condition_lingo_validation(compound_lingo):
|
|||
with pytest.raises(InvalidCondition):
|
||||
validate_condition_lingo(invalid_operator_lingo)
|
||||
|
||||
# invalid condition
|
||||
# type of condition is unknown
|
||||
with pytest.raises(InvalidConditionLingo):
|
||||
validate_condition_lingo({"dont_mind_me": "nothing_to_see_here"})
|
||||
|
|
Loading…
Reference in New Issue