Spaces:
Running
Running
""" | |
Security utilities for the application. | |
""" | |
import secrets | |
import string | |
from typing import Optional | |
import re | |
def generate_secure_token(length: int = 32) -> str: | |
"""Generate a secure random token.""" | |
alphabet = string.ascii_letters + string.digits | |
return ''.join(secrets.choice(alphabet) for _ in range(length)) | |
def validate_email(email: str) -> bool: | |
"""Validate email format.""" | |
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' | |
return re.match(pattern, email) is not None | |
def validate_password_strength(password: str) -> tuple[bool, str]: | |
""" | |
Validate password strength. | |
Returns (is_valid, message) | |
""" | |
if len(password) < 8: | |
return False, "Password must be at least 8 characters long" | |
if not re.search(r'[A-Z]', password): | |
return False, "Password must contain at least one uppercase letter" | |
if not re.search(r'[a-z]', password): | |
return False, "Password must contain at least one lowercase letter" | |
if not re.search(r'\d', password): | |
return False, "Password must contain at least one digit" | |
# Check for special characters | |
if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password): | |
return False, "Password must contain at least one special character" | |
return True, "Password is strong" | |
def sanitize_filename(filename: str) -> str: | |
"""Sanitize filename for safe storage.""" | |
# Remove path separators and dangerous characters | |
sanitized = re.sub(r'[^\w\-_.]', '_', filename) | |
# Limit length | |
if len(sanitized) > 255: | |
name, ext = sanitized.rsplit('.', 1) if '.' in sanitized else (sanitized, '') | |
max_name_length = 255 - len(ext) - 1 if ext else 255 | |
sanitized = name[:max_name_length] + ('.' + ext if ext else '') | |
return sanitized | |
def validate_uuid(uuid_string: str) -> bool: | |
"""Validate UUID format.""" | |
uuid_pattern = r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' | |
return re.match(uuid_pattern, uuid_string, re.IGNORECASE) is not None | |
class RateLimiter: | |
"""Simple in-memory rate limiter.""" | |
def __init__(self): | |
self.requests = {} | |
def is_allowed(self, key: str, max_requests: int, window_seconds: int) -> bool: | |
"""Check if request is allowed under rate limit.""" | |
import time | |
current_time = time.time() | |
if key not in self.requests: | |
self.requests[key] = [] | |
# Remove old requests outside the window | |
self.requests[key] = [ | |
req_time for req_time in self.requests[key] | |
if current_time - req_time < window_seconds | |
] | |
# Check if under limit | |
if len(self.requests[key]) >= max_requests: | |
return False | |
# Add current request | |
self.requests[key].append(current_time) | |
return True | |
# Global rate limiter instance | |
rate_limiter = RateLimiter() | |