from django.utils.html import format_html from django.contrib import admin from django import forms from django.forms.util import flatatt from django.utils.translation import ugettext as _ from .models import ( MailAddress, MailAddressForward, MailAddressMailbox, MailDomain, Mailbox, ) PASSWORD_MISMATCH_ERROR = _("Passwords don't match") class ReadOnlyPasswordHashWidget(forms.Widget): def render(self, name, value, attrs): final_attrs = self.build_attrs(attrs) summary = format_html("{0}: {1} ", _('Hash'), value) return format_html("{1}", flatatt(final_attrs), summary) class ReadOnlyPasswordHashField(forms.Field): widget = ReadOnlyPasswordHashWidget def __init__(self, *args, **kwargs): kwargs.setdefault("required", False) super(ReadOnlyPasswordHashField, self).__init__(*args, **kwargs) def bound_data(self, data, initial): return initial def _has_changed(self, initial, data): return False class MailboxCreationForm(forms.ModelForm): """ A form for creating mailboxes. """ password1 = forms.CharField(label=_('Password'), widget=forms.PasswordInput) password2 = forms.CharField(label=_('Password (again)'), widget=forms.PasswordInput) class Meta: model = Mailbox fields = ('username',) def clean_password2(self): """ Check that the two password entries match. """ password1 = self.cleaned_data.get('password1') password2 = self.cleaned_data.get('password2') if password1 and password2 and password1 != password2: raise forms.ValidationError(PASSWORD_MISMATCH_ERROR) return password2 def save(self, commit=True): """ Save the provided password in hashed format. """ mailbox = super(MailboxCreationForm, self).save(commit=False) mailbox.set_password(self.cleaned_data['password1']) mailbox.uid = 0 mailbox.gid = 0 if commit: mailbox.save() return mailbox class MailboxChangeForm(forms.ModelForm): """ A form for updating mailboxes. """ password = ReadOnlyPasswordHashField() class Meta: model = Mailbox fields = ('username', 'password', 'home', 'uid', 'gid', 'active') def clean_password(self): return self.initial['password'] class ActivationChangeMixin(object): def activate(self, request, queryset): queryset.update(active=True) def deactivate(self, request, queryset): queryset.update(active=False) activate.short_description = _('Activate') deactivate.short_description = _('Deactivate') class MailboxAdmin(ActivationChangeMixin, admin.ModelAdmin): """ Custom admin page for mailboxes. """ form = MailboxChangeForm add_form = MailboxCreationForm actions = ['activate', 'deactivate'] list_display = ('username', 'active') list_filter = ('active',) fieldsets = ( (None, { 'fields': ('username', 'password', 'active')}), (_('System'), { 'fields': ('home', 'uid', 'gid')}), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('username', 'password1', 'password2')}), ) search_fields = ('username',) ordering = ('username',) filter_horizontal = () def get_fieldsets(self, request, obj=None): if not obj: return self.add_fieldsets return super(MailboxAdmin, self).get_fieldsets(request, obj) def get_form(self, request, obj=None, **kwargs): """ Use special form during mailbox creation. """ defaults = {} if obj is None: defaults.update({ 'form': self.add_form, 'fields': admin.util.flatten_fieldsets(self.add_fieldsets), }) defaults.update(kwargs) return super(MailboxAdmin, self).get_form(request, obj, **defaults) class MailAddressMailboxInline(admin.TabularInline): model = MailAddressMailbox class MailAddressForwardInline(admin.TabularInline): model = MailAddressForward class MailAddressAdmin(ActivationChangeMixin, admin.ModelAdmin): actions = ['activate', 'deactivate'] list_display = ('__str__', 'active') list_filter = ('active',) inlines = [MailAddressMailboxInline, MailAddressForwardInline] admin.site.register(MailDomain) admin.site.register(Mailbox, MailboxAdmin) admin.site.register(MailAddress, MailAddressAdmin)