""" auth.py — password hashing (bcrypt) and session tokens (JWT). """ import os import time import bcrypt import jwt JWT_SECRET = os.environ.get("JWT_SECRET", "change-me-in-space-secrets") JWT_ALGO = "HS256" JWT_EXPIRY_SECONDS = 60 * 60 * 24 * 30 # 30 days def hash_password(plain_password: str) -> str: return bcrypt.hashpw(plain_password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8") def verify_password(plain_password: str, password_hash: str) -> bool: return bcrypt.checkpw(plain_password.encode("utf-8"), password_hash.encode("utf-8")) def issue_token(user_id: int, username: str) -> str: payload = { "sub": user_id, "username": username, "iat": int(time.time()), "exp": int(time.time()) + JWT_EXPIRY_SECONDS, } return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGO) def verify_token(token: str): try: payload = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGO]) return payload except jwt.ExpiredSignatureError: return None except jwt.InvalidTokenError: return None def is_valid_username(username: str) -> bool: if not username or not (3 <= len(username) <= 20): return False return username.isalnum() or "_" in username and all(ch.isalnum() or ch == "_" for ch in username)