mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
tests for modoboa.admin for python 2 and 3
This commit is contained in:
@@ -8,6 +8,7 @@ from django import forms
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import QueryDict
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.core.models import User
|
||||
@@ -98,7 +99,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
if label is not None:
|
||||
self.add_error(
|
||||
"name", _("A %s with this name already exists")
|
||||
% unicode(label)
|
||||
% force_text(label)
|
||||
)
|
||||
condition = (
|
||||
self.cleaned_data["quota"] != 0 and
|
||||
@@ -120,7 +121,8 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
if default_mailbox_quota == 0:
|
||||
self.add_error("default_mailbox_quota", msg)
|
||||
self.aliases = []
|
||||
for k in cleaned_data.keys():
|
||||
copied_data = cleaned_data.copy()
|
||||
for k in copied_data.keys():
|
||||
if not k.startswith("aliases"):
|
||||
continue
|
||||
if cleaned_data[k] == "":
|
||||
@@ -137,7 +139,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
if label is not None:
|
||||
self.add_error(
|
||||
k, _("A %s with this name already exists")
|
||||
% unicode(label)
|
||||
% force_text(label)
|
||||
)
|
||||
else:
|
||||
self.aliases.append(cleaned_data[k])
|
||||
|
||||
@@ -7,7 +7,9 @@ import random
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible, smart_text
|
||||
from django.utils.encoding import (
|
||||
python_2_unicode_compatible, smart_text, force_str, force_bytes
|
||||
)
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from reversion import revisions as reversion
|
||||
@@ -64,7 +66,7 @@ class Alias(AdminObject):
|
||||
"""Generate a random address (local part)."""
|
||||
m = hashlib.md5()
|
||||
for x in random.sample(range(10000000), 60):
|
||||
m.update(str(x))
|
||||
m.update(force_bytes(x))
|
||||
return m.hexdigest()[:20]
|
||||
|
||||
@property
|
||||
@@ -111,7 +113,6 @@ class Alias(AdminObject):
|
||||
is defined on the associated domain
|
||||
|
||||
"""
|
||||
to_create = []
|
||||
for address in set(address_list):
|
||||
if not address:
|
||||
continue
|
||||
@@ -195,10 +196,11 @@ class Alias(AdminObject):
|
||||
self.post_create(user)
|
||||
|
||||
def to_csv(self, csvwriter):
|
||||
row = ["alias", self.address.encode("utf-8"), self.enabled]
|
||||
row = ["alias", force_str(self.address), self.enabled]
|
||||
row += self.recipients
|
||||
csvwriter.writerow(row)
|
||||
|
||||
|
||||
reversion.register(Alias)
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@ from functools import reduce
|
||||
from django.db import models
|
||||
from django.db.models.manager import Manager
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import python_2_unicode_compatible, smart_text
|
||||
from django.utils.encoding import (
|
||||
python_2_unicode_compatible, smart_text, force_text
|
||||
)
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
@@ -281,7 +283,10 @@ class Domain(AdminObject):
|
||||
def to_csv(self, csvwriter):
|
||||
"""Export domain and domain aliases to CSV format."""
|
||||
csvwriter.writerow([
|
||||
"domain", self.name, self.quota, self.default_mailbox_quota,
|
||||
"domain",
|
||||
force_text(self.name),
|
||||
self.quota,
|
||||
self.default_mailbox_quota,
|
||||
self.enabled
|
||||
])
|
||||
for dalias in self.domainalias_set.all():
|
||||
@@ -296,6 +301,7 @@ class Domain(AdminObject):
|
||||
for domalias in self.domainalias_set.all():
|
||||
domalias.post_create(creator)
|
||||
|
||||
|
||||
reversion.register(Domain)
|
||||
|
||||
|
||||
|
||||
@@ -222,12 +222,12 @@ class DomainTestCase(ModoTestCase):
|
||||
url = reverse("admin:domain_detail", args=[domain.pk])
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn("Summary", response.content)
|
||||
self.assertIn("Administrators", response.content)
|
||||
self.assertNotIn("Resources usage", response.content)
|
||||
self.assertIn("Summary", response.content.decode())
|
||||
self.assertIn("Administrators", response.content.decode())
|
||||
self.assertNotIn("Resources usage", response.content.decode())
|
||||
self.set_global_parameter("enable_domain_limits", True, app="limits")
|
||||
response = self.client.get(url)
|
||||
self.assertIn("Resources usage", response.content)
|
||||
self.assertIn("Resources usage", response.content.decode())
|
||||
|
||||
def test_statitics_widget(self):
|
||||
"""Test statistics display in dashboard."""
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.encoding import force_text
|
||||
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
@@ -38,8 +39,8 @@ class ExportTestCase(ModoTestCase):
|
||||
)
|
||||
|
||||
def assertListEqual(self, list1, list2):
|
||||
list1 = list1.split("\r\n")
|
||||
list2 = list2.split("\r\n")
|
||||
list1 = force_text(list1).split("\r\n")
|
||||
list2 = force_text(list2).split("\r\n")
|
||||
self.assertEqual(len(list1), len(list2))
|
||||
for entry in list1:
|
||||
if not entry:
|
||||
@@ -85,7 +86,7 @@ class ExportTestCase(ModoTestCase):
|
||||
response = self.__export_identities(
|
||||
idtfilter="account", grpfilter="SuperAdmins"
|
||||
)
|
||||
elements = response.content.strip().split(";")
|
||||
elements = response.content.decode().strip().split(";")
|
||||
self.assertEqual(len(elements), 9)
|
||||
elements[2] = ""
|
||||
self.assertEqual(
|
||||
@@ -104,6 +105,6 @@ class ExportTestCase(ModoTestCase):
|
||||
def test_export_aliases(self):
|
||||
response = self.__export_identities(idtfilter="alias")
|
||||
self.assertEqual(
|
||||
response.content.strip(),
|
||||
response.content.decode().strip(),
|
||||
"alias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,6 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.encoding import force_bytes
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
@@ -84,14 +83,14 @@ domainalias;test.alias;test.com;True
|
||||
"sourcefile": f
|
||||
}
|
||||
)
|
||||
self.assertIn('Object already exists: domainalias', resp.content)
|
||||
self.assertIn('Object already exists: domainalias', resp.content.decode())
|
||||
|
||||
def test_identities_import(self):
|
||||
response = self.client.get(reverse("admin:identity_import"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn("Provide a CSV", response.content.decode())
|
||||
|
||||
f = ContentFile(b"""
|
||||
f = ContentFile("""
|
||||
account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; 0
|
||||
account; Truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 5; test.com
|
||||
alias; alias1@test.com; True; user1@test.com
|
||||
@@ -193,7 +192,7 @@ domain; domain2.com; 1000; 200; False
|
||||
reverse("admin:identity_import"),
|
||||
{"sourcefile": f, "crypt_password": True}
|
||||
)
|
||||
self.assertIn("You are not allowed to import domains", resp.content)
|
||||
self.assertIn("You are not allowed to import domains", resp.content.decode())
|
||||
f = ContentFile(b"""
|
||||
domainalias; domalias1.com; test.com; True
|
||||
""", name="identities.csv")
|
||||
@@ -202,7 +201,7 @@ domainalias; domalias1.com; test.com; True
|
||||
{"sourcefile": f, "crypt_password": True}
|
||||
)
|
||||
self.assertIn(
|
||||
"You are not allowed to import domain aliases", resp.content)
|
||||
"You are not allowed to import domain aliases", resp.content.decode())
|
||||
|
||||
def test_import_quota_too_big(self):
|
||||
self.client.logout()
|
||||
@@ -231,7 +230,7 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com
|
||||
)
|
||||
|
||||
def test_import_duplicate(self):
|
||||
f = ContentFile(b"""
|
||||
f = ContentFile("""
|
||||
account; admin@test.com; toto; Admin; ; True; DomainAdmins; admin@test.com; 0; test.com
|
||||
account; truc@test.com; toto; René; Truc; True; DomainAdmins; truc@test.com; 0; test.com
|
||||
""", name="identities.csv")
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import csv
|
||||
import io
|
||||
|
||||
from rfc6266 import build_header
|
||||
|
||||
@@ -15,6 +14,7 @@ from django.http import HttpResponse
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils import six
|
||||
|
||||
from ..forms import ExportIdentitiesForm, ExportDomainsForm
|
||||
from ..lib import get_domains, get_identities
|
||||
@@ -50,7 +50,7 @@ def export_identities(request):
|
||||
if request.method == "POST":
|
||||
form = ExportIdentitiesForm(request.POST)
|
||||
form.is_valid()
|
||||
fp = io.BytesIO()
|
||||
fp = six.StringIO()
|
||||
csvwriter = csv.writer(
|
||||
fp, delimiter=smart_str(form.cleaned_data["sepchar"])
|
||||
)
|
||||
@@ -80,7 +80,7 @@ def export_domains(request):
|
||||
if request.method == "POST":
|
||||
form = ExportDomainsForm(request.POST)
|
||||
form.is_valid()
|
||||
fp = io.BytesIO()
|
||||
fp = six.StringIO()
|
||||
csvwriter = csv.writer(
|
||||
fp, delimiter=smart_str(form.cleaned_data["sepchar"])
|
||||
)
|
||||
|
||||
@@ -14,6 +14,7 @@ from django.db import transaction
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import smart_str, force_text
|
||||
from django.utils import six
|
||||
|
||||
from reversion import revisions as reversion
|
||||
|
||||
@@ -39,8 +40,14 @@ def importdata(request, formclass=ImportDataForm):
|
||||
form = formclass(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
try:
|
||||
if six.PY2:
|
||||
infile = request.FILES['sourcefile']
|
||||
else:
|
||||
infile = StringIO(
|
||||
force_text(request.FILES['sourcefile'].read())
|
||||
)
|
||||
reader = csv.reader(
|
||||
request.FILES['sourcefile'],
|
||||
infile,
|
||||
delimiter=smart_str(form.cleaned_data['sepchar'])
|
||||
)
|
||||
except csv.Error as inst:
|
||||
|
||||
@@ -9,7 +9,8 @@ from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import (
|
||||
python_2_unicode_compatible, smart_bytes, smart_text, force_str)
|
||||
python_2_unicode_compatible, smart_bytes, smart_text, force_str, force_text
|
||||
)
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
@@ -411,13 +412,13 @@ class User(PermissionsMixin):
|
||||
"""
|
||||
row = [
|
||||
"account",
|
||||
smart_bytes(self.username),
|
||||
smart_bytes(self.password),
|
||||
smart_bytes(self.first_name),
|
||||
smart_bytes(self.last_name),
|
||||
self.is_active,
|
||||
self.role,
|
||||
smart_bytes(self.email)
|
||||
force_text(self.username),
|
||||
force_text(self.password),
|
||||
force_text(self.first_name),
|
||||
force_text(self.last_name),
|
||||
force_text(self.is_active),
|
||||
force_text(self.role),
|
||||
force_text(self.email)
|
||||
]
|
||||
results = signals.account_exported.send(
|
||||
sender=self.__class__, user=self)
|
||||
|
||||
@@ -13,7 +13,7 @@ from random import Random
|
||||
import string
|
||||
|
||||
from django.utils.crypto import constant_time_compare
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_text, force_bytes
|
||||
|
||||
|
||||
class PasswordHasher(object):
|
||||
@@ -36,7 +36,7 @@ class PasswordHasher(object):
|
||||
"""
|
||||
if self._target == 'ldap':
|
||||
return base64.b64encode(pwhash)
|
||||
return force_text(pwhash)
|
||||
return pwhash
|
||||
|
||||
def encrypt(self, clearvalue):
|
||||
"""Encrypt a password.
|
||||
@@ -51,8 +51,8 @@ class PasswordHasher(object):
|
||||
:rtype: str
|
||||
:return: encrypted password
|
||||
"""
|
||||
pwhash = self._b64encode(self._encrypt(clearvalue))
|
||||
return '%s%s' % (self.scheme, pwhash)
|
||||
pwhash = self._b64encode(self._encrypt(force_text(clearvalue)))
|
||||
return '%s%s' % (self.scheme, force_text(pwhash))
|
||||
|
||||
def verify(self, clearvalue, hashed_value):
|
||||
"""Verify a password against a hashed value.
|
||||
@@ -109,7 +109,7 @@ class MD5Hasher(PasswordHasher):
|
||||
return '{MD5}'
|
||||
|
||||
def _encrypt(self, clearvalue, salt=None):
|
||||
obj = hashlib.md5(clearvalue)
|
||||
obj = hashlib.md5(force_bytes(clearvalue))
|
||||
return obj.hexdigest()
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ class SHA256Hasher(PasswordHasher):
|
||||
return '{SHA256}'
|
||||
|
||||
def _encrypt(self, clearvalue, salt=None):
|
||||
return hashlib.sha256(clearvalue).digest()
|
||||
return hashlib.sha256(force_bytes(clearvalue)).digest()
|
||||
|
||||
def _b64encode(self, pwhash):
|
||||
"""Encode :keyword:`pwhash` using base64.
|
||||
|
||||
@@ -40,6 +40,7 @@ import ldap
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils import six
|
||||
|
||||
from modoboa.core.password_hashers import get_password_hasher
|
||||
from modoboa.lib.exceptions import InternalError
|
||||
|
||||
@@ -4,9 +4,8 @@ envlist = py27,py34
|
||||
[testenv]
|
||||
changedir=test_project
|
||||
commands =
|
||||
; python ../tests.py
|
||||
; coverage run --source modoboa manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.relaydomains
|
||||
coverage run --source modoboa manage.py test modoboa.admin
|
||||
python ../tests.py
|
||||
coverage run --source modoboa manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.relaydomains
|
||||
|
||||
coverage report --show-missing
|
||||
deps =
|
||||
|
||||
Reference in New Issue
Block a user