assitantchatbot / utils /security.py
aghaai's picture
Initial deployment of Unified Assistant with OpenAI and Hugging Face integration
bd161ec
"""
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()