2010-02-19 10 views
14

Ho un sito django con una vasta base di clienti. Vorrei dare al nostro servizio clienti la possibilità di modificare i normali account utente, fare cose come cambiare password, indirizzi e-mail, ecc. Tuttavia, se concedo a qualcuno l'autorizzazione auth | user | Can change user integrata, ottengono la possibilità di impostare il flag is_superuser su qualsiasi account, incluso il proprio. (!!!)Come si impedisce l'escalation dei permessi nell'amministratore di Django quando si concede l'autorizzazione "modifica utente"?

Qual è il modo migliore per rimuovere questa opzione per il personale non super-utente? Sono sicuro che coinvolga la sottoclasse django.contrib.auth.forms.UserChangeForm e l'agganci al mio oggetto già personalizzato UserAdmin ... in qualche modo. Ma non riesco a trovare alcuna documentazione su come farlo, e non ho ancora capito abbastanza bene l'interno.

risposta

19

hanno la possibilità di impostare il flag is_superuser su qualsiasi account, incluso il proprio. (!!!)

Non solo questo, ma anche acquisire la capacità di darsi le autorizzazioni one-by-one, stesso effetto ...

Sono sicuro che si tratta di sottoclasse django .contrib.auth.forms.UserChangeForm

Bene, non necessariamente. Il modulo che vedi nella pagina di modifica dell'amministratore di django viene creato dinamicamente dall'applicazione di amministrazione e basato su UserChangeForm, ma questa classe aggiunge a malapena la convalida di espressioni regolari al campo username.

e agganciandolo nella mia oggetto UserAdmin già-custom ...

Una consuetudine UserAdmin è il modo di andare qui. In sostanza, si vuole modificare la proprietà fieldsets a qualcosa di simile:

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',)}), 
    ) 

Ma il problema qui è che questa limitazione si applicherà a tutti gli utenti. Se questo non è ciò che desideri, potresti ad esempio sostituire lo change_view in un comportamento diverso a seconda dell'autorizzazione degli utenti. Frammento di codice:

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

Che ha fatto il trucco . Grazie per una risposta così completa! –

+0

Dato che utilizzo i gruppi per gestire le autorizzazioni, ho rimosso anche la sezione Gruppi da 'staff_fieldsets'. –

+0

Grazie! Questo mi ha aiutato molto! Tuttavia, Django 1.1.2 non sembrava gradire il "_" che avevi prima delle informazioni personali e il resto. – Tyug

0

codice completo per Django 1.1 (limitato alle informazioni utente di base per il personale (non superuser))

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

grande grazie a Clément. Quello che mi è venuto in mente quando ho fatto lo stesso per il mio sito è che mi serviva in aggiunta per rendere tutti i campi in sola lettura per gli utenti che non sono autonomi. Quindi, basandosi su risposta di Clemente I addeed campi di sola lettura e campo password nascondersi quando non è la visualizzazione di auto

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

La parte sottostante della risposta accettata è una condizione di competizione in cui se due utenti del personale cercano di accedere al modulo di amministrazione, allo stesso tempo , uno di questi potrebbe ottenere il modulo di superutente.

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 

per evitare questa condizione di competizione (e, a mio parere migliorare la qualità complessiva della soluzione), siamo in grado di sovrascrivere direttamente i get_fieldsets() e get_readonly_fields() metodi:

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) 
Problemi correlati