Compare commits

...

6 commits

5 changed files with 188 additions and 122 deletions

8
app.py
View file

@ -12,6 +12,7 @@ import json
import util
from entity_validator import validate
startup_timestamp = datetime.now()
@ -74,12 +75,9 @@ class ValidateHandler(tornado.web.RequestHandler, metaclass=ABCMeta):
entity = self.request.body.decode()
# TODO call validator
validation_result = {
"valid": "true"
}
validation_result = validate(json.loads(entity))
self.write(validation_result)
self.write(json.dumps(validation_result))
self.finish()

103
entity_validator.py Normal file
View file

@ -0,0 +1,103 @@
#!/usr/bin/env python3
from cerberus import Validator
from validation_functions import *
def validate(entity):
schema_fin={
'bic': {
'type': 'string',
'required': True,
'check_with': valid_bic},
'iban': {
'type': 'string',
'required': True,
'check_with': valid_iban},
'issuance': {
'type': 'string',
'required': True,
'check_with': iso_date},
'reference': {'type': 'string'},
'scan-sepa-mandate': {'type': 'string'},
'holder': {'type': 'string'}}
schema_membership={
'bis': {
'type': 'string',
'oneof': [{'check_with': iso_date},{'empty': True}]},
'mitgliedsbeitrag': {
'type': 'string',
'check_with': valid_money_amount},
'scan-antrag': {'type': 'string'},
'schliessberechtigung': {
'type': 'string',
'allowed': ['Ja', 'Nein', 'J', 'N', 'j', 'n', 'y', 'Y']},
'spendenbeitrag': {
'type': 'string',
'check_with': valid_money_amount},
'status': {
'type': 'string',
'required': True,
'allowed': ['V', 'E', 'F']},
'von': {
'type': 'string',
'required': True,
'check_with': iso_date}}
schema_base={
'address_code': {
'type': 'string'},
'address_country': {
'type': 'string'},
'address_label': {
'type': 'string'},
'address_locality': {
'type': 'string'},
'address_region': {
'type': 'string'},
'address_street': {
'type': 'string'},
'birth_date': {
'type': 'string',
'required': True,
'check_with': iso_date},
'birth_location': {
'type': 'string'},
'email': {
'type': 'string',
'required': True,
'regex': '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$'},
'fullname': {
'type': 'string',
'required': True},
'nickname': {
'type': 'string'},
'pgp-key': {
'type': 'string'},
'ssh-key': {
'type': 'string'}}
schema = {
'finanzdaten': {
'type': 'dict',
'schema': schema_fin},
'mitgliederdaten': {
'type': 'dict',
'schema': schema_membership},
'stammdaten': {
'type': 'dict',
'schema': schema_base},
'id': {
'type': 'string',
'required': True,
'regex': '^[a-f0-9]{5}$'},
'timestamp': {
'type': 'string',
'required': True}
}
v = Validator()
result = {
'valid': v.validate(entity, schema),
'errors': v.errors}
return result

52
test.py
View file

@ -54,6 +54,58 @@ class TestValidation(tornado.testing.AsyncHTTPTestCase):
validation_result = json.loads(response.body.decode())
self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
self.assertFalse(validation_result['valid'], "Validation result is expected to be valid==false")
def test_valid_entity(self):
entity = {
'finanzdaten':
{
'bic': 'PBNKDEFFXXX',
'holder': '',
'iban': 'DE89370400440532013000',
'issuance': '2012-01-01',
'reference': '0042',
'scan-sepa-mandate': ''
},
'mitgliederdaten':
{
'bis': '',
'mitgliedsbeitrag': '30',
'scan-antrag': '',
'schliessberechtigung': 'Ja',
'spendenbeitrag': '0',
'status': 'V',
'von': '2012-01-01'
},
'stammdaten':
{
'address_code': '39104',
'address_country': 'DE',
'address_label': 'Max Hackerberg\nLeibnizstr. 32\n39104 Magdeburg',
'address_locality': 'Magdeburg',
'address_region': '',
'address_street': 'Leibnizstr. 32',
'birth_date': '1970-01-01',
'birth_location': 'Hackstadt',
'email': 'max.hackerberg@netz39.de',
'fullname': 'Max Hackerberg',
'nickname': 'maxH',
'pgp-key': '',
'ssh-key': ''
},
'timestamp': '2020-03-25T23:58:11',
'id': '6af68'
}
response = self.fetch('/v0/validate',
method='POST',
body=json.dumps(entity))
self.assertEqual(200, response.code, "Validation must always return 200")
validation_result = json.loads(response.body.decode())
self.assertIn('valid', validation_result, "Key 'valid' expected in validation result")
self.assertTrue(validation_result['valid'], "Validation result is expected to be valid==true")

View file

@ -1,117 +0,0 @@
#!/usr/bin/python3
import cerberus
from schwifty import IBAN, BIC
import datetime
def valid_iban(field, value, error):
try:
IBAN(value)
return True
except ValueError:
error(field, 'not a valid IBAN')
def valid_bic(field, value, error):
try:
BIC(value)
return True
except ValueError:
error(field, 'not a valid BIC')
def iso_date(field, value, error):
try:
datetime.datetime.strptime(value, "%Y-%m-%d")
return True
except ValueError:
error(field, 'not a valid ISO 8601 date')
def valid_money_amount(field, value, error):
try:
float(value)
return True
except (ValueError, TypeError):
error(field, 'not a valid money value')
document = {
'finanzdaten':
{
'bic': 'PBNKDEFFXXX',
'holder': '',
'iban': 'DE89370400440532013000',
'issuance': '2012-01-01',
'reference': '0042',
'scan-sepa-mandate': ''
},
'mitgliederdaten':
{
'bis': '',
'mitgliedsbeitrag': '30',
'scan-antrag': '',
'schliessberechtigung': 'Ja',
'spendenbeitrag': '0',
'status': 'V',
'von': '2012-01-01'
},
'stammdaten':
{
'address_code': '39104',
'address_country': 'DE',
'address_label': 'Max Hackerberg\nLeibnizstr. 32\n39104 Magdeburg',
'address_locality': 'Magdeburg',
'address_region': '',
'address_street': 'Leibnizstr. 32',
'birth_date': '1970-01-01',
'birth_location': 'Hackstadt',
'email': 'max.hackerberg@netz39.de',
'fullname': 'Max Hackerberg',
'nickname': 'maxH',
'pgp-key': '',
'ssh-key': ''
},
'timestamp': '2020-03-25T23:58:11',
'id': '6af68'
}
schema_fin={
'bic': {
'type': 'string',
'required': True,
'check_with': valid_bic},
'iban': {
'type': 'string',
'required': True,
'check_with': valid_iban},
'issuance': {
'type': 'string',
'required': True,
'check_with': iso_date},
'reference': {'type': 'string'},
'scan-sepa-mandate': {'type': 'string'},
'holder': {'type': 'string'}}
schema_member={'bis': {
'type': 'string',
'oneof': [{'check_with': iso_date},{'empty': True}]},
'mitgliedsbeitrag': {
'type': 'string',
'check_with': valid_money_amount},
'scan-antrag': {'type': 'string'},
'schliessberechtigung': {
'type': 'string',
'allowed': ['Ja', 'Nein', 'J', 'N', 'j', 'n', 'y', 'Y']},
'spendenbeitrag': {
'type': 'string',
'check_with': valid_money_amount},
'status': {
'type': 'string',
'allowed': ['V', 'E', 'F']},
'von': {
'type': 'string',
'required': True,
'check_with': iso_date}}
v = cerberus.Validator()
print(v.validate(document['finanzdaten'], schema_fin))
print(v.errors)
print(v.validate(document['mitgliederdaten'], schema_member))
print(v.errors)

30
validation_functions.py Normal file
View file

@ -0,0 +1,30 @@
from schwifty import IBAN, BIC
import datetime
def valid_iban(field, value, error):
try:
IBAN(value)
return True
except ValueError:
error(field, 'not a valid IBAN')
def valid_bic(field, value, error):
try:
BIC(value)
return True
except ValueError:
error(field, 'not a valid BIC')
def iso_date(field, value, error):
try:
datetime.datetime.strptime(value, "%Y-%m-%d")
return True
except ValueError:
error(field, 'not a valid ISO 8601 date')
def valid_money_amount(field, value, error):
try:
float(value)
return True
except (ValueError, TypeError):
error(field, 'not a valid money value')