updated the architecture

This commit is contained in:
rarebuffalo
2026-04-07 18:13:43 +05:30
parent 087d8ffaee
commit 8330060e86
66 changed files with 3484 additions and 130 deletions

0
app/utils/__init__.py Normal file
View File

30
app/utils/auth.py Normal file
View File

@@ -0,0 +1,30 @@
from datetime import datetime, timedelta, timezone
from jose import JWTError, jwt
from passlib.context import CryptContext
from app.config import settings
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
def create_access_token(user_id: str) -> str:
expire = datetime.now(timezone.utc) + timedelta(minutes=settings.jwt_expiry_minutes)
payload = {"sub": user_id, "exp": expire}
return jwt.encode(payload, settings.jwt_secret, algorithm=settings.jwt_algorithm)
def decode_access_token(token: str) -> str | None:
try:
payload = jwt.decode(token, settings.jwt_secret, algorithms=[settings.jwt_algorithm])
return payload.get("sub")
except JWTError:
return None

46
app/utils/validators.py Normal file
View File

@@ -0,0 +1,46 @@
import ipaddress
import socket
from urllib.parse import urlparse
from fastapi import HTTPException
PRIVATE_NETWORKS = [
ipaddress.ip_network("10.0.0.0/8"),
ipaddress.ip_network("172.16.0.0/12"),
ipaddress.ip_network("192.168.0.0/16"),
ipaddress.ip_network("127.0.0.0/8"),
ipaddress.ip_network("169.254.0.0/16"),
ipaddress.ip_network("0.0.0.0/8"),
ipaddress.ip_network("::1/128"),
ipaddress.ip_network("fc00::/7"),
ipaddress.ip_network("fe80::/10"),
]
def validate_url(url: str) -> str:
parsed = urlparse(url)
if parsed.scheme not in ("http", "https"):
raise HTTPException(status_code=400, detail="URL must use http or https scheme")
hostname = parsed.hostname
if not hostname:
raise HTTPException(status_code=400, detail="Invalid URL: no hostname found")
blocked_hostnames = {"localhost", "0.0.0.0"}
if hostname in blocked_hostnames:
raise HTTPException(status_code=400, detail="Scanning internal addresses is not allowed")
try:
resolved_ip = socket.gethostbyname(hostname)
ip = ipaddress.ip_address(resolved_ip)
for network in PRIVATE_NETWORKS:
if ip in network:
raise HTTPException(
status_code=400,
detail="Scanning internal/private IP addresses is not allowed",
)
except socket.gaierror:
raise HTTPException(status_code=400, detail=f"Could not resolve hostname: {hostname}")
return url