Django log login attemps and after 3 failed attemps lock out user

Viewed 281

So i am pretty new to Django. Actually my first project.

I want to create a custom model "Logging" in which i want to log the admin login attempts and count the attempts. After 3 failed login attempts the user must me locked out. Ive already created a custom User model like this.

class UserManager(BaseUserManager):
def create_user(self,username,password,description):
    if not username:
        raise ValueError('Users must have an username ')

    user = self.model(username=username)
    user.set_password(password)
    user.description = description
    user.save(using=self._db)
    return user

def create_staffuser(self, username, password, description):
    user = self.create_user(
        username,
        password,
        description
    )
    user.staff = True
    user.save(using=self._db)
    return user

def create_superuser(self, username, password, description):
    user = self.model(username=username)
    user.set_password(password)
    user.description = description
    user.staff = True
    user.admin = True
    user.save(using=self._db)
    return user
class Users(AbstractBaseUser):
username = models.CharField(max_length=15,unique=True)
description = models.CharField(max_length=50,default="None")

is_active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False) # a superuser

# notice the absence of a "Password field", that is built in.

USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['description']

def get_full_name(self):
    return self.username

def get_short_name(self):
    return self.username

def __str__(self):
    return self.username

def has_perm(self, perm, obj=None):
    "Does the user have a specific permission?"
    # Simplest possible answer: Yes, always
    return True

def has_module_perms(self, app_label):
    "Does the user have permissions to view the app `app_label`?"
    # Simplest possible answer: Yes, always
    return True

@property
def is_staff(self):
    "Is the user a member of staff?"
    return self.staff

@property
def is_admin(self):
    "Is the user a admin member?"
    return self.admin
    
objects = UserManager()

So how can i log custom admin attempts?

1 Answers

You can make signal receivers for the user_login_failed [Django-doc] and user_logged_in [Django-doc] signals. We can thus create a model that looks like:

from django.conf import settings

class FailedLogin(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE
    )
    timestamp = models.DateTimeField(auto_now_add=True)

Then we define two signal receivers, one for a successful login that will remove FailedLogin records (if any):

from django.contrib.auth import get_user_model
from django.contrib.auth.signals import user_logged_in, user_login_failed
from django.dispatch import receiver

@receiver(user_logged_in)
def user_logged_recv(sender, request, user, **kwargs):
    FailedLogin.objects.filter(user=user).delete()

@receiver(user_login_failed)
def user_login_failed_recv(sender, credentials, request):
    User = get_user_model()
    try:
        u = User.objects.get(username=credentials.get('username'))
        # there is a user with the given username
        FailedLogin.objects.create(user=u)
        if FailedLogin.objects.filter(user=u).count() >= 3:
            # three tries or more, disactivate the user
            u.is_active = False
            u.save()
    except User.DoesNotExist:
        # user not found, we can not do anything
        pass
Related