2010-02-19 24 views
14

Tôi có một trang web django với một cơ sở khách hàng lớn. Tôi muốn cung cấp cho bộ phận dịch vụ khách hàng của chúng tôi khả năng thay đổi tài khoản người dùng bình thường, thực hiện những việc như thay đổi mật khẩu, địa chỉ email, v.v. Tuy nhiên, nếu tôi cấp cho ai đó quyền được xây dựng trong auth | user | Can change user, họ sẽ có khả năng đặt cờ is_superuser trên bất kỳ tài khoản nào, kể cả tài khoản của riêng họ. (!!!)Làm cách nào để ngăn chặn sự cho phép leo thang trong quản trị viên Django khi cấp quyền "thay đổi người dùng"?

Cách tốt nhất để xóa tùy chọn này cho nhân viên không phải là superuser là gì? Tôi chắc chắn nó liên quan đến việc phân lớp django.contrib.auth.forms.UserChangeForm và gắn nó vào đối tượng UserAdmin đã được tuỳ chỉnh của tôi ... bằng cách nào đó. Nhưng tôi không thể tìm thấy bất kỳ tài liệu hướng dẫn về cách làm điều này, và tôi chưa hiểu đủ về nội bộ.

Trả lời

19

chúng có khả năng đặt cờ is_superuser trên bất kỳ tài khoản nào, kể cả của riêng chúng. (!!!)

Không chỉ này, họ cũng đạt được khả năng cung cấp cho mình bất kỳ điều khoản một-by-one, cùng hiệu ứng ...

tôi chắc chắn rằng nó liên quan đến subclassing django .contrib.auth.forms.UserChangeForm

Vâng, không nhất thiết. Biểu mẫu bạn thấy trong trang thay đổi của quản trị viên django được tạo động bởi ứng dụng quản trị và dựa trên UserChangeForm, nhưng lớp này hầu như không thêm xác thực regex vào trường username.

và hooking nó vào đối tượng UserAdmin đã tùy chỉnh của tôi ...

Một tùy chỉnh UserAdmin là con đường để đi đây. Về cơ bản, bạn muốn thay đổi thuộc tính fieldsets thành một cái gì đó như thế:

class MyUserAdmin(UserAdmin): 
    fieldsets = (
     (None, {'fields': ('username', 'password')}), 
     (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), 
     # Removing the permission part 
     # (_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_superuser', 'user_permissions')}), 
     (_('Important dates'), {'fields': ('last_login', 'date_joined')}), 
     # Keeping the group parts? Ok, but they shouldn't be able to define 
     # their own groups, up to you... 
     (_('Groups'), {'fields': ('groups',)}), 
    ) 

Nhưng vấn đề ở đây là hạn chế này sẽ áp dụng cho tất cả người dùng. Nếu đây không phải là những gì bạn muốn, bạn có thể ghi đè ví dụ change_view để hoạt động khác nhau tùy thuộc vào sự cho phép của người dùng. Đoạn mã:

class MyUserAdmin(UserAdmin): 
    staff_fieldsets = (
     (None, {'fields': ('username', 'password')}), 
     (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), 
     # No permissions 
     (_('Important dates'), {'fields': ('last_login', 'date_joined')}), 
     (_('Groups'), {'fields': ('groups',)}), 
    ) 

    def change_view(self, request, *args, **kwargs): 
     # for non-superuser 
     if not request.user.is_superuser: 
      try: 
       self.fieldsets = self.staff_fieldsets 
       response = super(MyUserAdmin, self).change_view(request, *args, **kwargs) 
      finally: 
       # Reset fieldsets to its original value 
       self.fieldsets = UserAdmin.fieldsets 
      return response 
     else: 
      return super(MyUserAdmin, self).change_view(request, *args, **kwargs) 
+0

Điều đó đã làm các trick . Cảm ơn câu trả lời kỹ lưỡng như vậy! –

+0

Vì tôi đang sử dụng Groups để quản lý quyền, tôi cũng đã xóa phần Nhóm khỏi 'staff_fieldsets'. –

+0

Cảm ơn! Điều này đã giúp tôi rất nhiều! Tuy nhiên, Django 1.1.2 dường như không thích '_' bạn có trước Thông tin cá nhân và phần còn lại. – Tyug

0

Toàn mã cho django 1.1 (giới hạn thông tin người dùng cơ bản cho nhân viên (không superusers))

from django.contrib.auth.models import User 
from django.utils.translation import ugettext_lazy as _ 


class MyUserAdmin(UserAdmin): 
    my_fieldsets = (
     (None, {'fields': ('username', 'password')}), 
     (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), 
    ) 

    def change_view(self, request, object_id, extra_context=None): 
     # for non-superuser 
     print 'test' 
     if not request.user.is_superuser: 
      self.fieldsets = self.my_fieldsets 
      response = UserAdmin.change_view(self, request, object_id, 
extra_context=None) 
      return response 
     else: 
      return UserAdmin.change_view(self, request, object_id, 
extra_context=None) 


admin.site.unregister(User) 
admin.site.register(User, MyUserAdmin) 
0

lớn nhờ Clément. Những gì tôi đã đưa ra khi làm tương tự cho trang web của tôi là tôi cần bổ sung để làm cho tất cả các lĩnh vực chỉ đọc cho người dùng khác ngoài bản thân. Vì vậy, căn cứ vào câu trả lời Clément của tôi addeed lĩnh vực readonly và ẩn nấp trường mật khẩu khi xem không tự

class MyUserAdmin(UserAdmin): 
    model = User 
    staff_self_fieldsets = (
     (None, {'fields': ('username', 'password')}), 
     (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), 
     # No permissions 
     (_('Important dates'), {'fields': ('last_login', 'date_joined')}), 
    ) 

    staff_other_fieldsets = (
     (None, {'fields': ('username',)}), 
     (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}), 
     # No permissions 
     (_('Important dates'), {'fields': ('last_login', 'date_joined')}), 
    ) 

    staff_self_readonly_fields = ('last_login', 'date_joined') 

    def change_view(self, request, object_id, form_url='', extra_context=None, *args, **kwargs): 
     # for non-superuser 
     if not request.user.is_superuser: 
      try: 
       if int(object_id) != request.user.id: 
        self.readonly_fields = User._meta.get_all_field_names() 
        self.fieldsets = self.staff_other_fieldsets 
       else: 
        self.readonly_fields = self.staff_self_readonly_fields 
        self.fieldsets = self.staff_self_fieldsets 

       response = super(MyUserAdmin, self).change_view(request, object_id, form_url, extra_context, *args, **kwargs) 
      except: 
       logger.error('Admin change view error. Returned all readonly fields') 

       self.fieldsets = self.staff_other_fieldsets 
       self.readonly_fields = ('first_name', 'last_name', 'email', 'username', 'password', 'last_login', 'date_joined') 
       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 
       self.readonly_fields = UserAdmin.readonly_fields 
      return response 
     else: 
      return super(MyUserAdmin, self).change_view(request, object_id, form_url, extra_context, *args, **kwargs) 
2

Phần bên dưới của câu trả lời chấp nhận có một điều kiện chủng tộc mà nếu hai người dùng nhân viên cố gắng truy cập vào các hình thức quản trị cùng một lúc , một trong số họ có thể lấy mẫu superuser.

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 

Để tránh tình trạng chủng tộc này (và theo ý kiến ​​của tôi nâng cao chất lượng tổng thể của giải pháp), chúng ta có thể ghi đè lên các phương pháp get_fieldsets()get_readonly_fields() trực tiếp:

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) 
Các vấn đề liên quan