File: //proc/self/root/proc/self/root/usr/local/lib/python3.9/site-packages/wordfence/util/validation.py
from typing import Optional, Any, Set
class ValidationException(Exception):
def __init__(self, key: list, message: str, value=None):
self.key = key
self.value = value
super().__init__(
self.get_key_as_string() +
': ' +
message +
', received: ' +
repr(value)
)
def get_key_as_string(self) -> str:
return '.'.join([str(component) for component in self.key])
class Validator:
def validate(self, data, parent_key: Optional[list] = None):
pass
def validate_type(self, key, value, expected_type) -> None:
if isinstance(expected_type, Validator):
expected_type.validate(value, key)
elif not isinstance(value, expected_type):
raise ValidationException(
key,
'Value must be of type ' + str(expected_type),
value
)
class DictionaryValidator(Validator):
def __init__(
self,
expected: Optional[dict] = None,
validator: Validator = None,
allow_empty: bool = False,
optional_keys: Optional[Set[str]] = None
):
self.expected = expected if expected is not None else dict()
self.validator = validator
self.allow_empty = allow_empty
self.optional_keys = optional_keys if optional_keys is not None else {}
def _validate_expected_fields(self, data: dict, parent_key: list) -> None:
for key, expected_type in self.expected.items():
aggregate_key = parent_key + [key]
try:
value = data[key]
self.validate_type(aggregate_key, value, expected_type)
except KeyError:
if key not in self.optional_keys:
raise ValidationException(aggregate_key, 'Key not present')
def _validate_all_fields(self, data: dict, parent_key: list) -> None:
if self.validator is None:
return
for key, value in data.items():
if key not in self.expected:
self.validator.validate(value, parent_key + [key])
def validate(self, data, parent_key: Optional[list] = None) -> None:
if parent_key is None:
parent_key = []
if not isinstance(data, dict):
raise ValidationException(
parent_key,
'Element must be a dictionary',
data
)
if self.allow_empty and len(data) == 0:
return
self._validate_expected_fields(data, parent_key)
self._validate_all_fields(data, parent_key)
def add_field(self, key: Any, expected):
self.expected[key] = expected
class ListValidator(Validator):
def __init__(self, expected):
self.expected = expected
def validate(self, data, parent_key: Optional[list] = None) -> None:
if parent_key is None:
parent_key = []
if not isinstance(data, list):
raise ValidationException(
parent_key,
'Element must be a list',
data
)
if isinstance(self.expected, dict):
for index, expected_type in self.expected.items():
key = parent_key + [index]
try:
value = data[index]
self.validate_type(key, data[index], expected_type)
except IndexError:
raise ValidationException(
key,
'Index does not exist in list'
)
else:
for index, value in enumerate(data):
self.validate_type(parent_key + [index], value, self.expected)
class AllowedValueValidator(Validator):
def __init__(self, allowed: set):
self.allowed = allowed
def validate(self, data, parent_key: Optional[list] = None) -> None:
for value in self.allowed:
if data == value:
return
raise ValidationException(
parent_key,
'Value is not in allowed set: ' + repr(data)
)
class OptionalValueValidator(Validator):
def __init__(self, expected):
self.expected = expected
def validate(self, data, parent_key: Optional[list] = None) -> None:
if data is None:
return
if parent_key is None:
parent_key = []
if isinstance(self.expected, Validator):
self.expected.validate(data, parent_key)
else:
self.validate_type(parent_key, data, self.expected)
class NumberValidator(Validator):
def __init__(self):
pass
def validate(self, data, parent_key: Optional[list] = None) -> None:
if isinstance(data, int) or isinstance(data, float):
return
raise ValidationException(
parent_key,
'Value is not a valid number: ' + repr(data)
)