Reputation: 110093
To make a user inactive I usually do:
User.objects.get(pk=X).update(is_active=False)
However, this doesn't log out the user or do anything session-related. Is there a built-in in django to make a user immediately inactive, or what would be the best way to accomplish this?
One similar answer is this: https://stackoverflow.com/a/954318/651174, but that doesn't work great if there are millions of sessions (it's a brute force way iterating over all sessions). Though this is from 2009, so hopefully there's a better way as of today.
Upvotes: 4
Views: 2500
Reputation: 3811
Changing the user's password invalidates all the user's sessions since around Django version 2.2. (This works without scanning the whole session table. An HMAC of the password field is saved on login, and on any request where the request.user
is accessed, the login session is treated as no-longer-valid if the current HMAC does not match.)
https://docs.djangoproject.com/en/2.2/topics/auth/default/#session-invalidation-on-password-change-1
user = User.objects.get(pk=user_id)
user.is_active = False
user.set_unusable_password()
user.save()
Upvotes: 3
Reputation: 826
As mentioned, you can use django-user-session or django-qsessions. But these include some other metadata such as user agent and ip address, and you may not want these for some reason. Then you need to write your custom session backend
I adjusted the example a bit and created one to the my needs.
session_backend.py:
from django.contrib.auth import get_user_model
from django.contrib.sessions.backends.db import SessionStore as DBStore
from django.contrib.sessions.base_session import AbstractBaseSession
from django.db import models
User = get_user_model()
class QuickSession(AbstractBaseSession):
# Custom session model which stores user foreignkey to asssociate sessions with particular users.
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
@classmethod
def get_session_store_class(cls):
return SessionStore
class SessionStore(DBStore):
@classmethod
def get_model_class(cls):
return QuickSession
def create_model_instance(self, data):
obj = super().create_model_instance(data)
try:
user_id = int(data.get('_auth_user_id'))
user = User.objects.get(pk=user_id)
except (ValueError, TypeError, User.DoesNotExist):
user = None
obj.user = user
return obj
and in settings.py:
SESSION_ENGINE = 'path.to.session_backend'
To delete all session for a user:
from session_backend import QuickSession
QuickSession.objects.filter(user=request.user).delete()
You may write your custom save method for user model to automatically delete all sessions for the user if the is_active field is set to False.
Keep in mind that, user field for those who are not logged in will be NULL.
Upvotes: 3