From 3b0920540d5f5a552e493a0a70ecf736dbe7634f Mon Sep 17 00:00:00 2001 From: candifloss Date: Wed, 12 Feb 2025 15:59:36 +0530 Subject: [PATCH] Config validation before start --- app.py | 9 ++++++++ functions/validate_config.py | 34 ++++++++++++++++++++++++++++ functions/validate_values.py | 44 ++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 functions/validate_config.py create mode 100644 functions/validate_values.py diff --git a/app.py b/app.py index badf884..51e7d4f 100644 --- a/app.py +++ b/app.py @@ -1,3 +1,12 @@ +# Validate configuration before starting the app +from functions.validate_config import validate_config +from config import item_attributes + +config_status = validate_config(item_attributes) +if config_status != "Ok": + raise SystemExit(f"Configuration Error: {config_status}") + +# Import flask and sql to start the app from flask import Flask, redirect from sqlalchemy import exc from definitions.models import * diff --git a/functions/validate_config.py b/functions/validate_config.py new file mode 100644 index 0000000..9a6e3c8 --- /dev/null +++ b/functions/validate_config.py @@ -0,0 +1,34 @@ +from functions.validate_values import validate_value + +# Validate the configuration file to ensure all attributes are properly defined. +def validate_config(item_attributes): + for attrib_name, attrib in item_attributes.items(): + # Check for required fields + if not attrib.display_name: + return f"Missing display name for attribute '{attrib_name}'." + if not attrib.html_input_type: + return f"Missing input type for attribute '{attrib_name}'." + elif attrib.html_input_type not in ["text", "number", "date", "select"]: + return f"Invalid input type for attribute '{attrib_name}'." + elif attrib.html_input_type == "select" and not attrib.options: + return f"Selection missing options for attribute '{attrib_name}'." + + # Validate min and max values + if attrib.min or attrib.max: + if attrib.html_input_type not in ["number", "date"]: + return f"{attrib.display_name} must be of type 'number' or 'date' to have min or max values." + + # Validate default value + if attrib.default_val: + validation_result = validate_value(attrib, attrib.default_val) + if validation_result != "Ok": + return f"Invalid default value for attribute '{attrib_name}': {validation_result}" + + # Validate comparison + if attrib.compareto: + if attrib.compareto[0] not in ["lt", "gt", "le", "ge", "eq"]: + return f"Invalid comparison operator for attribute '{attrib_name}'. Valid operators are: lt, gt, le, ge, eq." + if attrib.compareto[1] not in item_attributes: + return f"Invalid reference attribute '{attrib.compareto[1]}' for comparison in attribute '{attrib_name}'." + + return "Ok" \ No newline at end of file diff --git a/functions/validate_values.py b/functions/validate_values.py new file mode 100644 index 0000000..fb165d1 --- /dev/null +++ b/functions/validate_values.py @@ -0,0 +1,44 @@ +import re +from datetime import datetime + +# Validate the input value based on the attribute's constraints +def validate_value(attrib, input_val): + # Check if the value is required + if attrib.required and not input_val: + return f"{attrib.display_name} is required." + + # Validate based on input type + if attrib.html_input_type == "number": + try: + input_val = int(input_val) + except ValueError: + return f"{attrib.display_name} must be a valid number." + + if attrib.min is not None and input_val < attrib.min: + return f"{attrib.display_name} must be at least {attrib.min}." + if attrib.max is not None and input_val > attrib.max: + return f"{attrib.display_name} must be at most {attrib.max}." + elif attrib.html_input_type == "date": + try: + input_val = datetime.strptime(input_val, "%Y-%m-%d") # Validate date format + except ValueError: + return f"{attrib.display_name} must be a valid date in YYYY-MM-DD format." + + if attrib.min is not None and input_val < datetime.strptime(attrib.min, "%Y-%m-%d"): + return f"{attrib.display_name} must be on or after {attrib.min}." + if attrib.max is not None and input_val > datetime.strptime(attrib.max, "%Y-%m-%d"): + return f"{attrib.display_name} must be on or before {attrib.max}." + elif attrib.html_input_type == "select": + if input_val not in attrib.options: + return f"{attrib.display_name} must be one of {attrib.options}." + elif attrib.html_input_type == "text": + if attrib.regex and not re.match(attrib.regex, input_val): + return f"{attrib.display_name} is invalid. Allowed pattern: {attrib.regex}." + + # Validate comparison + #if attrib.compareto: + # compare attrib value + #return "" + + # If all checks pass, return "Ok" + return "Ok" \ No newline at end of file