From a4b5ebafd9bdd8c67345920af648aff8fdeef79e Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 9 Apr 2012 20:07:09 +0200 Subject: [PATCH] * unit tests updated * some permission issues fixed see #204 --- admin/fixtures/test_content.json | 3 +- admin/forms.py | 5 +- admin/models.py | 7 +- admin/tests.py | 217 +++++++++++++++--------- admin/views.py | 10 +- extensions/webmail/imaputils.py | 4 +- lib/tests.py | 34 ++++ userprefs/templatetags/uprefs_extras.py | 13 +- 8 files changed, 189 insertions(+), 104 deletions(-) create mode 100644 lib/tests.py diff --git a/admin/fixtures/test_content.json b/admin/fixtures/test_content.json index f9b9b8bb3..32eaccfc4 100644 --- a/admin/fixtures/test_content.json +++ b/admin/fixtures/test_content.json @@ -1,2 +1 @@ -[{"pk": 2, "model": "auth.user", "fields": {"username": "user@test.com", "is_active": "True", "is_superuser": "False", "password": "{PLAIN}toto", "groups": [2]}},{"pk": 1, "model": "admin.ObjectDates", "fields": {"creation": "2011-09-07 09:27:07.579603"}}, {"pk": 1, "model": "admin.Domain", "fields": {"name" : "test.com", "quota" : "100", "dates": "1"}}, {"pk": 1, "model": "admin.Mailbox", "fields": {"address": "user", "domain": "1", "dates": "1", "uid": "1001", "gid": "1001", "path": "user", "quota": "10", "user": "2"}}] - \ No newline at end of file +[{"pk": 2, "model": "admin.user", "fields": {"username": "user@test.com", "is_active": "True", "is_superuser": "False", "password": "{PLAIN}toto", "groups": [2]}},{"pk": 3, "model": "admin.user", "fields": {"username": "admin@test.com", "is_active": "True", "is_superuser": "False", "password": "{PLAIN}toto", "groups": [1]}},{"pk": 1, "model": "admin.ObjectDates", "fields": {"creation": "2011-09-07 09:27:07.579603"}}, {"pk": 2, "model": "admin.ObjectDates", "fields": {"creation": "2011-09-07 09:27:07.579603"}}, {"pk": 1, "model": "admin.Domain", "fields": {"name" : "test.com", "quota" : "100", "dates": "1"}}, {"pk": 1, "model": "admin.Mailbox", "fields": {"address": "user", "domain": "1", "dates": "1", "uid": "1001", "gid": "1001", "path": "user", "quota": "10", "user": "2"}}, {"pk": 2, "model": "admin.Mailbox", "fields": {"address": "admin", "domain": "1", "dates": "2", "uid": "1001", "gid": "1001", "path": "admin", "quota": "10", "user": "3"}}] diff --git a/admin/forms.py b/admin/forms.py index 4cc8f6254..fffe1316d 100644 --- a/admin/forms.py +++ b/admin/forms.py @@ -220,8 +220,9 @@ class AccountFormGeneral(forms.ModelForm): def __init__(self, user, *args, **kwargs): super(AccountFormGeneral, self).__init__(*args, **kwargs) + self.fields["is_active"].label = _("Enabled") self.user = user - if user.belongs_to_group("DomainAdmins"): + if user.group == "DomainAdmins": del self.fields["role"] return @@ -436,7 +437,7 @@ class AccountForm(TabForms): def check_perms(self, account): if account.is_superuser: return False - return account.has_perm("auth.add_user") + return account.has_perm("admin.add_domain") def _before_is_valid(self, form): if form["id"] == "general": diff --git a/admin/models.py b/admin/models.py index c4324d7bf..7142fe0fb 100644 --- a/admin/models.py +++ b/admin/models.py @@ -519,12 +519,13 @@ class Mailbox(DatesAware): def rename_dir(self, newdomain, newaddress): if parameters.get_admin("CREATE_DIRECTORIES") == "yes": - if self.domain.name == domain and newaddress == self.address: + if self.domain.name == newdomain and newaddress == self.address: return True oldpath = "%s/%s" % (parameters.get_admin("STORAGE_PATH"), self.domain.name) newpath = "%s/%s" % (parameters.get_admin("STORAGE_PATH"), newdomain) - code = exec_as_vuser("mv %s/%s %s/%s" \ - % (oldpath, self.address, newpath, newaddress)) + oldpath = os.path.join(oldpath, self.address) + newpath = os.path.join(newpath, newaddress) + code = exec_as_vuser("mv %s %s" % (oldpath, newpath)) if code: self.path = "%s/" % newaddress return code diff --git a/admin/tests.py b/admin/tests.py index 101df80fa..fa8e3ccf1 100644 --- a/admin/tests.py +++ b/admin/tests.py @@ -1,15 +1,8 @@ # coding: utf-8 """ +Basic tests for the 'admin' application +======================================= -Liste des tests effectués -========================= - -Permissions ------------ - - -* Vérifier qu'un admin de domaine qui modifie son propre compte laisse - le rôle intact """ from django.test import TestCase @@ -18,6 +11,7 @@ from django.utils import simplejson from models import * from modoboa.admin.lib import * from modoboa.lib import parameters +from modoboa.lib.tests import ModoTestCase import os @@ -43,10 +37,10 @@ class DomainTestCase(TestCase): dom.delete() self.assertEqual(os.path.exists(path), False) -class DomainAliasTestCase(TestCase): +class DomainAliasTestCase(ModoTestCase): fixtures = ["test_content.json"] - def test(self): + def test_model(self): dom = Domain.objects.get(name="test.com") domal = DomainAlias() domal.name = "domalias.net" @@ -58,36 +52,52 @@ class DomainAliasTestCase(TestCase): domal.save() domal.delete() - -class MailboxTestCase(TestCase): + def test_form(self): + clt = Client() + clt.login(username="admin", password="password") + dom = Domain.objects.get(name="test.com") + values = dict(name=dom.name, quota=dom.quota, enabled=dom.enabled, + aliases="domalias.net", aliases_1="domalias.com") + self.check_ajax_post("/modoboa/admin/domains/1/edit/", values) + self.assertEqual(len(dom.domainalias_set.all()), 2) + + del values["aliases_1"] + self.check_ajax_post("/modoboa/admin/domains/1/edit/", values) + self.assertEqual(len(dom.domainalias_set.all()), 1) + +class AccountTestCase(ModoTestCase): fixtures = ["test_content.json",] def test(self): - dom = Domain.objects.get(name="test.com") - mb = Mailbox() - mb.address = "tester" - mb.domain = dom - mb.save(name="Tester toto", password="toto", enabled=True) + values = dict(username="tester@test.com", first_name="Tester", last_name="Toto", + password1="toto", password2="toto", role="SimpleUsers", + is_active=True, email="tester@test.com", stepid=2) + self.check_ajax_post("/modoboa/admin/accounts/new/", values) + + account = User.objects.get(username="tester@test.com") + mb = account.mailbox_set.all()[0] self.assertEqual(mb.full_address, "tester@test.com") self.assertEqual(os.path.exists(mb.full_path), True) self.assertEqual(mb.quota, 100) self.assertEqual(mb.enabled, True) - self.assertIsNotNone(mb.user) - self.assertEqual(mb.user.username, mb.full_address) - self.assertTrue(mb.user.check_password("toto")) - self.assertEqual(mb.user.first_name, "Tester") - self.assertEqual(mb.user.last_name, "toto") - self.assertEqual(dom.mailbox_count, 2) + self.assertEqual(account.username, mb.full_address) + self.assertTrue(account.check_password("toto")) + self.assertEqual(account.first_name, "Tester") + self.assertEqual(account.last_name, "Toto") + self.assertEqual(mb.domain.mailbox_count, 3) - mb.address = "pouet" - mb.save() + values["email"] = "pouet@test.com" + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % account.id, values) + + mb = Mailbox.objects.get(pk=mb.id) self.assertEqual(mb.path, "%s/" % mb.address) path = mb.full_path self.assertEqual(mb.full_address, "pouet@test.com") self.assertEqual(os.path.exists(path), True) - mb.delete() + self.check_ajax_get("/modoboa/admin/accounts/delete/?selection=%d" \ + % account.id, {}) self.assertEqual(os.path.exists(path), False) def test_update_password(self): @@ -97,90 +107,129 @@ class MailboxTestCase(TestCase): * The default admin changes his password (no associated Mailbox) * A normal user changes his password """ - clt = Client() - self.assertEqual(clt.login(username="admin", password="password"), True) - response = clt.post("/modoboa/userprefs/changepassword/", + self.check_ajax_post("/modoboa/userprefs/changepassword/", {"oldpassword" : "password", "newpassword" : "titi", "confirmation" : "titi"}) - self.assertEqual(response.status_code, 200) - obj = simplejson.loads(response.content) - self.assertEqual(obj["status"], "ok") - clt.logout() - self.assertEqual(clt.login(username="admin", password="titi"), True) + self.clt.logout() - self.assertEqual(clt.login(username="user@test.com", password="toto"), + self.assertEqual(self.clt.login(username="admin", password="titi"), True) + self.assertEqual(self.clt.login(username="user@test.com", password="toto"), True) - response = clt.post("/modoboa/userprefs/changepassword/", + + self.check_ajax_post("/modoboa/userprefs/changepassword/", {"oldpassword" : "toto", "newpassword" : "tutu", "confirmation" : "tutu"}) - self.assertEqual(response.status_code, 200) - obj = simplejson.loads(response.content) - self.assertEqual(obj["status"], "ok") - clt.logout() - self.assertEqual(clt.login(username="user@test.com", password="tutu"), True) - + self.clt.logout() + self.assertEqual(self.clt.login(username="user@test.com", password="tutu"), True) -class AliasTestCase(TestCase): +class AliasTestCase(ModoTestCase): fixtures = ["test_content.json"] - def test(self): - dom = Domain.objects.get(name="test.com") - mb = Mailbox.objects.get(domain=dom, address="user") - al = Alias() - al.address = "alias" - al.domain = dom - al.enabled = True - al.save([mb], ["toto@extdomain.com"]) - self.assertEqual(al.full_address, "alias@test.com") - self.assertEqual(mb.alias_count, 1) + def test_alias(self): + user = User.objects.get(username="user@test.com") + values = dict( + username="user@test.com", role="SimpleUsers", + is_active=user.is_active, email="user@test.com", + aliases="toto@test.com", aliases_1="titi@test.com" + ) + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % user.id, values) + self.assertEqual(len(user.mailbox_set.all()[0].alias_set.all()), 2) - al.address = "global" - al.save([mb], []) - self.assertEqual(al.full_address, "global@test.com") - self.assertEqual(mb.alias_count, 1) - self.assertEqual(al.extmboxes, "") + del values["aliases_1"] + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % user.id, values) + self.assertEqual(len(user.mailbox_set.all()[0].alias_set.all()), 1) - al.delete() - self.assertEqual(mb.alias_count, 0) + def test_dlist(self): + values = dict(email="all@test.com", + recipients="user@test.com", + recipients_1="admin@test.com", + recipients_2="ext@titi.com", + enabled=True) + self.check_ajax_post("/modoboa/admin/distriblists/new/", values) + user = User.objects.get(username="user@test.com") + self.assertEqual(len(user.mailbox_set.all()[0].alias_set.all()), 1) + admin = User.objects.get(username="admin@test.com") + self.assertEqual(len(admin.mailbox_set.all()[0].alias_set.all()), 1) -class PermissionsTestCase(TestCase): + dlist = Alias.objects.get(address="all", domain__name="test.com") + self.assertEqual(len(dlist.get_recipients()), 3) + del values["recipients_1"] + self.check_ajax_post("/modoboa/admin/distriblists/edit/%d/" % dlist.id, + values) + self.assertEqual(len(dlist.get_recipients()), 2) + + self.check_ajax_get("/modoboa/admin/distriblists/delete/?selection=%d" \ + % dlist.id, {}) + self.assertRaises(Alias.DoesNotExist, Alias.objects.get, + address="all", domain__name="test.com") + + +class PermissionsTestCase(ModoTestCase): fixtures = ["test_content.json"] def setUp(self): - self.clt = Client() - self.clt.login(username="admin", password="password") + from modoboa.lib.permissions import grant_access_to_object + + super(PermissionsTestCase, self).setUp() self.user = User.objects.get(username="user@test.com") + self.values = dict( + username=self.user.username, role="DomainAdmins", + is_active=self.user.is_active, email="user@test.com" + ) + grant_access_to_object(User.objects.get(username="admin@test.com"), + Domain.objects.get(name="test.com")) def tearDown(self): self.clt.logout() def test_domain_admins(self): - response = self.clt.post("/modoboa/admin/accounts/edit/%d/" % self.user.id, - {"role" : "DomainAdmins"}) - self.assertEqual(response.status_code, 200) - obj = simplejson.loads(response.content) - self.assertEqual(obj["status"], "ok") + self.values["role"] = "DomainAdmins" + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % self.user.id, + self.values) self.assertEqual(self.user.group == "DomainAdmins", True) - response = self.clt.get("/modoboa/admin/accounts/edit/%d/" % self.user.id, - {"role" : "SimpleUsers"}) - self.assertEqual(response.status_code, 200) - obj = simplejson.loads(response.content) - self.assertEqual(obj["status"], "ok") + self.values["role"] = "SimpleUsers" + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % self.user.id, + self.values) self.assertEqual(self.user.group == 'DomainAdmins', False) def test_superusers(self): - response = self.clt.post("/modoboa/admin/permissions/add/", - {"role" : "super_admins", "user" : self.user.id}) - self.assertEqual(response.status_code, 200) - obj = simplejson.loads(response.content) - self.assertEqual(obj["status"], "ok") + self.values["role"] = "SuperAdmins" + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % self.user.id, + self.values) self.assertEqual(User.objects.get(username="user@test.com").is_superuser, True) - response = self.clt.get("/modoboa/admin/permissions/delete/", - {"role" : "super_admins", "selection" : self.user.id}) - self.assertEqual(response.status_code, 200) - obj = simplejson.loads(response.content) - self.assertEqual(obj["status"], "ok") + self.values["role"] = "SimpleUsers" + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % self.user.id, + self.values) self.assertEqual(User.objects.get(username="user@test.com").is_superuser, False) + def test_self_modif(self): + self.clt.logout() + self.assertEqual(self.clt.login(username="admin@test.com", password="toto"), + True) + admin = User.objects.get(username="admin@test.com") + values = dict(username="admin@test.com", first_name="Admin", + is_active=True, email="admin@test.com") + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % admin.id, values) + self.assertEqual(admin.group, "DomainAdmins") + self.assertEqual(admin.can_access(Domain.objects.get(name="test.com")), True) + + values["role"] = "SuperAdmins" + self.check_ajax_post("/modoboa/admin/accounts/edit/%d/" % admin.id, values) + admin = User.objects.get(username="admin@test.com") + self.assertEqual(admin.group, "DomainAdmins") + + def test_domadmin_access(self): + self.clt.logout() + self.assertEqual(self.clt.login(username="admin@test.com", password="toto"), + True) + response = self.clt.get("/modoboa/admin/domains/") + self.assertEqual(response.status_code, 302) + + user = User.objects.get(username="user@test.com") + response = self.clt.get("/modoboa/admin/accounts/edit/%d/" % user.id, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertNotEqual(response["Content-Type"], "application/json") + + diff --git a/admin/views.py b/admin/views.py index 0b0580665..201e0ba0c 100644 --- a/admin/views.py +++ b/admin/views.py @@ -324,7 +324,15 @@ def newaccount(request, tplname='admin/newaccount.html'): @transaction.commit_on_success def editaccount(request, accountid, tplname="common/tabforms.html"): account = User.objects.get(pk=accountid) - mb = account.mailbox_set.all()[0] if account.has_mailbox else None + if account.has_mailbox: + mb = account.mailbox_set.all()[0] + if not request.user.can_access(mb.domain): + raise PermDeniedException(_("You don't have access to this domain")) + else: + if not request.user.can_access(account): + raise PermDeniedException(_("You can't access this account")) + mb = None + instances = dict(general=account, mail=mb, perms=account) events.raiseEvent("FillAccountInstances", request.user, account, instances) diff --git a/extensions/webmail/imaputils.py b/extensions/webmail/imaputils.py index 0c6ec969e..26978081b 100644 --- a/extensions/webmail/imaputils.py +++ b/extensions/webmail/imaputils.py @@ -133,7 +133,7 @@ class IMAPconnector(object): self.port = int(parameters.get_admin("IMAP_PORT")) status, msg = self.login(user, password) if not status: - raise Exception(msg) + raise WebmailError(msg) def _cmd(self, name, *args, **kwargs): """IMAP command wrapper @@ -219,6 +219,8 @@ class IMAPconnector(object): def login(self, user, passwd): + import socket + try: secured = parameters.get_admin("IMAP_SECURED") if secured == "yes": diff --git a/lib/tests.py b/lib/tests.py new file mode 100644 index 000000000..d1fbb54be --- /dev/null +++ b/lib/tests.py @@ -0,0 +1,34 @@ +# coding: utf-8 +from django.test import TestCase +from django.test.client import Client +from django.utils import simplejson + +class ModoTestCase(TestCase): + + def setUp(self, username="admin", password="password"): + self.clt = Client() + self.assertEqual(self.clt.login(username=username, password=password), True) + + def check_ajax_request(self, method, url, params, status="ok", **kwargs): + response = getattr(self.clt, method) \ + (url, params, HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertEqual(response.status_code, 200) + obj = simplejson.loads(response.content) + self.assertEqual(obj["status"], status) + for kw, v in kwargs.iteritems(): + self.assertEqual(obj[kw], v) + + def check_ajax_post(self, *args, **kwargs): + self.check_ajax_request("post", *args, **kwargs) + + def check_ajax_get(self, *args, **kwargs): + self.check_ajax_request("get", *args, **kwargs) + +class ExtTestCase(ModoTestCase): + name = None + + def setUp(self, *args, **kwargs): + super(ExtTestCase, self).setUp(*args, **kwargs) + self.clt.get("/modoboa/admin/settings/extensions/") + self.clt.post("/modoboa/admin/settings/extensions/save/", + {"select_%s" % self.name : "1"}) diff --git a/userprefs/templatetags/uprefs_extras.py b/userprefs/templatetags/uprefs_extras.py index e5200edb1..5540dd814 100644 --- a/userprefs/templatetags/uprefs_extras.py +++ b/userprefs/templatetags/uprefs_extras.py @@ -39,9 +39,9 @@ def user_menu(user): "label" : _("Change password"), "modal" : True, "modalcb" : "chpasswordform_cb"}, - {"name" : "preferences", + {"name" : "settings", "img" : "icon-list", - "label" : _("Preferences"), + "label" : _("Settings"), "url" : reverse("modoboa.userprefs.views.preferences")} ]} ] @@ -70,12 +70,3 @@ def loadextmenu(selection, user): menu = events.raiseQueryEvent("UserMenuDisplay", "top_menu", user) return render_to_string('common/menulist.html', {"selection" : selection, "entries" : menu, "user" : user}) - -@register.simple_tag -def extra_head_content(): - tpl = Template("{% for sc in static_content %}{{ sc|safe }}{% endfor %}") - return tpl.render( - Context( - dict(static_content=events.raiseQueryEvent("GetStaticContent", "userprefs")) - ) - )