mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-19 05:58:34 +02:00
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:
+17
-17
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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')"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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"))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -11,5 +11,5 @@ class _Singleton(type):
|
||||
return cls._instances[cls]
|
||||
|
||||
|
||||
class Singleton(_Singleton('SingletonMeta', (object,), {})):
|
||||
class Singleton(_Singleton("SingletonMeta", (object,), {})):
|
||||
pass
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -4,4 +4,4 @@ from django.apps import AppConfig
|
||||
|
||||
|
||||
class ParametersConfig(AppConfig):
|
||||
name = 'parameters'
|
||||
name = "parameters"
|
||||
|
||||
@@ -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
@@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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
@@ -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"),
|
||||
|
||||
@@ -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&t--u_'
|
||||
SECRET_KEY = "!8o(-dbbl3e+*bh7nx-^xysdt)1gso*%@4ze4-9_9o+i&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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user