"""Authenticatie-backends voor VacatureRadar. Sta inloggen toe met e-mailadres *of* gebruikersnaam, zodat het Stitch-loginscherm (dat om een e-mailadres vraagt) blijft werken zonder het bestaande admin-login op gebruikersnaam te breken. """ from __future__ import annotations from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend from django.db.models import Q class EmailOrUsernameModelBackend(ModelBackend): """Zoekt de gebruiker op via gebruikersnaam of (case-insensitief) e-mailadres.""" def authenticate(self, request, username=None, password=None, **kwargs): user_model = get_user_model() if username is None: username = kwargs.get(user_model.USERNAME_FIELD) if username is None or password is None: return None try: user = user_model.objects.get( Q(**{f"{user_model.USERNAME_FIELD}__iexact": username}) | Q(email__iexact=username) ) except user_model.DoesNotExist: # Draai toch een hash om timing-aanvallen (user-enumeratie) te beperken. user_model().set_password(password) return None except user_model.MultipleObjectsReturned: # Meerdere accounts met dezelfde e-mail: val terug op exacte username-match. user = ( user_model.objects.filter( **{f"{user_model.USERNAME_FIELD}__iexact": username} ) .order_by("id") .first() ) if user is None: return None if user.check_password(password) and self.user_can_authenticate(user): return user return None