Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPNLPF-2192: Outgoing message validation #185

Open
wants to merge 1 commit into
base: release/3.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions smart_kit/message/as_is_to_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@


class AsIsToMessage(SmartAppToMessage):
@property
def message_name(self) -> str:
return self.command.name

@property
def incremental_id(self) -> int:
return self.incoming_message.incremental_id

@cached_property
def as_dict(self):
Expand Down
2 changes: 1 addition & 1 deletion smart_kit/message/validators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
def get_validators_from_settings(validator_group: str, settings: Settings, model: SmartAppModel) \
-> List[BaseMessageValidator]:
validators = settings["template_settings"].get("validators", {})
return [dynamic_import_object(e["class"])(resources=model.resources, **e["params"])
return [dynamic_import_object(e["class"])(validator_group=validator_group, resources=model.resources, **e["params"])
for e in validators.get(validator_group, [])]
12 changes: 10 additions & 2 deletions smart_kit/message/validators/json_schema_validator.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from __future__ import annotations

from pathlib import Path
from typing import Callable, TYPE_CHECKING
from typing import Callable, TYPE_CHECKING, Optional
import jsonschema
from jsonschema.validators import RefResolver

from core.message.message import SmartAppMessage
from core.logging.logger_utils import log
from core.message.validators.base_validator import OnException
from smart_kit.message.validators.base_validator_with_resources import BaseMessageValidatorWithResources
from smart_kit.resources import SmartAppResources

if TYPE_CHECKING:
from core.message.from_message import SmartAppFromMessage
Expand All @@ -16,10 +18,16 @@
class JSONSchemaValidator(BaseMessageValidatorWithResources):
VALIDATOR_EXCEPTION = jsonschema.ValidationError

def __init__(self, validator_group: str = "incoming",
resources: Optional[SmartAppResources] = None,
on_exception: OnException = "raise", *args, **kwargs):
self._message_type = validator_group if validator_group in ("incoming", "outgoing") else "incoming"
super().__init__(resources, on_exception, *args, **kwargs)

def _update_resources(self):
self._store = self.resources.get("payload_schema")
self._schemas = {Path(k).stem: self._compile_schema(k, v) for k, v in self._store.items()
if len(Path(k).parents) == 1}
if k.startswith(f"/{self._message_type}/")}

def _compile_schema(self, uri: str, schema: dict) -> Callable[[dict], None]:
cls = jsonschema.validators.validator_for(schema)
Expand Down
4 changes: 2 additions & 2 deletions smart_kit/start_points/base_main_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def __init__(
self.postprocessor = postprocessor_cls()
self.db_adapter = self.get_db()
self.is_work = True
self.from_msg_validators = get_validators_from_settings("from", settings, model)
self.to_msg_validators = get_validators_from_settings("to", settings, model)
self.from_msg_validators = get_validators_from_settings("incoming", settings, model)
self.to_msg_validators = get_validators_from_settings("outgoing", settings, model)

template_settings = self.settings["template_settings"]
save_tries = template_settings.get("user_save_collisions_tries", 0)
Expand Down
2 changes: 1 addition & 1 deletion smart_kit/testing/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def process_message(self, raw_message: Dict, headers: tuple = ()) -> Tuple[Any,
masking_fields = self.settings["template_settings"].get("masking_fields")
message = SmartAppFromMessage(
raw_message, headers=headers, masking_fields=masking_fields,
validators=get_validators_from_settings("from", self.settings, self.app_model)
validators=get_validators_from_settings("incoming", self.settings, self.app_model)
)
user = self.__user_cls(self.environment.user_id, message, self.user_data, self.settings,
self.app_model.scenario_descriptions,
Expand Down
18 changes: 14 additions & 4 deletions smart_kit/testing/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ async def _run(self) -> bool:

callbacks = {}
app_callback_id = None

incoming_message_validators = get_validators_from_settings("incoming", self.settings, self.app_model)
outgoing_message_validators = get_validators_from_settings("outgoing", self.settings, self.app_model)
for index, raw_msg in enumerate(self.messages):
print('Шаг', index)
if index and self.interactive:
Expand Down Expand Up @@ -239,7 +242,7 @@ async def _run(self) -> bool:

message = self.create_message(
request, headers=headers,
validators=get_validators_from_settings("from", self.settings, self.app_model)
validators=incoming_message_validators
)

if not message.validate():
Expand All @@ -255,7 +258,14 @@ async def _run(self) -> bool:
self.post_setup_user(user)

commands = [command async for command in self.app_model.answer(message, user)]
answers = self._generate_answers(user=user, commands=commands, message=message)
answers = self._generate_answers(user=user, commands=commands, message=message,
validators=outgoing_message_validators)

for answer in answers:
if not answer.validate():
print(f"[!] Outgoing message {answer.message_name} validation failed.")
return False

answers.extend(self._generate_history_answers(user, message))

predefined_fields_resp = response.get("predefined_fields")
Expand Down Expand Up @@ -285,15 +295,15 @@ async def run(self) -> bool:
finally:
self.finalize()

def _generate_answers(self, user, commands, message):
def _generate_answers(self, user, commands, message, validators):
answers = []
commands = commands or []

commands = combine_commands(commands, user)

for command in commands:
request = SmartKitKafkaRequest(id=None, items=command.request_data)
answer = SmartAppToMessage(command=command, message=message, request=request)
answer = SmartAppToMessage(command=command, message=message, request=request, validators=validators)
answers.append(answer)
return answers

Expand Down
Loading