ttvdrops/accounts/views.py
2025-09-13 23:17:17 +02:00

135 lines
4.3 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import LoginView, LogoutView
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import CreateView
from accounts.forms import CustomUserCreationForm
from accounts.models import User
from twitch.models import Game, NotificationSubscription
if TYPE_CHECKING:
from django.forms import BaseModelForm
from django.http import HttpRequest, HttpResponse
class CustomLoginView(LoginView):
"""Custom login view with better styling."""
template_name = "accounts/login.html"
redirect_authenticated_user = True
def get_success_url(self) -> str:
"""Redirect to the dashboard after successful login.
Returns:
str: URL to redirect to after successful login.
"""
return reverse_lazy("twitch:dashboard") # pyright: ignore[reportReturnType]
class CustomLogoutView(LogoutView):
"""Custom logout view."""
next_page = reverse_lazy("twitch:dashboard") # pyright: ignore[reportAssignmentType]
http_method_names = ["get", "post", "options"]
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Allow GET requests for logout.
Args:
request: The HTTP request object.
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.
Returns:
HttpResponse: Response after logout.
"""
return self.post(request, *args, **kwargs)
class SignUpView(CreateView):
"""User registration view."""
model = User
form_class = CustomUserCreationForm
template_name = "accounts/signup.html"
success_url = reverse_lazy("twitch:dashboard")
def form_valid(self, form: BaseModelForm) -> HttpResponse:
"""Login the user after successful registration.
Args:
form: The validated user creation form.
Returns:
HttpResponse: Response after successful form processing.
"""
response = super().form_valid(form)
login(self.request, self.object) # type: ignore[attr-defined]
return response
@login_required
def profile_view(request: HttpRequest) -> HttpResponse:
"""User profile view.
Args:
request: The HTTP request object.
Returns:
HttpResponse: Rendered profile template.
"""
subscriptions = NotificationSubscription.objects.filter(user=request.user) # type: ignore[misc]
# Direct game subscriptions
direct_game_subscriptions = subscriptions.filter(game_id__isnull=False)
# Organization subscriptions
org_subscriptions = subscriptions.filter(organization_id__isnull=False)
# Get games from organization subscriptions (inherited games)
inherited_games = Game.objects.filter(owner__in=org_subscriptions.values("organization"))
# Create mapping of inherited game IDs to their organization names
inherited_game_org_map = {}
for game in inherited_games:
if game.owner:
inherited_game_org_map[game.id] = game.owner.name
# Combine direct and inherited game IDs
direct_game_ids = direct_game_subscriptions.values_list("game_id", flat=True)
inherited_game_ids = inherited_games.values_list("id", flat=True)
all_game_ids = set(direct_game_ids) | set(inherited_game_ids)
# Get all games (direct + inherited)
game_subscriptions_combined = Game.objects.filter(id__in=all_game_ids)
# Get direct game IDs for template indication
direct_game_ids = list(direct_game_subscriptions.values_list("game_id", flat=True))
# Get all games (direct + inherited) with inheritance info
games_with_inheritance = []
for game in game_subscriptions_combined:
is_inherited = game.id not in direct_game_ids
inherited_from = inherited_game_org_map.get(game.id) if is_inherited else None
games_with_inheritance.append({
"game": game,
"is_inherited": is_inherited,
"inherited_from": inherited_from,
})
return render(
request,
"accounts/profile.html",
{
"user": request.user,
"games_with_inheritance": games_with_inheritance,
"org_subscriptions": org_subscriptions,
},
)