from django.contrib import messages from django.contrib.auth import authenticate from django.contrib.auth import login as auth_login from django.contrib.auth import logout as auth_logout from django.contrib.auth.models import User from django.core.exceptions import ValidationError from django.core.validators import validate_email from django.http import HttpRequest, HttpResponse from django.shortcuts import redirect, render from django.views.decorators.http import require_http_methods from django_ratelimit.decorators import ratelimit from .models import UserProfile def home(request): return render(request, "frontend/home.html") @ratelimit(key="ip", rate="5/m", method="POST", block=False) @require_http_methods(["GET", "POST"]) def register(request: HttpRequest) -> HttpResponse: user = getattr(request, "user", None) if user and user.is_authenticated: return redirect("home") if getattr(request, "limited", False): messages.error(request, "Too many attempts. Try again in a minute.") if request.method == "POST" and not getattr(request, "limited", False): email = str(request.POST.get("email", "")).strip().lower() display_name = str(request.POST.get("display_name", "")).strip() password = request.POST.get("password") or "" password_confirm = request.POST.get("password_confirm") or "" errors: list[str] = [] if not email: errors.append("Email is required.") else: try: validate_email(email) except ValidationError: errors.append("Enter a valid email address.") if not display_name: errors.append("Display name is required.") if not password: errors.append("Password is required.") elif password != password_confirm: errors.append("Passwords do not match.") if email and User.objects.filter(username=email).exists(): errors.append("An account with that email already exists.") if ( display_name and UserProfile.objects.filter( # type: ignore[attr-defined] display_name=display_name ).exists() ): errors.append("That display name is already taken.") if errors: for error in errors: messages.error(request, error) else: user = User.objects.create_user( username=email, email=email, password=password ) UserProfile.objects.filter(user=user).update( # type: ignore[attr-defined] display_name=display_name ) auth_login(request, user) return redirect("home") return render(request, "frontend/register.html") @ratelimit(key="ip", rate="10/m", method="POST", block=False) @require_http_methods(["GET", "POST"]) def login(request: HttpRequest) -> HttpResponse: user = getattr(request, "user", None) if user and user.is_authenticated: return redirect("home") if getattr(request, "limited", False): messages.error(request, "Too many attempts. Try again in a minute.") if request.method == "POST" and not getattr(request, "limited", False): email = str(request.POST.get("email", "")).strip().lower() password = request.POST.get("password") or "" if not email or not password: messages.error(request, "Email and password are required.") else: user = authenticate(request, username=email, password=password) if user is None: messages.error(request, "Invalid email or password.") else: auth_login(request, user) return redirect("home") return render(request, "frontend/login.html") @require_http_methods(["GET", "POST"]) def logout(request: HttpRequest) -> HttpResponse: if request.method == "POST": auth_logout(request) return redirect("home") return render(request, "frontend/logout.html")