from django import forms from django.contrib import admin from django.forms.utils import flatatt from django.utils.html import format_html from django.utils.translation import gettext as _ from .models import MailAddress, MailAddressForward, MailAddressMailbox, Mailbox PASSWORD_MISMATCH_ERROR = _("Passwords don't match") class ReadOnlyPasswordHashWidget(forms.Widget): def render(self, name, value, attrs, renderer=None): 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 = ("osuser",) 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.username = Mailbox.objects.get_next_mailbox_name(mailbox.osuser) mailbox.set_password(self.cleaned_data["password1"]) if commit: mailbox.save() return mailbox class MailboxChangeForm(forms.ModelForm): """ A form for updating mailboxes. """ password = ReadOnlyPasswordHashField() class Meta: model = Mailbox fields = ("username", "password", "osuser", "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", "osuser", "active") list_filter = ("active", "osuser") fieldsets = ((None, {"fields": ("osuser", "username", "password", "active")}),) add_fieldsets = ( (None, {"classes": ("wide",), "fields": ("osuser", "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.options.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__", "mailaddressmailbox", "active") list_filter = ("active", "domain") inlines = [MailAddressMailboxInline, MailAddressForwardInline] admin.site.register(Mailbox, MailboxAdmin) admin.site.register(MailAddress, MailAddressAdmin)