From e6befb3de92f6c65c9e496200014376d8c70bca3 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Mon, 18 Dec 2017 14:04:19 +0000 Subject: [PATCH 01/11] standardise travis.yml across modoboa extensions --- .travis.yml | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 066b49c97..ee3f38ff9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,19 @@ -sudo: false language: python -cache: pip python: - "2.7" - "3.4" + - "3.5" - "3.6" + +env: + global: + - PYTHONWARNINGS="default,ignore::PendingDeprecationWarning,ignore::ResourceWarning" + matrix: + - DB="POSTGRESQL" + - DB="MYSQL" + +sudo: false + addons: apt: packages: @@ -12,30 +21,28 @@ addons: - postfix - slapd -env: - - DB="POSTGRESQL" - - DB="MYSQL" +cache: pip services: - - mysql - postgres + - mysql before_install: - pip install codecov - - if [[ $DB = 'POSTGRESQL' ]]; then pip install -q psycopg2; fi - - if [[ $DB = 'MYSQL' ]]; then pip install -q mysqlclient; fi + - if [[ $DB = "POSTGRESQL" ]]; then pip install -q psycopg2; fi + - if [[ $DB = "MYSQL" ]]; then pip install -q mysqlclient; fi install: - pip install -q -r requirements.txt - pip install -q -r ldap-requirements.txt - pip install -q -r test-requirements.txt - - pip install -e . + - python setup.py -q develop before_script: - - if [[ $DB = 'POSTGRESQL' ]]; then psql -c 'create database modoboa_test;' -U postgres; fi - - if [[ $DB = 'MYSQL' ]]; then mysql -e "create database IF NOT EXISTS modoboa_test;" -uroot; fi - - if [[ $DB = 'MYSQL' ]]; then mysql -e "CREATE USER 'modoboa'@'localhost' IDENTIFIED BY 'modoboa'" -uroot; fi - - if [[ $DB = 'MYSQL' ]]; then mysql -e "GRANT ALL PRIVILEGES ON * . * TO 'modoboa'@'localhost';" -uroot; fi + - if [[ $DB = "POSTGRESQL" ]]; then psql -c "CREATE DATABASE modoboa_test;" -U postgres; fi + - if [[ $DB = "MYSQL" ]]; then mysql -e "CREATE DATABASE IF NOT EXISTS modoboa_test;" -uroot; fi + - if [[ $DB = "MYSQL" ]]; then mysql -e "CREATE USER 'modoboa'@'localhost' IDENTIFIED BY 'modoboa'" -uroot; fi + - if [[ $DB = "MYSQL" ]]; then mysql -e "GRANT ALL PRIVILEGES ON * . * TO 'modoboa'@'localhost';" -uroot; fi - mkdir /tmp/slapd - slapd -f test_data/slapd.conf -h ldap://localhost:3389 & - sleep 3 From 3308c564807fbb069480238781caa89411e9031d Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Sun, 17 Dec 2017 22:41:49 +0000 Subject: [PATCH 02/11] StopIterator has been depreciated, use return [PEP479] https://www.python.org/dev/peps/pep-0479/#consequences-for-existing-code --- modoboa/admin/models/mxrecord.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modoboa/admin/models/mxrecord.py b/modoboa/admin/models/mxrecord.py index c769da392..b48645430 100644 --- a/modoboa/admin/models/mxrecord.py +++ b/modoboa/admin/models/mxrecord.py @@ -37,14 +37,14 @@ class MXRecordManager(models.Manager): if records.exists(): for record in records: yield record - raise StopIteration() + return self.get_queryset().filter(domain=domain).delete() delta = datetime.timedelta(seconds=ttl) domain_mxs = lib.get_domain_mx_list(domain.name) if len(domain_mxs) == 0: - raise StopIteration + return for mx_addr, mx_ip_addr in domain_mxs: record = self.get_queryset().create( domain=domain, From 892160d5aaa5c728c4dfef07db2293b739c38d3a Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Sun, 17 Dec 2017 20:42:03 +0000 Subject: [PATCH 03/11] updates for django 1.11 support - MIDDLEWARE_CLASSES is replaced by MIDDLEWARE - add MiddlewareMixin to modoboa middlewares - on_delete will become a required parameter for ForeignKey() set it to the current default CASCADE - on_delete will become a required parameter for OneToOneField() set it to the current default CASCADE - reverse and reverse_lazy have moved to django.urls - RadioChoiceInput widget has been removed, replace with HorizontalRadioSelect --- modoboa/admin/forms/account.py | 2 +- modoboa/admin/forms/domain.py | 2 +- modoboa/admin/handlers.py | 2 +- modoboa/admin/migrations/0001_initial.py | 24 +++++----- modoboa/admin/models/alias.py | 12 +++-- modoboa/admin/models/domain_alias.py | 3 +- modoboa/admin/models/mailbox.py | 9 ++-- modoboa/admin/models/mxrecord.py | 6 +-- modoboa/admin/templatetags/admin_tags.py | 2 +- modoboa/admin/tests/test_account.py | 2 +- modoboa/admin/tests/test_alias.py | 2 +- modoboa/admin/tests/test_api.py | 2 +- modoboa/admin/tests/test_domain.py | 2 +- modoboa/admin/tests/test_domain_alias.py | 2 +- modoboa/admin/tests/test_export.py | 2 +- modoboa/admin/tests/test_import_.py | 2 +- .../admin/tests/test_mailbox_operations.py | 2 +- modoboa/admin/tests/test_mx.py | 2 +- modoboa/admin/tests/test_password_schemes.py | 2 +- modoboa/admin/tests/test_user.py | 2 +- modoboa/admin/views/alias.py | 2 +- modoboa/admin/views/domain.py | 2 +- modoboa/admin/views/export.py | 2 +- modoboa/admin/views/import_.py | 2 +- modoboa/core/app_settings.py | 4 +- modoboa/core/handlers.py | 2 +- modoboa/core/middleware.py | 4 +- modoboa/core/migrations/0001_initial.py | 4 +- modoboa/core/models.py | 8 ++-- modoboa/core/templatetags/core_tags.py | 2 +- modoboa/core/tests/test_authentication.py | 2 +- modoboa/core/tests/test_core.py | 2 +- modoboa/core/tests/test_ldap.py | 2 +- modoboa/core/tests/test_views.py | 2 +- modoboa/core/views/auth.py | 2 +- modoboa/core/views/base.py | 2 +- modoboa/lib/form_utils.py | 46 ++----------------- modoboa/lib/middleware.py | 7 +-- modoboa/lib/migrations/0001_initial.py | 2 +- modoboa/limits/migrations/0001_initial.py | 4 +- .../migrations/0003_auto_20160413_1046.py | 4 +- .../migrations/0005_auto_20160415_1654.py | 2 +- modoboa/limits/models.py | 7 +-- modoboa/limits/tests/test_api.py | 2 +- modoboa/limits/tests/test_domain_limits.py | 2 +- modoboa/limits/tests/test_import.py | 2 +- modoboa/limits/tests/test_user_limits.py | 2 +- .../relaydomains/migrations/0001_initial.py | 6 +-- modoboa/relaydomains/tests.py | 2 +- .../templates/common/horizontal_select.html | 7 +++ .../common/horizontal_select_option.html | 2 + modoboa/transport/handlers.py | 2 +- modoboa/transport/tests.py | 2 +- modoboa/transport/views.py | 2 +- test_project/test_project/settings.py | 2 +- 55 files changed, 107 insertions(+), 126 deletions(-) create mode 100644 modoboa/templates/common/horizontal_select.html create mode 100644 modoboa/templates/common/horizontal_select_option.html diff --git a/modoboa/admin/forms/account.py b/modoboa/admin/forms/account.py index 19effd8ab..db0a312ce 100644 --- a/modoboa/admin/forms/account.py +++ b/modoboa/admin/forms/account.py @@ -6,7 +6,7 @@ from collections import OrderedDict from functools import reduce from django import forms -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import QueryDict from django.utils.translation import ugettext as _, ugettext_lazy diff --git a/modoboa/admin/forms/domain.py b/modoboa/admin/forms/domain.py index 23e2e9343..558b6e89f 100644 --- a/modoboa/admin/forms/domain.py +++ b/modoboa/admin/forms/domain.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from functools import reduce from django import forms -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import QueryDict from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.encoding import force_text diff --git a/modoboa/admin/handlers.py b/modoboa/admin/handlers.py index c51e01b27..da360c6d8 100644 --- a/modoboa/admin/handlers.py +++ b/modoboa/admin/handlers.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import signals from django.dispatch import receiver from django.utils.translation import ugettext as _ diff --git a/modoboa/admin/migrations/0001_initial.py b/modoboa/admin/migrations/0001_initial.py index ec5eb96bb..9be649089 100644 --- a/modoboa/admin/migrations/0001_initial.py +++ b/modoboa/admin/migrations/0001_initial.py @@ -31,8 +31,8 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('address', models.EmailField(max_length=75)), - ('alias', models.ForeignKey(to='admin.Alias')), - ('r_alias', models.ForeignKey(related_name='alias_recipient_aliases', blank=True, to='admin.Alias', null=True)), + ('alias', models.ForeignKey(to='admin.Alias', on_delete=models.CASCADE)), + ('r_alias', models.ForeignKey(related_name='alias_recipient_aliases', blank=True, to='admin.Alias', null=True, on_delete=models.CASCADE)), ], options={ 'db_table': 'modoboa_admin_aliasrecipient', @@ -85,7 +85,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('type', models.CharField(max_length=20, choices=[(b'rename', b'rename'), (b'delete', b'delete')])), ('argument', models.TextField()), - ('mailbox', models.ForeignKey(blank=True, to='admin.Mailbox', null=True)), + ('mailbox', models.ForeignKey(blank=True, to='admin.Mailbox', null=True, on_delete=models.CASCADE)), ], options={ }, @@ -116,43 +116,43 @@ class Migration(migrations.Migration): migrations.AddField( model_name='mailbox', name='dates', - field=models.ForeignKey(to='admin.ObjectDates'), + field=models.ForeignKey(to='admin.ObjectDates', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='mailbox', name='domain', - field=models.ForeignKey(to='admin.Domain'), + field=models.ForeignKey(to='admin.Domain', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='mailbox', name='user', - field=models.OneToOneField(to=settings.AUTH_USER_MODEL), + field=models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='domainalias', name='dates', - field=models.ForeignKey(to='admin.ObjectDates'), + field=models.ForeignKey(to='admin.ObjectDates', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='domainalias', name='target', - field=models.ForeignKey(verbose_name='target', to='admin.Domain', help_text='The domain this alias points to'), + field=models.ForeignKey(verbose_name='target', to='admin.Domain', help_text='The domain this alias points to', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='domain', name='dates', - field=models.ForeignKey(to='admin.ObjectDates'), + field=models.ForeignKey(to='admin.ObjectDates', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='aliasrecipient', name='r_mailbox', - field=models.ForeignKey(blank=True, to='admin.Mailbox', null=True), + field=models.ForeignKey(blank=True, to='admin.Mailbox', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterUniqueTogether( @@ -162,13 +162,13 @@ class Migration(migrations.Migration): migrations.AddField( model_name='alias', name='dates', - field=models.ForeignKey(to='admin.ObjectDates'), + field=models.ForeignKey(to='admin.ObjectDates', on_delete=models.CASCADE), preserve_default=True, ), migrations.AddField( model_name='alias', name='domain', - field=models.ForeignKey(to='admin.Domain', null=True), + field=models.ForeignKey(to='admin.Domain', null=True, on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterUniqueTogether( diff --git a/modoboa/admin/models/alias.py b/modoboa/admin/models/alias.py index 59b796725..225ed9e78 100644 --- a/modoboa/admin/models/alias.py +++ b/modoboa/admin/models/alias.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import hashlib import random -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.utils.encoding import ( python_2_unicode_compatible, smart_text, force_str, force_bytes @@ -37,7 +37,7 @@ class Alias(AdminObject): "The alias address." ) ) - domain = models.ForeignKey(Domain, null=True) + domain = models.ForeignKey(Domain, null=True, on_delete=models.CASCADE) enabled = models.BooleanField( ugettext_lazy("enabled"), help_text=ugettext_lazy("Check to activate this alias"), @@ -210,13 +210,15 @@ class AliasRecipient(models.Model): """An alias recipient.""" address = models.EmailField() - alias = models.ForeignKey(Alias) + alias = models.ForeignKey(Alias, on_delete=models.CASCADE) # if recipient is a local mailbox - r_mailbox = models.ForeignKey(Mailbox, blank=True, null=True) + r_mailbox = models.ForeignKey(Mailbox, blank=True, null=True, + on_delete=models.CASCADE) # if recipient is a local alias r_alias = models.ForeignKey( - Alias, related_name="alias_recipient_aliases", blank=True, null=True) + Alias, related_name="alias_recipient_aliases", blank=True, null=True, + on_delete=models.CASCADE) class Meta: app_label = "admin" diff --git a/modoboa/admin/models/domain_alias.py b/modoboa/admin/models/domain_alias.py index c9047886d..51ccfba69 100644 --- a/modoboa/admin/models/domain_alias.py +++ b/modoboa/admin/models/domain_alias.py @@ -40,7 +40,8 @@ class DomainAlias(AdminObject): help_text=ugettext_lazy("The alias name")) target = models.ForeignKey( Domain, verbose_name=ugettext_lazy('target'), - help_text=ugettext_lazy("The domain this alias points to") + help_text=ugettext_lazy("The domain this alias points to"), + on_delete=models.CASCADE ) enabled = models.BooleanField( ugettext_lazy('enabled'), diff --git a/modoboa/admin/models/mailbox.py b/modoboa/admin/models/mailbox.py index 1cf18320d..790cf9fbb 100644 --- a/modoboa/admin/models/mailbox.py +++ b/modoboa/admin/models/mailbox.py @@ -100,8 +100,8 @@ class Mailbox(AdminObject): ) quota = models.PositiveIntegerField(default=0) use_domain_quota = models.BooleanField(default=False) - domain = models.ForeignKey(Domain) - user = models.OneToOneField(User) + domain = models.ForeignKey(Domain, on_delete=models.CASCADE) + user = models.OneToOneField(User, on_delete=models.CASCADE) objects = MailboxManager() @@ -354,7 +354,7 @@ class SenderAddress(models.Model): """Extra sender address for Mailbox.""" address = models.EmailField() - mailbox = models.ForeignKey(Mailbox) + mailbox = models.ForeignKey(Mailbox, on_delete=models.CASCADE) class Meta: app_label = "admin" @@ -373,7 +373,8 @@ reversion.register(SenderAddress) class MailboxOperation(models.Model): """An operation on a mailbox.""" - mailbox = models.ForeignKey(Mailbox, blank=True, null=True) + mailbox = models.ForeignKey(Mailbox, blank=True, null=True, + on_delete=models.CASCADE) type = models.CharField( max_length=20, choices=(('rename', 'rename'), ('delete', 'delete')) ) diff --git a/modoboa/admin/models/mxrecord.py b/modoboa/admin/models/mxrecord.py index b48645430..4a4f71e5b 100644 --- a/modoboa/admin/models/mxrecord.py +++ b/modoboa/admin/models/mxrecord.py @@ -58,7 +58,7 @@ class MXRecordManager(models.Manager): class MXRecord(models.Model): """A model used to store MX records for Domain.""" - domain = models.ForeignKey("admin.Domain") + domain = models.ForeignKey("admin.Domain", on_delete=models.CASCADE) name = models.CharField(max_length=254) address = models.GenericIPAddressField() managed = models.BooleanField(default=False) @@ -86,9 +86,9 @@ class DNSBLQuerySet(models.QuerySet): class DNSBLResult(models.Model): """Store a DNSBL query result.""" - domain = models.ForeignKey("admin.Domain") + domain = models.ForeignKey("admin.Domain", on_delete=models.CASCADE) provider = models.CharField(max_length=254, db_index=True) - mx = models.ForeignKey(MXRecord) + mx = models.ForeignKey(MXRecord, on_delete=models.CASCADE) status = models.CharField(max_length=45, blank=True, db_index=True) objects = models.Manager.from_queryset(DNSBLQuerySet)() diff --git a/modoboa/admin/templatetags/admin_tags.py b/modoboa/admin/templatetags/admin_tags.py index 750ce39c3..202088157 100644 --- a/modoboa/admin/templatetags/admin_tags.py +++ b/modoboa/admin/templatetags/admin_tags.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from functools import reduce from django import template -from django.core.urlresolvers import reverse +from django.urls import reverse from django.template.loader import render_to_string from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _, ugettext_lazy diff --git a/modoboa/admin/tests/test_account.py b/modoboa/admin/tests/test_account.py index acf1baf9d..3f6f2144d 100644 --- a/modoboa/admin/tests/test_account.py +++ b/modoboa/admin/tests/test_account.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals from unittest import skipIf -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import override_settings from modoboa.core import factories as core_factories diff --git a/modoboa/admin/tests/test_alias.py b/modoboa/admin/tests/test_alias.py index 046b85275..3df90621d 100644 --- a/modoboa/admin/tests/test_alias.py +++ b/modoboa/admin/tests/test_alias.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals """Admin test cases.""" -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.core.models import User from modoboa.lib.tests import ModoTestCase diff --git a/modoboa/admin/tests/test_api.py b/modoboa/admin/tests/test_api.py index 3e897ce18..718adecc6 100644 --- a/modoboa/admin/tests/test_api.py +++ b/modoboa/admin/tests/test_api.py @@ -9,7 +9,7 @@ import json import dns.resolver from mock import patch -from django.core.urlresolvers import reverse +from django.urls import reverse from rest_framework.authtoken.models import Token diff --git a/modoboa/admin/tests/test_domain.py b/modoboa/admin/tests/test_domain.py index b3eeabfeb..553a861a8 100644 --- a/modoboa/admin/tests/test_domain.py +++ b/modoboa/admin/tests/test_domain.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals import dns.resolver from mock import patch -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.core import factories as core_factories from modoboa.core.models import User diff --git a/modoboa/admin/tests/test_domain_alias.py b/modoboa/admin/tests/test_domain_alias.py index 76f92fb16..5dd667702 100644 --- a/modoboa/admin/tests/test_domain_alias.py +++ b/modoboa/admin/tests/test_domain_alias.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.lib.tests import ModoTestCase diff --git a/modoboa/admin/tests/test_export.py b/modoboa/admin/tests/test_export.py index f7ba5177f..c48e3486d 100644 --- a/modoboa/admin/tests/test_export.py +++ b/modoboa/admin/tests/test_export.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils.encoding import force_text from modoboa.lib.tests import ModoTestCase diff --git a/modoboa/admin/tests/test_import_.py b/modoboa/admin/tests/test_import_.py index b40445f77..370c2087c 100644 --- a/modoboa/admin/tests/test_import_.py +++ b/modoboa/admin/tests/test_import_.py @@ -6,7 +6,7 @@ from mock import patch import dns.resolver from django.core.files.base import ContentFile -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.core import factories as core_factories from modoboa.core.models import User diff --git a/modoboa/admin/tests/test_mailbox_operations.py b/modoboa/admin/tests/test_mailbox_operations.py index 2f9a719ee..81c02de97 100644 --- a/modoboa/admin/tests/test_mailbox_operations.py +++ b/modoboa/admin/tests/test_mailbox_operations.py @@ -9,7 +9,7 @@ import tempfile import mock from django.core.management import call_command -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import override_settings from modoboa.lib.tests import ModoTestCase diff --git a/modoboa/admin/tests/test_mx.py b/modoboa/admin/tests/test_mx.py index 2e2a39b10..53d2a94c6 100644 --- a/modoboa/admin/tests/test_mx.py +++ b/modoboa/admin/tests/test_mx.py @@ -6,7 +6,7 @@ from mock import patch from django.core import mail from django.core import management -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import override_settings from modoboa.core import factories as core_factories diff --git a/modoboa/admin/tests/test_password_schemes.py b/modoboa/admin/tests/test_password_schemes.py index 160d1e0b2..277d202b9 100644 --- a/modoboa/admin/tests/test_password_schemes.py +++ b/modoboa/admin/tests/test_password_schemes.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.core.models import User from modoboa.lib.tests import ModoTestCase diff --git a/modoboa/admin/tests/test_user.py b/modoboa/admin/tests/test_user.py index 2eccfc900..1c55760ff 100644 --- a/modoboa/admin/tests/test_user.py +++ b/modoboa/admin/tests/test_user.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.core.models import User from modoboa.lib.tests import ModoTestCase diff --git a/modoboa/admin/views/alias.py b/modoboa/admin/views/alias.py index 20b1c4635..a7c97f58b 100644 --- a/modoboa/admin/views/alias.py +++ b/modoboa/admin/views/alias.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import IntegrityError from django.shortcuts import render from django.utils.translation import ugettext as _, ungettext diff --git a/modoboa/admin/views/domain.py b/modoboa/admin/views/domain.py index 2fd0f777e..4618b294a 100644 --- a/modoboa/admin/views/domain.py +++ b/modoboa/admin/views/domain.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals from functools import reduce -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import Sum from django.http import HttpResponseRedirect from django.shortcuts import render diff --git a/modoboa/admin/views/export.py b/modoboa/admin/views/export.py index 89e6dabb0..f916ea8c5 100644 --- a/modoboa/admin/views/export.py +++ b/modoboa/admin/views/export.py @@ -9,7 +9,7 @@ from rfc6266 import build_header from django.contrib.auth.decorators import ( login_required, permission_required, user_passes_test ) -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import HttpResponse from django.shortcuts import render from django.utils.translation import ugettext as _ diff --git a/modoboa/admin/views/import_.py b/modoboa/admin/views/import_.py index 44921471c..1291b41ee 100644 --- a/modoboa/admin/views/import_.py +++ b/modoboa/admin/views/import_.py @@ -9,7 +9,7 @@ from io import StringIO from django.contrib.auth.decorators import ( login_required, permission_required, user_passes_test ) -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import transaction from django.shortcuts import render from django.utils.translation import ugettext as _ diff --git a/modoboa/core/app_settings.py b/modoboa/core/app_settings.py index ee7e699f6..0f69de5ad 100644 --- a/modoboa/core/app_settings.py +++ b/modoboa/core/app_settings.py @@ -11,7 +11,7 @@ from django.contrib.auth import password_validation from modoboa.lib import fields as lib_fields from modoboa.lib.cryptutils import random_key from modoboa.lib.form_utils import ( - YesNoField, SeparatorField, InlineRadioSelect + YesNoField, SeparatorField, HorizontalRadioSelect ) from modoboa.parameters import forms as param_forms from modoboa.parameters import tools as param_tools @@ -44,7 +44,7 @@ class GeneralParametersForm(param_forms.AdminParametersForm): ('ldap', "LDAP")], initial="local", help_text=ugettext_lazy("The backend used for authentication"), - widget=InlineRadioSelect + widget=HorizontalRadioSelect() ) password_scheme = forms.ChoiceField( diff --git a/modoboa/core/handlers.py b/modoboa/core/handlers.py index c146dc89f..6f6c43649 100644 --- a/modoboa/core/handlers.py +++ b/modoboa/core/handlers.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import logging -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db.models import signals from django.dispatch import receiver from django.utils.encoding import smart_text diff --git a/modoboa/core/middleware.py b/modoboa/core/middleware.py index f8f66b403..df8f6939a 100644 --- a/modoboa/core/middleware.py +++ b/modoboa/core/middleware.py @@ -2,10 +2,12 @@ from __future__ import unicode_literals +from django.utils.deprecation import MiddlewareMixin + from . import models -class LocalConfigMiddleware(object): +class LocalConfigMiddleware(MiddlewareMixin): """A middleware to inject LocalConfig into request.""" def process_request(self, request): diff --git a/modoboa/core/migrations/0001_initial.py b/modoboa/core/migrations/0001_initial.py index 3824558f1..1be0eae38 100644 --- a/modoboa/core/migrations/0001_initial.py +++ b/modoboa/core/migrations/0001_initial.py @@ -67,8 +67,8 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('object_id', models.PositiveIntegerField()), ('is_owner', models.BooleanField(default=False)), - ('content_type', models.ForeignKey(to='contenttypes.ContentType')), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), ], options={ }, diff --git a/modoboa/core/models.py b/modoboa/core/models.py index 0d2b203f4..4750f645e 100644 --- a/modoboa/core/models.py +++ b/modoboa/core/models.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from email.header import Header import re -from django.core.urlresolvers import reverse +from django.urls import reverse from django.db import models from django.utils.encoding import ( python_2_unicode_compatible, smart_bytes, smart_text, force_str @@ -407,8 +407,8 @@ def populate_callback(user, group="SimpleUsers"): @python_2_unicode_compatible class ObjectAccess(models.Model): - user = models.ForeignKey(User) - content_type = models.ForeignKey(ContentType) + 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') is_owner = models.BooleanField(default=False) @@ -435,7 +435,7 @@ class LocalConfig(models.Model): """Store instance configuration here.""" api_pk = models.PositiveIntegerField(null=True) - site = models.ForeignKey("sites.Site") + site = models.ForeignKey("sites.Site", on_delete=models.CASCADE) # API results cache api_versions = jsonfield.JSONField() diff --git a/modoboa/core/templatetags/core_tags.py b/modoboa/core/templatetags/core_tags.py index 44d0735a4..20017f015 100644 --- a/modoboa/core/templatetags/core_tags.py +++ b/modoboa/core/templatetags/core_tags.py @@ -10,7 +10,7 @@ import re from django import template from django.conf import settings -from django.core.urlresolvers import reverse +from django.urls import reverse from django.template.loader import render_to_string from django.utils import timezone from django.utils.encoding import smart_text diff --git a/modoboa/core/tests/test_authentication.py b/modoboa/core/tests/test_authentication.py index 22df9d964..08c7fb4dc 100644 --- a/modoboa/core/tests/test_authentication.py +++ b/modoboa/core/tests/test_authentication.py @@ -10,7 +10,7 @@ from unittest import skipIf from mock import patch from django.core import mail -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import override_settings from modoboa.lib.tests import ModoTestCase diff --git a/modoboa/core/tests/test_core.py b/modoboa/core/tests/test_core.py index 6ca505c39..5efa811c5 100644 --- a/modoboa/core/tests/test_core.py +++ b/modoboa/core/tests/test_core.py @@ -8,7 +8,7 @@ from dateutil.relativedelta import relativedelta from six import StringIO from django.core import management -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import TestCase from django.utils import timezone diff --git a/modoboa/core/tests/test_ldap.py b/modoboa/core/tests/test_ldap.py index d7b166594..2de9be271 100644 --- a/modoboa/core/tests/test_ldap.py +++ b/modoboa/core/tests/test_ldap.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals from unittest import skipIf -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import override_settings from django.utils.functional import cached_property diff --git a/modoboa/core/tests/test_views.py b/modoboa/core/tests/test_views.py index 8e06bdfce..0c433c16b 100644 --- a/modoboa/core/tests/test_views.py +++ b/modoboa/core/tests/test_views.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from testfixtures import compare from django import forms -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.lib.tests import ModoTestCase from modoboa.parameters import forms as param_forms diff --git a/modoboa/core/views/auth.py b/modoboa/core/views/auth.py index 2ca28c56a..577263144 100644 --- a/modoboa/core/views/auth.py +++ b/modoboa/core/views/auth.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import logging -from django.core.urlresolvers import reverse +from django.urls import reverse from django.http import HttpResponse, HttpResponseRedirect from django.template.loader import render_to_string from django.utils import translation diff --git a/modoboa/core/views/base.py b/modoboa/core/views/base.py index 8d4634bf3..7b6291bac 100644 --- a/modoboa/core/views/base.py +++ b/modoboa/core/views/base.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from django.utils.http import is_safe_url from django.views import generic diff --git a/modoboa/lib/form_utils.py b/modoboa/lib/form_utils.py index 9aa259ff7..b9065bc30 100644 --- a/modoboa/lib/form_utils.py +++ b/modoboa/lib/form_utils.py @@ -11,12 +11,8 @@ import re from django.forms import TypedChoiceField from django.forms.fields import Field from django.forms.widgets import RadioSelect -from django.forms.widgets import RadioChoiceInput from django.shortcuts import render -from django.utils.encoding import ( - python_2_unicode_compatible, force_text, force_str) -from django.utils.html import conditional_escape -from django.utils.safestring import mark_safe +from django.utils.encoding import force_str from django.utils.translation import ugettext as _, ugettext_lazy from modoboa.lib.exceptions import BadRequest @@ -371,41 +367,9 @@ class TabForms(object): # -@python_2_unicode_compatible -class CustomRadioInput(RadioChoiceInput): - """Custom radio input.""" - - def __str__(self): - if "id" in self.attrs: - label_for = ' for="%s"' % self.attrs["id"] - else: - label_for = "" - choice_label = conditional_escape(force_text(self.choice_label)) - return mark_safe( - "" - % (label_for, self.tag(), choice_label) - ) - - -class InlineRadioRenderer(RadioSelect.renderer): - """Custom inline radio renderer.""" - - def __iter__(self): - for i, choice in enumerate(self.choices): - yield CustomRadioInput( - self.name, self.value, self.attrs.copy(), choice, i - ) - - def render(self): - return mark_safe( - u"\n".join([u"%s\n" % force_text(w) for w in self]) - ) - - -class InlineRadioSelect(RadioSelect): - """Custom inline radio widget.""" - - renderer = InlineRadioRenderer +class HorizontalRadioSelect(RadioSelect): + template_name = "common/horizontal_select.html" + option_template_name = "common/horizontal_select_option.html" class SeparatorField(Field): @@ -426,7 +390,7 @@ class YesNoField(TypedChoiceField): (True, ugettext_lazy("Yes")), (False, ugettext_lazy("No")) ), - "widget": InlineRadioSelect, + "widget": HorizontalRadioSelect(), "coerce": lambda x: x == "True" }) super(YesNoField, self).__init__(*args, **kwargs) diff --git a/modoboa/lib/middleware.py b/modoboa/lib/middleware.py index 6fd7c77f2..684726d65 100644 --- a/modoboa/lib/middleware.py +++ b/modoboa/lib/middleware.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals from django.http import HttpResponseRedirect from django.utils.encoding import smart_text +from django.utils.deprecation import MiddlewareMixin from modoboa.lib.exceptions import ModoboaException from modoboa.lib import signals as lib_signals @@ -14,7 +15,7 @@ from modoboa.lib.web_utils import ( ) -class AjaxLoginRedirect(object): +class AjaxLoginRedirect(MiddlewareMixin): def process_response(self, request, response): if request.is_ajax(): @@ -23,7 +24,7 @@ class AjaxLoginRedirect(object): return response -class CommonExceptionCatcher(object): +class CommonExceptionCatcher(MiddlewareMixin): """Modoboa exceptions catcher.""" def process_exception(self, request, exception): @@ -44,7 +45,7 @@ class CommonExceptionCatcher(object): ) -class RequestCatcherMiddleware(object): +class RequestCatcherMiddleware(MiddlewareMixin): """Simple middleware to store the current request.""" def process_request(self, request): diff --git a/modoboa/lib/migrations/0001_initial.py b/modoboa/lib/migrations/0001_initial.py index 02453b798..6f5cd6f93 100644 --- a/modoboa/lib/migrations/0001_initial.py +++ b/modoboa/lib/migrations/0001_initial.py @@ -29,7 +29,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('name', models.CharField(max_length=255)), ('value', models.CharField(max_length=255)), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), ], options={ }, diff --git a/modoboa/limits/migrations/0001_initial.py b/modoboa/limits/migrations/0001_initial.py index 468235c9b..2c1d96230 100644 --- a/modoboa/limits/migrations/0001_initial.py +++ b/modoboa/limits/migrations/0001_initial.py @@ -29,7 +29,7 @@ class Migration(migrations.Migration): name='LimitsPool', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)), + ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), ], options={ 'db_table': 'limits_limitspool', @@ -39,7 +39,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='limit', name='pool', - field=models.ForeignKey(to='limits.LimitsPool'), + field=models.ForeignKey(to='limits.LimitsPool', on_delete=models.CASCADE), preserve_default=True, ), migrations.AlterUniqueTogether( diff --git a/modoboa/limits/migrations/0003_auto_20160413_1046.py b/modoboa/limits/migrations/0003_auto_20160413_1046.py index 438479931..625a90568 100644 --- a/modoboa/limits/migrations/0003_auto_20160413_1046.py +++ b/modoboa/limits/migrations/0003_auto_20160413_1046.py @@ -58,8 +58,8 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('name', models.CharField(max_length=254)), ('max_value', models.IntegerField(default=-2)), - ('content_type', models.ForeignKey(to='contenttypes.ContentType')), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), ], ), migrations.AlterUniqueTogether( diff --git a/modoboa/limits/migrations/0005_auto_20160415_1654.py b/modoboa/limits/migrations/0005_auto_20160415_1654.py index ab97e7807..9b05b9f08 100644 --- a/modoboa/limits/migrations/0005_auto_20160415_1654.py +++ b/modoboa/limits/migrations/0005_auto_20160415_1654.py @@ -33,7 +33,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('name', models.CharField(max_length=254)), ('max_value', models.IntegerField(default=0)), - ('domain', models.ForeignKey(to='admin.Domain')), + ('domain', models.ForeignKey(to='admin.Domain', on_delete=models.CASCADE)), ], bases=(modoboa.limits.models.ObjectLimitMixin, models.Model), ), diff --git a/modoboa/limits/models.py b/modoboa/limits/models.py index 0797a7557..114a933c6 100644 --- a/modoboa/limits/models.py +++ b/modoboa/limits/models.py @@ -69,9 +69,10 @@ class ObjectLimitMixin(object): class UserObjectLimit(ObjectLimitMixin, models.Model): """Object level limit.""" - user = models.ForeignKey(settings.AUTH_USER_MODEL) + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) name = models.CharField(max_length=254) - content_type = models.ForeignKey("contenttypes.ContentType") + content_type = models.ForeignKey("contenttypes.ContentType", + on_delete=models.CASCADE) max_value = models.IntegerField(default=0) class Meta(object): @@ -132,7 +133,7 @@ class UserObjectLimit(ObjectLimitMixin, models.Model): class DomainObjectLimit(ObjectLimitMixin, models.Model): """Per-domain limits on object creation.""" - domain = models.ForeignKey("admin.Domain") + domain = models.ForeignKey("admin.Domain", on_delete=models.CASCADE) name = models.CharField(max_length=254) max_value = models.IntegerField(default=0) diff --git a/modoboa/limits/tests/test_api.py b/modoboa/limits/tests/test_api.py index ecfbe9d8f..4707c244b 100644 --- a/modoboa/limits/tests/test_api.py +++ b/modoboa/limits/tests/test_api.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals from testfixtures import compare -from django.core.urlresolvers import reverse +from django.urls import reverse from rest_framework.authtoken.models import Token diff --git a/modoboa/limits/tests/test_domain_limits.py b/modoboa/limits/tests/test_domain_limits.py index 3d9f44f99..92f6c8749 100644 --- a/modoboa/limits/tests/test_domain_limits.py +++ b/modoboa/limits/tests/test_domain_limits.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.admin import factories as admin_factories from modoboa.admin.models import Domain diff --git a/modoboa/limits/tests/test_import.py b/modoboa/limits/tests/test_import.py index dc743b438..1b61fd0c5 100644 --- a/modoboa/limits/tests/test_import.py +++ b/modoboa/limits/tests/test_import.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from django.core.files.base import ContentFile -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.admin import factories as admin_factories from modoboa.admin import models as admin_models diff --git a/modoboa/limits/tests/test_user_limits.py b/modoboa/limits/tests/test_user_limits.py index 2d87d0a72..39168a24b 100644 --- a/modoboa/limits/tests/test_user_limits.py +++ b/modoboa/limits/tests/test_user_limits.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.admin.factories import populate_database from modoboa.admin.models import Alias, Domain diff --git a/modoboa/relaydomains/migrations/0001_initial.py b/modoboa/relaydomains/migrations/0001_initial.py index 0f6bff791..84cf66c6a 100644 --- a/modoboa/relaydomains/migrations/0001_initial.py +++ b/modoboa/relaydomains/migrations/0001_initial.py @@ -17,8 +17,8 @@ class Migration(migrations.Migration): ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('target_host', models.CharField(help_text='Remote destination of this domain', max_length=255, verbose_name='target host')), ('verify_recipients', models.BooleanField(default=False, help_text='Check for valid recipients', verbose_name='verify recipients')), - ('dates', models.ForeignKey(to='admin.ObjectDates')), - ('domain', models.OneToOneField(null=True, to='admin.Domain')), + ('dates', models.ForeignKey(to='admin.ObjectDates', on_delete=models.CASCADE)), + ('domain', models.OneToOneField(null=True, to='admin.Domain', on_delete=models.CASCADE)), ], options={ 'ordering': ['domain__name'], @@ -40,7 +40,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='relaydomain', name='service', - field=models.ForeignKey(to='relaydomains.Service'), + field=models.ForeignKey(to='relaydomains.Service', on_delete=models.CASCADE), preserve_default=True, ), ] diff --git a/modoboa/relaydomains/tests.py b/modoboa/relaydomains/tests.py index e071fee22..86c1e4fef 100644 --- a/modoboa/relaydomains/tests.py +++ b/modoboa/relaydomains/tests.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from django.core.files.base import ContentFile -from django.core.urlresolvers import reverse +from django.urls import reverse from django.test import TestCase from modoboa.admin import factories as admin_factories diff --git a/modoboa/templates/common/horizontal_select.html b/modoboa/templates/common/horizontal_select.html new file mode 100644 index 000000000..d7145f734 --- /dev/null +++ b/modoboa/templates/common/horizontal_select.html @@ -0,0 +1,7 @@ +{% with id=widget.attrs.id %} + {% for group, options, index in widget.optgroups %} + {% for option in options %} + {% include option.template_name with widget=option %} + {% endfor %} + {% endfor %} +{% endwith %} \ No newline at end of file diff --git a/modoboa/templates/common/horizontal_select_option.html b/modoboa/templates/common/horizontal_select_option.html new file mode 100644 index 000000000..80f603bf9 --- /dev/null +++ b/modoboa/templates/common/horizontal_select_option.html @@ -0,0 +1,2 @@ + +{% if wrap_label %}{% endif %}{% include "django/forms/widgets/input.html" %}{% if wrap_label %} {{ widget.label }}{% endif %} \ No newline at end of file diff --git a/modoboa/transport/handlers.py b/modoboa/transport/handlers.py index 91a581022..aae87601a 100644 --- a/modoboa/transport/handlers.py +++ b/modoboa/transport/handlers.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals -from django.core.urlresolvers import reverse +from django.urls import reverse from django.dispatch import receiver from django.utils.translation import ugettext as _ diff --git a/modoboa/transport/tests.py b/modoboa/transport/tests.py index 052128fd6..5a35dd917 100644 --- a/modoboa/transport/tests.py +++ b/modoboa/transport/tests.py @@ -2,7 +2,7 @@ import json -from django.core.urlresolvers import reverse +from django.urls import reverse from modoboa.lib.tests import ModoAPITestCase, ModoTestCase diff --git a/modoboa/transport/views.py b/modoboa/transport/views.py index 944c97a9c..91298a082 100644 --- a/modoboa/transport/views.py +++ b/modoboa/transport/views.py @@ -1,7 +1,7 @@ """Transport views.""" from django import http -from django.core.urlresolvers import reverse, reverse_lazy +from django.urls import reverse, reverse_lazy from django.utils.translation import ugettext as _, ugettext_lazy from django.views import generic diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index c24c7f136..0cf7bdcde 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -69,7 +69,7 @@ INSTALLED_APPS += MODOBOA_APPS AUTH_USER_MODEL = 'core.User' -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'x_forwarded_for.middleware.XForwardedForMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', From e8eb9a84c1fc73a47ff596fd6b1e6eaab67a1980 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Sun, 17 Dec 2017 20:21:40 +0000 Subject: [PATCH 04/11] passlib 1.7 depreciated the use of .encrypt(), use .hash() --- modoboa/core/password_hashers/advanced.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/modoboa/core/password_hashers/advanced.py b/modoboa/core/password_hashers/advanced.py index ad27ae865..0f526221c 100644 --- a/modoboa/core/password_hashers/advanced.py +++ b/modoboa/core/password_hashers/advanced.py @@ -34,7 +34,8 @@ class BLFCRYPTHasher(PasswordHasher): # rounds = parameters.get_global_parameter("rounds_number") # To get around this, I use the default of 12. rounds = 12 - return bcrypt.encrypt(clearvalue, rounds=rounds) + bcrypt.using(rounds=rounds) + return bcrypt.hash(clearvalue) def verify(self, clearvalue, hashed_value): return bcrypt.verify(clearvalue, hashed_value) @@ -55,7 +56,7 @@ class MD5CRYPTHasher(PasswordHasher): return pwhash def _encrypt(self, clearvalue, salt=None): - return md5_crypt.encrypt(clearvalue) + return md5_crypt.hash(clearvalue) def verify(self, clearvalue, hashed_value): return md5_crypt.verify(clearvalue, hashed_value) @@ -78,7 +79,8 @@ class SHA256CRYPTHasher(PasswordHasher): def _encrypt(self, clearvalue, salt=None): rounds = param_tools.get_global_parameter("rounds_number") - return sha256_crypt.encrypt(clearvalue, rounds=rounds) + sha256_crypt.using(rounds=rounds) + return sha256_crypt.hash(clearvalue) def verify(self, clearvalue, hashed_value): return sha256_crypt.verify(clearvalue, hashed_value) @@ -101,7 +103,8 @@ class SHA512CRYPTHasher(PasswordHasher): def _encrypt(self, clearvalue, salt=None): rounds = param_tools.get_global_parameter("rounds_number") - return sha512_crypt.encrypt(clearvalue, rounds=rounds) + sha512_crypt.using(rounds=rounds) + return sha512_crypt.hash(clearvalue) def verify(self, clearvalue, hashed_value): return sha512_crypt.verify(clearvalue, hashed_value) From 0cd444be6b5dc6d42789fbaa4e9f89137d047f11 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Sun, 17 Dec 2017 20:27:19 +0000 Subject: [PATCH 05/11] django-reversion >= 2.0.0 should be used with django >= 1.8 https://django-reversion.readthedocs.io/en/stable/django-versions.html --- modoboa/core/handlers.py | 5 +++-- requirements.txt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modoboa/core/handlers.py b/modoboa/core/handlers.py index 6f6c43649..d3d78e2ce 100644 --- a/modoboa/core/handlers.py +++ b/modoboa/core/handlers.py @@ -13,6 +13,7 @@ from django.utils.translation import ugettext as _ from django.contrib.sites import models as sites_models from reversion import revisions as reversion +from reversion.models import Version from modoboa.lib import exceptions from modoboa.lib import permissions @@ -39,7 +40,7 @@ def post_revision_commit(sender, **kwargs): for version in kwargs["versions"]: if version.object is None: continue - prev_revisions = reversion.get_for_object(version.object) + prev_revisions = Version.objects.get_for_object(version.object) if prev_revisions.count() == 1: action = _("added") level = "info" @@ -64,7 +65,7 @@ def log_object_removal(sender, instance, **kwargs): if not reversion.is_registered(sender): return - del_list = reversion.get_deleted(sender) + del_list = Version.objects.get_deleted(sender) try: version = del_list.get(object_id=instance.id) except Version.DoesNotExist: diff --git a/requirements.txt b/requirements.txt index b66931b09..25251f92b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ django>=1.10,<=1.10.99 django-braces==1.11.0 django-ckeditor==5.2.1 -django-reversion==1.10.2 +django-reversion==2.0.12 django-subcommand2==0.1.1 django-versionfield2>=0.5.0 django-xforwardedfor-middleware From 2e18acb8ad251ddcf2f4b2a6afe975f5110df844 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Sun, 17 Dec 2017 21:40:43 +0000 Subject: [PATCH 06/11] upgrade django-auth-ldap and fix depreciated warning --- ldap-requirements.txt | 2 +- modoboa/lib/authbackends.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ldap-requirements.txt b/ldap-requirements.txt index 35eaac975..40145847b 100644 --- a/ldap-requirements.txt +++ b/ldap-requirements.txt @@ -1 +1 @@ -django-auth-ldap>=1.2.13 +django-auth-ldap>=1.3.0 diff --git a/modoboa/lib/authbackends.py b/modoboa/lib/authbackends.py index 995c24272..b46db0855 100644 --- a/modoboa/lib/authbackends.py +++ b/modoboa/lib/authbackends.py @@ -29,9 +29,9 @@ class SMTPBackend(object): smtp.login(username, password) except smtplib.SMTPException: return None - return self.get_or_create_user(username) + return self.get_or_build_user(username) - def get_or_create_user(self, username): + def get_or_build_user(self, username): """Get a user or create it the first time. .. note:: @@ -71,7 +71,7 @@ try: self.global_params = dict( param_tools.get_global_parameters("core")) - def get_or_create_user(self, username, ldap_user): + def get_or_build_user(self, username, ldap_user): """ This must return a (User, created) 2-tuple for the given LDAP user. username is the Django-friendly username of From ba861965b7d6d0bf48644993042c35ccb0102963 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Sun, 17 Dec 2017 22:02:01 +0000 Subject: [PATCH 07/11] upgrade dependencies with minor version updates --- requirements.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 25251f92b..2c325ca2d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ django>=1.10,<=1.10.99 django-braces==1.11.0 -django-ckeditor==5.2.1 +django-ckeditor==5.2.2 django-reversion==2.0.12 django-subcommand2==0.1.1 django-versionfield2>=0.5.0 @@ -8,16 +8,16 @@ django-xforwardedfor-middleware dj-database-url -coreapi==2.3.1 +coreapi==2.3.3 coreapi-cli==1.0.6 -djangorestframework==3.7.1 +djangorestframework==3.7.3 argparse # bcrypt requires libffi-dev bcrypt==3.1.4 dnspython==1.15.0 feedparser==5.2.1 -gevent==1.2.1 +gevent==1.2.2 ipaddress jsonfield==2.0.2 passlib==1.7.1 From 8fb3e244f63865741e1c30f53b39b757a92d15e4 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Sun, 17 Dec 2017 22:50:14 +0000 Subject: [PATCH 08/11] upgrade to django 1.11 pin to >=1.11.8 as thats the current version when the upgrade was done --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2c325ca2d..9e82af368 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django>=1.10,<=1.10.99 +django>=1.11.8,<=1.11.99 django-braces==1.11.0 django-ckeditor==5.2.2 django-reversion==2.0.12 From 4fe51d6726d60d060a51051c65eada8bae1c5060 Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Tue, 12 Dec 2017 00:04:22 +0000 Subject: [PATCH 09/11] random code clean ups - removed duplicate imports - whitespace fixes - removed unnecessary u"" prefixes - added missing r"" prefixes where required - added missing default values to DynamicForm() to prevent possible unassigned variable access --- modoboa/admin/forms/account.py | 2 -- modoboa/core/commands/deploy.py | 2 +- modoboa/core/handlers.py | 4 ---- modoboa/core/templatetags/core_tags.py | 2 +- modoboa/lib/form_utils.py | 3 +++ modoboa/lib/permissions.py | 2 -- modoboa/lib/validators.py | 11 +++++++---- modoboa/lib/web_utils.py | 4 ++-- modoboa/transport/urls.py | 6 +++--- 9 files changed, 17 insertions(+), 19 deletions(-) diff --git a/modoboa/admin/forms/account.py b/modoboa/admin/forms/account.py index db0a312ce..e160b6530 100644 --- a/modoboa/admin/forms/account.py +++ b/modoboa/admin/forms/account.py @@ -607,8 +607,6 @@ class AccountWizard(WizardForm): }) def done(self): - from modoboa.lib.web_utils import render_to_json_response - account = self.first_step.form.save() account.post_create(self.request.user) mailform = self.steps[1].form diff --git a/modoboa/core/commands/deploy.py b/modoboa/core/commands/deploy.py index e63ca890a..84c539a8e 100644 --- a/modoboa/core/commands/deploy.py +++ b/modoboa/core/commands/deploy.py @@ -28,7 +28,7 @@ from modoboa.core.commands import Command from modoboa.lib.api_client import ModoAPIClient if sys.version_info < (3, 0, 0): - input = raw_input + input = raw_input DBCONN_TPL = """ '{{ conn_name }}': { diff --git a/modoboa/core/handlers.py b/modoboa/core/handlers.py index d3d78e2ce..d5983626e 100644 --- a/modoboa/core/handlers.py +++ b/modoboa/core/handlers.py @@ -33,8 +33,6 @@ def post_revision_commit(sender, **kwargs): django-reversion for that. """ - from modoboa.lib.signals import get_request - current_user = get_request().user.username logger = logging.getLogger("modoboa.admin") for version in kwargs["versions"]: @@ -61,8 +59,6 @@ def log_object_removal(sender, instance, **kwargs): We want to know who was responsible for an object deletion. """ - from reversion.models import Version - if not reversion.is_registered(sender): return del_list = Version.objects.get_deleted(sender) diff --git a/modoboa/core/templatetags/core_tags.py b/modoboa/core/templatetags/core_tags.py index 20017f015..25ef503af 100644 --- a/modoboa/core/templatetags/core_tags.py +++ b/modoboa/core/templatetags/core_tags.py @@ -158,7 +158,7 @@ def colorize_level(level): @register.filter def tohtml(message): """Simple tag to format a text using HTML.""" - return re.sub(r"'(.*?)'", "\g<1>", message) + return re.sub(r"'(.*?)'", r"\g<1>", message) @register.simple_tag diff --git a/modoboa/lib/form_utils.py b/modoboa/lib/form_utils.py index b9065bc30..74abb7a37 100644 --- a/modoboa/lib/form_utils.py +++ b/modoboa/lib/form_utils.py @@ -194,6 +194,9 @@ class DynamicForm(object): """ + fields = {} + data = {} + def _create_field(self, typ, name, value=None, pos=None): """Create a new form field. """ diff --git a/modoboa/lib/permissions.py b/modoboa/lib/permissions.py index 72a14621e..73cc4439c 100644 --- a/modoboa/lib/permissions.py +++ b/modoboa/lib/permissions.py @@ -51,8 +51,6 @@ def grant_access_to_object(user, obj, is_owner=False): :param obj: an admin. object (Domain, Mailbox, ...) :param is_owner: the user is the unique object's owner """ - from modoboa.core.models import User - ct = ContentType.objects.get_for_model(obj) entry, created = ObjectAccess.objects.get_or_create( user=user, content_type=ct, object_id=obj.id) diff --git a/modoboa/lib/validators.py b/modoboa/lib/validators.py index c440eb805..bd5e29918 100644 --- a/modoboa/lib/validators.py +++ b/modoboa/lib/validators.py @@ -34,6 +34,7 @@ class HostnameValidator(object): if not self.regex.match(value): raise ValidationError(self.message, self.code) + validate_hostname = HostnameValidator() @@ -42,15 +43,16 @@ class UTF8EmailValidator(EmailValidator): """Validator for addresses using non-ASCII characters.""" # unicode letters range (must be a unicode string, not a raw string) - ul = u"\u00a1-\uffff" - ascii_set = u"-!#$%&'*+/=?^_`{}|~0-9A-Z" + ul = "\u00a1-\uffff" + ascii_set = "-!#$%&'*+/=?^_`{}|~0-9A-Z" user_regex_raw = ( # dot-atom - r"^[" + ascii_set + ul + "]+(\.[" + ascii_set + ul + "]+)*\Z" + r"^[" + ascii_set + ul + r"]+(\.[" + ascii_set + ul + r"]+)*\Z" # quoted-string r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)' ) - user_regex = re.compile("(" + user_regex_raw, re.IGNORECASE) + user_regex = re.compile(r"(" + user_regex_raw, re.IGNORECASE) + validate_utf8_email = UTF8EmailValidator() @@ -62,4 +64,5 @@ class UTF8AndEmptyUserEmailValidator(UTF8EmailValidator): user_regex = re.compile( r"(^$|" + UTF8EmailValidator.user_regex_raw, re.IGNORECASE) + validate_utf8_and_empty_user_email = UTF8AndEmptyUserEmailValidator() diff --git a/modoboa/lib/web_utils.py b/modoboa/lib/web_utils.py index 555a1ebf4..2596c94de 100644 --- a/modoboa/lib/web_utils.py +++ b/modoboa/lib/web_utils.py @@ -114,9 +114,9 @@ def size2integer(value): :param value: the string to convert :return: the corresponding integer value """ - m = re.match("(\d+)\s*(\w+)", value) + m = re.match(r"(\d+)\s*(\w+)", value) if m is None: - if re.match("\d+", value): + if re.match(r"\d+", value): return int(value) return 0 if m.group(2)[0] in ["K", "k"]: diff --git a/modoboa/transport/urls.py b/modoboa/transport/urls.py index 9a7319ac0..18b430451 100644 --- a/modoboa/transport/urls.py +++ b/modoboa/transport/urls.py @@ -8,10 +8,10 @@ from . import views urlpatterns = [ url(r"^$", views.TransportListView.as_view(), name="transport_list"), - url("^create/$", views.TransportCreateView.as_view(), + url(r"^create/$", views.TransportCreateView.as_view(), name="transport_create"), - url("^update/(?P\d+)/$", views.TransportUpdateView.as_view(), + url(r"^update/(?P\d+)/$", views.TransportUpdateView.as_view(), name="transport_update"), - url("^delete/(?P\d+)/$", views.TransportDeleteView.as_view(), + url(r"^delete/(?P\d+)/$", views.TransportDeleteView.as_view(), name="transport_delete"), ] From 33b37ec63e99169760c51e523f7e1969b18e9c4a Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Mon, 18 Dec 2017 15:31:28 +0000 Subject: [PATCH 10/11] updated new deployment settings.py - updated django urls to point to the current version - renamed MIDDLEWARE_CLASSES to MIDDLEWARE, MIDDLEWARE_CLASSES is depreciated in django >= 1.10 - whitespace and #noqa fixes --- .../core/commands/templates/settings.py.tpl | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl index c61596c2e..af59cce7a 100644 --- a/modoboa/core/commands/templates/settings.py.tpl +++ b/modoboa/core/commands/templates/settings.py.tpl @@ -1,26 +1,31 @@ """ Django settings for {{ name }} project. +Generated by 'django-admin startproject' using Django 1.11.8. + For more information on this file, see -https://docs.djangoproject.com/en/1.6/topics/settings/ +https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.6/ref/settings/ +https://docs.djangoproject.com/en/1.11/ref/settings/ """ -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -import os -from logging.handlers import SysLogHandler +from __future__ import unicode_literals +from logging.handlers import SysLogHandler +import os {% if devmode %} -from modoboa.core.dev_settings import * + +from modoboa.core.dev_settings import * # noqa {% endif %} + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '{{ secret_key }}' @@ -29,7 +34,7 @@ SECRET_KEY = '{{ secret_key }}' DEBUG = {{ devmode }} ALLOWED_HOSTS = [ - '{{ allowed_host }}' + '{{ allowed_host }}', ] SITE_ID = 1 @@ -76,7 +81,7 @@ INSTALLED_APPS += MODOBOA_APPS AUTH_USER_MODEL = 'core.User' -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'x_forwarded_for.middleware.XForwardedForMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -131,14 +136,14 @@ WSGI_APPLICATION = '{{ name }}.wsgi.application' # Database -# https://docs.djangoproject.com/en/1.6/ref/settings/#databases +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { {% for conn in db_connections.values %}{{ conn|safe }}{% endfor %} } # Internationalization -# https://docs.djangoproject.com/en/1.6/topics/i18n/ +# https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = '{{ lang }}' @@ -150,9 +155,8 @@ USE_L10N = True USE_TZ = True - # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.6/howto/static-files/ +# https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/sitestatic/' STATIC_ROOT = os.path.join(BASE_DIR, 'sitestatic') @@ -173,13 +177,14 @@ REST_FRAMEWORK = { } # Modoboa settings -#MODOBOA_CUSTOM_LOGO = os.path.join(MEDIA_URL, "custom_logo.png") +# MODOBOA_CUSTOM_LOGO = os.path.join(MEDIA_URL, "custom_logo.png") -#DOVECOT_LOOKUP_PATH = ('/path/to/dovecot', ) +# DOVECOT_LOOKUP_PATH = ('/path/to/dovecot', ) MODOBOA_API_URL = 'https://api.modoboa.org/1/' -# Password validation rules +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { @@ -276,5 +281,5 @@ try: from {{ extension }} import settings as {{ extension }}_settings {{ extension }}_settings.apply(globals()) except AttributeError: - from {{ extension }}.settings import * + from {{ extension }}.settings import * # noqa {% endfor %} From 92963a0f4cda46e6e21f4c82159aa0f8d7b9e8cd Mon Sep 17 00:00:00 2001 From: Andrew Fyfe Date: Mon, 18 Dec 2017 14:56:42 +0000 Subject: [PATCH 11/11] update test_project files synced with a fresh deployment using django 1.11.8 --- test_project/manage.py | 18 ++- test_project/test_project/__init__.py | 1 - test_project/test_project/settings.py | 207 ++++++++++++++++---------- test_project/test_project/urls.py | 2 +- test_project/test_project/wsgi.py | 6 +- 5 files changed, 149 insertions(+), 85 deletions(-) diff --git a/test_project/manage.py b/test_project/manage.py index 7fae8c557..ba4bba75c 100755 --- a/test_project/manage.py +++ b/test_project/manage.py @@ -7,7 +7,19 @@ import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings") - - from django.core.management import execute_from_command_line - + try: + from django.core.management import execute_from_command_line + except ImportError: + # The above import may fail for some other reason. Ensure that the + # issue is really that Django is missing to avoid masking other + # exceptions on Python 2. + try: + import django # noqa + except ImportError: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) + raise execute_from_command_line(sys.argv) diff --git a/test_project/test_project/__init__.py b/test_project/test_project/__init__.py index baffc4882..e69de29bb 100644 --- a/test_project/test_project/__init__.py +++ b/test_project/test_project/__init__.py @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py index 0cf7bdcde..3f9d0dcda 100644 --- a/test_project/test_project/settings.py +++ b/test_project/test_project/settings.py @@ -1,26 +1,29 @@ """ Django settings for test_project project. +Generated by 'django-admin startproject' using Django 1.11.8. + For more information on this file, see -https://docs.djangoproject.com/en/1.6/topics/settings/ +https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.6/ref/settings/ +https://docs.djangoproject.com/en/1.11/ref/settings/ """ from __future__ import unicode_literals -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -import os from logging.handlers import SysLogHandler +import os -from modoboa.test_settings import * # NOQA +from modoboa.test_settings import * # noqa -BASE_DIR = os.path.dirname(os.path.dirname(__file__)) + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.realpath(os.path.dirname(os.path.dirname(__file__))) # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ +# 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_' @@ -37,6 +40,10 @@ ALLOWED_HOSTS = [ SITE_ID = 1 +# Security settings + +X_FRAME_OPTIONS = "SAMEORIGIN" + # Application definition INSTALLED_APPS = ( @@ -47,8 +54,10 @@ INSTALLED_APPS = ( 'django.contrib.sites', 'django.contrib.staticfiles', 'reversion', + 'ckeditor', + 'ckeditor_uploader', 'rest_framework', - 'rest_framework.authtoken' + 'rest_framework.authtoken', ) # A dedicated place to register Modoboa applications @@ -59,10 +68,11 @@ MODOBOA_APPS = ( 'modoboa.core', 'modoboa.lib', 'modoboa.admin', - 'modoboa.limits', 'modoboa.transport', 'modoboa.relaydomains', + 'modoboa.limits', 'modoboa.parameters', + # Modoboa extensions here. ) INSTALLED_APPS += MODOBOA_APPS @@ -85,10 +95,88 @@ MIDDLEWARE = ( ) AUTHENTICATION_BACKENDS = ( + # 'modoboa.lib.authbackends.LDAPBackend', + # 'modoboa.lib.authbackends.SMTPBackend', 'django.contrib.auth.backends.ModelBackend', ) -# Password validation rules +# SMTP authentication +# AUTH_SMTP_SERVER_ADDRESS = 'localhost' +# AUTH_SMTP_SERVER_PORT = 25 +# AUTH_SMTP_SECURED_MODE = None # 'ssl' or 'starttls' are accepted + + +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', + ], + 'debug': TEMPLATE_DEBUG, + }, + }, +] + +ROOT_URLCONF = 'test_project.urls' + +WSGI_APPLICATION = 'test_project.wsgi.application' + + +# Internationalization +# https://docs.djangoproject.com/en/1.11/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +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') +STATICFILES_DIRS = ( + os.path.join(BASE_DIR, '..', 'modoboa', 'bower_components'), +) + +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', + ), +} + +# Modoboa settings +# MODOBOA_CUSTOM_LOGO = os.path.join(MEDIA_URL, "custom_logo.png") + +# DOVECOT_LOOKUP_PATH = ('/path/to/dovecot', ) + +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', @@ -113,77 +201,38 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] -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', - ], - 'debug': False, - }, +# CKeditor + +CKEDITOR_UPLOAD_PATH = "uploads/" + +CKEDITOR_IMAGE_BACKEND = "pillow" + +CKEDITOR_RESTRICT_BY_USER = True + +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'] + ], }, -] - -ROOT_URLCONF = 'test_project.urls' - -WSGI_APPLICATION = 'test_project.wsgi.application' - - -# Internationalization -# https://docs.djangoproject.com/en/1.6/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_L10N = False - -USE_TZ = True - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.6/howto/static-files/ - -STATIC_URL = '/sitestatic/' -STATIC_ROOT = os.path.join(BASE_DIR, 'sitestatic') -STATICFILES_DIRS = ( - os.path.join(BASE_DIR, '..', 'modoboa', 'bower_components'), -) - -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_PERMISSION_CLASSES': ( - 'rest_framework.permissions.IsAuthenticated', - ) } -# Modoboa settings -# MODOBOA_CUSTOM_LOGO = os.path.join(MEDIA_URL, "custom_logo.png") - -# DOVECOT_LOOKUP_PATH = ('/path/to/dovecot', ) - -MODOBOA_API_URL = 'http://api.modoboa.org/1/' - # Logging configuration LOGGING = { @@ -216,3 +265,5 @@ LOGGING = { } } } + +# Load settings from extensions diff --git a/test_project/test_project/urls.py b/test_project/test_project/urls.py index 1317f7c7b..136bd8a16 100644 --- a/test_project/test_project/urls.py +++ b/test_project/test_project/urls.py @@ -3,5 +3,5 @@ from __future__ import unicode_literals from django.conf.urls import include, url urlpatterns = [ - url(r'', include('modoboa.urls')), + url(r"", include("modoboa.urls")), ] diff --git a/test_project/test_project/wsgi.py b/test_project/test_project/wsgi.py index e63b59d9e..fce40e063 100644 --- a/test_project/test_project/wsgi.py +++ b/test_project/test_project/wsgi.py @@ -4,13 +4,15 @@ WSGI config for test_project project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ """ from __future__ import unicode_literals import os -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings") from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings") + application = get_wsgi_application()