How to revoke permission to edit Admin User in django admin

I have a custom user model, and I'm able to create groups without giving necessary permissions. I created a group by giving permission to view and change users. I added a staff user to that group without escalating them as an admin user or a superuser. But that user can edit admin user. How I can prevent users in that specific group from editing the admin user?

class MyAccountManager(BaseUserManager):
    def create_user(self, email, username, password=None):
        if not email:
            raise ValueError("Users must have an email address")
        if not username:
            raise ValueError("Users must have an username")
        user = self.model(
            email=self.normalize_email(email),
            username=username,
        )

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

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

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


class User(AbstractBaseUser,PermissionsMixin):
    email = models.EmailField(verbose_name='email', max_length=80, unique=True)
    username = models.CharField(max_length=30, unique=True)
    first_name = models.CharField(max_length=100,null=True)
    last_name = models.CharField(max_length=100,null=True)
    phone_no = models.CharField(max_length=12, null=True)
    date_joined = models.DateField(
        verbose_name='date joined', auto_now_add=True)
    last_login = models.DateField(verbose_name='last login', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_teacher = models.BooleanField(default=False)
    address = models.CharField(max_length=500, null=True, blank=True)

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    objects = MyAccountManager()

    def __str__(self):
        return self.email

    # def has_perm(self, perm, obj=None):
    #     return self.is_admin

    def has_module_perms(self, app_label):
        return True

Upvotes: 0

Views: 765

Answers (1)

Abhinav Dev
Abhinav Dev

Reputation: 153

For this, you need to separate the models virtually. You can use Django's Proxy Model. Add the following code to the bottom of your models.py.

from django.contrib.auth.models import  UserManager
class StaffManager(UserManager):
    def get_queryset(self):
        qs = super().get_queryset()
        return qs.filter(is_staff=True)


class StaffProxyModel(User):
    objects = StaffManager()
    class Meta:
        proxy = True
        verbose_name = 'Staff'
        verbose_name_plural = 'Staffs'


#admin.py
from django.contrib.auth.admin import UserAdmin
class StaffProxyModelAdmin(UserAdmin):
    pass
admin.site.register(StaffProxyModel, StaffProxyModelAdmin)

After making the changes run python manage.py makemigrations and python manage.py migrate. After doing above steps you'll be able to see "Staff proxy model" in the list of permissions. Grant change and view access to this model to your group. Your problem should be solved. Django will see the proxy model as a separate model although, at the database level, both User and Staff models are stored in the same table.

Upvotes: 1

Related Questions