diff --git a/modoboa/extensions/admin/forms/account.py b/modoboa/extensions/admin/forms/account.py index 674818b3e..2290196de 100644 --- a/modoboa/extensions/admin/forms/account.py +++ b/modoboa/extensions/admin/forms/account.py @@ -192,6 +192,7 @@ class AccountFormMail(forms.Form, DynamicForm): elif account.group == "SimpleUsers" and account.username != self.mb.full_address: newaddress = account.username if newaddress is not None: + self.mb.old_full_address = self.mb.full_address local_part, domname = split_mailbox(newaddress) try: domain = Domain.objects.get(name=domname) @@ -207,6 +208,7 @@ class AccountFormMail(forms.Form, DynamicForm): else False self.mb.set_quota(self.cleaned_data["quota"], override_rules) self.mb.save() + events.raiseEvent('MailboxModified', self.mb) def save(self, user, account): if self.cleaned_data["email"] == "": diff --git a/modoboa/extensions/postfix_autoreply/general_callbacks.py b/modoboa/extensions/postfix_autoreply/general_callbacks.py index 192345d44..86b89f9c1 100644 --- a/modoboa/extensions/postfix_autoreply/general_callbacks.py +++ b/modoboa/extensions/postfix_autoreply/general_callbacks.py @@ -85,10 +85,10 @@ def onMailboxDeleted(mailboxes): @events.observe("MailboxModified") -def onModifyMailbox(mailbox, oldmailbox): - if oldmailbox.full_address == mailbox.full_address: +def onMailboxModified(mailbox): + if mailbox.full_address == mailbox.old_full_address: return - alias = Alias.objects.get(full_address=oldmailbox.full_address) + alias = Alias.objects.get(full_address=mailbox.old_full_address) alias.full_address = mailbox.full_address alias.autoreply_address = \ "%s@autoreply.%s" % (mailbox.full_address, mailbox.domain.name) diff --git a/modoboa/extensions/postfix_autoreply/migrations/0006_auto__chg_field_armessage_untildate.py b/modoboa/extensions/postfix_autoreply/migrations/0006_auto__chg_field_armessage_untildate.py new file mode 100644 index 000000000..9458b7891 --- /dev/null +++ b/modoboa/extensions/postfix_autoreply/migrations/0006_auto__chg_field_armessage_untildate.py @@ -0,0 +1,121 @@ +# -*- coding: 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): + + # Changing field 'ARmessage.untildate' + db.alter_column(u'postfix_autoreply_armessage', 'untildate', self.gf('django.db.models.fields.DateTimeField')(null=True)) + + def backwards(self, orm): + + # User chose to not deal with backwards NULL issues for 'ARmessage.untildate' + raise RuntimeError("Cannot reverse this migration. 'ARmessage.untildate' and its values cannot be restored.") + + models = { + 'admin.domain': { + 'Meta': {'ordering': "['name']", 'object_name': 'Domain'}, + 'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'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.mailbox': { + 'Meta': {'object_name': 'Mailbox'}, + 'address': ('django.db.models.fields.CharField', [], {'max_length': '252'}), + 'dates': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.ObjectDates']"}), + 'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Domain']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'quota': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'use_domain_quota': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.User']"}) + }, + 'admin.objectdates': { + 'Meta': {'object_name': 'ObjectDates'}, + 'creation': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modification': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'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'}), + u'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'}) + }, + u'core.objectaccess': { + 'Meta': {'unique_together': "(('user', 'content_type', 'object_id'),)", 'object_name': 'ObjectAccess'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_owner': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['core.User']"}) + }, + u'core.user': { + 'Meta': {'ordering': "['username']", 'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '254', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_local': ('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': '256'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '254'}) + }, + u'postfix_autoreply.alias': { + 'Meta': {'object_name': 'Alias'}, + 'autoreply_address': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'full_address': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'postfix_autoreply.arhistoric': { + 'Meta': {'unique_together': "(('armessage', 'sender'),)", 'object_name': 'ARhistoric'}, + 'armessage': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['postfix_autoreply.ARmessage']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_sent': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'sender': ('django.db.models.fields.CharField', [], {'max_length': '254'}) + }, + u'postfix_autoreply.armessage': { + 'Meta': {'object_name': 'ARmessage'}, + 'content': ('django.db.models.fields.TextField', [], {}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'fromdate': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mbox': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['admin.Mailbox']"}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'untildate': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + u'postfix_autoreply.transport': { + 'Meta': {'object_name': 'Transport'}, + 'domain': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'method': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + } + } + + complete_apps = ['postfix_autoreply'] \ No newline at end of file diff --git a/modoboa/extensions/postfix_autoreply/models.py b/modoboa/extensions/postfix_autoreply/models.py index 9d1df0e46..ad8c1e03a 100644 --- a/modoboa/extensions/postfix_autoreply/models.py +++ b/modoboa/extensions/postfix_autoreply/models.py @@ -29,7 +29,7 @@ class ARmessage(models.Model): help_text=_("Activate/Deactivate your auto reply") ) fromdate = models.DateTimeField(default=timezone.now) - untildate = models.DateTimeField() + untildate = models.DateTimeField(null=True, blank=True) class ARhistoric(models.Model): diff --git a/modoboa/extensions/postfix_autoreply/tests.py b/modoboa/extensions/postfix_autoreply/tests.py new file mode 100644 index 000000000..fe73d2ddd --- /dev/null +++ b/modoboa/extensions/postfix_autoreply/tests.py @@ -0,0 +1,129 @@ +from django.core.urlresolvers import reverse +from modoboa.core.models import User +from modoboa.lib.tests import ExtTestCase +from modoboa.extensions.admin import factories +from modoboa.extensions.admin.models import ( + Domain +) +from modoboa.extensions.postfix_autoreply.models import ( + Transport, Alias, ARmessage +) + + +class EventsTestCase(ExtTestCase): + fixtures = ['initial_users.json'] + + def setUp(self): + super(EventsTestCase, self).setUp() + self.activate_extensions('postfix_autoreply') + factories.populate_database() + + def test_domain_created_event(self): + values = { + "name": "domain.tld", "quota": 100, "create_dom_admin": "no", + "stepid": 'step2' + } + self.ajax_post( + reverse("modoboa.extensions.admin.views.domain.newdomain"), + values + ) + trans = Transport.objects.get(domain='autoreply.domain.tld') + + def test_domain_deleted_event(self): + dom = Domain.objects.get(name="test.com") + trans = Transport.objects.get(domain='autoreply.test.com') + self.ajax_post( + reverse("modoboa.extensions.admin.views.domain.deldomain", + args=[dom.id]), + {} + ) + with self.assertRaises(Transport.DoesNotExist): + Transport.objects.get(domain='autoreply.test.com') + + def test_domain_modified_event(self): + values = { + "name": "test.fr", "quota": 100, "enabled": True + } + dom = Domain.objects.get(name="test.com") + self.ajax_post( + reverse("modoboa.extensions.admin.views.domain.editdomain", + args=[dom.id]), + values + ) + trans = Transport.objects.get(domain='autoreply.test.fr') + self.assertEqual( + Alias.objects.filter(full_address__contains='@test.fr').count(), 2 + ) + for al in Alias.objects.filter(full_address__contains='@test.fr'): + self.assertIn('autoreply.test.fr', al.autoreply_address) + + def test_mailbox_created_event(self): + values = { + 'username': "tester@test.com", 'first_name': 'Tester', 'last_name': 'Toto', + 'password1': 'toto', 'password2': 'toto', 'role': 'SimpleUsers', + 'quota_act': True, 'is_active': True, 'email': 'tester@test.com', + 'stepid': 'step2', 'autoreply': 'no' + } + self.ajax_post( + reverse("modoboa.extensions.admin.views.identity.newaccount"), + values + ) + al = Alias.objects.get(full_address='tester@test.com') + self.assertEqual(al.autoreply_address, 'tester@test.com@autoreply.test.com') + arm = ARmessage.objects.get(mbox__address='tester') + + def test_mailbox_deleted_event(self): + account = User.objects.get(username="user@test.com") + self.ajax_post( + reverse("modoboa.extensions.admin.views.identity.delaccount", + args=[account.id]), + {} + ) + with self.assertRaises(Alias.DoesNotExist): + Alias.objects.get(full_address='user@test.com') + with self.assertRaises(ARmessage.DoesNotExist): + ARmessage.objects.get(mbox__address='user', mbox__domain__name='test.com') + + + def test_modify_mailbox_event(self): + values = { + 'username': "leon@test.com", 'first_name': 'Tester', 'last_name': 'Toto', + 'role': 'SimpleUsers', 'quota_act': True, 'is_active': True, + 'email': 'leon@test.com', 'autoreply': 'no' + } + account = User.objects.get(username="user@test.com") + self.ajax_post( + reverse("modoboa.extensions.admin.views.identity.editaccount", + args=[account.id]), + values + ) + with self.assertRaises(Alias.DoesNotExist): + Alias.objects.get(full_address='user@test.com') + al = Alias.objects.get(full_address='leon@test.com') + + +class FormTestCase(ExtTestCase): + fixtures = ['initial_users.json'] + + def setUp(self): + super(FormTestCase, self).setUp() + self.activate_extensions('postfix_autoreply') + factories.populate_database() + + # def test_set_autoreply(self): + # self.clt.get( + # reverse('modoboa.core.views.user.index') + # ) + # values = { + # 'subject': 'test', 'content': "I'm off", "enabled": True + # } + # self.ajax_post( + # reverse('modoboa.extensions.postfix_autoreply.views.autoreply'), + # values + # ) + # account = User.objects.get(username="user@test.com") + # arm = ARmessage.objects.get(mbox=account.mailbox_set.all()[0]) + # self.assertEqual(arm.subject, 'test') + # self.assertTrue(arm.enabled) + # self.assertFalse(arm.untildate) + # self.assertTrue(arm.fromdate)