add separate models for mail addresses, domains and mailboxes
This commit is contained in:
		
							parent
							
								
									402c02203d
								
							
						
					
					
						commit
						618a9b8c11
					
				
					 5 changed files with 343 additions and 8 deletions
				
			
		|  | @ -1,3 +1,140 @@ | |||
| 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 _ | ||||
| 
 | ||||
| # Register your models here. | ||||
| from .models import ( | ||||
|     MailDomain, | ||||
|     Mailbox, | ||||
|     MailAddress | ||||
| ) | ||||
| 
 | ||||
| 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("<strong>{0}</strong>: {1} ", | ||||
|                               _('Hash'), value) | ||||
|         return format_html("<div{0}>{1}</div>", 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', 'domain') | ||||
| 
 | ||||
|     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', 'domain', 'password', 'home', 'uid', 'gid', | ||||
|                   'active') | ||||
| 
 | ||||
|     def clean_password(self): | ||||
|         return self.initial['password'] | ||||
| 
 | ||||
| 
 | ||||
| class MailboxAdmin(admin.ModelAdmin): | ||||
|     """ | ||||
|     Custom admin page for mailboxes. | ||||
| 
 | ||||
|     """ | ||||
|     form = MailboxChangeForm | ||||
|     add_form = MailboxCreationForm | ||||
| 
 | ||||
|     list_display = ('username', 'domain', 'active') | ||||
|     list_filter = ('active',) | ||||
|     fieldsets = ( | ||||
|         (None, { | ||||
|             'fields': ('username', 'domain', 'password', 'active')}), | ||||
|         (_('System'), { | ||||
|             'fields': ('home', 'uid', 'gid')}), | ||||
|     ) | ||||
|     add_fieldsets = ( | ||||
|         (None, { | ||||
|             'classes': ('wide',), | ||||
|             'fields': ('username', 'domain', 'password1', 'password2')}), | ||||
|     ) | ||||
|     search_fields = ('username', 'domain') | ||||
|     ordering = ('username', 'domain') | ||||
|     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) | ||||
| 
 | ||||
| 
 | ||||
| admin.site.register(MailDomain) | ||||
| admin.site.register(Mailbox, MailboxAdmin) | ||||
| admin.site.register(MailAddress) | ||||
|  |  | |||
|  | @ -8,11 +8,18 @@ from django.db import models | |||
| class Migration(SchemaMigration): | ||||
| 
 | ||||
|     def forwards(self, orm): | ||||
|         # Adding model 'MailDomain' | ||||
|         db.create_table(u'managemails_maildomain', ( | ||||
|             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||||
|             ('domain', self.gf('django.db.models.fields.CharField')(unique=True, max_length=128)), | ||||
|         )) | ||||
|         db.send_create_signal(u'managemails', ['MailDomain']) | ||||
| 
 | ||||
|         # Adding model 'Mailbox' | ||||
|         db.create_table(u'managemails_mailbox', ( | ||||
|             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||||
|             ('username', self.gf('django.db.models.fields.CharField')(max_length=128)), | ||||
|             ('domain', self.gf('django.db.models.fields.CharField')(max_length=128)), | ||||
|             ('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=128)), | ||||
|             ('domain', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['managemails.MailDomain'])), | ||||
|             ('password', self.gf('django.db.models.fields.CharField')(max_length=64)), | ||||
|             ('home', self.gf('django.db.models.fields.CharField')(max_length=255)), | ||||
|             ('uid', self.gf('django.db.models.fields.PositiveSmallIntegerField')()), | ||||
|  | @ -21,23 +28,102 @@ class Migration(SchemaMigration): | |||
|         )) | ||||
|         db.send_create_signal(u'managemails', ['Mailbox']) | ||||
| 
 | ||||
|         # Adding model 'MailAddress' | ||||
|         db.create_table(u'managemails_mailaddress', ( | ||||
|             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||||
|             ('localpart', self.gf('django.db.models.fields.CharField')(max_length=128)), | ||||
|             ('domain', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['managemails.MailDomain'])), | ||||
|             ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), | ||||
|         )) | ||||
|         db.send_create_signal(u'managemails', ['MailAddress']) | ||||
| 
 | ||||
|         # Adding unique constraint on 'MailAddress', fields ['localpart', 'domain'] | ||||
|         db.create_unique(u'managemails_mailaddress', ['localpart', 'domain_id']) | ||||
| 
 | ||||
|         # Adding model 'MailAddressMailbox' | ||||
|         db.create_table(u'managemails_mailaddressmailbox', ( | ||||
|             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||||
|             ('mailaddress', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['managemails.MailAddress'])), | ||||
|             ('mailbox', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['managemails.Mailbox'])), | ||||
|         )) | ||||
|         db.send_create_signal(u'managemails', ['MailAddressMailbox']) | ||||
| 
 | ||||
