0

I've got some nifty code that on user login, finds any other user logged in as that user and logs them out. It works just fine, but it doesn't offer any indication as to why these people are no longer logged in, so I'm trying to remedy that with Django's messaging system.

You've been logged out because somebody has been sharing their login credentials.
Don't do that, it's uncool.

The only problem is that message.error() (understandably) requires request as the first argument, and at the point at which I'm kicking other users, I don't have their request objects, I only have the kicking user's object.

So I'm working on options. I suppose I could write a model to log these sorts of messages, keyed by session id (which I have from every user), and then some middleware that checks the db for any messages for that session id on every request but that seems really wasteful, not to mention anti-DRY. There must be a better way to do it, but I don't know what it is yet.

Daniel Quinn
  • 6,010
  • 6
  • 38
  • 61

2 Answers2

2

I appear to have solved this in a rather round-about, hackish sort of way. I'll post it here in case anyone else comes looking with a similar problem.

First I had to set the storage backend to use sessions rather than whatever the default is. I thought the default was sessions, but from inspecting the database, I didn't see it.

# settings.py
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'

Next, I added a handler to the user.is_logged_in signal:

def kick_my_other_sessions(sender, request=None, user=None, **kwargs):

    from django.contrib.messages import constants
    from django.contrib.messages.storage.base import Message
    from django.contrib.sessions.backends.db import SessionStore
    from django.contrib.sessions.models import Session

    from tracking.models import Visitor

    keys = [v.session_key for v in Visitor.objects.filter(user=request.user).exclude(session_key=request.session.session_key)]
    for session in Session.objects.filter(session_key__in=keys):

        s = SessionStore(session.session_key)

        # Hack to log the user out without expiring the session immediately,
        # otherwise they'll never see their message
        s["_auth_user_id"] = 0

        # The _messages property is a list of Message objects
        s["_messages"] = [Message(constants.ERROR, "You've been logged out because someone else has logged into your account from another computer.")]

        s.save()

And that's it. Originally, I just deleted the session, but this (admittedly hackish) way, I can log out the user and let them retain the session so they can see their message.

Daniel Quinn
  • 6,010
  • 6
  • 38
  • 61
0

It was pretty cool when we could create messages like this:

user.message_set.create(message='blabla')

Now, this was brutally taken away, your only option is to create a message engine that persists ie. using models. Then, you could add messages to the database and the user will be able to retrieve them.

jpic
  • 32,891
  • 5
  • 112
  • 113