Browse Source

Implemented incoming data validation with JSON schema

tags/v0.1^2
Ivan Golikov 2 months ago
parent
commit
852bbc548b
9 changed files with 103 additions and 2 deletions
  1. +2
    -0
      .gitignore
  2. +1
    -0
      MANIFEST.in
  3. +0
    -0
      keeper/service/notification/__init__.py
  4. +21
    -0
      keeper/service/notification/schema.json
  5. +19
    -0
      keeper/service/notification/validator.py
  6. +1
    -1
      keeper/service/notification/writer.py
  7. +3
    -0
      setup.cfg
  8. +1
    -1
      tests/test_storage.py
  9. +55
    -0
      tests/test_validation.py

+ 2
- 0
.gitignore View File

@@ -4,5 +4,7 @@ venv/
__pycache__/
dist/
*.egg-info/
build/
.coverage

hook.conf

+ 1
- 0
MANIFEST.in View File

@@ -0,0 +1 @@
include keeper/service/notification/schema.json

+ 0
- 0
keeper/service/notification/__init__.py View File


+ 21
- 0
keeper/service/notification/schema.json View File

@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"datetime": {
"type": "string",
"format": "date-time"
},
"type": {
"type": "string",
"enum": ["alert", "error", "warning", "notice", "info", "debug"]
},
"message": {
"type": "string"
}
},
"required": ["id", "datetime", "type", "message"]
}

+ 19
- 0
keeper/service/notification/validator.py View File

@@ -0,0 +1,19 @@
import json
from jsonschema import (
Draft7Validator,
FormatChecker,
)
import pkg_resources

_schema_file = pkg_resources.resource_stream('keeper.service.notification', 'schema.json')
_schema = json.load(_schema_file)

_checker = FormatChecker()
_validator = Draft7Validator(schema=_schema, format_checker=_checker)


def validate_incoming_notification(notification: dict):
messages = [err.message for err in _validator.iter_errors(notification)]
is_valid = not bool(messages)

return is_valid, messages

keeper/service/writer.py → keeper/service/notification/writer.py View File

@@ -4,7 +4,7 @@ from flask import (
current_app,
)

from .lib import (
from ..lib import (
Singleton,
)


+ 3
- 0
setup.cfg View File

@@ -6,6 +6,9 @@ version = 0.1
packages = find:
install_requires =
flask~=2.0.1
jsonschema~=3.2.0
rfc3339-validator~=0.1.4
include_package_data = True

[options.extras_require]
test =


+ 1
- 1
tests/test_storage.py View File

@@ -7,7 +7,7 @@ from flask import (
from keeper.service.enums import (
NotificationTypeEnum,
)
from keeper.service.writer import (
from keeper.service.notification.writer import (
CsvNotificationWriter,
)



+ 55
- 0
tests/test_validation.py View File

@@ -0,0 +1,55 @@
from keeper.service.notification.validator import (
validate_incoming_notification,
)


def test_validate_notification():
valid_id = 1
invalid_id = '1'
valid_date = '2021-07-03T13:00:00.000+03:00'
invalid_date = '2021-07-03'
valid_type = 'info'
invalid_type = 'inf'
valid_message = 'Ff'
invalid_message = None

test_data_and_expectations = [
{
'data': {'id': valid_id, 'datetime': valid_date, 'type': valid_type, 'message': valid_message},
'result': True,
'messages': [],
},
{
'data': {},
'result': False,
'messages': [
"'id' is a required property",
"'datetime' is a required property",
"'type' is a required property",
"'message' is a required property",
],
},
{
'data': {'id': invalid_id, 'datetime': invalid_date, 'type': invalid_type, 'message': invalid_message},
'result': False,
'messages': [
"is not of type 'integer'",
"is not a 'date-time'",
"is not one of ['alert', 'error', 'warning', 'notice', 'info', 'debug']",
"is not of type 'string'",
]
}
]

for example_notification in test_data_and_expectations:
data = example_notification['data']
expected_result = example_notification['result']
expected_messages = example_notification['messages']

result, messages = validate_incoming_notification(data)

assert result == expected_result
assert len(expected_messages) == len(messages), "Got wrong number of validation error messages"

for msg in expected_messages:
assert any(msg in m for m in messages), f"Can't find error message by pattern {msg}"

Loading…
Cancel
Save