How do I prevent permission escalation in Django admin when granting “user change” permission?

后端 未结 5 1973
天命终不由人
天命终不由人 2020-12-23 21:49

I have a django site with a large customer base. I would like to give our customer service department the ability to alter normal user accounts, doing things like changing p

5条回答
  •  北海茫月
    2020-12-23 22:39

    The below part of the accepted answer has a race condition where if two staff users try to access the admin form at the same time, one of them may get the superuser form.

    try:
        self.readonly_fields = self.staff_self_readonly_fields
        response = super(MyUserAdmin, self).change_view(request, object_id, form_url, extra_context, *args, **kwargs)
    finally:
        # Reset fieldsets to its original value
        self.fieldsets = UserAdmin.fieldsets
    

    To avoid this race condition (and in my opinion improve the overall quality of the solution), we can override the get_fieldsets() and get_readonly_fields() methods directly:

    class UserAdmin(BaseUserAdmin):
        staff_fieldsets = (
            (None, {'fields': ('username')}),
            ('Personal info', {'fields': ('first_name', 'last_name', 'email')}),
            # No permissions
            ('Important dates', {'fields': ('last_login', 'date_joined')}),
        )
        staff_readonly_fields = ('username', 'first_name', 'last_name', 'email', 'last_login', 'date_joined')
    
        def get_fieldsets(self, request, obj=None):
            if not request.user.is_superuser:
                return self.staff_fieldsets
            else:
                return super(UserAdmin, self).get_fieldsets(request, obj)
    
        def get_readonly_fields(self, request, obj=None):
            if not request.user.is_superuser:
                return self.staff_readonly_fields
            else:
                return super(UserAdmin, self).get_readonly_fields(request, obj)
    

提交回复
热议问题