From 8e25023c001209f970257569777c1d19bcf9dae4 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Sat, 9 Jul 2011 15:08:21 +0200 Subject: [PATCH] Added unique constraint on the Domain.name column. --- admin/forms.py | 14 ++- .../0014_auto__add_unique_domain_name.py | 112 ++++++++++++++++++ admin/models.py | 11 +- admin/views.py | 65 +++++----- 4 files changed, 163 insertions(+), 39 deletions(-) create mode 100644 admin/migrations/0014_auto__add_unique_domain_name.py diff --git a/admin/forms.py b/admin/forms.py index 2d8fa524b..8584aff8d 100644 --- a/admin/forms.py +++ b/admin/forms.py @@ -14,9 +14,19 @@ class DomainForm(forms.ModelForm): fields = ("name", "quota", "enabled") def __init__(self, *args, **kwargs): + self.oldname = None + if kwargs.has_key("instance"): + self.oldname = kwargs["instance"].name super(DomainForm, self).__init__(*args, **kwargs) - for f in ['name', 'quota']: - self.fields[f].widget.attrs['size'] = 14 + + def save(self, force_insert=False, force_update=False, commit=True): + d = super(DomainForm, self).save(commit=False) + if commit: + if self.oldname is not None and d.name != self.oldname: + if not d.rename_dir(self.oldname): + raise AdminError(_("Failed to rename domain, check permissions")) + d.save() + return d class ProxyForm(forms.ModelForm): def __init__(self, user, *args, **kwargs): diff --git a/admin/migrations/0014_auto__add_unique_domain_name.py b/admin/migrations/0014_auto__add_unique_domain_name.py new file mode 100644 index 000000000..ad29ad746 --- /dev/null +++ b/admin/migrations/0014_auto__add_unique_domain_name.py @@ -0,0 +1,112 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding unique constraint on 'Domain', fields ['name'] + db.create_unique('admin_domain', ['name']) + + + def backwards(self, orm): + + # Removing unique constraint on 'Domain', fields ['name'] + db.delete_unique('admin_domain', ['name']) + + + models = { + 'admin.alias': { + 'Meta': {'object_name': 'Alias'}, + 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}), + 'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}), + 'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'extmboxes': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mboxes': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['admin.Mailbox']", 'symmetrical': 'False'}) + }, + 'admin.domain': { + 'Meta': {'object_name': 'Domain'}, + 'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'quota': ('django.db.models.fields.IntegerField', [], {}) + }, + 'admin.domainalias': { + 'Meta': {'object_name': 'DomainAlias'}, + 'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"}) + }, + 'admin.extension': { + 'Meta': {'object_name': 'Extension'}, + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '150'}) + }, + 'admin.mailbox': { + 'Meta': {'object_name': 'Mailbox'}, + 'address': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}), + 'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"}), + 'gid': ('django.db.models.fields.IntegerField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'quota': ('django.db.models.fields.IntegerField', [], {}), + 'uid': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'admin.objectdates': { + 'Meta': {'object_name': 'ObjectDates'}, + 'creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['admin'] diff --git a/admin/models.py b/admin/models.py index 29b01e9df..6e1feb7e9 100644 --- a/admin/models.py +++ b/admin/models.py @@ -63,7 +63,7 @@ class DatesAware(models.Model): super(DatesAware, self).save(*args, **kwargs) class Domain(DatesAware): - name = models.CharField(_('name'), max_length=100, + name = models.CharField(_('name'), max_length=100, unique=True, help_text=_("The domain name")) quota = models.IntegerField(help_text=_("Default quota in MB applied to mailboxes")) enabled = models.BooleanField(_('enabled'), @@ -79,10 +79,10 @@ class Domain(DatesAware): path = "%s/%s" % (parameters.get_admin("STORAGE_PATH"), self.name) return exec_as_vuser("mkdir -p %s" % path) - def rename_dir(self, newname): + def rename_dir(self, oldname): stpath = parameters.get_admin("STORAGE_PATH") return exec_as_vuser("mv %s/%s %s/%s" \ - % (stpath, self.name, stpath, newname)) + % (stpath, oldname, stpath, self.name)) def delete_dir(self): return exec_as_vuser("rm -r %s/%s" \ @@ -103,6 +103,11 @@ class Domain(DatesAware): if not keepdir: self.delete_dir() + def save(self, *args, **kwargs): + if not self.create_dir(): + raise AdminError("Failed to initialise domain, check permissions") + super(Domain, self).save(*args, **kwargs) + def __str__(self): return self.name diff --git a/admin/views.py b/admin/views.py index 7a738c626..b86326fac 100644 --- a/admin/views.py +++ b/admin/views.py @@ -47,32 +47,45 @@ def domains(request): domains=domains, deloptions=deloptions) +def _validate_domain(request, form, successmsg, commonctx, + callback=None, tplname="admin/adminform.html"): + """Domain validation + + Common function shared between creation and modification actions. + """ + error = None + if form.is_valid(): + try: + domain = form.save() + except AdminError, e: + error = str(e) + except IntegrityError: + error = _("Domain with this name already defined") + else: + if callback is not None: + callback(domain) + messages.info(request, successmsg, fail_silently=True) + return ajax_response(request, url=reverse(admin.views.domains)) + + commonctx["form"] = form + commonctx["error"] = error + return ajax_response(request, status="ko", template=tplname, **commonctx) + @login_required @permission_required("admin.add_domain") def newdomain(request, tplname="admin/adminform.html"): + def newdomain_cb(domain): + events.raiseEvent("CreateDomain", dom=domain) + commonctx = {"title" : _("New domain"), "submit_label" : _("Create"), "action" : reverse(newdomain), "formid" : "domform"} if request.method == "POST": form = DomainForm(request.POST) - error = None - if form.is_valid(): - if Domain.objects.filter(name=request.POST["name"]): - error = _("Domain with this name already defined") - else: - domain = form.save(commit=False) - if domain.create_dir(): - form.save() - events.raiseEvent("CreateDomain", dom=domain) - messages.info(request, _("Domain created"), fail_silently=True) - return ajax_response(request, url=reverse(admin.views.domains)) - - error = _("Failed to initialise domain, check permissions") - commonctx["form"] = form - commonctx["error"] = error - return ajax_response(request, status="ko", template=tplname, **commonctx) - + return _validate_domain(request, form, _("Domain created"), commonctx, + newdomain_cb) + form = DomainForm() commonctx["form"] = form return _render(request, tplname, commonctx) @@ -85,25 +98,9 @@ def editdomain(request, dom_id, tplname="admin/adminform.html"): "submit_label" : _("Update"), "action" : reverse(editdomain, args=[dom_id]), "formid" : "domform"} - olddomain = copy.deepcopy(domain) if request.method == "POST": form = DomainForm(request.POST, instance=domain) - error = None - if form.is_valid(): - if domain.name != olddomain.name: - if Domain.objects.filter(name=domain.name): - error = _("Domain with this name already defined") - else: - if not olddomain.rename_dir(domain.name): - error = _("Failed to rename domain, check permissions") - if not error: - form.save() - messages.info(request, _("Domain modified"), fail_silently=True) - return ajax_response(request, url=reverse(admin.views.domains)) - - commonctx["form"] = form - commonctx["error"] = error - return ajax_response(request, status="ko", template=tplname, **commonctx) + return _validate_domain(request, form, _("Domain modified"), commonctx) form = DomainForm(instance=domain) commonctx["form"] = form