Search code examples
pythondjangodjango-allauthmonkeypatching

How do I 'monkey patch' or override User.is_authenticated()? Creates issues with using django-lazysignup


I installed django-lazysignup and am facing the challenge now of User.is_authenticated() returning True, for what are not actually authenticated users, but instead lazy-signup users. I can update any checks for User.is_authenticated() in my code with my own function. However, other packages like django-allauth, check this method to decide whether a user is already signed-in, and redirect from attempts to reach the login page.

class RedirectAuthenticatedUserMixin(object):
    def dispatch(self, request, *args, **kwargs):
        self.request = request
        if request.user.is_authenticated():
            redirect_to = self.get_authenticated_redirect_url()
            response = HttpResponseRedirect(redirect_to)
            return _ajax_response(request, response)
...

Are there any recommendations that don't require replacing is_authenticated() in every package that I include? Seems most of them expect it to function a particular way, and django-lazysignup turns that on its head. Could I monkey patch the User model with a new is_authenticated() method? If it's possible, where would I do this so that it's attached to the page request?


Solution

  • Ended up just having to replace all calls to User.is_authenticated().

    To prevent django-allauth from redirecting lazy-users from the login page, this ended up looking something like this:

    from allauth.account.views import AjaxCapableProcessFormViewMixin
    
    def _ajax_response(request, response, form=None):
        if request.is_ajax():
            if (isinstance(response, HttpResponseRedirect)
                or isinstance(response, HttpResponsePermanentRedirect)):
                redirect_to = response['Location']
            else:
                redirect_to = None
            response = get_adapter().ajax_response(request,
                                               response,
                                               form=form,
                                               redirect_to=redirect_to)
        return response
    
    
    class RedirectUserWithAccountMixin(object):
        def dispatch(self, request, *args, **kwargs):
            self.request = request
            if user_has_account(request.user):
                redirect_to = self.get_authenticated_redirect_url()
                response = HttpResponseRedirect(redirect_to)
                return _ajax_response(request, response)
            else:
                response = super(RedirectUserWithAccountMixin,
                                 self).dispatch(request,
                                                *args,
                                                **kwargs)
            return response
    
        def get_authenticated_redirect_url(self):
            redirect_field_name = self.redirect_field_name
            return get_login_redirect_url(self.request,
                                          url=self.get_success_url(),
                                          redirect_field_name=redirect_field_name)
    
    class LoginView(RedirectUserWithAccountMixin,
                AjaxCapableProcessFormViewMixin,
                FormView):
    ...
    

    Where user_has_account() was my own method for checking whether the user was actually signed in.