Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Non-staff users can login to admin page

Tags:

python

django

Python 3.5.1 and Django 1.9

I have created a custom user model in my project:

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class UserManager(BaseUserManager):
    def create_user(self, username, password=None):
        user = self.model(
            username=username,
        )

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

    def create_superuser(self, username, password):
        user = self.create_user(
            username,
            password=password,
        )

        user.is_admin = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


# Users
class User(AbstractBaseUser):
    username = models.CharField(
        unique=True,
        max_length=50,
    )
    bio = models.TextField()

    is_active = models.BooleanField(default=True,
                                    verbose_name="Active",
                                    help_text="lorem")
    is_admin = models.BooleanField(default=False,
                                   verbose_name="Staff status",
                                   help_text="lorem")
    is_superuser = models.BooleanField(default=False,
                                       verbose_name="Superuser status",
                                       help_text="lorem")

    objects = UserManager()

    USERNAME_FIELD = 'username'

    def get_full_name(self):
        return self.username

    def get_short_name(self):
        return self.username

    def is_staff(self):
        return self.is_admin

    def __str__(self):
        return self.username

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, db):
        return True

I followed the guide in the official documentation here

I have defined AUTH_USER_MODEL in settings.py

Everything seems to work correctly with the custom user model, execpt...

Any user can login to the admin interface. This of course is not a good thing

Here is a screenshot of the admin interface when logged in as a non-admin user: non-admin login

And here when logged as an actual admin user admin login

Note the top right corners. When logged in with a non-admin user, the menu dose not appear. Strange.

Both admin and non-admin users have full access to the admin interface, they can both add, change and delete entries.

Clearly this is a terrible security issue, I don't even know where to start dubugging

like image 441
99lives Avatar asked Mar 23 '16 22:03

99lives


People also ask

How do I restrict access to admin pages in Django?

Django admin allows access to users marked as is_staff=True . To disable a user from being able to access the admin, you should set is_staff=False . This holds true even if the user is a superuser. is_superuser=True .

How do I give permission to admin in Django?

Test the 'view' permission is added to all models Using #3 for Django 1.7 only creates the permission objects if the model doesn't already exist. Is there a way to create a migration (or something else) to create the permission objects for existing models?

Can I use Django admin in production?

Django's Admin is amazing. A built-in and fully functional interface that quickly gets in and allows data entry is priceless. Developers can focus on building additional functionality instead of creating dummy interfaces to interact with the database.


2 Answers

You'll need to turn is_staff into a property. If you use the built-in User model, Django expects it to be a model field, which means all checks for staff status happen as if user.is_staff:, not as if user.is_staff():. All you need to do is to include a single line before your is_staff method definition:

@property
def is_staff(self):
    return self.is_admin

Since Python considers every function object to be True when used in a boolean context, all your users pass the check for is_staff.

If you want to know why the admin displays the correct value in the “STAFF STATUS” column, it's because is_staff is listed in list_display of the default ModelAdmin for the user model, and ModelAdmin does check items in list_display if they're callable or not, and in case they are, it calls them. However, this is only done for the purpose of displaying the value (since list_display is a more general mechanism), but not for any actual access control checks.

like image 152
koniiiik Avatar answered Oct 03 '22 18:10

koniiiik


You musst inheritat from AbstractBaseUser and PermissionsMixin.

You just included a "bio" field in your User class. Maybe just extend from AbstractUser and not AbstractBaseUser. The AbstractUser has most of the important stuff and you can include you bio field there

like image 24
YYYY-MM-DD Avatar answered Oct 03 '22 18:10

YYYY-MM-DD