import os import re from dotenv import load_dotenv from werkzeug.security import generate_password_hash # Create an empty .env file if it doesn't exist env_file = '.env' if not os.path.exists(env_file): with open(env_file, 'w') as file: file.write('# Environment variables\n') # Function to manually read and parse the .env file for duplicates def read_env_file(file_path): with open(file_path, 'r') as file: lines = file.readlines() exact_mac_names_seen = set() exact_iface_names_seen = set() errors = [] for line in lines: line = line.strip() if not line or line.startswith('#'): continue key, value = line.split('=', 1) key = key.strip() value = value.strip() if key.endswith('_MAC'): if key in exact_mac_names_seen: errors.append(f"Exact duplicate MAC entry: {key}") exact_mac_names_seen.add(key) elif key.endswith('_IFACE'): if key in exact_iface_names_seen: errors.append(f"Exact duplicate IFACE entry: {key}") exact_iface_names_seen.add(key) if errors: for error in errors: print(error) raise SystemExit(1) # Manually read and parse the .env file read_env_file(env_file) # Load environment variables load_dotenv() def validate_mac_address(mac): # Regular expression pattern for a MAC address mac_pattern = re.compile(r'^(?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2})$') return mac_pattern.match(mac) def validate_network_interface(iface): # Regular expression pattern for a network interface iface_pattern = re.compile(r'^(?:eth|wlan|eno|en)\d+$') return iface_pattern.match(iface) def validate_ip_or_domain(address): # Regular expression pattern for an IP address or domain name ip_domain_pattern = re.compile(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$|^[a-zA-Z0-9-]{1,63}(?:\.[a-zA-Z]{2,})+$') if ip_domain_pattern.match(address): # If it's an IP address, verify that each octet is within the correct range if re.match(r'^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$', address): octets = address.split('.') for octet in octets: if int(octet) < 0 or int(octet) > 255: return False return True return False def validate_environment_variables(): errors = [] mac_names_seen = {} iface_names_seen = {} # List of required MAC address environment variables, interfaces and ips mac_vars = {var: os.getenv(var) for var in os.environ if var.endswith('_MAC')} iface_vars = {var: os.getenv(var) for var in os.environ if var.endswith('_IFACE')} ip_vars = {var: os.getenv(var) for var in os.environ if var.endswith('_IP')} # Check for duplicate MAC names (case-insensitive) for var in mac_vars: name_lower = var.rsplit('_', 1)[0].lower() if name_lower in mac_names_seen: errors.append(f"Duplicate MAC entries: {mac_names_seen[name_lower]} and {var}") mac_names_seen[name_lower] = var # Check for duplicate interface names (case-insensitive) for var in iface_vars: name_lower = var.rsplit('_', 1)[0].lower() if name_lower in iface_names_seen: errors.append(f"Duplicate IFACE entries: {iface_names_seen[name_lower]} and {var}") iface_names_seen[name_lower] = var # Validate MAC addresses (required) for var, mac in mac_vars.items(): if not mac: errors.append(f"Missing environment variable: {var}") elif not validate_mac_address(mac): errors.append(f"Invalid MAC address format: {var} = {mac}") if not mac_vars: errors.append("No MAC addresses found in environment variables.") # Validate network interfaces (optional) for var, iface in iface_vars.items(): if iface == "": errors.append(f"Empty interface variable: {var}") elif iface and not validate_network_interface(iface): errors.append(f"Invalid network interface format: {var} = {iface}") # Validate IP addresses or domain names (optional) for var, address in ip_vars.items(): if address == "": errors.append(f"Empty IP address or domain name variable: {var}") elif address and not validate_ip_or_domain(address): errors.append(f"Invalid IP address or domain name format: {var} = {address}") if errors: for error in errors: print(error) raise SystemExit(1) # Validate environment variables validate_environment_variables() # Centralized configuration class Config: SECRET_KEY = os.getenv('WOL_SECRET_KEY', '28c93e98b2a87e47db16372bdb6e7593fb1addf9ccc10eae562827a7358cab3b') USER_PASS = os.getenv('WOL_USER_PASS', '4acG2wHmp1-B') USER_PASS_HASH = generate_password_hash(USER_PASS, method='pbkdf2:sha256', salt_length=16) # Hash the password once and store it REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379/0') RATE_LIMITS = ["200 per day", "50 per hour"] LOG_FILE = 'app.log' LOG_MAX_BYTES = 10000 LOG_BACKUP_COUNT = 1