mirror of
https://github.com/Rarebuffalo/securelens-backend.git
synced 2026-06-19 07:00:30 +00:00
updated the architecture
This commit is contained in:
0
app/utils/__init__.py
Normal file
0
app/utils/__init__.py
Normal file
30
app/utils/auth.py
Normal file
30
app/utils/auth.py
Normal 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
46
app/utils/validators.py
Normal 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
|
||||
Reference in New Issue
Block a user