#!/usr/bin/env bash # Validation functions for scripts # Usage: source "$SCRIPT_DIR/lib/common/validation.sh" # Source colors and logging if not already sourced [ -z "${RED:-}" ] && source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/colors.sh" [ -z "$(type -t log_error)" ] && source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/logging.sh" # Validate required environment variable validate_required() { local var_name="$1" local var_value="${!var_name:-}" if [ -z "$var_value" ]; then log_error "$var_name is required but not set" return 1 fi return 0 } # Validate file exists validate_file_exists() { local file_path="$1" local description="${2:-File}" if [ ! -f "$file_path" ]; then log_error "$description not found: $file_path" return 1 fi return 0 } # Validate directory exists validate_directory_exists() { local dir_path="$1" local description="${2:-Directory}" if [ ! -d "$dir_path" ]; then log_error "$description not found: $dir_path" return 1 fi return 0 } # Validate JSON file validate_json() { local json_file="$1" if ! python3 -m json.tool "$json_file" >/dev/null 2>&1; then log_error "Invalid JSON file: $json_file" return 1 fi return 0 } # Validate YAML file validate_yaml() { local yaml_file="$1" if ! command -v yamllint &>/dev/null; then log_warn "yamllint not installed, skipping YAML validation" return 0 fi if ! yamllint "$yaml_file" >/dev/null 2>&1; then log_error "Invalid YAML file: $yaml_file" return 1 fi return 0 } # Validate TOML file validate_toml() { local toml_file="$1" if ! python3 -c "import tomllib; open('$toml_file', 'rb').read()" 2>/dev/null; then log_error "Invalid TOML file: $toml_file" return 1 fi return 0 } # Validate URL format validate_url() { local url="$1" if [[ ! "$url" =~ ^https?:// ]]; then log_error "Invalid URL format: $url" return 1 fi return 0 } # Validate IP address validate_ip() { local ip="$1" if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then log_error "Invalid IP address format: $ip" return 1 fi # Check each octet is 0-255 IFS='.' read -ra ADDR <<< "$ip" for i in "${ADDR[@]}"; do if [ "$i" -gt 255 ] || [ "$i" -lt 0 ]; then log_error "Invalid IP address: $ip (octet out of range)" return 1 fi done return 0 } # Validate port number validate_port() { local port="$1" if [[ ! "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then log_error "Invalid port number: $port (must be 1-65535)" return 1 fi return 0 } # Validate Ethereum address validate_eth_address() { local address="$1" if [[ ! "$address" =~ ^0x[0-9a-fA-F]{40}$ ]]; then log_error "Invalid Ethereum address format: $address" return 1 fi return 0 } # Validate chain ID validate_chain_id() { local chain_id="$1" if [[ ! "$chain_id" =~ ^[0-9]+$ ]] || [ "$chain_id" -lt 1 ]; then log_error "Invalid chain ID: $chain_id" return 1 fi return 0 } # Validate non-empty string validate_non_empty() { local value="$1" local name="${2:-Value}" if [ -z "$value" ]; then log_error "$name cannot be empty" return 1 fi return 0 } # Validate numeric value validate_numeric() { local value="$1" local name="${2:-Value}" if [[ ! "$value" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then log_error "$name must be numeric: $value" return 1 fi return 0 } # Validate positive number validate_positive() { local value="$1" local name="${2:-Value}" if ! validate_numeric "$value" "$name"; then return 1 fi if (( $(echo "$value <= 0" | bc -l) )); then log_error "$name must be positive: $value" return 1 fi return 0 } # Validate command exists validate_command() { local cmd="$1" if ! command -v "$cmd" &>/dev/null; then log_error "Command not found: $cmd" return 1 fi return 0 } # Validate multiple requirements validate_all() { local failed=0 while [ $# -gt 0 ]; do if ! "$@"; then failed=1 fi shift done return $failed }