|         # Adding unique constraint on 'MailAddressMailbox', fields ['mailaddress', 'mailbox'] | ||||
|         db.create_unique(u'managemails_mailaddressmailbox', ['mailaddress_id', 'mailbox_id']) | ||||
| 
 | ||||
|         # Adding model 'MailAddressForward' | ||||
|         db.create_table(u'managemails_mailaddressforward', ( | ||||
|             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||||
|             ('mailaddress', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['managemails.MailAddress'])), | ||||
|             ('target', self.gf('django.db.models.fields.EmailField')(max_length=254)), | ||||
|         )) | ||||
|         db.send_create_signal(u'managemails', ['MailAddressForward']) | ||||
| 
 | ||||
|         # Adding unique constraint on 'MailAddressForward', fields ['mailaddress', 'target'] | ||||
|         db.create_unique(u'managemails_mailaddressforward', ['mailaddress_id', 'target']) | ||||
| 
 | ||||
| 
 | ||||
|     def backwards(self, orm): | ||||
|         # Removing unique constraint on 'MailAddressForward', fields ['mailaddress', 'target'] | ||||
|         db.delete_unique(u'managemails_mailaddressforward', ['mailaddress_id', 'target']) | ||||
| 
 | ||||
|         # Removing unique constraint on 'MailAddressMailbox', fields ['mailaddress', 'mailbox'] | ||||
|         db.delete_unique(u'managemails_mailaddressmailbox', ['mailaddress_id', 'mailbox_id']) | ||||
| 
 | ||||
|         # Removing unique constraint on 'MailAddress', fields ['localpart', 'domain'] | ||||
|         db.delete_unique(u'managemails_mailaddress', ['localpart', 'domain_id']) | ||||
| 
 | ||||
|         # Deleting model 'MailDomain' | ||||
|         db.delete_table(u'managemails_maildomain') | ||||
| 
 | ||||
|         # Deleting model 'Mailbox' | ||||
|         db.delete_table(u'managemails_mailbox') | ||||
| 
 | ||||
|         # Deleting model 'MailAddress' | ||||
|         db.delete_table(u'managemails_mailaddress') | ||||
| 
 | ||||
|         # Deleting model 'MailAddressMailbox' | ||||
|         db.delete_table(u'managemails_mailaddressmailbox') | ||||
| 
 | ||||
|         # Deleting model 'MailAddressForward' | ||||
|         db.delete_table(u'managemails_mailaddressforward') | ||||
| 
 | ||||
| 
 | ||||
