106 lines
3.7 KiB
Python
106 lines
3.7 KiB
Python
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 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")
|