diff --git a/evennia/web/utils/backends.py b/evennia/web/utils/backends.py index 6365d9e90..5794dbd2d 100644 --- a/evennia/web/utils/backends.py +++ b/evennia/web/utils/backends.py @@ -3,16 +3,38 @@ from django.contrib.auth import get_user_model class CaseInsensitiveModelBackend(ModelBackend): """ - By default ModelBackend does case _sensitive_ username authentication, which isn't what is - generally expected. This backend supports case insensitive username authentication. + By default ModelBackend does case _sensitive_ username + authentication, which isn't what is generally expected. This + backend supports case insensitive username authentication. + """ - def authenticate(self, username=None, password=None): - User = get_user_model() - try: - user = User.objects.get(username__iexact=username) - if user.check_password(password): - return user + def authenticate(self, username=None, password=None, autologin=None): + """ + Custom authenticate with bypass for auto-logins + + Args: + username (str, optional): Name of user to authenticate. + password (str, optional): Password of user + autologin (Player, optional): If given, assume this is + an already authenticated player and bypass authentication. + """ + if autologin: + # Note: Setting .backend on player is critical in order to + # be allowed to call django.auth.login(player) later. This + # is necessary for the auto-login feature of the webclient, + # but it's important to make sure Django doesn't change this + # requirement or the name of the property down the line. /Griatch + autologin.backend = "evennia.web.utils.backends.CaseInsensitiveModelBackend" + return autologin else: - return None - except User.DoesNotExist: - return None + # In this case .backend will be assigned automatically + # somewhere along the # way. + Player = get_user_model() + try: + player = Player.objects.get(username__iexact=username) + if player.check_password(password): + return player + else: + return None + except Player.DoesNotExist: + return None diff --git a/evennia/web/webclient/views.py b/evennia/web/webclient/views.py index fadcf87bc..b4f6a3fc2 100644 --- a/evennia/web/webclient/views.py +++ b/evennia/web/webclient/views.py @@ -6,7 +6,7 @@ page and serve it eventual static content. """ from __future__ import print_function from django.shortcuts import render -from django.contrib.auth import login +from django.contrib.auth import login, authenticate from evennia.players.models import PlayerDB from evennia.utils import logger @@ -33,6 +33,8 @@ def _shared_login(request): # The webclient has previously registered a login to this browser_session player = PlayerDB.objects.get(id=sesslogin) try: + # calls our custom authenticate in web/utils/backends.py + player = authenticate(autologin=player) login(request, player) except AttributeError: logger.log_trace() diff --git a/evennia/web/website/views.py b/evennia/web/website/views.py index 2e6af3285..db3c86724 100644 --- a/evennia/web/website/views.py +++ b/evennia/web/website/views.py @@ -7,6 +7,7 @@ templates on the fly. """ from django.contrib.admin.sites import site from django.conf import settings +from django.contrib.auth import authenticate from django.contrib.admin.views.decorators import staff_member_required from django.shortcuts import render @@ -39,6 +40,8 @@ def _shared_login(request): # The webclient has previously registered a login to this csession player = PlayerDB.objects.get(id=sesslogin) try: + # calls our custom authenticate, in web/utils/backend.py + authenticate(autologin=player) login(request, player) except AttributeError: logger.log_trace()