Ensure that the underlying marshmallow schema ValidationError is not propagated but gets reraised as InvalidConditionLingo.

pull/3140/head
derekpierre 2023-06-12 09:17:59 -04:00
parent ff57ca1bc9
commit c4b217e223
4 changed files with 31 additions and 15 deletions

View File

@ -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}")

View File

@ -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}",

View File

@ -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)

View File

@ -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"})