transient.chat/blueprints/auth.py

71 lines
2.2 KiB
Python

from flask import Blueprint, request, jsonify, current_app
from datetime import datetime, timezone
import os
from itsdangerous import URLSafeTimedSerializer, SignatureExpired, BadSignature
from models.state import user_sessions, user_ips, banned_ips, banned_usernames
auth_bp = Blueprint("auth", __name__)
def generate_user_key(username):
serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
return serializer.dumps({"u": username})
def verify_user_key(username, token, max_age=30*24*60*60): # 30 days
serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
try:
data = serializer.loads(token, max_age=max_age)
return data.get("u") == username
except (SignatureExpired, BadSignature):
return False
@auth_bp.route("/register", methods=["POST"])
def register():
data = request.get_json()
username = data.get("username")
user_ip = request.remote_addr
if not username:
return jsonify({"error": "No username provided"}), 400
if username in user_ips: # Check global user_ips to see if name is taken
return jsonify({"error": "Username taken"}), 409
if user_ip in banned_ips:
return jsonify({"error": "IP banned"}), 403
if username in banned_usernames:
return jsonify({"error": "Username banned"}), 403
user_key = generate_user_key(username)
user_sessions[username] = {
"key": user_key,
"last_active": datetime.now(timezone.utc).isoformat(),
}
user_ips[username] = user_ip
from models.database import db_set_user_ip
db_set_user_ip(username, user_ip)
return jsonify({"username": username, "key": user_key})
@auth_bp.route("/validate", methods=["POST"])
def validate():
data = request.get_json()
username = data.get("username")
key = data.get("key")
if not username or not key:
return jsonify({"error": "Invalid credentials"}), 403
if verify_user_key(username, key):
# Restore active user session in-memory if lost on restart
user_sessions[username] = {
"key": key,
"last_active": datetime.now(timezone.utc).isoformat(),
}
return jsonify({"status": "valid"})
return jsonify({"error": "Invalid credentials"}), 403