mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
@@ -28,7 +28,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:11
|
||||
image: postgres:12
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
database: ['postgres', 'mysql']
|
||||
python-version: [3.7, 3.8, 3.9, '3.10']
|
||||
python-version: [3.8, 3.9, '3.10']
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
pip install -r mysql-requirements.txt
|
||||
echo "DB=mysql" >> $GITHUB_ENV
|
||||
- name: Test with pytest
|
||||
if: ${{ matrix.python-version != '3.8' || matrix.database != 'postgres' }}
|
||||
if: ${{ matrix.python-version != '3.10' || matrix.database != 'postgres' }}
|
||||
run: |
|
||||
python ./tests.py
|
||||
cd test_project
|
||||
|
||||
@@ -9,12 +9,12 @@ You will need a Server to perform well with at least:
|
||||
* CPU: 2
|
||||
* RAM: 2GB
|
||||
* Disk: 10GB
|
||||
* Python 3
|
||||
* Python 3.8+
|
||||
|
||||
.. note:: **👀 Heads up for modoboa versions 1.15 and later**
|
||||
|
||||
Python 2 support has been dropped with modoboa version 1.15.
|
||||
If you still have Python 2 installed on your system either uninstall it
|
||||
|
||||
Python 2 support has been dropped with modoboa version 1.15.
|
||||
If you still have Python 2 installed on your system either uninstall it
|
||||
or force modoboa user to run with Python 3.
|
||||
|
||||
Recommended way
|
||||
@@ -35,13 +35,13 @@ postfix, dovecot, amavis and more) on one machine.
|
||||
|
||||
To use it, just run the following commands in your terminal:
|
||||
|
||||
.. sourcecode:: bash
|
||||
.. sourcecode:: bash
|
||||
|
||||
> git clone https://github.com/modoboa/modoboa-installer
|
||||
> cd modoboa-installer
|
||||
> sudo ./run.py <your domain>
|
||||
|
||||
|
||||
|
||||
|
||||
if you get this warning - '/usr/bin/env: ‘python’: No such file or directory', do make sure sure python is installed on your server. Sometimes python is installed but the installer can't detect it or which python version to run, especially on a debian based system. Then run this command first.
|
||||
|
||||
.. sourcecode:: bash
|
||||
|
||||
@@ -108,6 +108,23 @@ Rebuild Virtual Environment
|
||||
Specific instructions
|
||||
*********************
|
||||
|
||||
2.2.0
|
||||
=====
|
||||
|
||||
.. note::
|
||||
This version has not been released yet.
|
||||
|
||||
* Django has been updated to 4.2LTS. Please upgrade all your extensions alongside modoboa.
|
||||
* Support for Python 3.7 has been dropped, minimum Python version is now 3.8.
|
||||
* Support for Postgres 11 has been dropped, minimum Postgres version is now 12.
|
||||
|
||||
If you use Postgresql, you need to install pyscopg3+:
|
||||
|
||||
.. sourcecode:: bash
|
||||
|
||||
pip install psycopg[binary]>=3.1
|
||||
|
||||
|
||||
2.1.0
|
||||
=====
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ from django.conf import settings
|
||||
from django.contrib.auth import password_validation
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
@@ -31,14 +31,14 @@ class DomainSerializer(serializers.ModelSerializer):
|
||||
|
||||
quota = serializers.CharField(
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Quota shared between mailboxes. Can be expressed in KB, "
|
||||
"MB (default) or GB. A value of 0 means no quota."
|
||||
)
|
||||
)
|
||||
default_mailbox_quota = serializers.CharField(
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Default quota in MB applied to mailboxes. A value of 0 means "
|
||||
"no quota."
|
||||
)
|
||||
@@ -140,7 +140,7 @@ class DomainAliasSerializer(serializers.ModelSerializer):
|
||||
object_type="domain_aliases")
|
||||
except lib_exceptions.ModoboaException as inst:
|
||||
raise serializers.ValidationError({
|
||||
"domain": force_text(inst)})
|
||||
"domain": force_str(inst)})
|
||||
domain_alias.save(creator=creator)
|
||||
return domain_alias
|
||||
|
||||
@@ -331,7 +331,7 @@ class WritableAccountSerializer(AccountSerializer):
|
||||
object_type="mailboxes")
|
||||
except lib_exceptions.ModoboaException as inst:
|
||||
raise serializers.ValidationError({
|
||||
"mailbox": force_text(inst)})
|
||||
"mailbox": force_str(inst)})
|
||||
condition = (
|
||||
not data.get("random_password") and (
|
||||
data.get("password") or
|
||||
@@ -447,7 +447,7 @@ class AliasSerializer(serializers.ModelSerializer):
|
||||
recipients = serializers.ListField(
|
||||
child=lib_fields.DRFEmailFieldUTF8AndEmptyUser(),
|
||||
allow_empty=False,
|
||||
help_text=ugettext_lazy("A list of recipient")
|
||||
help_text=gettext_lazy("A list of recipient")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from django import http
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from django_filters import rest_framework as dj_filters
|
||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core import validators as dj_validators
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from django.contrib.auth import password_validation
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from django.core.files.base import ContentFile
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
@@ -165,7 +165,7 @@ domainalias; domalias1.com; domain1.com; True
|
||||
]
|
||||
self.assertCountEqual(
|
||||
expected_response,
|
||||
force_text(response.content.strip()).split("\r\n")
|
||||
force_str(response.content.strip()).split("\r\n")
|
||||
)
|
||||
|
||||
|
||||
@@ -385,7 +385,7 @@ dlist; dlist@test.com; True; user1@test.com; user@extdomain.com
|
||||
def test_export(self):
|
||||
response = self.client.get(reverse("v2:identities-export"))
|
||||
expected_response = "account,admin,,,,True,SuperAdmins,,\r\naccount,admin@test.com,{PLAIN}toto,,,True,DomainAdmins,admin@test.com,10,test.com\r\naccount,admin@test2.com,{PLAIN}toto,,,True,DomainAdmins,admin@test2.com,10,test2.com\r\naccount,user@test.com,{PLAIN}toto,,,True,SimpleUsers,user@test.com,10\r\naccount,user@test2.com,{PLAIN}toto,,,True,SimpleUsers,user@test2.com,10\r\nalias,alias@test.com,True,user@test.com\r\nalias,forward@test.com,True,user@external.com\r\nalias,postmaster@test.com,True,test@truc.fr,toto@titi.com\r\n" # NOQA:E501
|
||||
received_content = force_text(response.content.strip()).split("\r\n")
|
||||
received_content = force_str(response.content.strip()).split("\r\n")
|
||||
# Empty admin password because it is hashed using SHA512-CRYPT
|
||||
admin_row = received_content[0].split(",")
|
||||
admin_row[2] = ""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Admin API v2 viewsets."""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import os
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
from django.forms.fields import GenericIPAddressField
|
||||
|
||||
from modoboa.lib.form_utils import SeparatorField, YesNoField
|
||||
@@ -20,20 +20,20 @@ from . import constants
|
||||
class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
app = "admin"
|
||||
|
||||
dom_sep = SeparatorField(label=ugettext_lazy("Domains"))
|
||||
dom_sep = SeparatorField(label=gettext_lazy("Domains"))
|
||||
|
||||
enable_mx_checks = YesNoField(
|
||||
label=ugettext_lazy("Enable MX checks"),
|
||||
label=gettext_lazy("Enable MX checks"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Check that every domain has a valid MX record"
|
||||
)
|
||||
)
|
||||
|
||||
valid_mxs = forms.CharField(
|
||||
label=ugettext_lazy("Valid MXs"),
|
||||
label=gettext_lazy("Valid MXs"),
|
||||
initial="",
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"A list of IP or network address every MX record should match."
|
||||
" A warning will be sent if a record does not respect it."
|
||||
),
|
||||
@@ -42,68 +42,68 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
)
|
||||
|
||||
domains_must_have_authorized_mx = YesNoField(
|
||||
label=ugettext_lazy("New domains must use authorized MX(s)"),
|
||||
label=gettext_lazy("New domains must use authorized MX(s)"),
|
||||
initial=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Prevent the creation of a new domain if its MX record does "
|
||||
"not use one of the defined addresses."
|
||||
)
|
||||
)
|
||||
|
||||
enable_spf_checks = YesNoField(
|
||||
label=ugettext_lazy("Enable SPF checks"),
|
||||
label=gettext_lazy("Enable SPF checks"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Check if every domain has a valid SPF record"
|
||||
)
|
||||
)
|
||||
|
||||
enable_dkim_checks = YesNoField(
|
||||
label=ugettext_lazy("Enable DKIM checks"),
|
||||
label=gettext_lazy("Enable DKIM checks"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Check if every domain with DKIM signin enabled has a valid DNS "
|
||||
"record"
|
||||
)
|
||||
)
|
||||
|
||||
enable_dmarc_checks = YesNoField(
|
||||
label=ugettext_lazy("Enable DMARC checks"),
|
||||
label=gettext_lazy("Enable DMARC checks"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Check if every domain has a valid DMARC record"
|
||||
)
|
||||
)
|
||||
|
||||
enable_autoconfig_checks = YesNoField(
|
||||
label=ugettext_lazy("Enable autoconfig checks"),
|
||||
label=gettext_lazy("Enable autoconfig checks"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Check if every domain has a valid records for autoconfiguration"
|
||||
)
|
||||
)
|
||||
|
||||
enable_dnsbl_checks = YesNoField(
|
||||
label=ugettext_lazy("Enable DNSBL checks"),
|
||||
label=gettext_lazy("Enable DNSBL checks"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Check every domain against major DNSBL providers"
|
||||
)
|
||||
)
|
||||
|
||||
custom_dns_server = GenericIPAddressField(
|
||||
label=ugettext_lazy("Custom DNS server"),
|
||||
label=gettext_lazy("Custom DNS server"),
|
||||
required=False,
|
||||
initial="",
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Use a custom DNS server instead of local server configuration"
|
||||
)
|
||||
)
|
||||
|
||||
dkim_keys_storage_dir = forms.CharField(
|
||||
label=ugettext_lazy("DKIM keys storage directory"),
|
||||
label=gettext_lazy("DKIM keys storage directory"),
|
||||
initial="",
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Absolute path of the directory where DKIM private keys will "
|
||||
"be stored. Make sure this directory belongs to root user "
|
||||
"and is not readable by the outside world."
|
||||
@@ -112,81 +112,81 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
)
|
||||
|
||||
dkim_default_key_length = forms.ChoiceField(
|
||||
label=ugettext_lazy("Default DKIM key length"),
|
||||
label=gettext_lazy("Default DKIM key length"),
|
||||
initial=2048,
|
||||
choices=constants.DKIM_KEY_LENGTHS,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Default length in bits for newly generated DKIM keys."
|
||||
)
|
||||
)
|
||||
|
||||
default_domain_quota = forms.IntegerField(
|
||||
label=ugettext_lazy("Default domain quota"),
|
||||
label=gettext_lazy("Default domain quota"),
|
||||
initial=0,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Default quota (in MB) applied to freshly created domains with no "
|
||||
"value specified. A value of 0 means no quota."
|
||||
)
|
||||
)
|
||||
|
||||
default_domain_message_limit = forms.IntegerField(
|
||||
label=ugettext_lazy("Default domain sending limit"),
|
||||
label=gettext_lazy("Default domain sending limit"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Number of messages freshly created domains will be "
|
||||
"allowed to send per day. Leave empty for no limit."
|
||||
)
|
||||
)
|
||||
|
||||
mbsep = SeparatorField(label=ugettext_lazy("Mailboxes"))
|
||||
mbsep = SeparatorField(label=gettext_lazy("Mailboxes"))
|
||||
|
||||
handle_mailboxes = YesNoField(
|
||||
label=ugettext_lazy("Handle mailboxes on filesystem"),
|
||||
label=gettext_lazy("Handle mailboxes on filesystem"),
|
||||
initial=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Rename or remove mailboxes on the filesystem when they get"
|
||||
" renamed or removed within Modoboa"
|
||||
)
|
||||
)
|
||||
|
||||
default_mailbox_quota = forms.IntegerField(
|
||||
label=ugettext_lazy("Default mailbox quota"),
|
||||
label=gettext_lazy("Default mailbox quota"),
|
||||
initial=0,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Default mailbox quota (in MB) applied to freshly created "
|
||||
"mailboxes with no value specified. A value of 0 means no quota."
|
||||
)
|
||||
)
|
||||
|
||||
default_mailbox_message_limit = forms.IntegerField(
|
||||
label=ugettext_lazy("Default mailbox sending limit"),
|
||||
label=gettext_lazy("Default mailbox sending limit"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Number of messages freshly created mailboxes will be "
|
||||
"allowed to send per day. Leave empty for no limit."
|
||||
)
|
||||
)
|
||||
|
||||
auto_account_removal = YesNoField(
|
||||
label=ugettext_lazy("Automatic account removal"),
|
||||
label=gettext_lazy("Automatic account removal"),
|
||||
initial=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"When a mailbox is removed, also remove the associated account")
|
||||
)
|
||||
|
||||
auto_create_domain_and_mailbox = YesNoField(
|
||||
label=ugettext_lazy("Automatic domain/mailbox creation"),
|
||||
label=gettext_lazy("Automatic domain/mailbox creation"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Create a domain and a mailbox when an account is automatically "
|
||||
"created."
|
||||
)
|
||||
)
|
||||
|
||||
create_alias_on_mbox_rename = YesNoField(
|
||||
label=ugettext_lazy("Create an alias when a mailbox is renamed"),
|
||||
label=gettext_lazy("Create an alias when a mailbox is renamed"),
|
||||
initial=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Create an alias using the old address when a mailbox is renamed."
|
||||
)
|
||||
)
|
||||
@@ -207,7 +207,7 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
dpath = None
|
||||
code, output = exec_cmd("which dovecot")
|
||||
if not code:
|
||||
dpath = force_text(output).strip()
|
||||
dpath = force_str(output).strip()
|
||||
else:
|
||||
known_paths = getattr(
|
||||
settings, "DOVECOT_LOOKUP_PATH",
|
||||
@@ -222,7 +222,7 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
except OSError:
|
||||
hide_fields = True
|
||||
else:
|
||||
version = force_text(version)
|
||||
version = force_str(version)
|
||||
if code or not version.strip().startswith("2"):
|
||||
hide_fields = True
|
||||
else:
|
||||
@@ -234,7 +234,7 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
"""Ensure quota is a positive integer."""
|
||||
if self.cleaned_data["default_domain_quota"] < 0:
|
||||
raise forms.ValidationError(
|
||||
ugettext_lazy("Must be a positive integer")
|
||||
gettext_lazy("Must be a positive integer")
|
||||
)
|
||||
return self.cleaned_data["default_domain_quota"]
|
||||
|
||||
@@ -242,7 +242,7 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
"""Ensure quota is a positive integer."""
|
||||
if self.cleaned_data["default_mailbox_quota"] < 0:
|
||||
raise forms.ValidationError(
|
||||
ugettext_lazy("Must be a positive integer")
|
||||
gettext_lazy("Must be a positive integer")
|
||||
)
|
||||
return self.cleaned_data["default_mailbox_quota"]
|
||||
|
||||
@@ -252,12 +252,12 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
if storage_dir:
|
||||
if not os.path.isdir(storage_dir):
|
||||
raise forms.ValidationError(
|
||||
ugettext_lazy("Directory not found.")
|
||||
gettext_lazy("Directory not found.")
|
||||
)
|
||||
code, output = exec_cmd("which openssl")
|
||||
if code:
|
||||
raise forms.ValidationError(
|
||||
ugettext_lazy(
|
||||
gettext_lazy(
|
||||
"openssl not found, please make sure it is installed.")
|
||||
)
|
||||
return storage_dir
|
||||
@@ -274,7 +274,7 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
]
|
||||
except ValueError:
|
||||
raise forms.ValidationError(
|
||||
ugettext_lazy(
|
||||
gettext_lazy(
|
||||
"This field only allows valid IP addresses (or networks)"
|
||||
)
|
||||
)
|
||||
@@ -297,94 +297,94 @@ class AdminParametersForm(param_forms.AdminParametersForm):
|
||||
|
||||
GLOBAL_PARAMETERS_STRUCT = collections.OrderedDict([
|
||||
("domains", {
|
||||
"label": ugettext_lazy("Domains"),
|
||||
"label": gettext_lazy("Domains"),
|
||||
"params": collections.OrderedDict([
|
||||
("enable_mx_checks", {
|
||||
"label": ugettext_lazy("Enable MX checks"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Enable MX checks"),
|
||||
"help_text": gettext_lazy(
|
||||
"Check that every domain has a valid MX record"
|
||||
)
|
||||
}),
|
||||
("valid_mxs", {
|
||||
"label": ugettext_lazy("Valid MXs"),
|
||||
"label": gettext_lazy("Valid MXs"),
|
||||
"display": "enable_mx_checks=true",
|
||||
"help_text": ugettext_lazy(
|
||||
"help_text": gettext_lazy(
|
||||
"A list of IP or network address every MX record should "
|
||||
"match. A warning will be sent if a record does not "
|
||||
"respect it."
|
||||
),
|
||||
}),
|
||||
("domains_must_have_authorized_mx", {
|
||||
"label": ugettext_lazy("New domains must use authorized MX(s)"),
|
||||
"label": gettext_lazy("New domains must use authorized MX(s)"),
|
||||
"display": "enable_mx_checks=true",
|
||||
"help_text": ugettext_lazy(
|
||||
"help_text": gettext_lazy(
|
||||
"Prevent the creation of a new domain if its MX record "
|
||||
"does not use one of the defined addresses."
|
||||
)
|
||||
}),
|
||||
("enable_spf_checks", {
|
||||
"label": ugettext_lazy("Enable SPF checks"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Enable SPF checks"),
|
||||
"help_text": gettext_lazy(
|
||||
"Check if every domain has a valid SPF record"
|
||||
)
|
||||
}),
|
||||
("enable_dkim_checks", {
|
||||
"label": ugettext_lazy("Enable DKIM checks"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Enable DKIM checks"),
|
||||
"help_text": gettext_lazy(
|
||||
"Check if every domain with DKIM signin enabled "
|
||||
"has a valid DNS record"
|
||||
)
|
||||
}),
|
||||
("enable_dmarc_checks", {
|
||||
"label": ugettext_lazy("Enable DMARC checks"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Enable DMARC checks"),
|
||||
"help_text": gettext_lazy(
|
||||
"Check if every domain has a valid DMARC record"
|
||||
)
|
||||
}),
|
||||
("enable_autoconfig_checks", {
|
||||
"label": ugettext_lazy("Enable autoconfig checks"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Enable autoconfig checks"),
|
||||
"help_text": gettext_lazy(
|
||||
"Check if every domain has a valid records for "
|
||||
"autoconfiguration"
|
||||
)
|
||||
}),
|
||||
("enable_dnsbl_checks", {
|
||||
"label": ugettext_lazy("Enable DNSBL checks"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Enable DNSBL checks"),
|
||||
"help_text": gettext_lazy(
|
||||
"Check every domain against major DNSBL providers"
|
||||
)
|
||||
}),
|
||||
("custom_dns_server", {
|
||||
"label": ugettext_lazy("Custom DNS server"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Custom DNS server"),
|
||||
"help_text": gettext_lazy(
|
||||
"Use a custom DNS server instead of local server "
|
||||
"configuration"
|
||||
)
|
||||
}),
|
||||
("dkim_keys_storage_dir", {
|
||||
"label": ugettext_lazy("DKIM keys storage directory"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("DKIM keys storage directory"),
|
||||
"help_text": gettext_lazy(
|
||||
"Absolute path of the directory where DKIM private keys "
|
||||
"will be stored. Make sure this directory belongs to root "
|
||||
"user and is not readable by the outside world."
|
||||
),
|
||||
}),
|
||||
("dkim_default_key_length", {
|
||||
"label": ugettext_lazy("Default DKIM key length"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Default DKIM key length"),
|
||||
"help_text": gettext_lazy(
|
||||
"Default length in bits for newly generated DKIM keys."
|
||||
)
|
||||
}),
|
||||
("default_domain_quota", {
|
||||
"label": ugettext_lazy("Default domain quota"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Default domain quota"),
|
||||
"help_text": gettext_lazy(
|
||||
"Default quota (in MB) applied to freshly created domains "
|
||||
"with no value specified. A value of 0 means no quota."
|
||||
)
|
||||
}),
|
||||
("default_domain_message_limit", {
|
||||
"label": ugettext_lazy("Default domain sending limit"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Default domain sending limit"),
|
||||
"help_text": gettext_lazy(
|
||||
"Number of messages freshly created domains will be "
|
||||
"allowed to send per day. Leave empty for no limit."
|
||||
)
|
||||
@@ -392,47 +392,47 @@ GLOBAL_PARAMETERS_STRUCT = collections.OrderedDict([
|
||||
])
|
||||
}),
|
||||
("mailboxes", {
|
||||
"label": ugettext_lazy("Mailboxes"),
|
||||
"label": gettext_lazy("Mailboxes"),
|
||||
"params": collections.OrderedDict([
|
||||
("handle_mailboxes", {
|
||||
"label": ugettext_lazy("Handle mailboxes on filesystem"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Handle mailboxes on filesystem"),
|
||||
"help_text": gettext_lazy(
|
||||
"Rename or remove mailboxes on the filesystem when they get"
|
||||
" renamed or removed within Modoboa"
|
||||
)
|
||||
}),
|
||||
("default_mailbox_quota", {
|
||||
"label": ugettext_lazy("Default mailbox quota"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Default mailbox quota"),
|
||||
"help_text": gettext_lazy(
|
||||
"Default mailbox quota (in MB) applied to freshly created "
|
||||
"domains with no value specified. A value of 0 means no "
|
||||
"quota."
|
||||
)
|
||||
}),
|
||||
("default_mailbox_message_limit", {
|
||||
"label": ugettext_lazy("Default mailbox sending limit"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Default mailbox sending limit"),
|
||||
"help_text": gettext_lazy(
|
||||
"Number of messages freshly created mailboxes will be "
|
||||
"allowed to send per day. Leave empty for no limit."
|
||||
)
|
||||
}),
|
||||
("auto_account_removal", {
|
||||
"label": ugettext_lazy("Automatic account removal"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Automatic account removal"),
|
||||
"help_text": gettext_lazy(
|
||||
"When a mailbox is removed, also remove the associated "
|
||||
"account")
|
||||
}),
|
||||
("auto_create_domain_and_mailbox", {
|
||||
"label": ugettext_lazy("Automatic domain/mailbox creation"),
|
||||
"help_text": ugettext_lazy(
|
||||
"label": gettext_lazy("Automatic domain/mailbox creation"),
|
||||
"help_text": gettext_lazy(
|
||||
"Create a domain and a mailbox when an account is "
|
||||
"automatically created."
|
||||
)
|
||||
}),
|
||||
("create_alias_on_mbox_rename", {
|
||||
"label": ugettext_lazy(
|
||||
"label": gettext_lazy(
|
||||
"Create an alias when a mailbox is renamed"),
|
||||
"help_text": ugettext_lazy(
|
||||
"help_text": gettext_lazy(
|
||||
"Create an alias using the old address when a mailbox is "
|
||||
"renamed."
|
||||
)
|
||||
@@ -448,8 +448,8 @@ def load_admin_settings():
|
||||
from .api.v2 import serializers
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", AdminParametersForm, ugettext_lazy("Administration"))
|
||||
"global", AdminParametersForm, gettext_lazy("Administration"))
|
||||
param_tools.registry.add2(
|
||||
"global", "admin", ugettext_lazy("Administration"),
|
||||
"global", "admin", gettext_lazy("Administration"),
|
||||
GLOBAL_PARAMETERS_STRUCT,
|
||||
serializers.AdminGlobalParametersSerializer)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Admin constants."""
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
DNSBL_PROVIDERS = [
|
||||
"b.barracudacentral.org",
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.conf import settings
|
||||
from django.contrib.auth import password_validation
|
||||
from django.http import QueryDict
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.core.models import User
|
||||
@@ -29,34 +29,34 @@ class AccountFormGeneral(forms.ModelForm):
|
||||
"""General account form."""
|
||||
|
||||
username = forms.CharField(
|
||||
label=ugettext_lazy("Username"),
|
||||
help_text=ugettext_lazy(
|
||||
label=gettext_lazy("Username"),
|
||||
help_text=gettext_lazy(
|
||||
"The user's name. Must be a valid e-mail address for simple users "
|
||||
"or administrators with a mailbox."
|
||||
)
|
||||
)
|
||||
role = forms.ChoiceField(
|
||||
label=ugettext_lazy("Role"),
|
||||
choices=[("", ugettext_lazy("Choose"))],
|
||||
help_text=ugettext_lazy("What level of permission this user will have")
|
||||
label=gettext_lazy("Role"),
|
||||
choices=[("", gettext_lazy("Choose"))],
|
||||
help_text=gettext_lazy("What level of permission this user will have")
|
||||
)
|
||||
random_password = forms.BooleanField(
|
||||
label=ugettext_lazy("Random password"),
|
||||
help_text=ugettext_lazy(
|
||||
label=gettext_lazy("Random password"),
|
||||
help_text=gettext_lazy(
|
||||
"Generate a random password. If you're updating this account and "
|
||||
"check this box, a new password will be generated."
|
||||
),
|
||||
required=False
|
||||
)
|
||||
password1 = forms.CharField(
|
||||
label=ugettext_lazy("Password"), widget=forms.widgets.PasswordInput,
|
||||
label=gettext_lazy("Password"), widget=forms.widgets.PasswordInput,
|
||||
required=False
|
||||
)
|
||||
|
||||
password2 = forms.CharField(
|
||||
label=ugettext_lazy("Confirmation"),
|
||||
label=gettext_lazy("Confirmation"),
|
||||
widget=forms.widgets.PasswordInput,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Enter the same password as above, for verification."
|
||||
),
|
||||
required=False
|
||||
@@ -69,7 +69,7 @@ class AccountFormGeneral(forms.ModelForm):
|
||||
"master_user",
|
||||
)
|
||||
labels = {
|
||||
"is_active": ugettext_lazy("Enabled")
|
||||
"is_active": gettext_lazy("Enabled")
|
||||
}
|
||||
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
@@ -223,14 +223,14 @@ class AccountFormMail(forms.Form, DynamicForm):
|
||||
"""Form to handle mail part."""
|
||||
|
||||
email = lib_fields.UTF8EmailField(
|
||||
label=ugettext_lazy("E-mail"), required=False)
|
||||
label=gettext_lazy("E-mail"), required=False)
|
||||
create_alias_with_old_address = forms.BooleanField(
|
||||
label=ugettext_lazy("Create an alias using the old address"),
|
||||
label=gettext_lazy("Create an alias using the old address"),
|
||||
required=False,
|
||||
initial=False
|
||||
)
|
||||
quota = forms.CharField(
|
||||
label=ugettext_lazy("Quota"),
|
||||
label=gettext_lazy("Quota"),
|
||||
required=False,
|
||||
help_text=_(
|
||||
"Quota for this mailbox, can be expressed in KB, MB (default) or "
|
||||
@@ -243,25 +243,25 @@ class AccountFormMail(forms.Form, DynamicForm):
|
||||
)
|
||||
quota_act = forms.BooleanField(required=False)
|
||||
message_limit = forms.IntegerField(
|
||||
label=ugettext_lazy("Message sending limit"),
|
||||
label=gettext_lazy("Message sending limit"),
|
||||
required=False,
|
||||
min_value=0,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Number of messages this mailbox can send per day")
|
||||
)
|
||||
aliases = lib_fields.UTF8AndEmptyUserEmailField(
|
||||
label=ugettext_lazy("Alias(es)"),
|
||||
label=gettext_lazy("Alias(es)"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Alias(es) of this mailbox. Indicate only one address per input, "
|
||||
"press ENTER to add a new input. To create a catchall alias, just "
|
||||
"enter the domain name (@domain.tld)."
|
||||
)
|
||||
)
|
||||
senderaddress = lib_fields.UTF8AndEmptyUserEmailField(
|
||||
label=ugettext_lazy("Sender addresses"),
|
||||
label=gettext_lazy("Sender addresses"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Additional sender address(es) for this account. The user will be "
|
||||
"allowed to send emails using this address, even if it "
|
||||
"does not exist locally. Indicate one address per input. Press "
|
||||
@@ -473,9 +473,9 @@ class AccountPermissionsForm(forms.Form, DynamicForm):
|
||||
"""A form to assign domain(s) permission."""
|
||||
|
||||
domains = lib_fields.DomainNameField(
|
||||
label=ugettext_lazy("Domain(s)"),
|
||||
label=gettext_lazy("Domain(s)"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy("Domain(s) that user administrates")
|
||||
help_text=gettext_lazy("Domain(s) that user administrates")
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -4,7 +4,7 @@ from collections import OrderedDict
|
||||
|
||||
from django import forms
|
||||
from django.http import QueryDict
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.lib import exceptions as lib_exceptions, fields as lib_fields
|
||||
@@ -17,19 +17,19 @@ class AliasForm(forms.ModelForm, DynamicForm):
|
||||
"""A form to create/modify an alias."""
|
||||
|
||||
random_address = forms.BooleanField(
|
||||
label=ugettext_lazy("Random address"),
|
||||
label=gettext_lazy("Random address"),
|
||||
required=False)
|
||||
address = lib_fields.UTF8AndEmptyUserEmailField(
|
||||
label=ugettext_lazy("Email address"),
|
||||
help_text=ugettext_lazy(
|
||||
label=gettext_lazy("Email address"),
|
||||
help_text=gettext_lazy(
|
||||
"The alias address. To create a catchall alias, just enter the "
|
||||
"domain name (@domain.tld)."
|
||||
),
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
recipients = lib_fields.UTF8AndEmptyUserEmailField(
|
||||
label=ugettext_lazy("Recipients"), required=False,
|
||||
help_text=ugettext_lazy(
|
||||
label=gettext_lazy("Recipients"), required=False,
|
||||
help_text=gettext_lazy(
|
||||
"Addresses this alias will point to. Indicate only one address "
|
||||
"per input, press ENTER to add a new input."
|
||||
),
|
||||
@@ -40,7 +40,7 @@ class AliasForm(forms.ModelForm, DynamicForm):
|
||||
model = Alias
|
||||
fields = ("address", "domain", "enabled", "expire_at", "description")
|
||||
labels = {
|
||||
"domain": ugettext_lazy("Domain")
|
||||
"domain": gettext_lazy("Domain")
|
||||
}
|
||||
widgets = {
|
||||
"domain": forms.widgets.Select(
|
||||
|
||||
@@ -5,8 +5,8 @@ from functools import reduce
|
||||
from django import forms
|
||||
from django.http import QueryDict
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.core.models import User
|
||||
@@ -25,30 +25,30 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
"""A form to create/edit a domain."""
|
||||
|
||||
type = forms.ChoiceField( # NOQA:A003
|
||||
label=ugettext_lazy("Type"),
|
||||
label=gettext_lazy("Type"),
|
||||
)
|
||||
aliases = DomainNameField(
|
||||
label=ugettext_lazy("Alias(es)"),
|
||||
label=gettext_lazy("Alias(es)"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Alias(es) of this domain. Indicate only one name per input, "
|
||||
"press ENTER to add a new input."
|
||||
)
|
||||
)
|
||||
dkim_key_selector = forms.CharField(
|
||||
label=ugettext_lazy("Key selector"), initial="modoboa", required=False)
|
||||
label=gettext_lazy("Key selector"), initial="modoboa", required=False)
|
||||
quota = forms.CharField(
|
||||
label=ugettext_lazy("Quota"),
|
||||
label=gettext_lazy("Quota"),
|
||||
initial=0,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Quota shared between mailboxes. Can be expressed in KB, "
|
||||
"MB (default) or GB. A value of 0 means no quota."
|
||||
)
|
||||
)
|
||||
default_mailbox_quota = forms.CharField(
|
||||
label=ugettext_lazy("Default mailbox quota"),
|
||||
label=gettext_lazy("Default mailbox quota"),
|
||||
initial=0,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Default quota applied to mailboxes. Can be expressed in KB, MB "
|
||||
"(default) or GB. A value of 0 means no quota."
|
||||
)
|
||||
@@ -97,7 +97,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
name, [(DomainAlias, _("domain alias"))])
|
||||
if label is not None:
|
||||
raise forms.ValidationError(
|
||||
_("A %s with this name already exists") % force_text(label))
|
||||
_("A %s with this name already exists") % force_str(label))
|
||||
|
||||
domains_must_have_authorized_mx = (
|
||||
param_tools.get_global_parameter("domains_must_have_authorized_mx")
|
||||
@@ -182,7 +182,7 @@ class DomainFormGeneral(forms.ModelForm, DynamicForm):
|
||||
if label is not None:
|
||||
self.add_error(
|
||||
k, _("A %s with this name already exists")
|
||||
% force_text(label)
|
||||
% force_str(label)
|
||||
)
|
||||
else:
|
||||
self.aliases.append(cleaned_data[k])
|
||||
@@ -227,17 +227,17 @@ class DomainFormOptions(forms.Form):
|
||||
"""A form containing options for domain creation."""
|
||||
|
||||
create_dom_admin = YesNoField(
|
||||
label=ugettext_lazy("Create a domain administrator"),
|
||||
label=gettext_lazy("Create a domain administrator"),
|
||||
initial=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Automatically create an administrator for this domain"
|
||||
)
|
||||
)
|
||||
|
||||
dom_admin_username = forms.CharField(
|
||||
label=ugettext_lazy("Name"),
|
||||
label=gettext_lazy("Name"),
|
||||
initial="admin",
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"The administrator's name. Don't include the domain's name here, "
|
||||
"it will be automatically appended."
|
||||
),
|
||||
@@ -245,27 +245,27 @@ class DomainFormOptions(forms.Form):
|
||||
)
|
||||
|
||||
random_password = YesNoField(
|
||||
label=ugettext_lazy("Random password"),
|
||||
label=gettext_lazy("Random password"),
|
||||
initial=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Generate a random password for the administrator."
|
||||
),
|
||||
required=False
|
||||
)
|
||||
|
||||
with_mailbox = YesNoField(
|
||||
label=ugettext_lazy("With a mailbox"),
|
||||
label=gettext_lazy("With a mailbox"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Create a mailbox for the administrator."
|
||||
),
|
||||
required=False
|
||||
)
|
||||
|
||||
create_aliases = YesNoField(
|
||||
label=ugettext_lazy("Create aliases"),
|
||||
label=gettext_lazy("Create aliases"),
|
||||
initial=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Automatically create standard aliases for this domain"
|
||||
),
|
||||
required=False
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"""Export related forms."""
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
|
||||
class ExportDataForm(forms.Form):
|
||||
sepchar = forms.CharField(
|
||||
label=ugettext_lazy("Separator"),
|
||||
label=gettext_lazy("Separator"),
|
||||
max_length=1,
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
|
||||
class ForwardForm(forms.Form):
|
||||
"""Forward definition form."""
|
||||
|
||||
dest = forms.CharField(
|
||||
label=ugettext_lazy("Recipient(s)"),
|
||||
label=gettext_lazy("Recipient(s)"),
|
||||
widget=forms.Textarea(attrs={"class": "form-control"}),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Indicate one or more recipients separated by a ','")
|
||||
)
|
||||
keepcopies = forms.BooleanField(
|
||||
label=ugettext_lazy("Keep local copies"),
|
||||
label=gettext_lazy("Keep local copies"),
|
||||
required=False,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Forward messages and store copies into your local mailbox")
|
||||
)
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
"""Forms related to import operations."""
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
|
||||
class ImportDataForm(forms.Form):
|
||||
|
||||
"""Base form to import objects."""
|
||||
|
||||
sourcefile = forms.FileField(label=ugettext_lazy("Select a file"))
|
||||
sourcefile = forms.FileField(label=gettext_lazy("Select a file"))
|
||||
sepchar = forms.CharField(
|
||||
label=ugettext_lazy("Separator"),
|
||||
label=gettext_lazy("Separator"),
|
||||
max_length=1,
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
continue_if_exists = forms.BooleanField(
|
||||
label=ugettext_lazy("Continue on error"), required=False,
|
||||
help_text=ugettext_lazy("Don't treat duplicated objects as error")
|
||||
label=gettext_lazy("Continue on error"), required=False,
|
||||
help_text=gettext_lazy("Don't treat duplicated objects as error")
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -35,8 +35,8 @@ class ImportIdentitiesForm(ImportDataForm):
|
||||
"""A form to import identities."""
|
||||
|
||||
crypt_password = forms.BooleanField(
|
||||
label=ugettext_lazy("Crypt passwords"), required=False,
|
||||
help_text=ugettext_lazy(
|
||||
label=gettext_lazy("Crypt passwords"), required=False,
|
||||
help_text=gettext_lazy(
|
||||
"Check this option if passwords contained in your file "
|
||||
"are not crypted"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import signals
|
||||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import models as core_models, signals as core_signals
|
||||
from modoboa.lib import exceptions, permissions, signals as lib_signals
|
||||
|
||||
@@ -15,8 +15,8 @@ from dns.name import IDNA_2008_UTS_46
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from django.contrib.auth import password_validation
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
@@ -232,14 +232,14 @@ def get_domain_mx_list(domain):
|
||||
continue
|
||||
for ip_answer in ip_answers:
|
||||
try:
|
||||
address_smart = smart_text(ip_answer.address)
|
||||
address_smart = smart_str(ip_answer.address)
|
||||
mx_ip = ipaddress.ip_address(address_smart)
|
||||
except ValueError as e:
|
||||
logger.warning(
|
||||
_("Invalid IP address format for "
|
||||
"{domain}; {addr}").format(
|
||||
domain=mx_domain,
|
||||
addr=smart_text(ip_answer.address)
|
||||
addr=smart_str(ip_answer.address)
|
||||
), exc_info=e)
|
||||
else:
|
||||
result.append((mx_domain, mx_ip))
|
||||
@@ -249,7 +249,7 @@ def get_domain_mx_list(domain):
|
||||
def domain_has_authorized_mx(name):
|
||||
"""Check if domain has authorized mx record at least."""
|
||||
valid_mxs = param_tools.get_global_parameter("valid_mxs")
|
||||
valid_mxs = [ipaddress.ip_network(smart_text(v.strip()))
|
||||
valid_mxs = [ipaddress.ip_network(smart_str(v.strip()))
|
||||
for v in valid_mxs.split() if v.strip()]
|
||||
domain_mxs = get_domain_mx_list(name)
|
||||
for _mx_addr, mx_ip_addr in domain_mxs:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import csv
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.core.models import User
|
||||
@@ -56,5 +56,5 @@ class ExportCommand(BaseCommand):
|
||||
def handle(self, *args, **options):
|
||||
exts_pool.load_all()
|
||||
self.csvwriter = csv.writer(
|
||||
self.stdout, delimiter=smart_text(options["sepchar"]))
|
||||
self.stdout, delimiter=smart_str(options["sepchar"]))
|
||||
getattr(self, "export_{}".format(options["objtype"]))()
|
||||
|
||||
@@ -9,7 +9,7 @@ from chardet.universaldetector import UniversalDetector
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.core.extensions import exts_pool
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
import os
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.lib import sysutils
|
||||
from modoboa.parameters import tools as param_tools
|
||||
@@ -41,15 +41,15 @@ class ManageDKIMKeys(BaseCommand):
|
||||
"openssl genrsa -out {} {}".format(pkey_path, key_size))
|
||||
if code:
|
||||
print("Failed to generate DKIM private key for domain {}: {}"
|
||||
.format(domain.name, smart_text(output)))
|
||||
.format(domain.name, smart_str(output)))
|
||||
domain.dkim_private_key_path = pkey_path
|
||||
code, output = sysutils.exec_cmd(
|
||||
"openssl rsa -in {} -pubout".format(pkey_path))
|
||||
if code:
|
||||
print("Failed to generate DKIM public key for domain {}: {}"
|
||||
.format(domain.name, smart_text(output)))
|
||||
.format(domain.name, smart_str(output)))
|
||||
public_key = ""
|
||||
for cpt, line in enumerate(smart_text(output).splitlines()):
|
||||
for cpt, line in enumerate(smart_str(output).splitlines()):
|
||||
if cpt == 0 or line.startswith("-----"):
|
||||
continue
|
||||
public_key += line
|
||||
|
||||
@@ -10,9 +10,9 @@ from django.core.mail import EmailMessage
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.admin import constants, models
|
||||
from modoboa.dnstools import models as dns_models
|
||||
@@ -40,7 +40,7 @@ class CheckMXRecords(BaseCommand):
|
||||
def valid_mxs(self):
|
||||
"""Return valid MXs set in admin."""
|
||||
valid_mxs = param_tools.get_global_parameter("valid_mxs")
|
||||
return [ipaddress.ip_network(smart_text(v.strip()))
|
||||
return [ipaddress.ip_network(smart_str(v.strip()))
|
||||
for v in valid_mxs.split() if v.strip()]
|
||||
|
||||
def add_arguments(self, parser):
|
||||
@@ -70,7 +70,7 @@ class CheckMXRecords(BaseCommand):
|
||||
results = {}
|
||||
for ip, mxs in mx_list.items():
|
||||
try:
|
||||
ip = ipaddress.ip_address(smart_text(ip))
|
||||
ip = ipaddress.ip_address(smart_str(ip))
|
||||
except ValueError:
|
||||
continue
|
||||
else:
|
||||
|
||||
@@ -7,9 +7,9 @@ from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import (
|
||||
force_bytes, force_str, smart_text
|
||||
force_bytes, force_str, smart_str
|
||||
)
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from reversion import revisions as reversion
|
||||
|
||||
@@ -68,22 +68,22 @@ class Alias(AdminObject):
|
||||
"""Mailbox alias."""
|
||||
|
||||
address = models.CharField(
|
||||
ugettext_lazy("address"), max_length=254,
|
||||
help_text=ugettext_lazy(
|
||||
gettext_lazy("address"), max_length=254,
|
||||
help_text=gettext_lazy(
|
||||
"The alias address."
|
||||
)
|
||||
)
|
||||
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"),
|
||||
gettext_lazy("enabled"),
|
||||
help_text=gettext_lazy("Check to activate this alias"),
|
||||
default=True
|
||||
)
|
||||
internal = models.BooleanField(default=False)
|
||||
description = models.TextField(
|
||||
ugettext_lazy("Description"), blank=True)
|
||||
gettext_lazy("Description"), blank=True)
|
||||
expire_at = models.DateTimeField(
|
||||
ugettext_lazy("Expire at"), blank=True, null=True)
|
||||
gettext_lazy("Expire at"), blank=True, null=True)
|
||||
_objectname = "MailboxAlias"
|
||||
|
||||
objects = AliasManager()
|
||||
@@ -258,6 +258,6 @@ class AliasRecipient(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
"""Return alias and recipient."""
|
||||
return smart_text(
|
||||
return smart_str(
|
||||
"{} -> {}".format(self.alias.address, self.address)
|
||||
)
|
||||
|
||||
@@ -6,9 +6,9 @@ from reversion import revisions as reversion
|
||||
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import force_text, smart_text
|
||||
from django.utils.encoding import force_str, smart_str
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.core.models import User
|
||||
@@ -23,46 +23,46 @@ from . import mixins
|
||||
class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
"""Mail domain."""
|
||||
|
||||
name = models.CharField(ugettext_lazy("name"), max_length=253, unique=True,
|
||||
help_text=ugettext_lazy("The domain name"))
|
||||
name = models.CharField(gettext_lazy("name"), max_length=253, unique=True,
|
||||
help_text=gettext_lazy("The domain name"))
|
||||
quota = models.PositiveIntegerField(
|
||||
default=0,
|
||||
)
|
||||
default_mailbox_quota = models.PositiveIntegerField(
|
||||
verbose_name=ugettext_lazy("Default mailbox quota"),
|
||||
verbose_name=gettext_lazy("Default mailbox quota"),
|
||||
default=0
|
||||
)
|
||||
message_limit = models.PositiveIntegerField(
|
||||
ugettext_lazy("Message sending limit"),
|
||||
gettext_lazy("Message sending limit"),
|
||||
null=True, blank=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Number of messages this domain can send per day"
|
||||
)
|
||||
)
|
||||
enabled = models.BooleanField(
|
||||
ugettext_lazy("enabled"),
|
||||
help_text=ugettext_lazy("Check to activate this domain"),
|
||||
gettext_lazy("enabled"),
|
||||
help_text=gettext_lazy("Check to activate this domain"),
|
||||
default=True
|
||||
)
|
||||
type = models.CharField(default="domain", max_length=20) # NOQA:A003
|
||||
enable_dns_checks = models.BooleanField(
|
||||
ugettext_lazy("Enable DNS checks"), default=True,
|
||||
help_text=ugettext_lazy("Check to enable DNS checks for this domain")
|
||||
gettext_lazy("Enable DNS checks"), default=True,
|
||||
help_text=gettext_lazy("Check to enable DNS checks for this domain")
|
||||
)
|
||||
|
||||
transport = models.OneToOneField(
|
||||
"transport.Transport", null=True, on_delete=models.SET_NULL)
|
||||
|
||||
enable_dkim = models.BooleanField(
|
||||
ugettext_lazy("Enable DKIM signing"),
|
||||
help_text=ugettext_lazy(
|
||||
gettext_lazy("Enable DKIM signing"),
|
||||
help_text=gettext_lazy(
|
||||
"If you activate this feature, a DKIM key will be "
|
||||
"generated for this domain."),
|
||||
default=False
|
||||
)
|
||||
dkim_key_selector = models.CharField(max_length=30, default="modoboa")
|
||||
dkim_key_length = models.PositiveIntegerField(
|
||||
ugettext_lazy("Key length"), choices=constants.DKIM_KEY_LENGTHS,
|
||||
gettext_lazy("Key length"), choices=constants.DKIM_KEY_LENGTHS,
|
||||
blank=True, null=True
|
||||
)
|
||||
dkim_public_key = models.TextField(blank=True)
|
||||
@@ -313,7 +313,8 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""Store current data if domain is renamed."""
|
||||
if self.oldname != self.name:
|
||||
# We check that the instance exists to use m2m relationship
|
||||
if self.pk and self.oldname != self.name:
|
||||
self.old_mail_homes = {
|
||||
mb.id: mb.mail_home for mb in self.mailbox_set.all()
|
||||
}
|
||||
@@ -339,7 +340,7 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
super().delete()
|
||||
|
||||
def __str__(self):
|
||||
return smart_text(self.name)
|
||||
return smart_str(self.name)
|
||||
|
||||
def from_csv(self, user, row):
|
||||
"""Create a new domain from a CSV entry.
|
||||
@@ -397,7 +398,7 @@ class Domain(mixins.MessageLimitMixin, AdminObject):
|
||||
result = [
|
||||
[
|
||||
"domain",
|
||||
force_text(self.name),
|
||||
force_str(self.name),
|
||||
self.quota,
|
||||
self.default_mailbox_quota,
|
||||
self.enabled
|
||||
|
||||
@@ -4,8 +4,8 @@ from reversion import revisions as reversion
|
||||
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
from django.db import models
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.core import models as core_models, signals as core_signals
|
||||
from modoboa.lib.exceptions import BadRequest, Conflict
|
||||
@@ -30,16 +30,16 @@ class DomainAlias(AdminObject):
|
||||
|
||||
"""Domain aliases."""
|
||||
|
||||
name = models.CharField(ugettext_lazy("name"), max_length=100, unique=True,
|
||||
help_text=ugettext_lazy("The alias name"))
|
||||
name = models.CharField(gettext_lazy("name"), max_length=100, unique=True,
|
||||
help_text=gettext_lazy("The alias name"))
|
||||
target = models.ForeignKey(
|
||||
Domain, verbose_name=ugettext_lazy("target"),
|
||||
help_text=ugettext_lazy("The domain this alias points to"),
|
||||
Domain, verbose_name=gettext_lazy("target"),
|
||||
help_text=gettext_lazy("The domain this alias points to"),
|
||||
on_delete=models.CASCADE
|
||||
)
|
||||
enabled = models.BooleanField(
|
||||
ugettext_lazy("enabled"),
|
||||
help_text=ugettext_lazy("Check to activate this alias"),
|
||||
gettext_lazy("enabled"),
|
||||
help_text=gettext_lazy("Check to activate this alias"),
|
||||
default=True
|
||||
)
|
||||
|
||||
@@ -51,7 +51,7 @@ class DomainAlias(AdminObject):
|
||||
app_label = "admin"
|
||||
|
||||
def __str__(self):
|
||||
return smart_text(self.name)
|
||||
return smart_str(self.name)
|
||||
|
||||
def from_csv(self, user, row):
|
||||
"""Create a domain alias from a CSV row
|
||||
|
||||
@@ -6,8 +6,8 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.db.models.manager import Manager
|
||||
from django.utils.encoding import smart_text, force_text
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.encoding import smart_str, force_str
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.core.models import User
|
||||
from modoboa.lib import exceptions as lib_exceptions
|
||||
@@ -89,15 +89,15 @@ class Mailbox(mixins.MessageLimitMixin, AdminObject):
|
||||
"""User mailbox."""
|
||||
|
||||
address = models.CharField(
|
||||
ugettext_lazy("address"), max_length=252,
|
||||
help_text=ugettext_lazy(
|
||||
gettext_lazy("address"), max_length=252,
|
||||
help_text=gettext_lazy(
|
||||
"Mailbox address (without the @domain.tld part)")
|
||||
)
|
||||
quota = models.PositiveIntegerField(default=0)
|
||||
use_domain_quota = models.BooleanField(default=False)
|
||||
message_limit = models.PositiveIntegerField(
|
||||
ugettext_lazy("Message sending limit"), null=True, blank=True,
|
||||
help_text=ugettext_lazy(
|
||||
gettext_lazy("Message sending limit"), null=True, blank=True,
|
||||
help_text=gettext_lazy(
|
||||
"Number of messages this mailbox can send per day")
|
||||
)
|
||||
domain = models.ForeignKey(Domain, on_delete=models.CASCADE)
|
||||
@@ -115,7 +115,7 @@ class Mailbox(mixins.MessageLimitMixin, AdminObject):
|
||||
self.old_message_limit = self.message_limit
|
||||
|
||||
def __str__(self):
|
||||
return smart_text(self.full_address)
|
||||
return smart_str(self.full_address)
|
||||
|
||||
def __full_address(self, localpart):
|
||||
return "%s@%s" % (localpart, self.domain.name)
|
||||
@@ -154,7 +154,7 @@ class Mailbox(mixins.MessageLimitMixin, AdminObject):
|
||||
if code:
|
||||
raise lib_exceptions.InternalError(
|
||||
_("Failed to retrieve mailbox location (%s)") % output)
|
||||
self.__mail_home = force_text(output.strip())
|
||||
self.__mail_home = force_str(output.strip())
|
||||
return self.__mail_home
|
||||
|
||||
@property
|
||||
@@ -363,7 +363,7 @@ class SenderAddress(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
"""Return address."""
|
||||
return smart_text(self.address)
|
||||
return smart_str(self.address)
|
||||
|
||||
|
||||
reversion.register(SenderAddress)
|
||||
|
||||
+15
-24
@@ -2,31 +2,22 @@
|
||||
|
||||
import django.dispatch
|
||||
|
||||
check_extra_account_form = django.dispatch.Signal(
|
||||
providing_args=["account", "form"])
|
||||
extra_account_dashboard_widgets = django.dispatch.Signal(
|
||||
providing_args=["user", "account"])
|
||||
extra_account_forms = django.dispatch.Signal(
|
||||
providing_args=["user", "account"])
|
||||
extra_admin_content = django.dispatch.Signal(
|
||||
providing_args=["user", "location", "currentpage"])
|
||||
extra_domain_actions = django.dispatch.Signal(
|
||||
providing_args=["user", "domain"])
|
||||
extra_domain_dashboard_widgets = django.dispatch.Signal(
|
||||
providing_args=["user", "domain"])
|
||||
check_extra_account_form = django.dispatch.Signal() # Provides account, form
|
||||
extra_account_dashboard_widgets = django.dispatch.Signal() # Provides user, account
|
||||
extra_account_forms = django.dispatch.Signal() # Provides user, account
|
||||
extra_admin_content = django.dispatch.Signal() # Provides user, location, currentpage
|
||||
extra_domain_actions = django.dispatch.Signal() # Provides user, domain
|
||||
extra_domain_dashboard_widgets = django.dispatch.Signal() # Provides user, domain
|
||||
extra_domain_filters = django.dispatch.Signal()
|
||||
extra_domain_forms = django.dispatch.Signal(providing_args=["user", "domain"])
|
||||
extra_domain_menu_entries = django.dispatch.Signal(providing_args=["user"])
|
||||
extra_domain_qset_filters = django.dispatch.Signal(
|
||||
providing_args=["domfilter", "extrafilters"])
|
||||
extra_domain_forms = django.dispatch.Signal() # Provides user, domain
|
||||
extra_domain_menu_entries = django.dispatch.Signal() # Provides user
|
||||
extra_domain_qset_filters = django.dispatch.Signal() # Provides domfilter, extrafilters
|
||||
# extra_domain_types = django.dispatch.Signal()
|
||||
extra_domain_wizard_steps = django.dispatch.Signal()
|
||||
get_account_form_instances = django.dispatch.Signal(
|
||||
providing_args=["user", "account"])
|
||||
get_domain_form_instances = django.dispatch.Signal(
|
||||
providing_args=["user", "domain"])
|
||||
get_account_form_instances = django.dispatch.Signal() # Provides user, account
|
||||
get_domain_form_instances = django.dispatch.Signal() # Provides user, domain
|
||||
# get_domain_tags = django.dispatch.Signal(providing_args=["domain"])
|
||||
import_object = django.dispatch.Signal(providing_args=["objtype"])
|
||||
use_external_recipients = django.dispatch.Signal(providing_args=["recipients"])
|
||||
new_dkim_keys = django.dispatch.Signal(providing_args=["domains"])
|
||||
extra_account_identities_actions = django.dispatch.Signal(providing_args=["account"])
|
||||
import_object = django.dispatch.Signal() # Provides objtype
|
||||
use_external_recipients = django.dispatch.Signal() # Provides recipients
|
||||
new_dkim_keys = django.dispatch.Signal() # Provides domain
|
||||
extra_account_identities_actions = django.dispatch.Signal() # Provides account
|
||||
|
||||
@@ -6,7 +6,7 @@ from django import template
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.lib.templatetags.lib_tags import render_link
|
||||
@@ -16,7 +16,7 @@ from .. import signals
|
||||
register = template.Library()
|
||||
|
||||
genders = {
|
||||
"Enabled": (ugettext_lazy("enabled_m"), ugettext_lazy("enabled_f"))
|
||||
"Enabled": (gettext_lazy("enabled_m"), gettext_lazy("enabled_f"))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ from io import StringIO
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
from .. import factories, models
|
||||
@@ -50,7 +50,7 @@ class ExportTestCase(ModoTestCase):
|
||||
]
|
||||
self.assertCountEqual(
|
||||
expected_response,
|
||||
force_text(response.content.strip()).split("\r\n")
|
||||
force_str(response.content.strip()).split("\r\n")
|
||||
)
|
||||
|
||||
# Test management command too.
|
||||
@@ -59,12 +59,12 @@ class ExportTestCase(ModoTestCase):
|
||||
response = sys.stdout.getvalue()
|
||||
sys.stdout = stdout_backup
|
||||
self.assertCountEqual(
|
||||
expected_response, force_text(response.strip()).split("\r\n"))
|
||||
expected_response, force_str(response.strip()).split("\r\n"))
|
||||
|
||||
def test_export_identities(self):
|
||||
response = self.__export_identities()
|
||||
expected_response = "account;admin;;;;True;SuperAdmins;;\r\naccount;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com\r\naccount;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\nalias;alias@test.com;True;user@test.com\r\nalias;forward@test.com;True;user@external.com\r\nalias;postmaster@test.com;True;test@truc.fr;toto@titi.com\r\n" # NOQA:E501
|
||||
received_content = force_text(response.content.strip()).split("\r\n")
|
||||
received_content = force_str(response.content.strip()).split("\r\n")
|
||||
# Empty admin password because it is hashed using SHA512-CRYPT
|
||||
admin_row = received_content[0].split(";")
|
||||
admin_row[2] = ""
|
||||
@@ -86,7 +86,7 @@ class ExportTestCase(ModoTestCase):
|
||||
expected_response = "account;user@test.com;{PLAIN}toto;;;True;SimpleUsers;user@test.com;10\r\naccount;user@test2.com;{PLAIN}toto;;;True;SimpleUsers;user@test2.com;10\r\naccount;toto@test.com;{PLAIN}toto;Léon;;True;SimpleUsers;toto@test.com;10" # NOQA:E501
|
||||
self.assertCountEqual(
|
||||
expected_response.split("\r\n"),
|
||||
force_text(response.content.strip()).split("\r\n")
|
||||
force_str(response.content.strip()).split("\r\n")
|
||||
)
|
||||
|
||||
def test_export_superadmins(self):
|
||||
@@ -111,7 +111,7 @@ class ExportTestCase(ModoTestCase):
|
||||
expected_response = "account;admin@test.com;{PLAIN}toto;;;True;DomainAdmins;admin@test.com;10;test.com\r\naccount;admin@test2.com;{PLAIN}toto;;;True;DomainAdmins;admin@test2.com;10;test2.com" # NOQA:E501
|
||||
self.assertCountEqual(
|
||||
expected_response.split("\r\n"),
|
||||
force_text(response.content.strip()).split("\r\n")
|
||||
force_str(response.content.strip()).split("\r\n")
|
||||
)
|
||||
|
||||
def test_export_aliases(self):
|
||||
|
||||
@@ -8,7 +8,7 @@ from testfixtures import LogCapture
|
||||
from django.core import mail, management
|
||||
from django.test import override_settings
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import factories as core_factories
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
@@ -221,7 +221,7 @@ class DNSBLTestCase(ModoTestCase):
|
||||
management.call_command(
|
||||
"modo", "check_mx", "--email", "user@example.test")
|
||||
self.assertEqual(len(mail.outbox), 2)
|
||||
|
||||
|
||||
@mock.patch("gevent.socket.gethostbyname")
|
||||
@mock.patch("socket.getaddrinfo")
|
||||
@mock.patch.object(dns.resolver.Resolver, "resolve")
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.db import IntegrityError
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _, ungettext
|
||||
from django.utils.translation import gettext as _, ngettext
|
||||
from django.views import generic
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
@@ -102,7 +102,7 @@ def delalias(request):
|
||||
if not request.user.can_access(alias):
|
||||
raise PermDeniedException
|
||||
alias.delete()
|
||||
msg = ungettext("Alias deleted", "Aliases deleted", len(selection))
|
||||
msg = ngettext("Alias deleted", "Aliases deleted", len(selection))
|
||||
return render_to_json_response(msg)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""DNSBL related views."""
|
||||
|
||||
from django.contrib.auth import mixins as auth_mixins
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views import generic
|
||||
|
||||
from .. import models
|
||||
|
||||
@@ -13,7 +13,7 @@ from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _, ungettext
|
||||
from django.utils.translation import gettext as _, ngettext
|
||||
from django.views import generic
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.decorators.http import require_http_methods
|
||||
@@ -247,7 +247,7 @@ def deldomain(request, dom_id):
|
||||
raise PermDeniedException(_("You can't delete your own domain"))
|
||||
dom.delete(request.user, keepdir)
|
||||
|
||||
msg = ungettext("Domain deleted", "Domains deleted", 1)
|
||||
msg = ngettext("Domain deleted", "Domains deleted", 1)
|
||||
return render_to_json_response(msg)
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from django.contrib.auth.decorators import (
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from ..forms import ExportDataForm
|
||||
from ..lib import get_domains, get_identities
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.contrib.auth.decorators import (
|
||||
)
|
||||
from django.shortcuts import render
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _, ungettext
|
||||
from django.utils.translation import gettext as _, ngettext
|
||||
from django.views import generic
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.decorators.http import require_http_methods
|
||||
@@ -191,7 +191,7 @@ def editaccount(request, pk):
|
||||
def delaccount(request, pk):
|
||||
User.objects.get(pk=pk).delete()
|
||||
return render_to_json_response(
|
||||
ungettext("Account deleted", "Accounts deleted", 1)
|
||||
ngettext("Account deleted", "Accounts deleted", 1)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ from django.contrib.auth.decorators import (
|
||||
from django.db import transaction
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.lib.exceptions import Conflict, ModoboaException
|
||||
from .. import lib
|
||||
|
||||
@@ -4,7 +4,7 @@ from reversion import revisions as reversion
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.lib.web_utils import render_to_json_response
|
||||
from ..forms import ForwardForm
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Core API serializers."""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Core API viewsets."""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
import django_otp
|
||||
from django_otp.plugins.otp_static.models import StaticDevice, StaticToken
|
||||
|
||||
@@ -13,10 +13,10 @@ from django.core.exceptions import ValidationError as djangoValidationError
|
||||
from django.template import loader
|
||||
|
||||
from django.utils import formats
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||
from django.utils.translation import gettext_lazy, gettext as _
|
||||
|
||||
from rest_framework import serializers, status
|
||||
from rest_framework.exceptions import APIException
|
||||
@@ -36,7 +36,7 @@ class CustomValidationError(APIException):
|
||||
if detail is not None:
|
||||
self.detail = detail
|
||||
else:
|
||||
self.detail = {'detail': force_text(self.default_detail)}
|
||||
self.detail = {'detail': force_str(self.default_detail)}
|
||||
|
||||
|
||||
class NoSMSAvailable(Exception):
|
||||
@@ -57,7 +57,7 @@ class CoreGlobalParametersSerializer(serializers.Serializer):
|
||||
|
||||
# General settings
|
||||
authentication_type = serializers.ChoiceField(
|
||||
choices=[("local", ugettext_lazy("Local")),
|
||||
choices=[("local", gettext_lazy("Local")),
|
||||
("ldap", "LDAP")],
|
||||
default="local"
|
||||
)
|
||||
@@ -65,11 +65,11 @@ class CoreGlobalParametersSerializer(serializers.Serializer):
|
||||
choices=[("sha512crypt", "sha512crypt"),
|
||||
("sha256crypt", "sha256crypt"),
|
||||
("blfcrypt", "bcrypt"),
|
||||
("md5crypt", ugettext_lazy("md5crypt (weak)")),
|
||||
("sha256", ugettext_lazy("sha256 (weak)")),
|
||||
("md5", ugettext_lazy("md5 (weak)")),
|
||||
("crypt", ugettext_lazy("crypt (weak)")),
|
||||
("plain", ugettext_lazy("plain (weak)"))],
|
||||
("md5crypt", gettext_lazy("md5crypt (weak)")),
|
||||
("sha256", gettext_lazy("sha256 (weak)")),
|
||||
("md5", gettext_lazy("md5 (weak)")),
|
||||
("crypt", gettext_lazy("crypt (weak)")),
|
||||
("plain", gettext_lazy("plain (weak)"))],
|
||||
default="sha512crypt"
|
||||
)
|
||||
rounds_number = serializers.IntegerField(default=70000)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import logging
|
||||
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.datastructures import MultiValueDictKeyError
|
||||
|
||||
from django.contrib.auth import login
|
||||
|
||||
+218
-218
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.db.models import signals
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
|
||||
def load_core_settings():
|
||||
@@ -16,9 +16,9 @@ def load_core_settings():
|
||||
from .api.v2 import serializers
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", app_settings.GeneralParametersForm, ugettext_lazy("General"))
|
||||
"global", app_settings.GeneralParametersForm, gettext_lazy("General"))
|
||||
param_tools.registry.add2(
|
||||
"global", "core", ugettext_lazy("General"),
|
||||
"global", "core", gettext_lazy("General"),
|
||||
app_settings.GLOBAL_PARAMETERS_STRUCT,
|
||||
serializers.CoreGlobalParametersSerializer)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from django.conf import settings
|
||||
from django.core.checks import Warning, register
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
W001 = Warning(
|
||||
_("You have USE_TZ set to False, this may result in issues during "
|
||||
|
||||
+10
-10
@@ -1,12 +1,12 @@
|
||||
"""Core application constants."""
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
SIMPLEUSERS_ROLE = ("SimpleUsers", ugettext_lazy("Simple user"))
|
||||
DOMAINADMINS_ROLE = ("DomainAdmins", ugettext_lazy("Domain administrator"))
|
||||
RESELLERS_ROLE = ("Resellers", ugettext_lazy("Reseller"))
|
||||
SUPERADMINS_ROLE = ("SuperAdmins", ugettext_lazy("Super administrator"))
|
||||
SIMPLEUSERS_ROLE = ("SimpleUsers", gettext_lazy("Simple user"))
|
||||
DOMAINADMINS_ROLE = ("DomainAdmins", gettext_lazy("Domain administrator"))
|
||||
RESELLERS_ROLE = ("Resellers", gettext_lazy("Reseller"))
|
||||
SUPERADMINS_ROLE = ("SuperAdmins", gettext_lazy("Super administrator"))
|
||||
|
||||
ROLES = (
|
||||
SIMPLEUSERS_ROLE,
|
||||
@@ -50,14 +50,14 @@ LDAP_GROUP_TYPES = (
|
||||
)
|
||||
|
||||
LDAP_SECURE_MODES = [
|
||||
("none", ugettext_lazy("No")),
|
||||
("none", gettext_lazy("No")),
|
||||
("starttls", "STARTTLS"),
|
||||
("ssl", "SSL/TLS")
|
||||
]
|
||||
|
||||
LDAP_AUTH_METHODS = [
|
||||
("searchbind", ugettext_lazy("Search and bind")),
|
||||
("directbind", ugettext_lazy("Direct bind"))
|
||||
("searchbind", gettext_lazy("Search and bind")),
|
||||
("directbind", gettext_lazy("Direct bind"))
|
||||
]
|
||||
|
||||
PERMISSIONS = {
|
||||
@@ -105,11 +105,11 @@ PERMISSIONS = {
|
||||
}
|
||||
|
||||
SMS_BACKENDS = [
|
||||
("", ugettext_lazy("Choose a provider")),
|
||||
("", gettext_lazy("Choose a provider")),
|
||||
("ovh", "OVH"),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
SMS_BACKENDS.insert(1, ("dummy", ugettext_lazy("Dummy")))
|
||||
SMS_BACKENDS.insert(1, ("dummy", gettext_lazy("Dummy")))
|
||||
|
||||
TFA_DEVICE_TOKEN_KEY = "otp_device_id"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Custom authentication for DRF."""
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django_otp.models import Device
|
||||
from drf_spectacular.contrib.rest_framework_simplejwt import SimpleJWTScheme
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"""Extension management."""
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include
|
||||
from django.urls import re_path
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
|
||||
@@ -111,7 +112,7 @@ class ExtensionsPool(object):
|
||||
pattern = "{}.urls"
|
||||
try:
|
||||
result.append(
|
||||
url(root, include(pattern.format(ext_name)))
|
||||
re_path(root, include(pattern.format(ext_name)))
|
||||
)
|
||||
except ImportError:
|
||||
# No urls for this extension
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.contrib.auth import (
|
||||
forms as auth_forms, get_user_model, password_validation
|
||||
)
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
import django_otp
|
||||
|
||||
@@ -20,11 +20,11 @@ class LoginForm(forms.Form):
|
||||
"""User login form."""
|
||||
|
||||
username = forms.CharField(
|
||||
label=ugettext_lazy("Username"),
|
||||
label=gettext_lazy("Username"),
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
password = forms.CharField(
|
||||
label=ugettext_lazy("Password"),
|
||||
label=gettext_lazy("Password"),
|
||||
widget=forms.PasswordInput(attrs={"class": "form-control"})
|
||||
)
|
||||
rememberme = forms.BooleanField(
|
||||
@@ -37,15 +37,15 @@ class ProfileForm(forms.ModelForm):
|
||||
"""Form to update User profile."""
|
||||
|
||||
oldpassword = forms.CharField(
|
||||
label=ugettext_lazy("Old password"), required=False,
|
||||
label=gettext_lazy("Old password"), required=False,
|
||||
widget=forms.PasswordInput(attrs={"class": "form-control"})
|
||||
)
|
||||
newpassword = forms.CharField(
|
||||
label=ugettext_lazy("New password"), required=False,
|
||||
label=gettext_lazy("New password"), required=False,
|
||||
widget=forms.PasswordInput(attrs={"class": "form-control"})
|
||||
)
|
||||
confirmation = forms.CharField(
|
||||
label=ugettext_lazy("Confirmation"), required=False,
|
||||
label=gettext_lazy("Confirmation"), required=False,
|
||||
widget=forms.PasswordInput(attrs={"class": "form-control"})
|
||||
)
|
||||
|
||||
@@ -115,7 +115,7 @@ class APIAccessForm(forms.Form):
|
||||
"""Form to control API access."""
|
||||
|
||||
enable_api_access = forms.BooleanField(
|
||||
label=ugettext_lazy("Enable API access"), required=False)
|
||||
label=gettext_lazy("Enable API access"), required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Initialize form."""
|
||||
@@ -149,7 +149,7 @@ class VerifySMSCodeForm(forms.Form):
|
||||
"""A form to verify a code received by SMS."""
|
||||
|
||||
code = forms.CharField(
|
||||
label=ugettext_lazy("Verification code"),
|
||||
label=gettext_lazy("Verification code"),
|
||||
widget=forms.widgets.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ from django.contrib.sites import models as sites_models
|
||||
from django.db.models import signals
|
||||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.lib import exceptions, permissions
|
||||
from modoboa.lib.signals import get_request
|
||||
@@ -39,7 +39,7 @@ def post_revision_commit(sender, **kwargs):
|
||||
action = _("modified")
|
||||
level = "warning"
|
||||
message = _("%(object)s '%(name)s' %(action)s by user %(user)s") % {
|
||||
"object": smart_text(version.content_type).capitalize(),
|
||||
"object": smart_str(version.content_type).capitalize(),
|
||||
"name": version.object_repr, "action": action,
|
||||
"user": current_user
|
||||
}
|
||||
@@ -61,7 +61,7 @@ def log_object_removal(sender, instance, **kwargs):
|
||||
return
|
||||
logger = logging.getLogger("modoboa.admin")
|
||||
msg = _("%(object)s '%(name)s' %(action)s by ") % {
|
||||
"object": smart_text(version.content_type).capitalize(),
|
||||
"object": smart_str(version.content_type).capitalize(),
|
||||
"name": version.object_repr, "action": _("deleted")
|
||||
}
|
||||
request = get_request()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from django.core.mail import EmailMessage
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.core.extensions import exts_pool
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 4.2 on 2023-04-25 12:00
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("core", "0024_alter_user_language"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameIndex(
|
||||
model_name="user",
|
||||
new_name="core_user_email_c0c03f_idx",
|
||||
old_fields=("email", "is_active"),
|
||||
),
|
||||
]
|
||||
+19
-21
@@ -6,9 +6,9 @@ from email.header import Header
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.encoding import force_str, smart_bytes, smart_text
|
||||
from django.utils.encoding import force_str, smart_bytes, smart_str
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from django.contrib.auth.models import AbstractUser, Group
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
@@ -49,26 +49,26 @@ class User(AbstractUser):
|
||||
is_active = models.BooleanField(default=True, db_index=True)
|
||||
is_local = models.BooleanField(default=True, db_index=True)
|
||||
master_user = models.BooleanField(
|
||||
ugettext_lazy("Allow mailboxes access"), default=False,
|
||||
help_text=ugettext_lazy(
|
||||
gettext_lazy("Allow mailboxes access"), default=False,
|
||||
help_text=gettext_lazy(
|
||||
"Allow this administrator to access user mailboxes"
|
||||
)
|
||||
)
|
||||
password = models.CharField(ugettext_lazy("password"), max_length=256)
|
||||
password = models.CharField(gettext_lazy("password"), max_length=256)
|
||||
|
||||
language = models.CharField(
|
||||
ugettext_lazy("language"),
|
||||
gettext_lazy("language"),
|
||||
max_length=10, default="en", choices=constants.LANGUAGES,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"Prefered language to display pages."
|
||||
)
|
||||
)
|
||||
phone_number = PhoneNumberField(
|
||||
ugettext_lazy("Phone number"), blank=True, null=True)
|
||||
gettext_lazy("Phone number"), blank=True, null=True)
|
||||
secondary_email = models.EmailField(
|
||||
ugettext_lazy("Secondary email"), max_length=254,
|
||||
gettext_lazy("Secondary email"), max_length=254,
|
||||
blank=True, null=True,
|
||||
help_text=ugettext_lazy(
|
||||
help_text=gettext_lazy(
|
||||
"An alternative e-mail address, can be used for recovery needs.")
|
||||
)
|
||||
|
||||
@@ -78,9 +78,7 @@ class User(AbstractUser):
|
||||
|
||||
class Meta(object):
|
||||
ordering = ["username"]
|
||||
index_together = [
|
||||
["email", "is_active"]
|
||||
]
|
||||
indexes = [models.Index(fields=["email", "is_active"])]
|
||||
|
||||
password_expr = re.compile(r'\{([\w\-]+)\}(.+)')
|
||||
|
||||
@@ -144,7 +142,7 @@ class User(AbstractUser):
|
||||
return hasher().verify(raw_value, val2)
|
||||
|
||||
def __str__(self):
|
||||
return smart_text(self.get_username())
|
||||
return smart_str(self.get_username())
|
||||
|
||||
def get_absolute_url(self):
|
||||
"""Return detail url for this user."""
|
||||
@@ -369,13 +367,13 @@ class User(AbstractUser):
|
||||
"""Return row that can be included in a CSV file."""
|
||||
row = [
|
||||
"account",
|
||||
smart_text(self.username),
|
||||
smart_text(self.password),
|
||||
smart_text(self.first_name),
|
||||
smart_text(self.last_name),
|
||||
smart_text(self.is_active),
|
||||
smart_text(self.role),
|
||||
smart_text(self.email)
|
||||
smart_str(self.username),
|
||||
smart_str(self.password),
|
||||
smart_str(self.first_name),
|
||||
smart_str(self.last_name),
|
||||
smart_str(self.is_active),
|
||||
smart_str(self.role),
|
||||
smart_str(self.email)
|
||||
]
|
||||
results = signals.account_exported.send(
|
||||
sender=self.__class__, user=self)
|
||||
|
||||
@@ -3,7 +3,7 @@ Password hashers for Modoboa.
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
from modoboa.core.password_hashers.advanced import ( # NOQA:F401
|
||||
BLFCRYPTHasher, MD5CRYPTHasher, SHA256CRYPTHasher, SHA512CRYPTHasher,
|
||||
@@ -53,5 +53,5 @@ def get_dovecot_schemes():
|
||||
if retcode:
|
||||
schemes = default_schemes
|
||||
|
||||
return ["{{{}}}".format(smart_text(scheme))
|
||||
return ["{{{}}}".format(smart_str(scheme))
|
||||
for scheme in schemes.split()]
|
||||
|
||||
@@ -40,7 +40,7 @@ class BLFCRYPTHasher(PasswordHasher):
|
||||
# rounds = parameters.get_global_parameter("rounds_number")
|
||||
# To get around this, I use the default of 12.
|
||||
rounds = 12
|
||||
return bcrypt.hash(clearvalue, rounds=rounds)
|
||||
return bcrypt.using(rounds=rounds).hash(clearvalue)
|
||||
|
||||
def verify(self, clearvalue, hashed_value):
|
||||
return bcrypt.verify(clearvalue, hashed_value)
|
||||
@@ -85,7 +85,7 @@ class SHA256CRYPTHasher(PasswordHasher):
|
||||
|
||||
def _encrypt(self, clearvalue, salt=None):
|
||||
rounds = param_tools.get_global_parameter("rounds_number")
|
||||
return sha256_crypt.hash(clearvalue, rounds=rounds)
|
||||
return sha256_crypt.using(rounds=rounds).hash(clearvalue)
|
||||
|
||||
def verify(self, clearvalue, hashed_value):
|
||||
return sha256_crypt.verify(clearvalue, hashed_value)
|
||||
@@ -107,7 +107,7 @@ class SHA512CRYPTHasher(PasswordHasher):
|
||||
|
||||
def _encrypt(self, clearvalue, salt=None):
|
||||
rounds = param_tools.get_global_parameter("rounds_number")
|
||||
return sha512_crypt.hash(clearvalue, rounds=rounds)
|
||||
return sha512_crypt.using(rounds=rounds).hash(clearvalue)
|
||||
|
||||
def verify(self, clearvalue, hashed_value):
|
||||
return sha512_crypt.verify(clearvalue, hashed_value)
|
||||
|
||||
@@ -11,7 +11,7 @@ import string
|
||||
from random import Random
|
||||
|
||||
from django.utils.crypto import constant_time_compare
|
||||
from django.utils.encoding import force_bytes, force_text
|
||||
from django.utils.encoding import force_bytes, force_str
|
||||
|
||||
|
||||
class MetaHasher(type):
|
||||
@@ -65,8 +65,8 @@ class PasswordHasher(metaclass=MetaHasher):
|
||||
:rtype: str
|
||||
:return: encrypted password
|
||||
"""
|
||||
pwhash = self._b64encode(self._encrypt(force_text(clearvalue)))
|
||||
return "%s%s" % (self.scheme, force_text(pwhash))
|
||||
pwhash = self._b64encode(self._encrypt(force_str(clearvalue)))
|
||||
return "%s%s" % (self.scheme, force_str(pwhash))
|
||||
|
||||
def verify(self, clearvalue, hashed_value):
|
||||
"""Verify a password against a hashed value.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Custom password validators."""
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext as _, ungettext
|
||||
from django.utils.translation import gettext as _, ngettext
|
||||
|
||||
|
||||
class ComplexityValidator(object):
|
||||
@@ -20,7 +20,7 @@ class ComplexityValidator(object):
|
||||
sum(1 for char in password if char.isdigit()) < self.digits)
|
||||
if condition:
|
||||
raise ValidationError(
|
||||
ungettext(
|
||||
ngettext(
|
||||
"Password must contain at least {} digit.",
|
||||
"Password must contain at least {} digits.",
|
||||
self.digits
|
||||
@@ -30,7 +30,7 @@ class ComplexityValidator(object):
|
||||
sum(1 for char in password if char.islower()) < self.lower)
|
||||
if condition:
|
||||
raise ValidationError(
|
||||
ungettext(
|
||||
ngettext(
|
||||
"Password must contain at least {} lowercase letter.",
|
||||
"Password must contain at least {} lowercase letters.",
|
||||
self.lower
|
||||
@@ -41,7 +41,7 @@ class ComplexityValidator(object):
|
||||
sum(1 for char in password if char.isupper()) < self.upper)
|
||||
if condition:
|
||||
raise ValidationError(
|
||||
ungettext(
|
||||
ngettext(
|
||||
"Password must contain at least {} uppercase letter.",
|
||||
"Password must contain at least {} uppercase letters.",
|
||||
self.upper
|
||||
@@ -53,7 +53,7 @@ class ComplexityValidator(object):
|
||||
self.specials)
|
||||
if condition:
|
||||
raise ValidationError(
|
||||
ungettext(
|
||||
ngettext(
|
||||
"Password must contain at least {} special character.",
|
||||
"Password must contain at least {} special characters.",
|
||||
self.specials
|
||||
|
||||
+19
-30
@@ -2,36 +2,25 @@
|
||||
|
||||
import django.dispatch
|
||||
|
||||
account_auto_created = django.dispatch.Signal(providing_args=["user"])
|
||||
account_exported = django.dispatch.Signal(providing_args=["account"])
|
||||
account_imported = django.dispatch.Signal(
|
||||
providing_args=["user", "account", "row"])
|
||||
account_deleted = django.dispatch.Signal(providing_args=["user"])
|
||||
account_role_changed = django.dispatch.Signal(
|
||||
providing_args=["account", "role"])
|
||||
account_password_updated = django.dispatch.Signal(
|
||||
providing_args=["account", "password", "created"])
|
||||
allow_password_change = django.dispatch.Signal(providing_args=["user"])
|
||||
can_create_object = django.dispatch.Signal(
|
||||
providing_args=["context", "klass", "object_type", "count", "instance"])
|
||||
extra_account_actions = django.dispatch.Signal(providing_args=["account"])
|
||||
extra_admin_dashboard_widgets = django.dispatch.Signal(
|
||||
providing_args=["user"])
|
||||
extra_admin_menu_entries = django.dispatch.Signal(
|
||||
providing_args=["location", "user"])
|
||||
extra_role_permissions = django.dispatch.Signal(providing_args=["role"])
|
||||
extra_static_content = django.dispatch.Signal(
|
||||
providing_args=["caller", "st_type", "user"])
|
||||
account_auto_created = django.dispatch.Signal() # Provides user
|
||||
account_exported = django.dispatch.Signal() # Provides account
|
||||
account_imported = django.dispatch.Signal() # Provides user, account, row
|
||||
account_deleted = django.dispatch.Signal() # Provides user
|
||||
account_role_changed = django.dispatch.Signal() # Provides account, role
|
||||
account_password_updated = django.dispatch.Signal() # Provides account password created
|
||||
allow_password_change = django.dispatch.Signal() # Provides user
|
||||
can_create_object = django.dispatch.Signal() # Provides context, klass, object_type, count, instance
|
||||
extra_account_actions = django.dispatch.Signal() # Provides account
|
||||
extra_admin_dashboard_widgets = django.dispatch.Signal() # Provides user
|
||||
extra_admin_menu_entries = django.dispatch.Signal() # Provides location, user
|
||||
extra_role_permissions = django.dispatch.Signal() # Provides role
|
||||
extra_static_content = django.dispatch.Signal() # Provides caller, st_type, user
|
||||
extra_uprefs_routes = django.dispatch.Signal()
|
||||
extra_user_menu_entries = django.dispatch.Signal(
|
||||
providing_args=["location", "user"])
|
||||
get_announcements = django.dispatch.Signal(providing_args=["location"])
|
||||
get_top_notifications = django.dispatch.Signal(
|
||||
providing_args=["include_all"])
|
||||
initial_data_loaded = django.dispatch.Signal(providing_args=["extname"])
|
||||
extra_user_menu_entries = django.dispatch.Signal() # Provides location, user
|
||||
get_announcements = django.dispatch.Signal() # Provides location
|
||||
get_top_notifications = django.dispatch.Signal() # Provides include_all
|
||||
initial_data_loaded = django.dispatch.Signal() # Provides extname
|
||||
register_postfix_maps = django.dispatch.Signal()
|
||||
user_can_set_role = django.dispatch.Signal(
|
||||
providing_args=["user", "role", "account"])
|
||||
user_login = django.dispatch.Signal(
|
||||
providing_args=["username", "password"])
|
||||
user_can_set_role = django.dispatch.Signal() # Provides user, role, account
|
||||
user_login = django.dispatch.Signal() # Provides username, password
|
||||
user_logout = django.dispatch.Signal()
|
||||
|
||||
@@ -4,7 +4,7 @@ import ovh
|
||||
|
||||
from django import forms
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ from django.contrib.sessions.models import Session
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import get_language, ugettext as _
|
||||
from django.utils.translation import get_language, gettext as _
|
||||
|
||||
from .. import models
|
||||
from .. import signals
|
||||
@@ -241,7 +241,7 @@ def display_messages(msgs):
|
||||
level = "info"
|
||||
for m in msgs:
|
||||
level = m.tags
|
||||
text += smart_text(m) + "\\\n"
|
||||
text += smart_str(m) + "\\\n"
|
||||
|
||||
if level == "info":
|
||||
level = "success"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"""Custom urls."""
|
||||
|
||||
from django.conf.urls import url
|
||||
from django.urls import re_path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url("^$", views.test_view, name="index")
|
||||
re_path("^$", views.test_view, name="index")
|
||||
]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from pkg_resources import parse_version
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core.extensions import exts_pool
|
||||
from modoboa.lib.api_client import ModoAPIClient
|
||||
|
||||
@@ -5,7 +5,7 @@ from functools import reduce
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.shortcuts import render
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core.models import Log
|
||||
from modoboa.core.utils import check_for_updates
|
||||
|
||||
@@ -13,7 +13,7 @@ from django.utils import translation
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.html import escape
|
||||
from django.utils.http import urlsafe_base64_encode
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views import generic
|
||||
from django.views.decorators.cache import never_cache
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from django.contrib.auth import mixins as auth_mixins
|
||||
from django.urls import reverse
|
||||
from django.utils.http import is_safe_url
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.views import generic
|
||||
|
||||
from ..extensions import exts_pool
|
||||
@@ -16,7 +16,7 @@ def find_nextlocation(request, user):
|
||||
nextlocation = request.POST.get("next", request.GET.get("next"))
|
||||
condition = (
|
||||
nextlocation and
|
||||
is_safe_url(nextlocation, request.get_host())
|
||||
url_has_allowed_host_and_scheme(nextlocation, request.get_host())
|
||||
)
|
||||
if condition:
|
||||
return nextlocation
|
||||
|
||||
@@ -9,8 +9,8 @@ from django.conf import settings
|
||||
from django.shortcuts import render
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import translation
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
|
||||
@@ -52,7 +52,7 @@ def profile(request, tplname="core/user_profile.html"):
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
if update_password and form.cleaned_data["confirmation"] != "":
|
||||
request.session["password"] = force_text(encrypt(
|
||||
request.session["password"] = force_str(encrypt(
|
||||
form.cleaned_data["confirmation"]
|
||||
))
|
||||
translation.activate(request.user.language)
|
||||
|
||||
@@ -4,7 +4,7 @@ import collections
|
||||
|
||||
from django import forms
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from modoboa.dmarc.api.v2 import serializers
|
||||
from modoboa.lib import form_utils
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Django signal handlers for modoboa_dmarc."""
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from django.dispatch import receiver
|
||||
|
||||
from modoboa.admin import signals as admin_signals
|
||||
|
||||
+5
-10
@@ -14,14 +14,13 @@ import tldextract
|
||||
from defusedxml.ElementTree import fromstring
|
||||
from dns import resolver, reversename
|
||||
import magic
|
||||
import pytz.exceptions
|
||||
import six
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.parameters import tools as param_tools
|
||||
@@ -57,7 +56,7 @@ def import_record(xml_node, report):
|
||||
record.spf_result = policy_evaluated.find("spf").text
|
||||
reason = policy_evaluated.find("reason")
|
||||
if reason:
|
||||
record.reason_type = smart_text(reason.find("type").text)[:14]
|
||||
record.reason_type = smart_str(reason.find("type").text)[:14]
|
||||
if record.reason_type not in constants.ALLOWED_REASON_TYPES:
|
||||
record.reason_type = "other"
|
||||
comment = reason.find("comment").text or ""
|
||||
@@ -128,11 +127,7 @@ def import_report(content):
|
||||
print(f"Report skipped because of malformed data (empty {attr})")
|
||||
return
|
||||
value = setattr(report, "policy_{}".format(attr), node.text)
|
||||
try:
|
||||
report.save()
|
||||
except (pytz.exceptions.AmbiguousTimeError):
|
||||
print("Report skipped because of invalid date.")
|
||||
return
|
||||
report.save()
|
||||
for record in root.findall("record"):
|
||||
import_record(record, report)
|
||||
|
||||
@@ -223,7 +218,7 @@ def week_range(year, weeknumber):
|
||||
"{}-{}-{}".format(year, weeknumber, 1), fmt)
|
||||
end_week = datetime.datetime.strptime(
|
||||
"{}-{}-{}".format(year, weeknumber, 0), fmt)
|
||||
return tz.localize(start_week), tz.localize(end_week)
|
||||
return start_week.replace(tzinfo=tz), end_week.replace(tzinfo=tz)
|
||||
|
||||
|
||||
def insert_record(target: dict, record, name: str) -> None:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""DMARC models."""
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from collections import OrderedDict
|
||||
|
||||
from django import template
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.utils import timezone
|
||||
from django.views import generic
|
||||
|
||||
from django.contrib.auth import mixins as auth_mixins
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.parameters import tools as param_tools
|
||||
@@ -45,7 +45,7 @@ def week_range(year, weeknumber):
|
||||
"{}-{}-{}".format(year, weeknumber, 1), fmt)
|
||||
end_week = datetime.datetime.strptime(
|
||||
"{}-{}-{}".format(year, weeknumber, 0), fmt)
|
||||
return tz.localize(start_week), tz.localize(end_week)
|
||||
return start_week.replace(tzinfo=tz), end_week.replace(tzinfo=tz)
|
||||
|
||||
|
||||
class DomainReportView(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import ipaddress
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.admin import lib as admin_lib
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from . import constants
|
||||
from . import lib
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""App related views."""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views import generic
|
||||
|
||||
from django.contrib.auth import mixins as auth_mixins
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import collections
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from modoboa.lib import form_utils
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""AppConfig for IMAP migration."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
|
||||
def load_imapmigration_settings():
|
||||
@@ -15,9 +15,9 @@ def load_imapmigration_settings():
|
||||
from .api.v2 import serializers
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", app_settings.ParametersForm, ugettext_lazy("IMAP Migration"))
|
||||
"global", app_settings.ParametersForm, gettext_lazy("IMAP Migration"))
|
||||
param_tools.registry.add2(
|
||||
"global", "imap_migration", ugettext_lazy("IMAP Migration"),
|
||||
"global", "imap_migration", gettext_lazy("IMAP Migration"),
|
||||
app_settings.IMAP_MIGRATION_PARAMETERS_STRUCT,
|
||||
serializers.IMAPMigrationSettingsSerializer,
|
||||
True)
|
||||
|
||||
@@ -5,7 +5,7 @@ import socket
|
||||
import ssl
|
||||
|
||||
from django.utils.encoding import smart_bytes, smart_str
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib import email_utils
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from django.core.checks import Warning, register
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import ldap.modlist as modlist
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_bytes, force_str
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
|
||||
@@ -7,7 +7,7 @@ import pkg_resources
|
||||
import requests
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
logger = logging.getLogger("modoboa.admin")
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from cryptography.hazmat.primitives.hashes import SHA1
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.encoding import smart_bytes, smart_text
|
||||
from django.utils.encoding import smart_bytes, smart_str
|
||||
|
||||
|
||||
def random_key(length=16):
|
||||
@@ -34,12 +34,12 @@ def _get_fernet():
|
||||
|
||||
def encrypt(clear_value):
|
||||
"""Encrypt a value using secret_key."""
|
||||
return smart_text(_get_fernet().encrypt(smart_bytes(clear_value)))
|
||||
return smart_str(_get_fernet().encrypt(smart_bytes(clear_value)))
|
||||
|
||||
|
||||
def decrypt(encrypted_value):
|
||||
"""Decrypt a value using secret_key."""
|
||||
return smart_text(_get_fernet().decrypt(smart_bytes(encrypted_value)))
|
||||
return smart_str(_get_fernet().decrypt(smart_bytes(encrypted_value)))
|
||||
|
||||
|
||||
def get_password(request):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.lib.exceptions import InternalError
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ from lxml.html.clean import Cleaner
|
||||
|
||||
from django.core.mail import EmailMessage
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.encoding import smart_str, smart_text
|
||||
from django.utils.encoding import smart_str, smart_str
|
||||
from django.utils.html import conditional_escape, escape
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib import u2u_decode
|
||||
@@ -130,7 +130,7 @@ class Email(object):
|
||||
if not len(value):
|
||||
continue
|
||||
if encoding:
|
||||
value = smart_text(value, encoding=encoding)
|
||||
value = smart_str(value, encoding=encoding)
|
||||
elif isinstance(value, bytes):
|
||||
# SMTPUTF8 fallback (most of the time)
|
||||
# Address contains non ASCII chars but is not RFC2047
|
||||
@@ -229,7 +229,7 @@ class Email(object):
|
||||
_RE_REMOVE_EXTRA_WHITESPACE.sub("\n\n", content).strip()
|
||||
)
|
||||
mail_text = escape(mail_text)
|
||||
return smart_text(mail_text)
|
||||
return smart_str(mail_text)
|
||||
|
||||
def _post_process_html(self, content):
|
||||
html = lxml.html.fromstring(content)
|
||||
@@ -253,7 +253,7 @@ class Email(object):
|
||||
)
|
||||
mail_text = lxml.html.tostring(
|
||||
cleaner.clean_html(html), encoding="unicode")
|
||||
return smart_text(mail_text)
|
||||
return smart_str(mail_text)
|
||||
|
||||
def _map_cid(self, url):
|
||||
if url.startswith("cid:"):
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
class ModoboaException(Exception):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Custom form fields."""
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
@@ -12,7 +12,7 @@ class DomainNameField(forms.fields.CharField):
|
||||
"""A subclass of CharField that only accepts a valid domain name."""
|
||||
|
||||
default_error_messages = {
|
||||
"invalid": ugettext_lazy("Enter a valid domain name")
|
||||
"invalid": gettext_lazy("Enter a valid domain name")
|
||||
}
|
||||
|
||||
default_validators = [validators.validate_hostname]
|
||||
@@ -41,7 +41,7 @@ class DRFEmailFieldUTF8(serializers.CharField):
|
||||
"""Custom DRF email field to support UTF8."""
|
||||
|
||||
default_error_messages = {
|
||||
"invalid": ugettext_lazy("Enter a valid email address.")
|
||||
"invalid": gettext_lazy("Enter a valid email address.")
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -55,7 +55,7 @@ class DRFEmailFieldUTF8AndEmptyUser(serializers.CharField):
|
||||
"""Custom DRF email field to support UTF8 and empty local part."""
|
||||
|
||||
default_error_messages = {
|
||||
"invalid": ugettext_lazy("Enter a valid email address.")
|
||||
"invalid": gettext_lazy("Enter a valid email address.")
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
@@ -9,7 +9,7 @@ from django.forms.fields import Field
|
||||
from django.forms.widgets import RadioSelect
|
||||
from django.shortcuts import render
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
|
||||
from modoboa.lib.exceptions import BadRequest
|
||||
from modoboa.lib.web_utils import render_to_json_response
|
||||
@@ -393,8 +393,8 @@ class YesNoField(TypedChoiceField):
|
||||
"""Constructor."""
|
||||
kwargs.update({
|
||||
"choices": (
|
||||
(True, ugettext_lazy("Yes")),
|
||||
(False, ugettext_lazy("No"))
|
||||
(True, gettext_lazy("Yes")),
|
||||
(False, gettext_lazy("No"))
|
||||
),
|
||||
"widget": HorizontalRadioSelect(),
|
||||
"coerce": lambda x: x == "True"
|
||||
|
||||
@@ -35,7 +35,7 @@ import ldap
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_bytes, force_str
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core.password_hashers import get_password_hasher
|
||||
from modoboa.lib.exceptions import InternalError
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
from modoboa.lib import signals as lib_signals
|
||||
from modoboa.lib.exceptions import ModoboaException
|
||||
@@ -11,10 +11,14 @@ from modoboa.lib.web_utils import (
|
||||
)
|
||||
|
||||
|
||||
def is_ajax(request):
|
||||
return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
|
||||
|
||||
|
||||
class AjaxLoginRedirect(MiddlewareMixin):
|
||||
|
||||
def process_response(self, request, response):
|
||||
if request.is_ajax():
|
||||
if is_ajax(request):
|
||||
if isinstance(response, HttpResponseRedirect):
|
||||
response.status_code = 278
|
||||
return response
|
||||
@@ -27,17 +31,17 @@ class CommonExceptionCatcher(MiddlewareMixin):
|
||||
if not isinstance(exception, ModoboaException):
|
||||
return None
|
||||
|
||||
if request.is_ajax() or "/api/" in request.path:
|
||||
if is_ajax(request) or "/api/" in request.path:
|
||||
if exception.http_code is None:
|
||||
return ajax_response(
|
||||
request, status="ko", respmsg=smart_text(exception),
|
||||
request, status="ko", respmsg=smart_str(exception),
|
||||
norefresh=True
|
||||
)
|
||||
return render_to_json_response(
|
||||
smart_text(exception), status=exception.http_code
|
||||
smart_str(exception), status=exception.http_code
|
||||
)
|
||||
return _render_error(
|
||||
request, user_context={"error": smart_text(exception)}
|
||||
request, user_context={"error": smart_str(exception)}
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import re
|
||||
import subprocess
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.encoding import force_str
|
||||
|
||||
|
||||
def exec_cmd(cmd, sudo_user=None, pinput=None, capture_output=True, **kwargs):
|
||||
@@ -59,7 +59,7 @@ def doveadm_cmd(params, pinput=None, capture_output=True, **kwargs):
|
||||
dpath = None
|
||||
code, output = exec_cmd("which doveadm")
|
||||
if not code:
|
||||
dpath = force_text(output).strip()
|
||||
dpath = force_str(output).strip()
|
||||
else:
|
||||
known_paths = getattr(
|
||||
settings, "DOVEADM_LOOKUP_PATH",
|
||||
|
||||
@@ -4,7 +4,7 @@ Form rendering tags.
|
||||
|
||||
from django import forms, template
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from modoboa.lib.form_utils import SeparatorField
|
||||
@@ -43,7 +43,7 @@ def render_field(
|
||||
from modoboa.core.templatetags.core_tags import visirule
|
||||
|
||||
if isinstance(field.field, SeparatorField):
|
||||
return "<h5%s>%s</h5>" % (visirule(field), smart_text(field.label))
|
||||
return "<h5%s>%s</h5>" % (visirule(field), smart_str(field.label))
|
||||
configure_field_classes(field)
|
||||
context = {
|
||||
"field": field, "help_display_mode": help_display_mode,
|
||||
|
||||
@@ -5,7 +5,7 @@ from datetime import datetime
|
||||
from django import template
|
||||
from django.template import Context, Template
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.core import signals as core_signals
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import os
|
||||
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.encoding import smart_bytes, smart_text
|
||||
from django.utils.encoding import smart_bytes, smart_str
|
||||
|
||||
from ..email_utils import (
|
||||
Email, prepare_addresses, split_address, split_local_part
|
||||
@@ -44,7 +44,7 @@ class EmailTests(SimpleTestCase):
|
||||
|
||||
with open(message_path, "rb") as fp:
|
||||
# output should always be unicode (py2) or str (py3)
|
||||
mail_text = smart_text(fp.read())
|
||||
mail_text = smart_str(fp.read())
|
||||
|
||||
return mail_text
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import re
|
||||
from email.header import decode_header, make_header
|
||||
from email.utils import parseaddr
|
||||
|
||||
from django.utils.encoding import smart_text
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
# check spaces between encoded_words (and strip them)
|
||||
sre = re.compile(r"\?=[ \t]+=\?")
|
||||
@@ -40,7 +40,7 @@ def decode_mime(m):
|
||||
"""Substitute matching encoded_word with unicode equiv."""
|
||||
h = decode_header(clean_spaces(m))
|
||||
try:
|
||||
u = smart_text(make_header(h))
|
||||
u = smart_str(make_header(h))
|
||||
except (LookupError, UnicodeDecodeError):
|
||||
return m.group(0)
|
||||
return u
|
||||
|
||||
@@ -4,14 +4,14 @@ import re
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import EmailValidator, URLValidator
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django.utils.translation import gettext_lazy
|
||||
|
||||
|
||||
class HostnameValidator(object):
|
||||
|
||||
"""Validator for fqdn."""
|
||||
|
||||
message = ugettext_lazy("Enter a valid domain name")
|
||||
message = gettext_lazy("Enter a valid domain name")
|
||||
code = "invalid"
|
||||
regex = re.compile(URLValidator.host_re)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import collections
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from modoboa.lib.form_utils import SeparatorField, YesNoField
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""App config for limits."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
def load_limits_settings():
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import collections
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
DEFAULT_USER_LIMITS = collections.OrderedDict((
|
||||
("domains", {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Custom forms."""
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.lib.permissions import get_object_owner
|
||||
from . import utils
|
||||
|
||||
@@ -4,7 +4,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import signals
|
||||
from django.dispatch import receiver
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.admin import models as admin_models, signals as admin_signals
|
||||
from modoboa.core import models as core_models, signals as core_signals
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from modoboa.lib.exceptions import ModoboaException
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user