|     models = { | ||||
|         u'managemails.mailaddress': { | ||||
|             'Meta': {'unique_together': "(('localpart', 'domain'),)", 'object_name': 'MailAddress'}, | ||||
|             'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||||
|             'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailDomain']"}), | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'localpart': ('django.db.models.fields.CharField', [], {'max_length': '128'}) | ||||
|         }, | ||||
|         u'managemails.mailaddressforward': { | ||||
|             'Meta': {'unique_together': "(('mailaddress', 'target'),)", 'object_name': 'MailAddressForward'}, | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'mailaddress': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailAddress']"}), | ||||
|             'target': ('django.db.models.fields.EmailField', [], {'max_length': '254'}) | ||||
|         }, | ||||
|         u'managemails.mailaddressmailbox': { | ||||
|             'Meta': {'unique_together': "(('mailaddress', 'mailbox'),)", 'object_name': 'MailAddressMailbox'}, | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'mailaddress': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailAddress']"}), | ||||
|             'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.Mailbox']"}) | ||||
|         }, | ||||
|         u'managemails.mailbox': { | ||||
|             'Meta': {'object_name': 'Mailbox'}, | ||||
|             'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||||
|             'domain': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||||
|             'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailDomain']"}), | ||||
|             'gid': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), | ||||
|             'home': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'password': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||||
|             'uid': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), | ||||
|             'username': ('django.db.models.fields.CharField', [], {'max_length': '128'}) | ||||
|             'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}) | ||||
|         }, | ||||
|         u'managemails.maildomain': { | ||||
|             'Meta': {'object_name': 'MailDomain'}, | ||||
|             'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,58 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| from south.utils import datetime_utils as datetime | ||||
| from south.db import db | ||||
| from south.v2 import SchemaMigration | ||||
| from django.db import models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(SchemaMigration): | ||||
| 
 | ||||
|     def forwards(self, orm): | ||||
| 
 | ||||
|         # Changing field 'Mailbox.password' | ||||
|         db.alter_column(u'managemails_mailbox', 'password', self.gf('django.db.models.fields.CharField')(max_length=255)) | ||||
| 
 | ||||
|     def backwards(self, orm): | ||||
| 
 | ||||
|         # Changing field 'Mailbox.password' | ||||
|         db.alter_column(u'managemails_mailbox', 'password', self.gf('django.db.models.fields.CharField')(max_length=64)) | ||||
| 
 | ||||
|     models = { | ||||
|         u'managemails.mailaddress': { | ||||
|             'Meta': {'unique_together': "(('localpart', 'domain'),)", 'object_name': 'MailAddress'}, | ||||
|             'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||||
|             'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailDomain']"}), | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'localpart': ('django.db.models.fields.CharField', [], {'max_length': '128'}) | ||||
|         }, | ||||
|         u'managemails.mailaddressforward': { | ||||
|             'Meta': {'unique_together': "(('mailaddress', 'target'),)", 'object_name': 'MailAddressForward'}, | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'mailaddress': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailAddress']"}), | ||||
|             'target': ('django.db.models.fields.EmailField', [], {'max_length': '254'}) | ||||
|         }, | ||||
|         u'managemails.mailaddressmailbox': { | ||||
|             'Meta': {'unique_together': "(('mailaddress', 'mailbox'),)", 'object_name': 'MailAddressMailbox'}, | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'mailaddress': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailAddress']"}), | ||||
|             'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.Mailbox']"}) | ||||
|         }, | ||||
|         u'managemails.mailbox': { | ||||
|             'Meta': {'object_name': 'Mailbox'}, | ||||
|             'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||||
|             'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['managemails.MailDomain']"}), | ||||
|             'gid': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), | ||||
|             'home': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||||
|             'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}), | ||||
|             'uid': ('django.db.models.fields.PositiveSmallIntegerField', [], {}), | ||||
|             'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}) | ||||
|         }, | ||||
|         u'managemails.maildomain': { | ||||
|             'Meta': {'object_name': 'MailDomain'}, | ||||
|             'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}), | ||||
|             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     complete_apps = ['managemails'] | ||||
|  | @ -1,11 +1,64 @@ | |||
| from django.db import models | ||||
| from django.utils.encoding import python_2_unicode_compatible | ||||
| from django.utils.translation import ugettext as _ | ||||
| from passlib.hash import sha512_crypt | ||||
| 
 | ||||
| 
 | ||||
| @python_2_unicode_compatible | ||||
| class MailDomain(models.Model): | ||||
|     domain = models.CharField(max_length=128, unique=True) | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _('Mail domain') | ||||
|         verbose_name_plural = _('Mail domains') | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.domain | ||||
| 
 | ||||
| 
 | ||||
| class Mailbox(models.Model): | ||||
|     username = models.CharField(max_length=128) | ||||
|     domain = models.CharField(max_length=128) | ||||
|     password = models.CharField(max_length=64) | ||||
|     username = models.CharField(max_length=128, unique=True) | ||||
|     domain = models.ForeignKey(MailDomain) | ||||
|     password = models.CharField(max_length=255) | ||||
|     home = models.CharField(max_length=255) | ||||
|     uid = models.PositiveSmallIntegerField() | ||||
|     gid = models.PositiveSmallIntegerField() | ||||
|     active = models.BooleanField(default=True) | ||||
| 
 | ||||
|     class Meta: | ||||
|         verbose_name = _('Mailbox') | ||||
|         verbose_name_plural = _('Mailboxes') | ||||
| 
 | ||||
|     def set_password(self, password): | ||||
|         self.password = sha512_crypt.encrypt(password) | ||||
| 
 | ||||
| 
 | ||||
| @python_2_unicode_compatible | ||||
| class MailAddress(models.Model): | ||||
|     localpart = models.CharField(max_length=128) | ||||
|     domain = models.ForeignKey(MailDomain) | ||||
|     active = models.BooleanField(default=True) | ||||
| 
 | ||||
|     class Meta: | ||||
|         unique_together = ('localpart', 'domain') | ||||
|         verbose_name = _('Mail address') | ||||
|         verbose_name_plural = _('Mail addresses') | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return "{0}@{1}".format(self.localpart, self.domain) | ||||
| 
 | ||||
| 
 | ||||
| class MailAddressMailbox(models.Model): | ||||
|     mailaddress = models.ForeignKey(MailAddress) | ||||
|     mailbox = models.ForeignKey(Mailbox) | ||||
| 
 | ||||
|     class Meta: | ||||
|         unique_together = ('mailaddress', 'mailbox') | ||||
| 
 | ||||
| 
 | ||||
| class MailAddressForward(models.Model): | ||||
|     mailaddress = models.ForeignKey(MailAddress) | ||||
|     target = models.EmailField(max_length=254) | ||||
| 
 | ||||
|     class Meta: | ||||
|         unique_together = ('mailaddress', 'target') | ||||
|  |  | |||
|  | @ -5,3 +5,4 @@ django-model-utils==2.0.3 | |||
| logutils==0.3.3 | ||||
| South==0.8.4 | ||||
| psycopg2==2.5.3 | ||||
| passlib==1.6.2 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue