98 lines
3.4 KiB
Python
98 lines
3.4 KiB
Python
#! /usr/bin/env python3
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from helper import list_profiles, build_rules_filename, build_database_filename
|
|
from schwifty import IBAN
|
|
import sys
|
|
import click
|
|
import os
|
|
import yaml
|
|
import re
|
|
import colorful as cf
|
|
|
|
try:
|
|
from yaml import CLoader as Loader, CDumper as Dumper
|
|
except ImportError:
|
|
from yaml import Loader, Dumper
|
|
|
|
ALLOWED_KEYS = ["name", "tags", "iban", "description"]
|
|
TAGS_REGEXP = re.compile(r'[\w]+(?:,\s{0,1}[\w]+)*')
|
|
|
|
def verbose_print(text, verbose):
|
|
if verbose:
|
|
print(text)
|
|
|
|
|
|
@click.command(name="validate")
|
|
@click.option("--verbose", "-v", default=False, is_flag=True)
|
|
def command(verbose):
|
|
for profile in list_profiles():
|
|
print(f"Checking {profile}:")
|
|
db_path = build_database_filename(profile)
|
|
rules_path = build_rules_filename(profile)
|
|
|
|
# Rules
|
|
if os.path.exists(rules_path) and os.path.isfile(rules_path):
|
|
with open(rules_path) as fh:
|
|
data = yaml.load(fh, Loader=Loader)
|
|
|
|
if not data:
|
|
print(cf.green(" Ruleset is empty"))
|
|
else:
|
|
errors = 0
|
|
for rule in data:
|
|
# validate yaml keys:
|
|
for key in rule.keys():
|
|
if key not in ALLOWED_KEYS:
|
|
verbose_print(cf.red(f"Rule uses the invalid key '{key}': {rule}"),verbose)
|
|
errors+=1
|
|
|
|
if not rule.get("tags"):
|
|
verbose_print(cf.red(f"Rule has no tags: {rule}"),verbose)
|
|
errors+=1
|
|
|
|
if not TAGS_REGEXP.fullmatch(rule.get("tags")):
|
|
verbose_print(cf.red(f"Rule has an invalid list of tags: {rule}"),verbose)
|
|
errors+=1
|
|
|
|
|
|
# validate name regex
|
|
if rule.get("name"):
|
|
try:
|
|
re.compile(rule["name"])
|
|
except:
|
|
verbose_print(cf.red(f" Invalid name regex: '{rule.get('name')}'"),verbose)
|
|
errors+=1
|
|
|
|
# validate description regex
|
|
if rule.get("description"):
|
|
try:
|
|
re.compile(rule["description"])
|
|
except:
|
|
verbose_print(cf.red(f" Invalid description regex: '{rule.get('description')}'"),verbose)
|
|
errors+=1
|
|
|
|
# validate IBAN
|
|
if rule.get("iban"):
|
|
try:
|
|
IBAN(rule.get("iban"))
|
|
except:
|
|
verbose_print(cf.red(f" Invalid IBAN: '{rule.get('iban')}'"), verbose)
|
|
errors+=1
|
|
|
|
if errors == 0:
|
|
print(cf.green(f" All rules are valid"))
|
|
else:
|
|
print(cf.red(f" Found {errors} invalid rules"))
|
|
|
|
else:
|
|
print(cf.red(f" The rule file doesn't exists"))
|
|
sys.exit(1)
|
|
|
|
# Database
|
|
if os.path.exists(db_path) and os.path.isfile(db_path):
|
|
print(cf.green(f" Database exists"))
|
|
else:
|
|
print(cf.red(f" The database file doesn't exists"))
|
|
sys.exit(1)
|