import random import string from fastapi import APIRouter, Query, Depends, HTTPException from fastapi.responses import HTMLResponse from typing import Optional # ========================== # 🔐 Auth & Configuration # ========================== # Try to import the auth system, otherwise mock it for standalone use try: from app.routers.auth.system import get_current_user except ImportError: def get_current_user(): return {"username": "Anonymous"} AUTH_ENABLED = False # Set to True to enforce login def auth_dependency(): return Depends(get_current_user) if AUTH_ENABLED else None # ========================== # 🛠️ Router Setup # ========================== router = APIRouter( prefix="/security", tags=["Password Tools"], ) # ========================== # 🎲 Password Logic (API) # ========================== @router.get("/generate-password") def generate_password( length: int = Query(16, ge=8, le=128, description="Length of the password"), include_uppercase: bool = True, include_lowercase: bool = True, include_numbers: bool = True, include_symbols: bool = True, exclude_ambiguous: bool = False, current_user: dict = auth_dependency() ): """ Generates a cryptographically strong random password with advanced options. """ # Character Sets lower = string.ascii_lowercase upper = string.ascii_uppercase nums = string.digits syms = "!@#$%^&*()_+-=[]{}|;:,.<>?" ambiguous = "il1Lo0O" # Filter ambiguous characters if requested if exclude_ambiguous: lower = "".join([c for c in lower if c not in ambiguous]) upper = "".join([c for c in upper if c not in ambiguous]) nums = "".join([c for c in nums if c not in ambiguous]) syms = "".join([c for c in syms if c not in ambiguous]) # Build Pool pool = "" guaranteed_chars = [] if include_lowercase: pool += lower guaranteed_chars.append(random.choice(lower)) if include_uppercase: pool += upper guaranteed_chars.append(random.choice(upper)) if include_numbers: pool += nums guaranteed_chars.append(random.choice(nums)) if include_symbols: pool += syms guaranteed_chars.append(random.choice(syms)) if not pool: raise HTTPException(status_code=400, detail="At least one character type must be selected.") # Generate remaining characters remaining_length = length - len(guaranteed_chars) if remaining_length < 0: password_chars = guaranteed_chars[:length] else: password_chars = guaranteed_chars + [random.choice(pool) for _ in range(remaining_length)] # Shuffle to remove predictable patterns random.shuffle(password_chars) final_password = "".join(password_chars) # Calculate basic entropy/strength pool_size = len(pool) entropy = length * (len(bin(pool_size)) - 2) strength = "Weak" if entropy > 50: strength = "Medium" if entropy > 80: strength = "Strong" if entropy > 120: strength = "Very Strong" user_info = current_user.get("username", "Anonymous") if current_user else "Anonymous" return { "requested_by": user_info, "password": final_password, "length": length, "strength": strength, "entropy_bits": int(entropy) } # ========================== # 🎨 Modern UI Endpoint # ========================== # Path becomes: /security/password-generator/ui @router.get("/password-generator/ui", response_class=HTMLResponse) async def password_ui(): html_content = """ Password Tool
...
Strength: -
16
""" return html_content