Matthias Nagel bc4b8a1e7f Feat: Implementierung des Spieler- und Eltern-Verifizierungsprozesses
Fügt einen umfassenden Verifizierungsprozess für neu erstellte Spieler
und zugeordnete Eltern hinzu. Dies ersetzt das frühere Einladungscode-System.

Wesentliche Änderungen:
- **`CustomUser` Modell:** Erweitert um `is_verified` (Standard `False`) und
  `verification_code` (UUID) Felder. `is_active` ist nun standardmäßig `False`
  bis zur Verifizierung. Das `InvitationCode`-Modell wurde entfernt.
- **E-Mail-Utility (`accounts/utils.py`):** Eine neue Funktion `send_verification_email`
  sendet oder simuliert E-Mails (basierend auf `settings.MTP_EMAIL_SEND`).
  Simulierte E-Mails werden im `.mbox`-Format in `tmp_mails/` gespeichert.
- **`settings.py`:** `DEFAULT_FROM_EMAIL` wurde hinzugefügt.
- **`PlayerCreateView` (`accounts/views.py`):**
    - Generiert `verification_code` für neue Spieler und Eltern.
    - Setzt das Passwort für neue Benutzer auf unbrauchbar (`set_unusable_password`).
    - Löst den Versand von Verifizierungs-E-Mails aus.
- **`verify_account` View (`accounts/views.py`):**
    - Eine neue View, die über einen Link in der E-Mail aufgerufen wird.
    - Ermöglicht Spielern, ein Passwort festzulegen.
    - Ermöglicht Eltern, einen eindeutigen Benutzernamen und ein Passwort festzulegen.
    - Setzt `is_active` und `is_verified` auf `True` und invalidiert den
      Verifizierungscode nach erfolgreicher Einrichtung.
    - Loggt den Benutzer nach erfolgreicher Verifizierung direkt ein und zeigt
      eine Erfolgsmeldung an.
    - Behebt ein Problem bei der Bestimmung von Eltern-Benutzern.
- **Formulare (`accounts/forms.py`):** Neue `PlayerVerificationForm` und
  `ParentVerificationForm` für den Verifizierungsprozess.
- **E-Mail-Templates:** Neue Text- und HTML-Templates für Spieler- und
  Eltern-Verifizierungs-E-Mails (`accounts/templates/accounts/email/`).
- **Verifizierungs-Template:** Neues Template für die Verifizierungsseite
  (`accounts/templates/accounts/verify_account.html`).
- **URLs (`accounts/urls.py`):** Entfernung der alten `invitation_code` und
  `register` URLs, Hinzufügung der neuen `verify_account` URL.
- **Datenbankmigrationen:** Migrationen für die Änderungen am `CustomUser`-Modell
  erstellt und angewendet.
- **Temporäres Verzeichnis:** `tmp_mails/` Verzeichnis für E-Mail-Simulation erstellt.
2025-11-23 16:34:25 +01:00

46 lines
2.3 KiB
Python

from django import forms
from .models import CustomUser
class CustomUserCreationForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
birth_date = forms.DateField(input_formats=['%d.%m.%Y', '%Y-%m-%d'], widget=forms.DateInput(format='%d.%m.%Y', attrs={'type': 'date'}))
class Meta:
model = CustomUser
fields = ('username', 'first_name', 'last_name', 'email', 'birth_date', 'player_number', 'password')
class CustomUserChangeForm(forms.ModelForm):
birth_date = forms.DateField(input_formats=['%d.%m.%Y', '%Y-%m-%d'], widget=forms.DateInput(format='%d.%m.%Y', attrs={'type': 'date'}))
class Meta:
model = CustomUser
fields = ('username', 'first_name', 'last_name', 'email', 'birth_date', 'player_number', 'team')
class PlayerCreationForm(forms.ModelForm):
parent1_search = forms.CharField(label="Search Parent 1 by Username/Email", required=False)
parent1_new = forms.EmailField(label="Or create new Parent 1 with Email", required=False)
parent2_search = forms.CharField(label="Search Parent 2 by Username/Email", required=False)
parent2_new = forms.EmailField(label="Or create new Parent 2 with Email", required=False)
birth_date = forms.DateField(input_formats=['%d.%m.%Y', '%Y-%m-%d'], widget=forms.DateInput(format='%d.%m.%Y', attrs={'type': 'date'}))
class Meta:
model = CustomUser
fields = ('username', 'first_name', 'last_name', 'email', 'birth_date', 'player_number', 'team')
class PlayerVerificationForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput, label="Passwort")
password_confirm = forms.CharField(widget=forms.PasswordInput, label="Passwort bestätigen")
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get('password') != cleaned_data.get('password_confirm'):
raise forms.ValidationError("Die Passwörter stimmen nicht überein.")
return cleaned_data
class ParentVerificationForm(PlayerVerificationForm):
username = forms.CharField(max_length=150, label="Benutzername")
def clean_username(self):
username = self.cleaned_data.get('username')
if CustomUser.objects.filter(username=username).exists():
raise forms.ValidationError("Dieser Benutzername ist bereits vergeben.")
return username