fix quotes

This ensures all files use " for quotes with the exception of
migrations, as this are auto generated I've not modified them.

pip install unify
unify --in-place --recursive --quote \" .
This commit is contained in:
Andrew Fyfe
2018-02-03 00:43:58 +00:00
parent 0e466a98e6
commit 8a1d5736c9
70 changed files with 649 additions and 649 deletions
+17 -17
View File
@@ -26,20 +26,20 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
'sphinx.ext.intersphinx',
"sphinx.ext.intersphinx",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['.templates']
templates_path = [".templates"]
# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = u'Modoboa'
@@ -50,9 +50,9 @@ copyright = u'2018, Antoine Nguyen'
# built documents.
#
# The short X.Y version.
version = '1.10'
version = "1.10"
# The full version, including alpha/beta/rc tags.
release = '1.10.0'
release = "1.10.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -66,7 +66,7 @@ release = '1.10.0'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['.build']
exclude_patterns = [".build"]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
@@ -83,7 +83,7 @@ exclude_patterns = ['.build']
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
@@ -94,11 +94,11 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if on_rtd:
html_theme = 'default'
html_theme = "default"
else:
html_theme = 'nature'
html_theme = "nature"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -127,7 +127,7 @@ else:
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
@@ -171,7 +171,7 @@ html_static_path = ['_static']
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Modoboadoc'
htmlhelp_basename = "Modoboadoc"
# -- Options for LaTeX output --------------------------------------------------
@@ -185,8 +185,8 @@ htmlhelp_basename = 'Modoboadoc'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Modoboa.tex', u'Modoboa Documentation',
u'Antoine Nguyen', 'manual'),
("index", "Modoboa.tex", u'Modoboa Documentation',
u'Antoine Nguyen', "manual"),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -218,10 +218,10 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'modoboa', u'Modoboa Documentation',
("index", "modoboa", u'Modoboa Documentation',
[u'Antoine Nguyen'], 1)
]
intersphinx_mapping = {
'amavis': ('http://modoboa-amavis.readthedocs.org/en/latest/', None)
"amavis": ("http://modoboa-amavis.readthedocs.org/en/latest/", None)
}
+2 -2
View File
@@ -81,7 +81,7 @@ class AccountViewSet(viewsets.ModelViewSet):
user = self.request.user
ids = user.objectaccess_set \
.filter(content_type=ContentType.objects.get_for_model(user)) \
.values_list('object_id', flat=True)
.values_list("object_id", flat=True)
queryset = core_models.User.objects.filter(pk__in=ids)
domain = self.request.query_params.get("domain")
if domain:
@@ -139,7 +139,7 @@ class AliasViewSet(viewsets.ModelViewSet):
ids = (
user.objectaccess_set.filter(
content_type=ContentType.objects.get_for_model(models.Alias))
.values_list('object_id', flat=True)
.values_list("object_id", flat=True)
)
queryset = models.Alias.objects.filter(pk__in=ids)
domain = self.request.query_params.get("domain")
+16 -16
View File
@@ -79,44 +79,44 @@ def populate_database():
"""
dom = DomainFactory(name="test.com", quota=50)
admin = UserFactory(
username="admin@test.com", groups=('DomainAdmins', ),
password='{PLAIN}toto'
username="admin@test.com", groups=("DomainAdmins", ),
password="{PLAIN}toto"
)
MailboxFactory(address='admin', domain=dom, user=admin)
MailboxFactory(address="admin", domain=dom, user=admin)
account = UserFactory.create(
username="user@test.com", groups=('SimpleUsers',),
username="user@test.com", groups=("SimpleUsers",),
)
MailboxFactory.create(address='user', domain=dom, user=account)
MailboxFactory.create(address="user", domain=dom, user=account)
al = AliasFactory.create(
address='forward@test.com', domain=dom
address="forward@test.com", domain=dom
)
AliasRecipientFactory.create(
address='user@external.com', alias=al)
address="user@external.com", alias=al)
al = AliasFactory.create(
address='alias@test.com', domain=dom
address="alias@test.com", domain=dom
)
mb = account.mailbox
AliasRecipientFactory.create(
address=mb.full_address, alias=al, r_mailbox=mb)
al = AliasFactory.create(
address='postmaster@test.com', domain=dom
address="postmaster@test.com", domain=dom
)
for address in ['toto@titi.com', 'test@truc.fr']:
for address in ["toto@titi.com", "test@truc.fr"]:
AliasRecipientFactory.create(address=address, alias=al)
dom.add_admin(admin)
dom2 = DomainFactory.create(name='test2.com', default_mailbox_quota=0)
dom2 = DomainFactory.create(name="test2.com", default_mailbox_quota=0)
admin = UserFactory.create(
username='admin@test2.com', groups=('DomainAdmins',),
password='{PLAIN}toto'
username="admin@test2.com", groups=("DomainAdmins",),
password="{PLAIN}toto"
)
MailboxFactory.create(address='admin', domain=dom2, user=admin)
MailboxFactory.create(address="admin", domain=dom2, user=admin)
u = UserFactory.create(
username='user@test2.com', groups=('SimpleUsers',)
username="user@test2.com", groups=("SimpleUsers",)
)
MailboxFactory.create(address='user', domain=dom2, user=u)
MailboxFactory.create(address="user", domain=dom2, user=u)
dom2.add_admin(admin)
+5 -5
View File
@@ -13,9 +13,9 @@ from .import_ import ImportDataForm, ImportIdentitiesForm
from .export import ExportDataForm, ExportDomainsForm, ExportIdentitiesForm
__all__ = [
'DomainFormGeneral', 'DomainFormOptions', 'DomainForm',
'AccountFormGeneral', 'AccountFormMail', 'AccountPermissionsForm',
'AccountForm', 'AliasForm', 'ImportDataForm', 'ImportIdentitiesForm',
'ExportDataForm', 'ExportDomainsForm', 'ExportIdentitiesForm',
'ForwardForm', 'DomainWizard', 'AccountWizard'
"DomainFormGeneral", "DomainFormOptions", "DomainForm",
"AccountFormGeneral", "AccountFormMail", "AccountPermissionsForm",
"AccountForm", "AliasForm", "ImportDataForm", "ImportIdentitiesForm",
"ExportDataForm", "ExportDomainsForm", "ExportIdentitiesForm",
"ForwardForm", "DomainWizard", "AccountWizard"
]
+6 -6
View File
@@ -527,9 +527,9 @@ class AccountForm(TabForms):
def extra_context(self, context):
account = self.instances["general"]
context.update({
'title': account.username,
'formid': 'accountform',
'action': reverse("admin:account_change",
"title": account.username,
"formid": "accountform",
"action": reverse("admin:account_change",
args=[account.id]),
})
@@ -604,9 +604,9 @@ class AccountWizard(WizardForm):
def extra_context(self, context):
context.update({
'title': _("New account"),
'action': reverse("admin:account_add"),
'formid': 'newaccount_form'
"title": _("New account"),
"action": reverse("admin:account_add"),
"formid": "newaccount_form"
})
def done(self):
+1 -1
View File
@@ -82,7 +82,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
"""Check unicity and more."""
name = self.cleaned_data["name"]
label = lib.check_if_domain_exists(
name, [(DomainAlias, _('domain alias'))])
name, [(DomainAlias, _("domain alias"))])
if label is not None:
raise forms.ValidationError(
_("A %s with this name already exists") % force_text(label))
+1 -1
View File
@@ -161,7 +161,7 @@ def account_auto_created(sender, user, **kwargs):
if not param_tools.get_global_parameter("auto_create_domain_and_mailbox"):
return
localpart, domname = split_mailbox(user.username)
if user.role != 'SimpleUsers' and domname is None:
if user.role != "SimpleUsers" and domname is None:
return
sadmins = core_models.User.objects.filter(is_superuser=True)
try:
+2 -2
View File
@@ -59,7 +59,7 @@ def get_identities(user, searchquery=None, idtfilter=None, grpfilter=None):
if idtfilter is None or not idtfilter or idtfilter == "account":
ids = user.objectaccess_set \
.filter(content_type=ContentType.objects.get_for_model(user)) \
.values_list('object_id', flat=True)
.values_list("object_id", flat=True)
q = Q(pk__in=ids)
if searchquery is not None:
q &= Q(username__icontains=searchquery) \
@@ -76,7 +76,7 @@ def get_identities(user, searchquery=None, idtfilter=None, grpfilter=None):
or (idtfilter in ["alias", "forward", "dlist"]):
alct = ContentType.objects.get_for_model(Alias)
ids = user.objectaccess_set.filter(content_type=alct) \
.values_list('object_id', flat=True)
.values_list("object_id", flat=True)
q = Q(pk__in=ids, internal=False)
if searchquery is not None:
q &= (
@@ -80,7 +80,7 @@ class Command(BaseCommand):
)
if not code:
return False
with open(path, 'w') as fp:
with open(path, "w") as fp:
print(os.getpid(), file=fp)
return True
@@ -46,12 +46,12 @@ class ExportCommand(BaseCommand):
dumped_aliases += [alias.pk]
qset = (
models.Alias.objects.exclude(pk__in=dumped_aliases)
.prefetch_related('aliasrecipient_set')
.prefetch_related("aliasrecipient_set")
)
for alias in qset:
alias.to_csv(self.csvwriter)
def handle(self, *args, **options):
exts_pool.load_all()
self.csvwriter = csv.writer(sys.stdout, delimiter=options['sepchar'])
self.csvwriter = csv.writer(sys.stdout, delimiter=options["sepchar"])
getattr(self, "export_{}".format(options["objtype"]))()
@@ -30,7 +30,7 @@ class ImportCommand(BaseCommand):
help="Separator used in file.")
parser.add_argument(
"--continue-if-exists", action="store_true",
dest='continue_if_exists', default=False,
dest="continue_if_exists", default=False,
help="Continue even if an entry already exists.")
parser.add_argument(
"--crypt-password", action="store_true",
+2 -2
View File
@@ -48,7 +48,7 @@ class Alias(AdminObject):
ugettext_lazy("Description"), blank=True)
expire_at = models.DateTimeField(
ugettext_lazy("Expire at"), blank=True, null=True)
_objectname = 'MailboxAlias'
_objectname = "MailboxAlias"
class Meta:
permissions = (
@@ -139,7 +139,7 @@ class Alias(AdminObject):
domain=domain, address=local_part).first()
if rcpt is None:
rcpt = Alias.objects.filter(
address='%s@%s' % (local_part, domname)
address="%s@%s" % (local_part, domname)
).first()
if rcpt is None:
raise NotFound(
+2 -2
View File
@@ -27,7 +27,7 @@ from .. import constants
class Domain(AdminObject):
"""Mail domain."""
name = models.CharField(ugettext_lazy('name'), max_length=100, unique=True,
name = models.CharField(ugettext_lazy("name"), max_length=100, unique=True,
help_text=ugettext_lazy("The domain name"))
quota = models.PositiveIntegerField(
default=0,
@@ -45,7 +45,7 @@ class Domain(AdminObject):
)
)
enabled = models.BooleanField(
ugettext_lazy('enabled'),
ugettext_lazy("enabled"),
help_text=ugettext_lazy("Check to activate this domain"),
default=True
)
+2 -2
View File
@@ -39,12 +39,12 @@ class DomainAlias(AdminObject):
name = models.CharField(ugettext_lazy("name"), max_length=100, unique=True,
help_text=ugettext_lazy("The alias name"))
target = models.ForeignKey(
Domain, verbose_name=ugettext_lazy('target'),
Domain, verbose_name=ugettext_lazy("target"),
help_text=ugettext_lazy("The domain this alias points to"),
on_delete=models.CASCADE
)
enabled = models.BooleanField(
ugettext_lazy('enabled'),
ugettext_lazy("enabled"),
help_text=ugettext_lazy("Check to activate this alias"),
default=True
)
+9 -9
View File
@@ -66,9 +66,9 @@ class MailboxManager(Manager):
"""
qf = None
if squery is not None:
if '@' in squery:
parts = squery.split('@')
addrfilter = '@'.join(parts[:-1])
if "@" in squery:
parts = squery.split("@")
addrfilter = "@".join(parts[:-1])
domfilter = parts[-1]
qf = (
Q(address__contains=addrfilter) &
@@ -81,7 +81,7 @@ class MailboxManager(Manager):
)
ids = admin.objectaccess_set \
.filter(content_type=ContentType.objects.get_for_model(Mailbox)) \
.values_list('object_id', flat=True)
.values_list("object_id", flat=True)
if qf is not None:
qf = Q(pk__in=ids) & qf
else:
@@ -94,7 +94,7 @@ class Mailbox(AdminObject):
"""User mailbox."""
address = models.CharField(
ugettext_lazy('address'), max_length=252,
ugettext_lazy("address"), max_length=252,
help_text=ugettext_lazy(
"Mailbox address (without the @domain.tld part)")
)
@@ -376,7 +376,7 @@ class MailboxOperation(models.Model):
mailbox = models.ForeignKey(Mailbox, blank=True, null=True,
on_delete=models.CASCADE)
type = models.CharField(
max_length=20, choices=(('rename', 'rename'), ('delete', 'delete'))
max_length=20, choices=(("rename", "rename"), ("delete", "delete"))
)
argument = models.TextField()
@@ -384,6 +384,6 @@ class MailboxOperation(models.Model):
app_label = "admin"
def __str__(self):
if self.type == 'rename':
return 'Rename %s -> %s' % (self.argument, self.mailbox.mail_home)
return 'Delete %s' % self.argument
if self.type == "rename":
return "Rename %s -> %s" % (self.argument, self.mailbox.mail_home)
return "Delete %s" % self.argument
+4 -4
View File
@@ -7,7 +7,7 @@ class DomainsMap(object):
"""Map to list all domains."""
filename = 'sql-domains.cf'
filename = "sql-domains.cf"
mysql = (
"SELECT name FROM admin_domain "
"WHERE name='%s' AND type='domain' AND enabled=1"
@@ -26,7 +26,7 @@ class DomainsAliasesMap(object):
"""Map to list all domain aliases."""
filename = 'sql-domain-aliases.cf'
filename = "sql-domain-aliases.cf"
mysql = (
"SELECT dom.name FROM admin_domain dom "
"INNER JOIN admin_domainalias domal ON dom.id=domal.target_id "
@@ -48,7 +48,7 @@ class AliasesMap(object):
"""A map to list all mailbox aliases."""
filename = 'sql-aliases.cf'
filename = "sql-aliases.cf"
mysql = (
"SELECT alr.address FROM modoboa_admin_aliasrecipient AS alr "
"INNER JOIN admin_alias AS al ON alr.alias_id=al.id "
@@ -73,7 +73,7 @@ class MaintainMap(object):
"""Map files to list non available mailboxes."""
filename = 'sql-maintain.cf'
filename = "sql-maintain.cf"
mysql = (
"SELECT '450 Requested mail action not taken: mailbox unavailable' "
"FROM admin_mailbox mb INNER JOIN admin_domain dom "
+6 -6
View File
@@ -75,7 +75,7 @@ def domains_menu(selection, user, ajax_mode=True):
"modalcb": "admin.exportform_cb"}
]
return render_to_string('common/menulist.html', {
return render_to_string("common/menulist.html", {
"entries": entries,
"selection": selection,
"user": user
@@ -123,7 +123,7 @@ def identities_menu(user, selection=None, ajax_mode=True):
"modalcb": "admin.exportform_cb"}
]
return render_to_string('common/menulist.html', {
return render_to_string("common/menulist.html", {
"entries": entries,
"user": user
})
@@ -229,15 +229,15 @@ def domain_aliases(domain):
:rtype: str
"""
if not domain.aliases.count():
return '---'
res = ''
return "---"
res = ""
for alias in domain.aliases.all():
res += '%s<br/>' % alias.name
res += "%s<br/>" % alias.name
return mark_safe(res)
@register.simple_tag
def identity_modify_link(identity, active_tab='default'):
def identity_modify_link(identity, active_tab="default"):
"""Return the appropriate modification link.
According to the identity type, a specific modification link (URL)
+8 -8
View File
@@ -28,7 +28,7 @@ class AuthenticationTestCase(ModoTestCase):
cls.mb = factories.MailboxFactory(
domain__name="test.com", address="user",
user__username="user@test.com",
user__groups=('SimpleUsers',)
user__groups=("SimpleUsers",)
)
def test_authentication_unicode(self):
@@ -56,7 +56,7 @@ class AccountTestCase(ModoTestCase):
username="tester@test.com", first_name="Tester", last_name="Toto",
password1="Toto1234", password2="Toto1234", role="SimpleUsers",
quota_act=True,
is_active=True, email="tester@test.com", stepid='step2'
is_active=True, email="tester@test.com", stepid="step2"
)
self.ajax_post(reverse("admin:account_add"), values)
@@ -459,8 +459,8 @@ class AccountTestCase(ModoTestCase):
@skipIf(NO_LDAP, "No ldap module installed")
@override_settings(AUTHENTICATION_BACKENDS=(
'modoboa.lib.authbackends.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
"modoboa.lib.authbackends.LDAPBackend",
"django.contrib.auth.backends.ModelBackend",
))
class LDAPAccountTestCase(test_ldap.LDAPTestCaseMixin, ModoTestCase):
"""Check LDAP related code."""
@@ -597,7 +597,7 @@ class PermissionsTestCase(ModoTestCase):
response = self.client.get(
reverse("admin:account_change", args=[self.user.id]),
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
HTTP_X_REQUESTED_WITH="XMLHttpRequest")
self.assertNotEqual(response["Content-Type"], "application/json")
def test_domainadmin_deletes_superadmin(self):
@@ -611,7 +611,7 @@ class PermissionsTestCase(ModoTestCase):
username="superadmin2@test.com", first_name="Super",
last_name="Admin", password1="Toto1234", password2="Toto1234",
role="SuperAdmins", is_active=True,
email="superadmin2@test.com", stepid='step2'
email="superadmin2@test.com", stepid="step2"
)
self.ajax_post(
reverse("admin:account_add"),
@@ -641,7 +641,7 @@ class PermissionsTestCase(ModoTestCase):
username="user10@test.com", first_name="Test",
last_name="Test", password1="Toto1234", password2="Toto1234",
role="SimpleUsers", is_active=True, master_user=True,
email="user10@test.com", stepid='step2'
email="user10@test.com", stepid="step2"
)
self.ajax_post(
reverse("admin:account_add"),
@@ -656,7 +656,7 @@ class PermissionsTestCase(ModoTestCase):
dom = models.Domain.objects.get(name="test.com")
mb = factories.MailboxFactory(
domain=dom, address="admin2",
user__username="admin2@test.com", user__groups=('DomainAdmins', ),
user__username="admin2@test.com", user__groups=("DomainAdmins", ),
user__password="{PLAIN}toto")
dom.add_admin(mb.user)
self.client.logout()
+8 -8
View File
@@ -69,7 +69,7 @@ class DomainAPITestCase(ModoAPITestCase):
self.assertIn("default_mailbox_quota", response.data)
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
response = self.client.post(
url, {"name": "test4.com", "default_mailbox_quota": 10})
self.assertEqual(response.status_code, 403)
@@ -84,7 +84,7 @@ class DomainAPITestCase(ModoAPITestCase):
reseller = core_factories.UserFactory(
username="reseller", groups=("Resellers", ))
token = Token.objects.create(user=reseller)
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
self.client.credentials(HTTP_AUTHORIZATION="Token " + token.key)
url = reverse("api:domain-list")
mock_query.side_effect = utils.mock_dns_query_result
@@ -169,7 +169,7 @@ class DomainAliasAPITestCase(ModoAPITestCase):
self.assertEqual(len(response.data), 1)
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
response = self.client.get(reverse("api:domain_alias-list"))
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 0)
@@ -191,7 +191,7 @@ class DomainAliasAPITestCase(ModoAPITestCase):
self.assertEqual(dalias.target, target)
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
response = self.client.post(
url, {"name": "dalias4.com", "target": target.pk}, format="json")
self.assertEqual(response.status_code, 403)
@@ -389,7 +389,7 @@ class AccountAPITestCase(ModoAPITestCase):
def test_create_account_as_domadmin(self):
"""As DomainAdmin, try to create a new account."""
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
data = copy.deepcopy(self.ACCOUNT_DATA)
data["mailbox"]["quota"] = 1000
url = reverse("api:account-list")
@@ -604,7 +604,7 @@ class AliasAPITestCase(ModoAPITestCase):
response = self.client.post(url, self.ALIAS_DATA, format="json")
self.assertEqual(response.status_code, 201)
alias = json.loads(response.content.decode('utf-8'))
alias = json.loads(response.content.decode("utf-8"))
alias = models.Alias.objects.filter(pk=alias["pk"]).first()
domadmin = core_models.User.objects.get(username="admin@test.com")
self.assertTrue(domadmin.can_access(alias))
@@ -626,7 +626,7 @@ class AliasAPITestCase(ModoAPITestCase):
def test_create_alias_as_domadmin(self):
"""As DomainAdmin, try to create a new alias."""
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
url = reverse("api:alias-list")
response = self.client.post(url, self.ALIAS_DATA, format="json")
self.assertEqual(response.status_code, 201)
@@ -723,7 +723,7 @@ class SenderAddressAPITestCase(ModoAPITestCase):
self.assertEqual(response.status_code, 201)
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
data = {"address": "user@test2.com", "mailbox": mbox.pk}
response = self.client.post(url, data)
self.assertEqual(response.status_code, 400)
+3 -3
View File
@@ -176,7 +176,7 @@ class DomainTestCase(ModoTestCase):
values = {
"name": "pouet.com", "quota": 10, "default_mailbox_quota": 100,
"create_dom_admin": True, "dom_admin_username": "toto",
"create_aliases": True, "type": "domain", "stepid": 'step3'
"create_aliases": True, "type": "domain", "stepid": "step3"
}
response = self.ajax_post(
reverse("admin:domain_add"),
@@ -347,13 +347,13 @@ class DomainTestCase(ModoTestCase):
url = reverse("core:dashboard")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn("Global statistics", response.content.decode('utf-8'))
self.assertIn("Global statistics", response.content.decode("utf-8"))
self.client.force_login(
User.objects.get(username="admin@test.com"))
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
content = response.content.decode('utf-8')
content = response.content.decode("utf-8")
self.assertNotIn("Global statistics", content)
self.assertIn("Per-domain statistics", content)
+1 -1
View File
@@ -17,7 +17,7 @@ class DomainAliasTestCase(ModoTestCase):
"""Create test data."""
super(DomainAliasTestCase, cls).setUpTestData()
factories.populate_database()
cls.dom = Domain.objects.get(name='test.com')
cls.dom = Domain.objects.get(name="test.com")
def test_model(self):
dom = Domain.objects.get(name="test.com")
+1 -1
View File
@@ -217,7 +217,7 @@ account; user1@test.com; toto; User; One; True; SimpleUsers; user1@test.com; ; t
reverse("admin:identity_import"),
{"sourcefile": f, "crypt_password": True}
)
self.assertIn('wrong quota value', resp.content.decode())
self.assertIn("wrong quota value", resp.content.decode())
def test_import_domain_by_domainadmin(self):
"""Check if a domain admin is not allowed to import a domain."""
+11 -11
View File
@@ -21,7 +21,7 @@ class PasswordSchemesTestCase(ModoTestCase):
username="tester@test.com", first_name="Tester", last_name="Toto",
password1="Toto1234", password2="Toto1234", role="SimpleUsers",
quota_act=True,
is_active=True, email="tester@test.com", stepid='step2'
is_active=True, email="tester@test.com", stepid="step2"
)
self.ajax_post(
reverse("admin:account_add"),
@@ -31,30 +31,30 @@ class PasswordSchemesTestCase(ModoTestCase):
def _test_scheme(self, name, startpattern):
self.set_global_parameter("password_scheme", name, app="core")
self._create_account()
account = User.objects.get(username='tester@test.com')
account = User.objects.get(username="tester@test.com")
self.assertTrue(account.password.startswith(startpattern))
self.assertTrue(account.check_password('Toto1234'))
self.assertTrue(account.check_password("Toto1234"))
def test_bcrypt_scheme(self):
self._test_scheme('blfcrypt', '{BLF-CRYPT}')
self._test_scheme("blfcrypt", "{BLF-CRYPT}")
def test_sha512crypt_scheme(self):
self._test_scheme('sha512crypt', '{SHA512-CRYPT}')
self._test_scheme("sha512crypt", "{SHA512-CRYPT}")
def test_sha256crypt_scheme(self):
self._test_scheme('sha256crypt', '{SHA256-CRYPT}')
self._test_scheme("sha256crypt", "{SHA256-CRYPT}")
def test_md5crypt_scheme(self):
self._test_scheme('md5crypt', '{MD5-CRYPT}')
self._test_scheme("md5crypt", "{MD5-CRYPT}")
def test_sha256_scheme(self):
self._test_scheme('sha256', '{SHA256}')
self._test_scheme("sha256", "{SHA256}")
def test_md5_scheme(self):
self._test_scheme('md5', '{MD5}')
self._test_scheme("md5", "{MD5}")
def test_crypt(self):
self._test_scheme('crypt', '{CRYPT}')
self._test_scheme("crypt", "{CRYPT}")
def test_plain(self):
self._test_scheme('plain', '{PLAIN}')
self._test_scheme("plain", "{PLAIN}")
+1 -1
View File
@@ -49,7 +49,7 @@ class RepairTestCase(ModoTestCase):
def test_management_command_with_nul_domain(self):
"""Just assume nothing raise when an alias has no domain."""
models.Alias.objects.create(address='@modoboa.xxx')
models.Alias.objects.create(address="@modoboa.xxx")
ret = management.call_command("modo", "repair", "--quiet")
assert ret is None
+1 -1
View File
@@ -27,7 +27,7 @@ urlpatterns = [
name="domain_quota_list"),
url(r'^domains/flatlist/$', domain_views.domains_list,
name="domain_flat_list"),
url(r'^domains/new/', domain_views.newdomain, name='domain_add'),
url(r'^domains/new/', domain_views.newdomain, name="domain_add"),
url(r'^domains/(?P<dom_id>\d+)/edit/$', domain_views.editdomain,
name="domain_change"),
url(r'^domains/(?P<dom_id>\d+)/delete/$', domain_views.deldomain,
+7 -7
View File
@@ -37,7 +37,7 @@ def _validate_alias(request, form, successmsg, callback=None):
callback(request.user, alias)
return render_to_json_response(successmsg)
return render_to_json_response({'form_errors': form.errors}, status=400)
return render_to_json_response({"form_errors": form.errors}, status=400)
def _new_alias(request, title, action, successmsg,
@@ -87,12 +87,12 @@ def editalias(request, alid, tplname="admin/aliasform.html"):
return _validate_alias(request, form, successmsg)
ctx = {
'action': reverse("admin:alias_change", args=[alias.id]),
'formid': 'aliasform',
'title': alias.address,
'action_label': _('Update'),
'action_classes': 'submit',
'form': AliasForm(request.user, instance=alias)
"action": reverse("admin:alias_change", args=[alias.id]),
"formid": "aliasform",
"title": alias.address,
"action_label": _("Update"),
"action_classes": "submit",
"form": AliasForm(request.user, instance=alias)
}
return render(request, tplname, ctx)
+4 -4
View File
@@ -51,16 +51,16 @@ def _domains(request):
(flt, request.GET.get(flt, None))
for flt in ["domfilter", "searchquery"] + extra_filters
)
request.session['domains_filters'] = filters
request.session["domains_filters"] = filters
domainlist = get_domains(request.user, **filters)
if sort_order == 'name':
if sort_order == "name":
domainlist = sorted(
domainlist,
key=lambda d: getattr(d, sort_order), reverse=sort_dir == '-'
key=lambda d: getattr(d, sort_order), reverse=sort_dir == "-"
)
else:
domainlist = sorted(domainlist, key=lambda d: d.tags[0]["name"],
reverse=sort_dir == '-')
reverse=sort_dir == "-")
context = {
"handle_mailboxes": request.localconfig.parameters.get_value(
"handle_mailboxes", raise_exception=False),
+2 -2
View File
@@ -52,7 +52,7 @@ def export_identities(request):
fp = six.StringIO()
csvwriter = csv.writer(fp, delimiter=form.cleaned_data["sepchar"])
identities = get_identities(
request.user, **request.session['identities_filters'])
request.user, **request.session["identities_filters"])
for ident in identities:
ident.to_csv(csvwriter)
content = fp.getvalue()
@@ -80,7 +80,7 @@ def export_domains(request):
fp = six.StringIO()
csvwriter = csv.writer(fp, delimiter=form.cleaned_data["sepchar"])
for dom in get_domains(request.user,
**request.session['domains_filters']):
**request.session["domains_filters"]):
dom.to_csv(csvwriter)
content = fp.getvalue()
fp.close()
+6 -6
View File
@@ -37,17 +37,17 @@ from .. import signals
)
def _identities(request):
filters = dict((fname, request.GET.get(fname, None))
for fname in ['searchquery', 'idtfilter', 'grpfilter'])
request.session['identities_filters'] = filters
for fname in ["searchquery", "idtfilter", "grpfilter"])
request.session["identities_filters"] = filters
idents_list = get_identities(request.user, **filters)
sort_order, sort_dir = get_sort_order(request.GET, "identity",
["identity", "name_or_rcpt", "tags"])
if sort_order in ["identity", "name_or_rcpt"]:
objects = sorted(idents_list, key=lambda o: getattr(o, sort_order),
reverse=sort_dir == '-')
reverse=sort_dir == "-")
else:
objects = sorted(idents_list, key=lambda o: o.tags[0],
reverse=sort_dir == '-')
reverse=sort_dir == "-")
context = {
"handle_mailboxes": request.localconfig.parameters.get_value(
"handle_mailboxes", raise_exception=False)
@@ -104,7 +104,7 @@ def list_quotas(request):
"* 1048576)) * 100"
)
mboxes = mboxes.extra(
select={'quota_usage': select},
select={"quota_usage": select},
where=["admin_quota.username=%s" % where],
tables=["admin_quota", "admin_domain"],
order_by=["%s%s" % (sort_dir, sort_order)]
@@ -157,7 +157,7 @@ def identities(request, tplname="admin/identities.html"):
@permission_required("core.add_user")
def accounts_list(request):
accs = User.objects.filter(is_superuser=False) \
.exclude(groups__name='SimpleUsers')
.exclude(groups__name="SimpleUsers")
res = [a.username for a in accs.all()]
return render_to_json_response(res)
+3 -3
View File
@@ -39,8 +39,8 @@ def importdata(request, formclass=ImportDataForm):
if form.is_valid():
try:
infile = io.TextIOWrapper(
request.FILES['sourcefile'].file, encoding="utf8")
reader = csv.reader(infile, delimiter=form.cleaned_data['sepchar'])
request.FILES["sourcefile"].file, encoding="utf8")
reader = csv.reader(infile, delimiter=form.cleaned_data["sepchar"])
except csv.Error as inst:
error = smart_text(inst)
else:
@@ -63,7 +63,7 @@ def importdata(request, formclass=ImportDataForm):
continue
raise Conflict(
_("Object already exists: %s"
% form.cleaned_data['sepchar'].join(row[:2]))
% form.cleaned_data["sepchar"].join(row[:2]))
)
cpt += 1
msg = _("%d objects imported successfully" % cpt)
+1 -1
View File
@@ -40,7 +40,7 @@ def forward(request, tplname="admin/forward.html"):
return render_to_json_response(_("Forward updated"))
return render_to_json_response(
{'form_errors': form.errors}, status=400
{"form_errors": form.errors}, status=400
)
form = ForwardForm()
+7 -7
View File
@@ -40,8 +40,8 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
authentication_type = forms.ChoiceField(
label=ugettext_lazy("Authentication type"),
choices=[('local', ugettext_lazy("Local")),
('ldap', "LDAP")],
choices=[("local", ugettext_lazy("Local")),
("ldap", "LDAP")],
initial="local",
help_text=ugettext_lazy("The backend used for authentication"),
widget=HorizontalRadioSelect()
@@ -115,16 +115,16 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
ldap_auth_method = forms.ChoiceField(
label=ugettext_lazy("Authentication method"),
choices=[('searchbind', ugettext_lazy("Search and bind")),
('directbind', ugettext_lazy("Direct bind"))],
initial='searchbind',
choices=[("searchbind", ugettext_lazy("Search and bind")),
("directbind", ugettext_lazy("Direct bind"))],
initial="searchbind",
help_text=ugettext_lazy("Choose the authentication method to use"),
widget=forms.Select(attrs={"class": "form-control"})
)
ldap_bind_dn = forms.CharField(
label=ugettext_lazy("Bind DN"),
initial='',
initial="",
help_text=ugettext_lazy(
"The distinguished name to use when binding to the LDAP server. "
"Leave empty for an anonymous bind"
@@ -135,7 +135,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm):
ldap_bind_password = forms.CharField(
label=ugettext_lazy("Bind password"),
initial='',
initial="",
help_text=ugettext_lazy(
"The password to use when binding to the LDAP server "
"(with 'Bind DN')"
+4 -4
View File
@@ -90,10 +90,10 @@ def handle_command_line():
epilog="""Available commands:
%s
""" % "\n".join(["\t%s" % c for c in sorted(commands)]))
parser.add_argument('--verbose', action='store_true',
help='Activate verbose output')
parser.add_argument('command', type=str,
help='A valid command name')
parser.add_argument("--verbose", action="store_true",
help="Activate verbose output")
parser.add_argument("command", type=str,
help="A valid command name")
(args, remaining) = parser.parse_known_args()
if args.command not in commands:
+53 -53
View File
@@ -58,40 +58,40 @@ class DeployCommand(Command):
def __init__(self, *args, **kwargs):
super(DeployCommand, self).__init__(*args, **kwargs)
self._parser.add_argument('name', type=str,
help='The name of your Modoboa instance')
self._parser.add_argument("name", type=str,
help="The name of your Modoboa instance")
self._parser.add_argument(
'--collectstatic', action='store_true', default=False,
help='Run django collectstatic command'
"--collectstatic", action="store_true", default=False,
help="Run django collectstatic command"
)
self._parser.add_argument(
'--dburl', type=str, nargs="+", default=None,
help='A database-url with a name')
"--dburl", type=str, nargs="+", default=None,
help="A database-url with a name")
self._parser.add_argument(
'--domain', type=str, default=None,
help='The domain under which you want to deploy modoboa')
"--domain", type=str, default=None,
help="The domain under which you want to deploy modoboa")
self._parser.add_argument(
'--lang', type=str, default="en-us",
"--lang", type=str, default="en-us",
help="Set the default language"
)
self._parser.add_argument(
'--timezone', type=str, default="UTC",
"--timezone", type=str, default="UTC",
help="Set the local timezone"
)
self._parser.add_argument(
'--devel', action='store_true', default=False,
help='Create a development instance'
"--devel", action="store_true", default=False,
help="Create a development instance"
)
self._parser.add_argument(
'--extensions', type=str, nargs='*',
"--extensions", type=str, nargs="*",
help="The list of extension to deploy"
)
self._parser.add_argument(
'--dont-install-extensions', action='store_true', default=False,
help='Do not install extensions using pip'
"--dont-install-extensions", action="store_true", default=False,
help="Do not install extensions using pip"
)
self._parser.add_argument(
'--admin-username', default='admin',
"--admin-username", default="admin",
help="Username of the initial super administrator"
)
@@ -101,7 +101,7 @@ class DeployCommand(Command):
:param name: the command name
:param cwd: the directory where the command must be executed
"""
cmd = [sys.executable, 'manage.py', name]
cmd = [sys.executable, "manage.py", name]
cmd.extend(args)
if not self._verbose:
p = subprocess.Popen(
@@ -120,7 +120,7 @@ class DeployCommand(Command):
)
print("%s failed, check your configuration" % cmd, file=sys.stderr)
def ask_db_info(self, name='default'):
def ask_db_info(self, name="default"):
"""Prompt the user for database information
Gather all information required to create a new database
@@ -130,33 +130,33 @@ class DeployCommand(Command):
"""
print("Configuring database connection: %s" % name)
info = {
'conn_name': name,
'ENGINE': input(
'Database type (mysql, postgres or sqlite3): ')
"conn_name": name,
"ENGINE": input(
"Database type (mysql, postgres or sqlite3): ")
}
if info['ENGINE'] not in ['mysql', 'postgres', 'sqlite3']:
raise RuntimeError('Unsupported database engine')
if info["ENGINE"] not in ["mysql", "postgres", "sqlite3"]:
raise RuntimeError("Unsupported database engine")
if info['ENGINE'] == 'sqlite3':
info['ENGINE'] = 'django.db.backends.sqlite3'
info['NAME'] = '%s.db' % name
if info["ENGINE"] == "sqlite3":
info["ENGINE"] = "django.db.backends.sqlite3"
info["NAME"] = "%s.db" % name
return info
if info['ENGINE'] == 'postgres':
info['ENGINE'] = 'django.db.backends.postgresql_psycopg2'
if info["ENGINE"] == "postgres":
info["ENGINE"] = "django.db.backends.postgresql_psycopg2"
default_port = 5432
else:
info['ENGINE'] = 'django.db.backends.mysql'
info["ENGINE"] = "django.db.backends.mysql"
default_port = 3306
info['HOST'] = input("Database host (default: 'localhost'): ")
info['PORT'] = input(
info["HOST"] = input("Database host (default: 'localhost'): ")
info["PORT"] = input(
"Database port (default: '%s'): " % default_port)
# leave port setting empty, if default value is supplied and
# leave it to django
if info['PORT'] == default_port:
info['PORT'] = ''
info['NAME'] = input('Database name: ')
info['USER'] = input('Username: ')
info['PASSWORD'] = getpass.getpass('Password: ')
if info["PORT"] == default_port:
info["PORT"] = ""
info["NAME"] = input("Database name: ")
info["USER"] = input("Username: ")
info["PASSWORD"] = getpass.getpass("Password: ")
return info
def _get_extension_list(self):
@@ -188,9 +188,9 @@ class DeployCommand(Command):
def handle(self, parsed_args):
django.setup()
management.call_command(
'startproject', parsed_args.name, verbosity=False
"startproject", parsed_args.name, verbosity=False
)
path = "%(name)s/%(name)s" % {'name': parsed_args.name}
path = "%(name)s/%(name)s" % {"name": parsed_args.name}
sys.path.append(parsed_args.name)
conn_tpl = Template(DBCONN_TPL)
@@ -206,7 +206,7 @@ class DeployCommand(Command):
info = self.ask_db_info(conn_name)
# If we set this earlier, our fallback method will never
# be triggered
info['conn_name'] = conn_name
info["conn_name"] = conn_name
connections[conn_name] = conn_tpl.render(Context(info))
else:
connections["default"] = conn_tpl.render(
@@ -216,7 +216,7 @@ class DeployCommand(Command):
allowed_host = parsed_args.domain
else:
allowed_host = input(
'What will be the hostname used to access Modoboa? ')
"What will be the hostname used to access Modoboa? ")
if not allowed_host:
allowed_host = "localhost"
extra_settings = []
@@ -238,20 +238,20 @@ class DeployCommand(Command):
)
mod = __import__(
parsed_args.name, globals(), locals(), [smart_str('settings')]
parsed_args.name, globals(), locals(), [smart_str("settings")]
)
tpl = self._render_template(
"%s/settings.py.tpl" % self._templates_dir, {
'db_connections': connections,
'secret_key': mod.settings.SECRET_KEY,
'name': parsed_args.name,
'allowed_host': allowed_host,
'lang': parsed_args.lang,
'timezone': parsed_args.timezone,
'bower_components_dir': bower_components_dir,
'devmode': parsed_args.devel,
'extensions': extensions,
'extra_settings': extra_settings
"db_connections": connections,
"secret_key": mod.settings.SECRET_KEY,
"name": parsed_args.name,
"allowed_host": allowed_host,
"lang": parsed_args.lang,
"timezone": parsed_args.timezone,
"bower_components_dir": bower_components_dir,
"devmode": parsed_args.devel,
"extensions": extensions,
"extra_settings": extra_settings
}
)
with codecs.open("%s/settings.py" % path, "w", "utf-8") as fp:
@@ -264,7 +264,7 @@ class DeployCommand(Command):
if isfile("%s/settings.pyc" % path):
os.unlink("%s/settings.pyc" % path)
self._exec_django_command(
"migrate", parsed_args.name, '--noinput'
"migrate", parsed_args.name, "--noinput"
)
self._exec_django_command(
"load_initial_data", parsed_args.name,
@@ -272,7 +272,7 @@ class DeployCommand(Command):
)
if parsed_args.collectstatic:
self._exec_django_command(
"collectstatic", parsed_args.name, '--noinput'
"collectstatic", parsed_args.name, "--noinput"
)
self._exec_django_command(
"set_default_site", parsed_args.name, allowed_host
+2 -2
View File
@@ -13,8 +13,8 @@ class HelpCommand(Command):
def __init__(self, *args, **kwargs):
super(HelpCommand, self).__init__(*args, **kwargs)
self._parser.add_argument('name', type=str,
help='A command name')
self._parser.add_argument("name", type=str,
help="A command name")
def handle(self, parsed_args):
if parsed_args.name not in self._commands:
+1 -1
View File
@@ -79,7 +79,7 @@ class ExtensionsPool(object):
def load_extension(self, name):
"""Load a registered extension."""
__import__(name, locals(), globals(), [smart_str('modo_extension')])
__import__(name, locals(), globals(), [smart_str("modo_extension")])
extinstance = self.get_extension(name)
if extinstance is None:
return None
+2 -2
View File
@@ -83,7 +83,7 @@ class User(AbstractUser):
class Meta(object):
ordering = ["username"]
index_together = [
['email', 'is_active']
["email", "is_active"]
]
password_expr = re.compile(r'\{([\w\-]+)\}(.+)')
@@ -412,7 +412,7 @@ class ObjectAccess(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
content_object = GenericForeignKey("content_type", "object_id")
is_owner = models.BooleanField(default=False)
class Meta(object):
+2 -2
View File
@@ -22,8 +22,8 @@ def get_password_hasher(scheme):
:return: The hasher class
"""
try:
scheme = scheme.replace('-', '')
hasher = globals()['%sHasher' % scheme.upper()]
scheme = scheme.replace("-", "")
hasher = globals()["%sHasher" % scheme.upper()]
except KeyError:
hasher = PLAINHasher
return hasher
+4 -4
View File
@@ -22,7 +22,7 @@ class BLFCRYPTHasher(PasswordHasher):
"""
@property
def scheme(self):
return '{BLF-CRYPT}' if self._target == 'local' else '{CRYPT}'
return "{BLF-CRYPT}" if self._target == "local" else "{CRYPT}"
def _b64encode(self, pwhash):
return pwhash
@@ -50,7 +50,7 @@ class MD5CRYPTHasher(PasswordHasher):
"""
@property
def scheme(self):
return '{MD5-CRYPT}' if self._target == 'local' else '{CRYPT}'
return "{MD5-CRYPT}" if self._target == "local" else "{CRYPT}"
def _b64encode(self, pwhash):
return pwhash
@@ -72,7 +72,7 @@ class SHA256CRYPTHasher(PasswordHasher):
"""
@property
def scheme(self):
return '{SHA256-CRYPT}' if self._target == 'local' else '{CRYPT}'
return "{SHA256-CRYPT}" if self._target == "local" else "{CRYPT}"
def _b64encode(self, pwhash):
return pwhash
@@ -96,7 +96,7 @@ class SHA512CRYPTHasher(PasswordHasher):
"""
@property
def scheme(self):
return '{SHA512-CRYPT}' if self._target == 'local' else '{CRYPT}'
return "{SHA512-CRYPT}" if self._target == "local" else "{CRYPT}"
def _b64encode(self, pwhash):
return pwhash
+7 -7
View File
@@ -22,7 +22,7 @@ class PasswordHasher(object):
Base class of all hashers.
"""
def __init__(self, target='local'):
def __init__(self, target="local"):
self._target = target
def _encrypt(self, clearvalue, salt=None):
@@ -34,7 +34,7 @@ class PasswordHasher(object):
:param str pwhash: password hash
:return: base64 encoded hash or original hash
"""
if self._target == 'ldap':
if self._target == "ldap":
return base64.b64encode(pwhash)
return pwhash
@@ -52,7 +52,7 @@ class PasswordHasher(object):
:return: encrypted password
"""
pwhash = self._b64encode(self._encrypt(force_text(clearvalue)))
return '%s%s' % (self.scheme, force_text(pwhash))
return "%s%s" % (self.scheme, force_text(pwhash))
def verify(self, clearvalue, hashed_value):
"""Verify a password against a hashed value.
@@ -74,7 +74,7 @@ class PLAINHasher(PasswordHasher):
"""
@property
def scheme(self):
return '{PLAIN}'
return "{PLAIN}"
def _encrypt(self, clearvalue, salt=None):
return clearvalue
@@ -89,7 +89,7 @@ class CRYPTHasher(PasswordHasher):
"""
@property
def scheme(self):
return '{CRYPT}'
return "{CRYPT}"
def _encrypt(self, clearvalue, salt=None):
if salt is None:
@@ -106,7 +106,7 @@ class MD5Hasher(PasswordHasher):
"""
@property
def scheme(self):
return '{MD5}'
return "{MD5}"
def _encrypt(self, clearvalue, salt=None):
obj = hashlib.md5(force_bytes(clearvalue))
@@ -122,7 +122,7 @@ class SHA256Hasher(PasswordHasher):
"""
@property
def scheme(self):
return '{SHA256}'
return "{SHA256}"
def _encrypt(self, clearvalue, salt=None):
return hashlib.sha256(force_bytes(clearvalue)).digest()
+5 -5
View File
@@ -72,7 +72,7 @@ def admin_menu(selection, user):
"img": "",
"label": _("Parameters")},
]
return render_to_string('common/menu.html', {
return render_to_string("common/menu.html", {
"entries": entries,
"css": "nav nav-sidebar",
"selection": selection,
@@ -163,7 +163,7 @@ def tohtml(message):
@register.simple_tag
def visirule(field):
if not hasattr(field, 'form') or \
if not hasattr(field, "form") or \
not hasattr(field.form, "visirules") or \
field.html_name not in field.form.visirules:
return ""
@@ -191,7 +191,7 @@ class ConnectedUsers(template.Node):
# Build a list of user ids from that query
for session in sessions:
data = session.get_decoded()
uid = data.get('_auth_user_id', None)
uid = data.get("_auth_user_id", None)
if uid:
uid_list.append(uid)
@@ -202,7 +202,7 @@ class ConnectedUsers(template.Node):
context[self.varname].append(User.objects.get(pk=uid))
except User.DoesNotExist:
pass
return ''
return ""
@register.tag
@@ -211,7 +211,7 @@ def connected_users(parser, token):
tag, a, varname = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError(
'connected_users usage: {% connected_users as users %}'
"connected_users usage: {% connected_users as users %}"
)
return ConnectedUsers(varname)
+4 -4
View File
@@ -28,7 +28,7 @@ class AuthenticationTestCase(ModoTestCase):
"""Create test data."""
super(AuthenticationTestCase, cls).setUpTestData()
cls.account = factories.UserFactory(
username="user@test.com", groups=('SimpleUsers',)
username="user@test.com", groups=("SimpleUsers",)
)
def test_authentication(self):
@@ -75,10 +75,10 @@ class PasswordResetTestCase(ModoTestCase):
super(PasswordResetTestCase, cls).setUpTestData()
cls.account_ok = factories.UserFactory(
username="user@test.com", secondary_email="test@ext.com",
groups=('SimpleUsers',)
groups=("SimpleUsers",)
)
cls.account_ko = factories.UserFactory(
username="user2@test.com", groups=('SimpleUsers',)
username="user2@test.com", groups=("SimpleUsers",)
)
def test_reset_password(self):
@@ -104,7 +104,7 @@ class PasswordResetTestCase(ModoTestCase):
self.assertEqual(len(mail.outbox), 0)
@skipIf(NO_SMTP, 'No SMTP server available')
@skipIf(NO_SMTP, "No SMTP server available")
@override_settings(AUTHENTICATION_BACKENDS=(
"modoboa.lib.authbackends.SMTPBackend",
"django.contrib.auth.backends.ModelBackend"
+3 -3
View File
@@ -28,7 +28,7 @@ class AuthenticationTestCase(ModoTestCase):
"""Create test data."""
super(AuthenticationTestCase, cls).setUpTestData()
cls.account = factories.UserFactory(
username="user@test.com", groups=('SimpleUsers',)
username="user@test.com", groups=("SimpleUsers",)
)
def test_authentication(self):
@@ -109,7 +109,7 @@ class ProfileTestCase(ModoTestCase):
"""Create test data."""
super(ProfileTestCase, cls).setUpTestData()
cls.account = factories.UserFactory(
username="user@test.com", groups=('SimpleUsers',)
username="user@test.com", groups=("SimpleUsers",)
)
def test_update_profile(self):
@@ -168,7 +168,7 @@ class APIAccessFormTestCase(ModoTestCase):
"""Create test data."""
super(APIAccessFormTestCase, cls).setUpTestData()
cls.account = factories.UserFactory(
username="user@test.com", groups=('SimpleUsers',)
username="user@test.com", groups=("SimpleUsers",)
)
def test_form_access(self):
+6 -6
View File
@@ -16,7 +16,7 @@ from .. import factories
from .. import models
@skipIf(NO_LDAP, 'No ldap module installed')
@skipIf(NO_LDAP, "No ldap module installed")
class LDAPTestCaseMixin(object):
"""Set of methods used to test LDAP features."""
@@ -71,8 +71,8 @@ class LDAPTestCaseMixin(object):
@override_settings(AUTHENTICATION_BACKENDS=(
'modoboa.lib.authbackends.LDAPBackend',
'django.contrib.auth.backends.ModelBackend'
"modoboa.lib.authbackends.LDAPBackend",
"django.contrib.auth.backends.ModelBackend"
))
class LDAPAuthenticationTestCase(LDAPTestCaseMixin, ModoTestCase):
"""Validate LDAP authentication scenarios."""
@@ -137,12 +137,12 @@ class ProfileTestCase(LDAPTestCaseMixin, ModoTestCase):
"""Create test data."""
super(ProfileTestCase, cls).setUpTestData()
cls.account = factories.UserFactory(
username="user@test.com", groups=('SimpleUsers',)
username="user@test.com", groups=("SimpleUsers",)
)
@override_settings(AUTHENTICATION_BACKENDS=(
'modoboa.lib.authbackends.LDAPBackend',
'django.contrib.auth.backends.ModelBackend'
"modoboa.lib.authbackends.LDAPBackend",
"django.contrib.auth.backends.ModelBackend"
))
def test_update_password_ldap(self):
"""Update password for an LDAP user."""
+2 -2
View File
@@ -108,12 +108,12 @@ class DashboardTestCase(ModoTestCase):
url = reverse("core:dashboard")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn("Latest news", response.content.decode('utf-8'))
self.assertIn("Latest news", response.content.decode("utf-8"))
self.client.logout()
self.client.login(username=self.dadmin.username, password="toto")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn("Latest news", response.content.decode('utf-8'))
self.assertIn("Latest news", response.content.decode("utf-8"))
self.client.logout()
self.client.login(username=self.user.username, password="toto")
response = self.client.get(url)
+2 -2
View File
@@ -22,7 +22,7 @@ from .. import signals
@login_required
@user_passes_test(lambda u: u.is_superuser)
def viewsettings(request, tplname='core/settings_header.html'):
def viewsettings(request, tplname="core/settings_header.html"):
return render(request, tplname, {
"selection": "settings"
})
@@ -71,7 +71,7 @@ def get_logs_page(request, page_id=None):
"""Return a page of logs."""
sort_order, sort_dir = get_sort_order(
request.GET, "date_created",
allowed_values=['date_created', 'level', 'logger', 'message']
allowed_values=["date_created", "level", "logger", "message"]
)
if page_id is None:
page_id = request.GET.get("page", None)
+1 -1
View File
@@ -29,7 +29,7 @@ def dologin(request):
if request.method == "POST":
form = forms.LoginForm(request.POST)
if form.is_valid():
logger = logging.getLogger('modoboa.auth')
logger = logging.getLogger("modoboa.auth")
user = authenticate(username=form.cleaned_data["username"],
password=form.cleaned_data["password"])
if user and user.is_active:
+2 -2
View File
@@ -27,7 +27,7 @@ def index(request, tplname="core/user_index.html"):
@login_required
def profile(request, tplname='core/user_profile.html'):
def profile(request, tplname="core/user_profile.html"):
"""Profile detail/update view."""
update_password = True
results = signals.allow_password_change.send(
@@ -50,7 +50,7 @@ def profile(request, tplname='core/user_profile.html'):
request.user.language)
return render_to_json_response(_("Profile updated"))
return render_to_json_response(
{'form_errors': form.errors}, status=400)
{"form_errors": form.errors}, status=400)
form = ProfileForm(update_password, instance=request.user)
return render_to_json_response({
+1 -1
View File
@@ -86,7 +86,7 @@ try:
if grp.strip() in ldap_user.group_names:
group = "DomainAdmins"
break
if group == 'SimpleUsers':
if group == "SimpleUsers":
lpart, domain = split_mailbox(username)
if domain is None:
return None
+1 -1
View File
@@ -15,7 +15,7 @@ from cryptography.fernet import Fernet
def random_key(length=16):
"""Generate a new key used to encrypt user passwords in session storage."""
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)"
return get_random_string(length, chars)
+2 -2
View File
@@ -25,7 +25,7 @@ def db_type(cname="default"):
if cname not in settings.DATABASES:
raise InternalError(
_("Connection to database %s not configured" % cname))
for t in ['postgres', 'mysql', 'sqlite']:
if settings.DATABASES[cname]['ENGINE'].find(t) != -1:
for t in ["postgres", "mysql", "sqlite"]:
if settings.DATABASES[cname]["ENGINE"].find(t) != -1:
return t
return None
+5 -5
View File
@@ -128,7 +128,7 @@ class Email(object):
# msg parameter to maintain compatibility with
# modoboa_webmail.lib.imapemail.ImapEmail
if header in msg:
return "".join([smart_text(v, encoding=(e or 'ascii'))
return "".join([smart_text(v, encoding=(e or "ascii"))
for v, e in email.header.decode_header(msg[header])
])
return ""
@@ -188,7 +188,7 @@ class Email(object):
cid = None
if "Content-ID" in msg:
cid = msg["Content-ID"]
if cid.startswith('<') and cid.endswith('>'):
if cid.startswith("<") and cid.endswith(">"):
cid = cid[1:-1]
else:
matches = _RE_CID.match(msg["Content-Type"])
@@ -379,7 +379,7 @@ def set_email_headers(msg, subject, sender, rcpt):
"""
import pkg_resources
msg["Subject"] = Header(subject, 'utf8')
msg["Subject"] = Header(subject, "utf8")
msg["From"] = sender
msg["To"] = prepare_addresses(rcpt)
msg["Message-ID"] = make_msgid()
@@ -388,7 +388,7 @@ def set_email_headers(msg, subject, sender, rcpt):
msg["Date"] = formatdate(time.time(), True)
def __sendmail(sender, rcpt, msgstring, server='localhost', port=25):
def __sendmail(sender, rcpt, msgstring, server="localhost", port=25):
"""Message sending
Return a tuple (True, None) on success, (False, error message)
@@ -425,7 +425,7 @@ def sendmail_simple(
:param content: message's content
:return: tuple
"""
msg = MIMEText(content, _charset='utf-8')
msg = MIMEText(content, _charset="utf-8")
set_email_headers(msg, subject, sender, rcpt)
return __sendmail(sender, rcpt, msg.as_string(), **kwargs)
+3 -3
View File
@@ -17,9 +17,9 @@ class ModoboaException(Exception):
http_code = None
def __init__(self, *args, **kwargs):
if 'http_code' in kwargs:
self.http_code = kwargs['http_code']
del kwargs['http_code']
if "http_code" in kwargs:
self.http_code = kwargs["http_code"]
del kwargs["http_code"]
super(ModoboaException, self).__init__(*args, **kwargs)
+7 -7
View File
@@ -19,7 +19,7 @@ from modoboa.lib.exceptions import BadRequest
from modoboa.lib.web_utils import render_to_json_response
ABC = abc.ABCMeta(force_str('ABC'), (object,), {})
ABC = abc.ABCMeta(force_str("ABC"), (object,), {})
class WizardStep(object):
@@ -87,7 +87,7 @@ class WizardForm(ABC):
result = {}
for step in self.steps:
for name, value in list(step.form.errors.items()):
if name == '__all__':
if name == "__all__":
continue
result[name] = value
return result
@@ -283,8 +283,8 @@ class TabForms(object):
"""
result = {}
for f in self.forms:
for name, value in list(f['instance'].errors.items()):
if name == '__all__':
for name, value in list(f["instance"].errors.items()):
if name == "__all__":
continue
result[name] = value
return result
@@ -298,9 +298,9 @@ class TabForms(object):
to_remove = []
for f in self.forms:
if mandatory_only and \
('mandatory' not in f or not f["mandatory"]):
("mandatory" not in f or not f["mandatory"]):
continue
elif optional_only and ('mandatory' in f and f["mandatory"]):
elif optional_only and ("mandatory" in f and f["mandatory"]):
continue
if not self._before_is_valid(f):
to_remove.append(f)
@@ -349,7 +349,7 @@ class TabForms(object):
self.save()
return self.done()
return render_to_json_response(
{'form_errors': self.errors}, status=400
{"form_errors": self.errors}, status=400
)
context = {
"tabs": self,
+40 -40
View File
@@ -61,13 +61,13 @@ PRINTABLE = set(range(0x20, 0x26)) | set(range(0x27, 0x7f))
def modified_utf7(s):
s_utf7 = s.encode('utf-7')
return s_utf7[1:-1].replace(b'/', b',')
s_utf7 = s.encode("utf-7")
return s_utf7[1:-1].replace(b"/", b",")
def doB64(_in, r):
if _in:
r.extend([b'&', modified_utf7(''.join(_in)), b'-'])
r.extend([b"&", modified_utf7("".join(_in)), b"-"])
del _in[:]
@@ -78,32 +78,32 @@ def encoder(s):
if ord(c) in PRINTABLE:
doB64(_in, r)
r.append(c.encode())
elif c == '&':
elif c == "&":
doB64(_in, r)
r.append(b'&-')
r.append(b"&-")
else:
_in.append(c)
doB64(_in, r)
return (b''.join(r), len(s))
return (b"".join(r), len(s))
# decoding
def modified_unutf7(s):
s_utf7 = b'+' + s.replace(b',', b'/') + b'-'
return s_utf7.decode('utf-7')
s_utf7 = b"+" + s.replace(b",", b"/") + b"-"
return s_utf7.decode("utf-7")
def decoder(s):
r = []
decoded = bytearray()
for c in s:
if c == ord('&') and not decoded:
decoded.append(ord('&'))
elif c == ord('-') and decoded:
if c == ord("&") and not decoded:
decoded.append(ord("&"))
elif c == ord("-") and decoded:
if len(decoded) == 1:
r.append('&')
r.append("&")
else:
r.append(modified_unutf7(decoded[1:]))
decoded = bytearray()
@@ -113,22 +113,22 @@ def decoder(s):
r.append(chr(c))
if decoded:
r.append(modified_unutf7(decoded[1:]))
bin_str = ''.join(r)
bin_str = "".join(r)
return (bin_str, len(s))
class StreamReader(codecs.StreamReader):
def decode(self, s, errors='strict'):
def decode(self, s, errors="strict"):
return decoder(s)
class StreamWriter(codecs.StreamWriter):
def decode(self, s, errors='strict'):
def decode(self, s, errors="strict"):
return encoder(s)
def imap4_utf_7(name):
if name == 'imap4-utf-7':
if name == "imap4-utf-7":
return (encoder, decoder, StreamReader, StreamWriter)
@@ -139,7 +139,7 @@ codecs.register(imap4_utf_7)
def imapUTF7Encode(ust):
"Returns imap utf-7 encoded version of string"
return ust.encode('imap4-utf-7')
return ust.encode("imap4-utf-7")
def imapUTF7EncodeSequence(seq):
@@ -149,7 +149,7 @@ def imapUTF7EncodeSequence(seq):
def imapUTF7Decode(st):
"Returns utf7 encoded version of imap utf-7 string"
return st.decode('imap4-utf-7')
return st.decode("imap4-utf-7")
def imapUTF7DecodeSequence(seq):
@@ -159,17 +159,17 @@ def imapUTF7DecodeSequence(seq):
def utf8Decode(st):
"Returns utf7 encoded version of imap utf-7 string"
return st.decode('utf-8')
return st.decode("utf-8")
def utf7SequenceToUTF8(seq):
"Returns utf7 encoded version of imap utf-7 strings in sequence"
return [itm.decode('imap4-utf-7').encode('utf-8') for itm in seq]
return [itm.decode("imap4-utf-7").encode("utf-8") for itm in seq]
__all__ = ['imapUTF7Encode', 'imapUTF7Decode', ]
__all__ = ["imapUTF7Encode", "imapUTF7Decode", ]
if __name__ == '__main__':
if __name__ == "__main__":
# print u'bøx'.encode('imap4-utf-7')
# print 'expected b&APg-x'
@@ -177,29 +177,29 @@ if __name__ == '__main__':
# print u'båx'.encode('imap4-utf-7')
# print 'expected b&AOU-x'
print('#######')
print('bøx')
print("#######")
print("bøx")
e = imapUTF7Encode(u'bøx')
print(e)
print(imapUTF7Decode(e).encode('latin-1'))
print(imapUTF7Decode(e).encode("latin-1"))
print('#######')
print('båx')
print("#######")
print("båx")
e = imapUTF7Encode(u'båx')
print(e)
print(imapUTF7Decode(e).encode('latin-1'))
print(imapUTF7Decode(e).encode("latin-1"))
print('#######')
print('~/bågø')
print("#######")
print("~/bågø")
e = imapUTF7Encode(u'~/bågø')
print(e)
print(imapUTF7Decode(e).encode('latin-1'))
print(imapUTF7Decode(e).encode("latin-1"))
print('#######')
print('Ting & Såger')
print("#######")
print("Ting & Såger")
e = imapUTF7Encode(u'Ting & Såger')
print(e)
print(imapUTF7Decode(e).encode('latin-1'))
print(imapUTF7Decode(e).encode("latin-1"))
# e = imapUTF7Decode('b&AOU-x')
# print e.encode('latin-1')
@@ -207,13 +207,13 @@ if __name__ == '__main__':
# e = imapUTF7Decode('b&APg-x')
# print e.encode('latin-1')
print('#######')
print('~/Følder/mailbåx & stuff + more')
print("#######")
print("~/Følder/mailbåx & stuff + more")
n = u'~/Følder/mailbåx & stuff + more'
e = imapUTF7Encode(n)
print(e)
print(imapUTF7Decode(e).encode('latin-1'))
print(imapUTF7Decode(e).encode("latin-1"))
print('#######')
print('~peter/mail/&ZeVnLIqe-/&U,BTFw-')
print(imapUTF7Decode('~peter/mail/&ZeVnLIqe-/&U,BTFw-').encode('utf-8'))
print("#######")
print("~peter/mail/&ZeVnLIqe-/&U,BTFw-")
print(imapUTF7Decode("~peter/mail/&ZeVnLIqe-/&U,BTFw-").encode("utf-8"))
+2 -2
View File
@@ -72,7 +72,7 @@ class LDAPAuthBackend(object):
"""Get a connection from the server."""
kwargs = {}
if six.PY3:
kwargs['bytes_mode'] = False
kwargs["bytes_mode"] = False
conn = ldap.initialize(self.server_uri, **kwargs)
conn.set_option(ldap.OPT_X_TLS_DEMAND, True)
conn.set_option(ldap.OPT_DEBUG_LEVEL, 255)
@@ -121,7 +121,7 @@ class LDAPAuthBackend(object):
user_dn = self._find_user_dn(user)
if self.ldap_ad:
newpassword = (
('"%s"' % newpassword).encode('utf-16').lstrip('\377\376')
('"%s"' % newpassword).encode("utf-16").lstrip("\377\376")
)
ldif = [(ldap.MOD_REPLACE,
self.pwd_attr,
+1 -1
View File
@@ -11,5 +11,5 @@ class _Singleton(type):
return cls._instances[cls]
class Singleton(_Singleton('SingletonMeta', (object,), {})):
class Singleton(_Singleton("SingletonMeta", (object,), {})):
pass
+2 -2
View File
@@ -16,7 +16,7 @@ register = template.Library()
@register.simple_tag
def join(items, sep=','):
def join(items, sep=","):
res = ""
for k, v in list(items.items()):
if res != "":
@@ -100,7 +100,7 @@ def extra_static_content(caller, st_type, user):
)
@register.filter(name='localize_header_name')
@register.filter(name="localize_header_name")
def localize_header_name(headername):
""" Localizes the header names """
names = {
+7 -7
View File
@@ -17,7 +17,7 @@ from modoboa.core import models as core_models
from .. import sysutils
try:
s = socket.create_connection(('127.0.0.1', 25))
s = socket.create_connection(("127.0.0.1", 25))
s.close()
NO_SMTP = False
except socket.error:
@@ -72,21 +72,21 @@ class ModoTestCase(ParametersMixin, TestCase):
if params is None:
params = {}
response = getattr(self.client, method)(
url, params, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
url, params, HTTP_X_REQUESTED_WITH="XMLHttpRequest")
self.assertEqual(response.status_code, status)
return response.json()
def ajax_post(self, *args, **kwargs):
return self.ajax_request('post', *args, **kwargs)
return self.ajax_request("post", *args, **kwargs)
def ajax_put(self, *args, **kwargs):
return self.ajax_request('put', *args, **kwargs)
return self.ajax_request("put", *args, **kwargs)
def ajax_delete(self, *args, **kwargs):
return self.ajax_request('delete', *args, **kwargs)
return self.ajax_request("delete", *args, **kwargs)
def ajax_get(self, *args, **kwargs):
return self.ajax_request('get', *args, **kwargs)
return self.ajax_request("get", *args, **kwargs)
class ModoAPITestCase(ParametersMixin, APITestCase):
@@ -103,4 +103,4 @@ class ModoAPITestCase(ParametersMixin, APITestCase):
def setUp(self):
"""Setup."""
super(ModoAPITestCase, self).setUp()
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token.key)
self.client.credentials(HTTP_AUTHORIZATION="Token " + self.token.key)
+5 -5
View File
@@ -49,12 +49,12 @@ class U2UTestCase(TestCase):
)
mailsploit_sample = (
'"=?utf-8?b?cG90dXNAd2hpdGVob3VzZS5nb3Y=?==?utf-8?Q?=0A=00?="\n'
'<=?utf-8?b?cG90dXNAd2hpdGVob3VzZS5nb3Y=?==?utf-8?Q?=0A=00?='
'@mailsploit.com>')
"<=?utf-8?b?cG90dXNAd2hpdGVob3VzZS5nb3Y=?==?utf-8?Q?=0A=00?="
"@mailsploit.com>")
expected_result = (
'potus@whitehouse.gov',
'=?utf-8?b?cG90dXNAd2hpdGVob3VzZS5nb3Y=?==?utf-8?Q??='
'@mailsploit.com')
"potus@whitehouse.gov",
"=?utf-8?b?cG90dXNAd2hpdGVob3VzZS5nb3Y=?==?utf-8?Q??="
"@mailsploit.com")
self.assertEqual(
u2u_decode.decode_address(mailsploit_sample),
expected_result)
+3 -3
View File
@@ -88,7 +88,7 @@ def render_to_json_response(context, **response_kwargs):
:return: ``HttpResponse`` object
"""
data = json.dumps(context)
response_kwargs['content_type'] = 'application/json'
response_kwargs["content_type"] = "application/json"
return HttpResponse(data, **response_kwargs)
@@ -136,8 +136,8 @@ class NavigationParameters(object):
def __init__(self, request, sessionkey):
self.request = request
self.sessionkey = sessionkey
self.parameters = [('pattern', '', True),
('criteria', 'from_addr', False)]
self.parameters = [("pattern", "", True),
("criteria", "from_addr", False)]
def __getitem__(self, key):
"""Retrieve an item."""
+6 -6
View File
@@ -41,7 +41,7 @@ class APIAdminLimitsTestCase(lib_tests.ModoAPITestCase):
def test_domadmins_limit(self):
"""Check domain admins limit."""
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.r_token.key)
HTTP_AUTHORIZATION="Token " + self.r_token.key)
limit = self.reseller.userobjectlimit_set.get(name="domain_admins")
url = reverse("api:account-list")
@@ -82,7 +82,7 @@ class APIAdminLimitsTestCase(lib_tests.ModoAPITestCase):
def test_domains_limit(self):
"""Check domains limit."""
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.r_token.key)
HTTP_AUTHORIZATION="Token " + self.r_token.key)
limit = self.reseller.userobjectlimit_set.get(name="domains")
quota = self.reseller.userobjectlimit_set.get(name="quota")
quota.max_value = 3
@@ -104,7 +104,7 @@ class APIAdminLimitsTestCase(lib_tests.ModoAPITestCase):
response = self.client.post(url, data, format="json")
self.assertEqual(response.status_code, 403)
self.assertEqual(
response.content.decode('utf-8'), '"Domains: limit reached"'
response.content.decode("utf-8"), '"Domains: limit reached"'
)
self.client.delete(
@@ -120,7 +120,7 @@ class APIAdminLimitsTestCase(lib_tests.ModoAPITestCase):
def test_domain_aliases_limit(self):
"""Check domain aliases limit."""
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.r_token.key)
HTTP_AUTHORIZATION="Token " + self.r_token.key)
domain = Domain.objects.get(name="test.com")
domain.add_admin(self.reseller)
limit = self.reseller.userobjectlimit_set.get(name="domain_aliases")
@@ -142,7 +142,7 @@ class APIAdminLimitsTestCase(lib_tests.ModoAPITestCase):
def test_mailboxes_limit(self):
"""Check mailboxes limit."""
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
limit = self.user.userobjectlimit_set.get(name="mailboxes")
url = reverse("api:account-list")
@@ -173,7 +173,7 @@ class APIAdminLimitsTestCase(lib_tests.ModoAPITestCase):
def test_aliases_limit(self):
"""Check mailbox aliases limit."""
self.client.credentials(
HTTP_AUTHORIZATION='Token ' + self.da_token.key)
HTTP_AUTHORIZATION="Token " + self.da_token.key)
limit = self.user.userobjectlimit_set.get(name="mailbox_aliases")
url = reverse("api:alias-list")
+136 -136
View File
@@ -30,7 +30,7 @@ class PermissionsTestCase(lib_tests.ModoTestCase):
values = dict(
username="reseller@test.com", first_name="Reseller", last_name="",
password1="Toto1234", password2="Toto1234", role="Resellers",
is_active=True, email="reseller@test.com", stepid='step2'
is_active=True, email="reseller@test.com", stepid="step2"
)
self.ajax_post(reverse("admin:account_add"), values)
account = User.objects.get(username="reseller@test.com")
@@ -60,19 +60,19 @@ class ResourceTestCase(lib_tests.ModoTestCase):
populate_database()
def _create_account(
self, username, role='SimpleUsers', status=200, **kwargs):
self, username, role="SimpleUsers", status=200, **kwargs):
values = dict(
username=username, first_name="Tester", last_name="Toto",
password1="Toto1234", password2="Toto1234", role=role,
quota_act=True,
is_active=True, email=username, stepid='step2',
is_active=True, email=username, stepid="step2",
)
values.update(kwargs)
return self.ajax_post(
reverse("admin:account_add"), values, status
)
def _create_alias(self, email, rcpt='user@test.com', status=200):
def _create_alias(self, email, rcpt="user@test.com", status=200):
values = dict(
address=email, recipients=rcpt, enabled=True
)
@@ -130,7 +130,7 @@ class DomainAdminTestCase(ResourceTestCase):
def setUpTestData(cls):
"""Create test data."""
super(DomainAdminTestCase, cls).setUpTestData()
cls.user = User.objects.get(username='admin@test.com')
cls.user = User.objects.get(username="admin@test.com")
cls.user.userobjectlimit_set.filter(
name__in=["mailboxes", "mailbox_aliases"]).update(max_value=2)
@@ -140,40 +140,40 @@ class DomainAdminTestCase(ResourceTestCase):
self.client.force_login(self.user)
def test_mailboxes_limit(self):
self._create_account('tester1@test.com')
self._check_limit('mailboxes', 1, 2)
self._create_account('tester2@test.com')
self._check_limit('mailboxes', 2, 2)
self._create_account('tester3@test.com', status=403)
self._check_limit('mailboxes', 2, 2)
self._create_account("tester1@test.com")
self._check_limit("mailboxes", 1, 2)
self._create_account("tester2@test.com")
self._check_limit("mailboxes", 2, 2)
self._create_account("tester3@test.com", status=403)
self._check_limit("mailboxes", 2, 2)
self.ajax_post(
reverse('admin:account_delete',
args=[User.objects.get(username='tester2@test.com').id]),
reverse("admin:account_delete",
args=[User.objects.get(username="tester2@test.com").id]),
{}
)
self._check_limit('mailboxes', 1, 2)
self._check_limit("mailboxes", 1, 2)
def test_aliases_limit(self):
self._create_alias('alias1@test.com')
self._check_limit('mailbox_aliases', 1, 2)
self._create_alias('alias2@test.com')
self._check_limit('mailbox_aliases', 2, 2)
self._create_alias('alias3@test.com', status=403)
self._check_limit('mailbox_aliases', 2, 2)
self._create_alias("alias1@test.com")
self._check_limit("mailbox_aliases", 1, 2)
self._create_alias("alias2@test.com")
self._check_limit("mailbox_aliases", 2, 2)
self._create_alias("alias3@test.com", status=403)
self._check_limit("mailbox_aliases", 2, 2)
# Set unlimited value
self.user.userobjectlimit_set.filter(name="mailbox_aliases").update(
max_value=-1)
self._create_alias('alias3@test.com')
self._check_limit('mailbox_aliases', 3, -1)
self._create_alias("alias3@test.com")
self._check_limit("mailbox_aliases", 3, -1)
self.ajax_post(
reverse('admin:alias_delete') + '?selection=%d'
% Alias.objects.get(address='alias2@test.com').id,
reverse("admin:alias_delete") + "?selection=%d"
% Alias.objects.get(address="alias2@test.com").id,
{}
)
self._check_limit('mailbox_aliases', 2, -1)
self._check_limit("mailbox_aliases", 2, -1)
def test_aliases_limit_through_account_form(self):
user = User.objects.get(username='user@test.com')
user = User.objects.get(username="user@test.com")
values = dict(
username=user.username, role=user.role,
is_active=user.is_active, email=user.email, quota_act=True,
@@ -184,8 +184,8 @@ class DomainAdminTestCase(ResourceTestCase):
reverse("admin:account_change", args=[user.id]),
values
)
Alias.objects.get(address='alias1@test.com')
self._check_limit('mailbox_aliases', 2, 2)
Alias.objects.get(address="alias1@test.com")
self._check_limit("mailbox_aliases", 2, 2)
class ResellerTestCase(ResourceTestCase):
@@ -197,7 +197,7 @@ class ResellerTestCase(ResourceTestCase):
cls.localconfig.parameters.set_value("deflt_user_quota_limit", 1000)
cls.localconfig.save()
cls.user = UserFactory(
username='reseller', groups=('Resellers',)
username="reseller", groups=("Resellers",)
)
def setUp(self):
@@ -209,32 +209,32 @@ class ResellerTestCase(ResourceTestCase):
response = self.client.get(reverse("admin:domain_list"))
self.assertContains(response, "Domains (0%)")
self.assertContains(response, "Domain aliases (0%)")
self._create_domain('domain1.tld')
self._check_limit('domains', 1, 2)
self._create_domain('domain2.tld')
self._check_limit('domains', 2, 2)
self._create_domain('domain3.tld', 403)
self._check_limit('domains', 2, 2)
self._create_domain("domain1.tld")
self._check_limit("domains", 1, 2)
self._create_domain("domain2.tld")
self._check_limit("domains", 2, 2)
self._create_domain("domain3.tld", 403)
self._check_limit("domains", 2, 2)
self.ajax_post(
reverse('admin:domain_delete',
args=[Domain.objects.get(name='domain2.tld').id]),
reverse("admin:domain_delete",
args=[Domain.objects.get(name="domain2.tld").id]),
{}
)
self._check_limit('domains', 1, 2)
self._check_limit("domains", 1, 2)
def test_domain_aliases_limit(self):
self._create_domain('pouet.com')
self._domain_alias_operation('add', 'pouet.com', 'domain-alias1.tld')
self._check_limit('domain_aliases', 1, 2)
self._domain_alias_operation('add', 'pouet.com', 'domain-alias2.tld')
self._check_limit('domain_aliases', 2, 2)
self._create_domain("pouet.com")
self._domain_alias_operation("add", "pouet.com", "domain-alias1.tld")
self._check_limit("domain_aliases", 1, 2)
self._domain_alias_operation("add", "pouet.com", "domain-alias2.tld")
self._check_limit("domain_aliases", 2, 2)
self._domain_alias_operation(
'add', 'pouet.com', 'domain-alias3.tld', 403
"add", "pouet.com", "domain-alias3.tld", 403
)
self._check_limit('domain_aliases', 2, 2)
self._check_limit("domain_aliases", 2, 2)
self._domain_alias_operation(
'delete', 'pouet.com', 'domain-alias2.tld')
self._check_limit('domain_aliases', 1, 2)
"delete", "pouet.com", "domain-alias2.tld")
self._check_limit("domain_aliases", 1, 2)
def test_domain_admins_limit(self):
response = self.client.get(reverse("admin:identity_list"))
@@ -242,21 +242,21 @@ class ResellerTestCase(ResourceTestCase):
self.assertContains(response, "Mailboxes (0%)")
self.assertContains(response, "Mailbox aliases (0%)")
self._create_domain('domain.tld')
self._create_account('admin1@domain.tld', role='DomainAdmins')
self._check_limit('domain_admins', 1, 2)
self._create_account('admin2@domain.tld', role='DomainAdmins')
self._check_limit('domain_admins', 2, 2)
self._create_domain("domain.tld")
self._create_account("admin1@domain.tld", role="DomainAdmins")
self._check_limit("domain_admins", 1, 2)
self._create_account("admin2@domain.tld", role="DomainAdmins")
self._check_limit("domain_admins", 2, 2)
resp = self._create_account(
'admin3@domain.tld',
role='DomainAdmins',
"admin3@domain.tld",
role="DomainAdmins",
status=400)
self.assertEqual(
resp['form_errors']['role'][0],
'Select a valid choice. DomainAdmins is not one of the available '
'choices.'
resp["form_errors"]["role"][0],
"Select a valid choice. DomainAdmins is not one of the available "
"choices."
)
self._check_limit('domain_admins', 2, 2)
self._check_limit("domain_admins", 2, 2)
self.user.userobjectlimit_set.filter(
name="mailboxes").update(max_value=3)
@@ -272,17 +272,17 @@ class ResellerTestCase(ResourceTestCase):
values, status=400
)
self.assertEqual(
resp['form_errors']['role'][0],
'Select a valid choice. DomainAdmins is not one of the available '
'choices.'
resp["form_errors"]["role"][0],
"Select a valid choice. DomainAdmins is not one of the available "
"choices."
)
self._check_limit('domain_admins', 2, 2)
self._check_limit("domain_admins", 2, 2)
def test_domain_admin_resource_are_empty(self):
self._create_domain('domain.tld')
self._create_account('admin1@domain.tld', role='DomainAdmins')
domadmin = User.objects.get(username='admin1@domain.tld')
for l in ['mailboxes', 'mailbox_aliases']:
self._create_domain("domain.tld")
self._create_account("admin1@domain.tld", role="DomainAdmins")
domadmin = User.objects.get(username="admin1@domain.tld")
for l in ["mailboxes", "mailbox_aliases"]:
self.assertEqual(
domadmin.userobjectlimit_set.get(name=l).max_value, 0
)
@@ -290,13 +290,13 @@ class ResellerTestCase(ResourceTestCase):
def test_domain_admins_limit_from_domain_tpl(self):
self.user.userobjectlimit_set.filter(
name="domains").update(max_value=3)
self._create_domain('domain1.tld', withtpl=True)
self._create_domain('domain2.tld', withtpl=True)
self._check_limit('domain_admins', 2, 2)
self._check_limit('domains', 2, 3)
self._create_domain('domain3.tld', status=200, withtpl=True)
self._check_limit('domain_admins', 2, 2)
self._check_limit('domains', 3, 3)
self._create_domain("domain1.tld", withtpl=True)
self._create_domain("domain2.tld", withtpl=True)
self._check_limit("domain_admins", 2, 2)
self._check_limit("domains", 2, 3)
self._create_domain("domain3.tld", status=200, withtpl=True)
self._check_limit("domain_admins", 2, 2)
self._check_limit("domains", 3, 3)
def test_quota(self):
"""Check quota resource."""
@@ -353,51 +353,51 @@ class ResellerTestCase(ResourceTestCase):
def test_reseller_deletes_domain(self):
"""Check if all resources are restored after the deletion."""
self._create_domain('domain.tld', withtpl=True)
self._create_domain("domain.tld", withtpl=True)
dom = Domain.objects.get(name="domain.tld")
self.ajax_post(
reverse("admin:domain_delete", args=[dom.id]),
{}
)
self._check_limit('domains', 0, 2)
self._check_limit('domain_admins', 1, 2)
self._check_limit('mailboxes', 0, 2)
self._check_limit('mailbox_aliases', 0, 2)
self._check_limit("domains", 0, 2)
self._check_limit("domain_admins", 1, 2)
self._check_limit("mailboxes", 0, 2)
self._check_limit("mailbox_aliases", 0, 2)
def test_sadmin_removes_ownership(self):
self._create_domain('domain.tld', withtpl=True)
self._create_domain("domain.tld", withtpl=True)
dom = Domain.objects.get(name="domain.tld")
self.client.logout()
self.client.login(username='admin', password='password')
self.client.login(username="admin", password="password")
self.ajax_get(
"{0}?domid={1}&daid={2}".format(
reverse('admin:permission_remove'),
reverse("admin:permission_remove"),
dom.id, self.user.id
), {}
)
self._check_limit('domains', 0, 2)
self._check_limit('domain_admins', 0, 2)
self._check_limit('mailboxes', 0, 2)
self._check_limit('mailbox_aliases', 0, 2)
self._check_limit("domains", 0, 2)
self._check_limit("domain_admins", 0, 2)
self._check_limit("mailboxes", 0, 2)
self._check_limit("mailbox_aliases", 0, 2)
def test_allocate_from_pool(self):
self._create_domain('domain.tld')
self._create_account('admin1@domain.tld', role='DomainAdmins')
user = User.objects.get(username='admin1@domain.tld')
self._create_domain("domain.tld")
self._create_account("admin1@domain.tld", role="DomainAdmins")
user = User.objects.get(username="admin1@domain.tld")
# Give 1 mailbox and 2 aliases to the admin -> should work
values = {
'username': user.username, 'role': user.role, 'quota_act': True,
'is_active': user.is_active, 'email': user.email,
'mailboxes_limit': 1, 'mailbox_aliases_limit': 2,
'language': 'en'
"username": user.username, "role": user.role, "quota_act": True,
"is_active": user.is_active, "email": user.email,
"mailboxes_limit": 1, "mailbox_aliases_limit": 2,
"language": "en"
}
self.ajax_post(
reverse("admin:account_change", args=[user.id]),
values
)
self._check_limit('mailboxes', 1, 1)
self._check_limit('mailbox_aliases', 0, 0)
self._check_limit("mailboxes", 1, 1)
self._check_limit("mailbox_aliases", 0, 0)
# Delete the admin -> resources should go back to the
# reseller's pool
@@ -405,20 +405,20 @@ class ResellerTestCase(ResourceTestCase):
reverse("admin:account_delete", args=[user.id]),
{}
)
self._check_limit('mailboxes', 0, 2)
self._check_limit('mailbox_aliases', 0, 2)
self._check_limit("mailboxes", 0, 2)
self._check_limit("mailbox_aliases", 0, 2)
def test_restore_resources(self):
"""Give resource to a domain admin and restore them."""
self._create_domain('domain.tld')
dom = Domain.objects.get(name='domain.tld')
self._create_account('admin1@domain.tld', role='DomainAdmins')
user = User.objects.get(username='admin1@domain.tld')
self._create_domain("domain.tld")
dom = Domain.objects.get(name="domain.tld")
self._create_account("admin1@domain.tld", role="DomainAdmins")
user = User.objects.get(username="admin1@domain.tld")
values = {
'username': user.username, 'role': user.role, 'quota_act': True,
'is_active': user.is_active, 'email': user.email,
'mailboxes_limit': 1, 'mailbox_aliases_limit': 2,
'language': 'en'
"username": user.username, "role": user.role, "quota_act": True,
"is_active": user.is_active, "email": user.email,
"mailboxes_limit": 1, "mailbox_aliases_limit": 2,
"language": "en"
}
self.ajax_post(
reverse("admin:account_change", args=[user.id]),
@@ -426,71 +426,71 @@ class ResellerTestCase(ResourceTestCase):
)
dom.add_admin(user)
self.client.logout()
self.client.login(username='admin1@domain.tld', password='Toto1234')
self._create_account('user1@domain.tld')
self._create_alias('alias1@domain.tld', 'user1@domain.tld')
self._create_alias('alias2@domain.tld', 'user1@domain.tld')
self.client.login(username="admin1@domain.tld", password="Toto1234")
self._create_account("user1@domain.tld")
self._create_alias("alias1@domain.tld", "user1@domain.tld")
self._create_alias("alias2@domain.tld", "user1@domain.tld")
self.client.logout()
self.client.login(username='reseller', password='toto')
self.client.login(username="reseller", password="toto")
# Delete the admin -> resources should go back to the
# reseller's pool
self.ajax_post(
reverse("admin:account_delete", args=[user.id]),
{}
)
self._check_limit('mailboxes', 1, 2)
self._check_limit('mailbox_aliases', 2, 2)
self._check_limit("mailboxes", 1, 2)
self._check_limit("mailbox_aliases", 2, 2)
def test_change_role(self):
self._create_domain('domain.tld')
self._create_account('admin1@domain.tld', role='DomainAdmins')
user = User.objects.get(username='admin1@domain.tld')
self._create_domain("domain.tld")
self._create_account("admin1@domain.tld", role="DomainAdmins")
user = User.objects.get(username="admin1@domain.tld")
# Give 1 mailbox and 2 aliases to the admin -> should work
values = {
'username': user.username, 'role': user.role, 'quota_act': True,
'is_active': user.is_active, 'email': user.email,
'mailboxes_limit': 1, 'mailbox_aliases_limit': 2,
'language': 'en'
"username": user.username, "role": user.role, "quota_act": True,
"is_active": user.is_active, "email": user.email,
"mailboxes_limit": 1, "mailbox_aliases_limit": 2,
"language": "en"
}
self.ajax_post(
reverse("admin:account_change", args=[user.id]),
values
)
self._check_limit('mailboxes', 1, 1)
self._check_limit('mailbox_aliases', 0, 0)
self._check_limit("mailboxes", 1, 1)
self._check_limit("mailbox_aliases", 0, 0)
# Change admin role to SimpleUser -> resources should go back
# to the reseller.
values = {
'username': user.username, 'role': 'SimpleUsers',
'quota_act': True,
'is_active': user.is_active, 'email': user.email,
'language': 'en',
"username": user.username, "role": "SimpleUsers",
"quota_act": True,
"is_active": user.is_active, "email": user.email,
"language": "en",
}
self.ajax_post(
reverse("admin:account_change", args=[user.id]),
values
)
self._check_limit('mailboxes', 1, 2)
self._check_limit('mailbox_aliases', 0, 2)
self._check_limit("mailboxes", 1, 2)
self._check_limit("mailbox_aliases", 0, 2)
def test_allocate_too_much(self):
self._create_domain('domain.tld')
self._create_account('admin1@domain.tld', role='DomainAdmins')
user = User.objects.get(username='admin1@domain.tld')
self._create_domain("domain.tld")
self._create_account("admin1@domain.tld", role="DomainAdmins")
user = User.objects.get(username="admin1@domain.tld")
# Give 2 mailboxes and 3 aliases to the admin -> should fail.
values = {
'username': user.username, 'role': user.role, 'quota_act': True,
'is_active': user.is_active, 'email': user.email,
'mailboxes_limit': 2, 'mailbox_aliases_limit': 3,
'language': 'en'
"username": user.username, "role": user.role, "quota_act": True,
"is_active": user.is_active, "email": user.email,
"mailboxes_limit": 2, "mailbox_aliases_limit": 3,
"language": "en"
}
resp = self.ajax_post(
reverse("admin:account_change", args=[user.id]),
values, 424
)
self.assertEqual(resp, 'Not enough resources')
self._check_limit('mailboxes', 1, 2)
self._check_limit('mailbox_aliases', 0, 2)
self.assertEqual(resp, "Not enough resources")
self._check_limit("mailboxes", 1, 2)
self._check_limit("mailbox_aliases", 0, 2)
+1 -1
View File
@@ -4,4 +4,4 @@ from django.apps import AppConfig
class ParametersConfig(AppConfig):
name = 'parameters'
name = "parameters"
+40 -40
View File
@@ -53,12 +53,12 @@ class Operations(object):
"default_mailbox_quota": domain.default_mailbox_quota
}
aliases = [alias.name for alias in domain.domainalias_set.all()]
if optype == 'add':
if optype == "add":
aliases.append(name)
else:
aliases.remove(name)
for cpt, alias in enumerate(aliases):
fname = 'aliases' if not cpt else 'aliases_%d' % cpt
fname = "aliases" if not cpt else "aliases_%d" % cpt
values[fname] = alias
return self.ajax_post(
reverse("admin:domain_change",
@@ -115,20 +115,20 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
FIXME: add a check for domain alias.
"""
self._create_relay_domain('relaydomain1.tld')
transport = tr_models.Transport.objects.get(pattern='relaydomain1.tld')
self._create_relay_domain("relaydomain1.tld")
transport = tr_models.Transport.objects.get(pattern="relaydomain1.tld")
self.assertEqual(
transport._settings["relay_target_host"], 'external.host.tld')
transport._settings["relay_target_host"], "external.host.tld")
self.assertEqual(
transport._settings["relay_verify_recipients"], False)
resp = self._create_relay_domain('test.com', 400)
self.assertEqual(resp['form_errors']['name'][0],
'Domain with this Name already exists.')
resp = self._create_relay_domain('relaydomainalias.tld', 400)
resp = self._create_relay_domain("test.com", 400)
self.assertEqual(resp["form_errors"]["name"][0],
"Domain with this Name already exists.")
resp = self._create_relay_domain("relaydomainalias.tld", 400)
self.assertEqual(
resp['form_errors']['name'][0],
'A domain alias with this name already exists'
resp["form_errors"]["name"][0],
"A domain alias with this name already exists"
)
def test_create_relaydomainalias(self):
@@ -140,21 +140,21 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
FIXME: add a check for domain alias.
"""
self._relay_domain_alias_operation(
'add', self.dom, 'relaydomainalias1.tld'
"add", self.dom, "relaydomainalias1.tld"
)
resp = self._relay_domain_alias_operation(
'add', self.dom, 'test.com', 400
"add", self.dom, "test.com", 400
)
self.assertEqual(
resp['form_errors']['aliases_2'][0],
'A domain with this name already exists'
resp["form_errors"]["aliases_2"][0],
"A domain with this name already exists"
)
resp = self._relay_domain_alias_operation(
'add', self.dom, self.dom.name, 400
"add", self.dom, self.dom.name, 400
)
self.assertEqual(
resp['form_errors']['aliases_2'][0],
'A domain with this name already exists'
resp["form_errors"]["aliases_2"][0],
"A domain with this name already exists"
)
def test_edit_relaydomain(self):
@@ -238,12 +238,12 @@ class RelayDomainsTestCase(ModoTestCase, Operations):
"quota": 0, "default_mailbox_quota": 0
}
self.ajax_post(
reverse('admin:domain_change', args=[self.dom.id]),
reverse("admin:domain_change", args=[self.dom.id]),
values
)
admin_models.DomainAlias.objects.get(name='relaydomainalias.net')
admin_models.DomainAlias.objects.get(name="relaydomainalias.net")
with self.assertRaises(admin_models.DomainAlias.DoesNotExist):
admin_models.DomainAlias.objects.get(name='relaydomainalias.tld')
admin_models.DomainAlias.objects.get(name="relaydomainalias.tld")
def test_delete_relaydomain(self):
"""Test the removal of a relay domain."""
@@ -316,7 +316,7 @@ class LimitsTestCase(ModoTestCase, Operations):
"deflt_user_{0}_limit".format(name), 2, app="limits")
cls.localconfig.save()
cls.user = UserFactory.create(
username='reseller', groups=('Resellers',)
username="reseller", groups=("Resellers",)
)
def setUp(self):
@@ -326,38 +326,38 @@ class LimitsTestCase(ModoTestCase, Operations):
def test_relay_domains_limit(self):
self._create_relay_domain(
'relaydomain1.tld', quota=1, default_mailbox_quota=1)
self._check_limit('domains', 1, 2)
"relaydomain1.tld", quota=1, default_mailbox_quota=1)
self._check_limit("domains", 1, 2)
self._create_relay_domain(
'relaydomain2.tld', quota=1, default_mailbox_quota=1)
self._check_limit('domains', 2, 2)
self._create_relay_domain('relaydomain3.tld', 403)
self._check_limit('domains', 2, 2)
domid = admin_models.Domain.objects.get(name='relaydomain2.tld').id
"relaydomain2.tld", quota=1, default_mailbox_quota=1)
self._check_limit("domains", 2, 2)
self._create_relay_domain("relaydomain3.tld", 403)
self._check_limit("domains", 2, 2)
domid = admin_models.Domain.objects.get(name="relaydomain2.tld").id
self.ajax_post(
reverse('admin:domain_delete', args=[domid]), {})
self._check_limit('domains', 1, 2)
reverse("admin:domain_delete", args=[domid]), {})
self._check_limit("domains", 1, 2)
def test_relay_domain_aliases_limit(self):
self._create_relay_domain(
'relaydomain1.tld', quota=1, default_mailbox_quota=1)
"relaydomain1.tld", quota=1, default_mailbox_quota=1)
domain = admin_models.Domain.objects.get(name="relaydomain1.tld")
self._relay_domain_alias_operation(
'add', domain, 'relay-domain-alias1.tld'
"add", domain, "relay-domain-alias1.tld"
)
self._check_limit('domain_aliases', 1, 2)
self._check_limit("domain_aliases", 1, 2)
self._relay_domain_alias_operation(
'add', domain, 'relay-domain-alias2.tld'
"add", domain, "relay-domain-alias2.tld"
)
self._check_limit('domain_aliases', 2, 2)
self._check_limit("domain_aliases", 2, 2)
self._relay_domain_alias_operation(
'add', domain, 'relay-domain-alias3.tld', 403
"add", domain, "relay-domain-alias3.tld", 403
)
self._check_limit('domain_aliases', 2, 2)
self._check_limit("domain_aliases", 2, 2)
self._relay_domain_alias_operation(
'delete', domain, 'relay-domain-alias2.tld'
"delete", domain, "relay-domain-alias2.tld"
)
self._check_limit('domain_aliases', 1, 2)
self._check_limit("domain_aliases", 1, 2)
class MapFilesTestCase(MapFilesTestCaseMixin, TestCase):
+26 -26
View File
@@ -7,46 +7,46 @@ import os
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DB = os.environ.get('DB', 'POSTGRESQL')
DB = os.environ.get("DB", "POSTGRESQL")
if DB == 'MYSQL':
if DB == "MYSQL":
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'modoboa',
'USER': 'root',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '',
'ATOMIC_REQUESTS': True,
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "modoboa",
"USER": "root",
"PASSWORD": "",
"HOST": "localhost",
"PORT": "",
"ATOMIC_REQUESTS": True,
# MySQL's Strict Mode fixes many data integrity problems in MySQL,
# such as data truncation upon insertion, by escalating warnings
# into errors. It is strongly recommended you activate it.
# MySQL >= 5.7 set STRICT_TRANS_TABLES by default
# See: https://docs.djangoproject.com/en/1.11/ref/databases/#mysql-sql-mode
'OPTIONS': {
'init_command': 'SET sql_mode=\'STRICT_TRANS_TABLES\'',
"OPTIONS": {
"init_command": 'SET sql_mode=\'STRICT_TRANS_TABLES\'',
},
},
}
elif DB == 'SQLITE':
elif DB == "SQLITE":
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'modoboa.db',
'PORT': '',
'ATOMIC_REQUESTS': True,
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": "modoboa.db",
"PORT": "",
"ATOMIC_REQUESTS": True,
},
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'modoboa',
'USER': 'postgres',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '',
'ATOMIC_REQUESTS': True,
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "modoboa",
"USER": "postgres",
"PASSWORD": "",
"HOST": "localhost",
"PORT": "",
"ATOMIC_REQUESTS": True,
},
}
+1 -1
View File
@@ -4,7 +4,7 @@ from django.apps import AppConfig
class TransportConfig(AppConfig):
name = 'modoboa.transport'
name = "modoboa.transport"
def ready(self):
from . import handlers
+5 -5
View File
@@ -17,17 +17,17 @@ from modoboa.core import signals as core_signals
from modoboa.core import views as core_views
from modoboa.core.extensions import exts_pool
API_TITLE = 'Modoboa API'
API_TITLE = "Modoboa API"
urlpatterns = [
url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name='javascript-catalog'),
url(r'^jsi18n/$', JavaScriptCatalog.as_view(), name="javascript-catalog"),
url(r'^ckeditor/upload/', login_required(cku_views.upload),
name="ckeditor_upload"),
url(r'^ckeditor/browse/', login_required(cku_views.browse),
name="ckeditor_browse"),
url('', include('modoboa.core.urls', namespace="core")),
url('^user/forward/', forward, name="user_forward"),
url('admin/', include('modoboa.admin.urls', namespace="admin")),
url("", include("modoboa.core.urls", namespace="core")),
url("^user/forward/", forward, name="user_forward"),
url("admin/", include("modoboa.admin.urls", namespace="admin")),
# No namespace
url(r'^accounts/password_reset/$', core_views.password_reset,
name="password_reset"),
+111 -111
View File
@@ -26,16 +26,16 @@ BASE_DIR = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '!8o(-dbbl3e+*bh7nx-^xysdt)1gso*%@4ze4-9_9o+i&amp;t--u_'
SECRET_KEY = "!8o(-dbbl3e+*bh7nx-^xysdt)1gso*%@4ze4-9_9o+i&amp;t--u_"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = 'DEBUG' in os.environ
DEBUG = "DEBUG" in os.environ
TEMPLATE_DEBUG = DEBUG
ALLOWED_HOSTS = [
'127.0.0.1',
'localhost',
"127.0.0.1",
"localhost",
]
SITE_ID = 1
@@ -47,57 +47,57 @@ X_FRAME_OPTIONS = "SAMEORIGIN"
# Application definition
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.sites',
'django.contrib.staticfiles',
'reversion',
'ckeditor',
'ckeditor_uploader',
'rest_framework',
'rest_framework.authtoken',
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.sites",
"django.contrib.staticfiles",
"reversion",
"ckeditor",
"ckeditor_uploader",
"rest_framework",
"rest_framework.authtoken",
)
# A dedicated place to register Modoboa applications
# Do not delete it.
# Do not change the order.
MODOBOA_APPS = (
'modoboa',
'modoboa.core',
'modoboa.lib',
'modoboa.admin',
'modoboa.transport',
'modoboa.relaydomains',
'modoboa.limits',
'modoboa.parameters',
"modoboa",
"modoboa.core",
"modoboa.lib",
"modoboa.admin",
"modoboa.transport",
"modoboa.relaydomains",
"modoboa.limits",
"modoboa.parameters",
# Modoboa extensions here.
)
INSTALLED_APPS += MODOBOA_APPS
AUTH_USER_MODEL = 'core.User'
AUTH_USER_MODEL = "core.User"
MIDDLEWARE = (
'x_forwarded_for.middleware.XForwardedForMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'modoboa.core.middleware.LocalConfigMiddleware',
'modoboa.lib.middleware.AjaxLoginRedirect',
'modoboa.lib.middleware.CommonExceptionCatcher',
'modoboa.lib.middleware.RequestCatcherMiddleware',
"x_forwarded_for.middleware.XForwardedForMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"modoboa.core.middleware.LocalConfigMiddleware",
"modoboa.lib.middleware.AjaxLoginRedirect",
"modoboa.lib.middleware.CommonExceptionCatcher",
"modoboa.lib.middleware.RequestCatcherMiddleware",
)
AUTHENTICATION_BACKENDS = (
# 'modoboa.lib.authbackends.LDAPBackend',
# 'modoboa.lib.authbackends.SMTPBackend',
'django.contrib.auth.backends.ModelBackend',
"django.contrib.auth.backends.ModelBackend",
)
# SMTP authentication
@@ -108,37 +108,37 @@ AUTHENTICATION_BACKENDS = (
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'modoboa.core.context_processors.top_notifications',
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.template.context_processors.i18n",
"django.template.context_processors.media",
"django.template.context_processors.static",
"django.template.context_processors.tz",
"django.contrib.messages.context_processors.messages",
"modoboa.core.context_processors.top_notifications",
],
'debug': TEMPLATE_DEBUG,
"debug": TEMPLATE_DEBUG,
},
},
]
ROOT_URLCONF = 'test_project.urls'
ROOT_URLCONF = "test_project.urls"
WSGI_APPLICATION = 'test_project.wsgi.application'
WSGI_APPLICATION = "test_project.wsgi.application"
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = "en-us"
TIME_ZONE = 'UTC'
TIME_ZONE = "UTC"
USE_I18N = True
@@ -149,21 +149,21 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/sitestatic/'
STATIC_ROOT = os.path.join(BASE_DIR, 'sitestatic')
STATIC_URL = "/sitestatic/"
STATIC_ROOT = os.path.join(BASE_DIR, "sitestatic")
STATICFILES_DIRS = (
os.path.join(BASE_DIR, '..', 'modoboa', 'bower_components'),
os.path.join(BASE_DIR, "..", "modoboa", "bower_components"),
)
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
# Rest framework settings
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.TokenAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
}
@@ -172,31 +172,31 @@ REST_FRAMEWORK = {
# DOVECOT_LOOKUP_PATH = ('/path/to/dovecot', )
MODOBOA_API_URL = 'https://api.modoboa.org/1/'
MODOBOA_API_URL = "https://api.modoboa.org/1/"
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
{
'NAME': 'modoboa.core.password_validation.ComplexityValidator',
'OPTIONS': {
'upper': 1,
'lower': 1,
'digits': 1,
'specials': 0
"NAME": "modoboa.core.password_validation.ComplexityValidator",
"OPTIONS": {
"upper": 1,
"lower": 1,
"digits": 1,
"specials": 0
}
},
]
@@ -214,21 +214,21 @@ CKEDITOR_BROWSE_SHOW_DIRS = True
CKEDITOR_ALLOW_NONIMAGE_FILES = False
CKEDITOR_CONFIGS = {
'default': {
'allowedContent': True,
'toolbar': 'Modoboa',
'width': None,
'toolbar_Modoboa': [
['Bold', 'Italic', 'Underline'],
['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
['BidiLtr', 'BidiRtl', 'Language'],
['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent'],
['Undo', 'Redo'],
['Link', 'Unlink', 'Anchor', '-', 'Smiley'],
['TextColor', 'BGColor', '-', 'Source'],
['Font', 'FontSize'],
['Image', ],
['SpellChecker']
"default": {
"allowedContent": True,
"toolbar": "Modoboa",
"width": None,
"toolbar_Modoboa": [
["Bold", "Italic", "Underline"],
["JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"],
["BidiLtr", "BidiRtl", "Language"],
["NumberedList", "BulletedList", "-", "Outdent", "Indent"],
["Undo", "Redo"],
["Link", "Unlink", "Anchor", "-", "Smiley"],
["TextColor", "BGColor", "-", "Source"],
["Font", "FontSize"],
["Image", ],
["SpellChecker"]
],
},
}
@@ -236,33 +236,33 @@ CKEDITOR_CONFIGS = {
# Logging configuration
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'syslog': {
'format': '%(name)s: %(levelname)s %(message)s'
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"syslog": {
"format": "%(name)s: %(levelname)s %(message)s"
},
},
'handlers': {
'syslog-auth': {
'class': 'logging.handlers.SysLogHandler',
'facility': SysLogHandler.LOG_AUTH,
'formatter': 'syslog'
"handlers": {
"syslog-auth": {
"class": "logging.handlers.SysLogHandler",
"facility": SysLogHandler.LOG_AUTH,
"formatter": "syslog"
},
'modoboa': {
'class': 'modoboa.core.loggers.SQLHandler',
"modoboa": {
"class": "modoboa.core.loggers.SQLHandler",
}
},
'loggers': {
'modoboa.auth': {
'handlers': ['syslog-auth', 'modoboa'],
'level': 'INFO',
'propagate': False
"loggers": {
"modoboa.auth": {
"handlers": ["syslog-auth", "modoboa"],
"level": "INFO",
"propagate": False
},
'modoboa.admin': {
'handlers': ['modoboa'],
'level': 'INFO',
'propagate': False
"modoboa.admin": {
"handlers": ["modoboa"],
"level": "INFO",
"propagate": False
}
}
}
+1 -1
View File
@@ -25,7 +25,7 @@ class DeployTest(unittest.TestCase):
cmd = (
"modoboa-admin.py deploy --collectstatic "
"--dburl %s --domain %s --admin-username admin %s"
% (dburl, 'localhost', self.projname)
% (dburl, "localhost", self.projname)
)
code, output = exec_cmd(cmd, cwd=self.workdir)
self.assertEqual(code, 0)