Merge pull request #3496 from modoboa/reqs/prepare-for-django-5.2

Prepare for django 5.2
This commit is contained in:
Antoine Nguyen
2025-06-17 10:54:50 +02:00
committed by GitHub
9 changed files with 13 additions and 70 deletions
+2 -2
View File
@@ -29,7 +29,7 @@ jobs:
environment: test
services:
postgres:
image: postgres:12
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
@@ -72,7 +72,7 @@ jobs:
strategy:
matrix:
database: ['postgres', 'mysql']
python-version: [3.9, '3.10', '3.11', '3.12']
python-version: ['3.10', '3.11', '3.12', '3.13']
fail-fast: false
steps:
@@ -52,8 +52,5 @@ class PasswordSchemesTestCase(ModoAPITestCase):
def test_md5_scheme(self):
self._test_scheme("md5", "{MD5}")
def test_crypt(self):
self._test_scheme("crypt", "{CRYPT}")
def test_plain(self):
self._test_scheme("plain", "{PLAIN}")
-6
View File
@@ -507,12 +507,6 @@ class NotificationAPITestCase(ModoAPITestCase):
data = resp.json()
self.assertEqual(len(data), 0)
self.set_global_parameter("password_scheme", "crypt")
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
data = resp.json()
self.assertEqual(len(data), 1)
class AuthenticatorData(bytes):
@@ -9,7 +9,6 @@ from modoboa.core.password_hashers.advanced import ( # NOQA:F401
SSHAHasher,
)
from modoboa.core.password_hashers.base import ( # NOQA:F401
CRYPTHasher,
MD5Hasher,
PLAINHasher,
SHA256Hasher,
+1 -25
View File
@@ -5,11 +5,7 @@ Contains weak hashers (the original ones) available with Modoboa.
"""
import base64
import crypt
import hashlib
from random import Random
import string
from typing import Optional
from django.utils.crypto import constant_time_compare
@@ -53,7 +49,7 @@ class PasswordHasher(metaclass=MetaHasher):
def __init__(self, target="local"):
self._target = target
def _encrypt(self, clearvalue: str, salt: Optional[str] = None) -> str:
def _encrypt(self, clearvalue: str, salt: Optional[str] = None) -> str: # NOQA
raise NotImplementedError
def _b64encode(self, pwhash):
@@ -129,26 +125,6 @@ class PLAINHasher(PasswordHasher):
return clearvalue
class CRYPTHasher(PasswordHasher):
"""
crypt password hasher.
Uses python `crypt` standard module.
"""
_weak = True
deprecated = True
@property
def scheme(self):
return "{CRYPT}"
def _encrypt(self, clearvalue: str, salt: Optional[str] = None) -> str:
if salt is None:
salt = "".join(Random().sample(string.ascii_letters + string.digits, 2))
return crypt.crypt(clearvalue, salt)
class MD5Hasher(PasswordHasher):
"""
MD5 password hasher.
@@ -233,19 +233,11 @@ class AuthenticationTestCase(ModoTestCase):
supported_schemes = get_dovecot_schemes()[0]
self.assertEqual(supported_schemes, ["{MD5-CRYPT}", "{PLAIN}"])
def test_deprecated_password_scheme(self):
hasher = get_password_hasher("crypt")
self.assertEqual(hasher.label, "crypt (weak, deprecated)")
def test_is_password_scheme_in_use(self):
hasher = get_password_hasher("plain")
self.assertTrue(
models.User.objects.is_password_scheme_in_use(hasher),
)
hasher = get_password_hasher("crypt")
self.assertFalse(
models.User.objects.is_password_scheme_in_use(hasher),
)
def test_fido_auth_begin(self):
url = reverse("core:fido_auth_begin")
-7
View File
@@ -35,10 +35,3 @@ class CheckSessionCookieSecureTest(SimpleModoTestCase):
os.environ["OIDC_RSA_PRIVATE_KEY"] = "KEY"
msgs = checks.check_rsa_private_key_exists(None)
self.assertEqual(len(msgs), 0)
def test_password_hasher_checks(self):
msgs = checks.check_password_hasher(None)
self.assertEqual(msgs, [])
self.set_global_parameter("password_scheme", "crypt")
msgs = checks.check_password_hasher(None)
self.assertEqual(msgs, [checks.W002])
+5 -6
View File
@@ -10,26 +10,25 @@ authors = [
]
description = "Mail hosting made simple"
readme = "README.rst"
requires-python = ">=3.8"
requires-python = ">=3.10"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.2",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: ISC License (ISCL)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Communications :: Email",
"Topic :: Internet :: WWW/HTTP",
]
keywords = ["email"]
license = {file = "LICENSE"}
dependencies = [
"django>4.0,<5.0",
"django==5.2",
"django-phonenumber-field[phonenumbers]==8.1.0",
"django-reversion==5.1.0",
"django-xforwardedfor-middleware==2.0",
@@ -60,7 +59,7 @@ dependencies = [
"ovh",
"oath",
"redis>=4.2.0rc1",
"rrdtool>=0.1.10",
"rrdtool-bindings>=0.2.0",
"qrcode",
"aiosmtplib",
# PDF credentials
+5 -12
View File
@@ -15,7 +15,7 @@ else:
class DeployTest(unittest.TestCase):
dbtype = DB
dbhost = "localhost"
dbhost = "127.0.0.1"
dbport = PORT
projname = "modoboa_test"
dbuser = DB == "mysql" and "modoboa" or "postgres"
@@ -25,20 +25,13 @@ class DeployTest(unittest.TestCase):
self.workdir = tempfile.mkdtemp()
def test_silent(self):
dburl = "default:%s://%s:%s@%s:%s/%s" % (
self.dbtype,
self.dbuser,
self.dbpassword,
self.dbhost,
self.dbport,
"modoboa",
)
dburl = f"default:{self.dbtype}://{self.dbuser}:{self.dbpassword}@{self.dbhost}:{self.dbport}/modoboa"
cmd = (
"modoboa-admin.py deploy --collectstatic "
"--dburl %s --domain %s --admin-username admin %s"
% (dburl, "localhost", self.projname)
f"modoboa-admin.py deploy --collectstatic "
f"--dburl {dburl} --domain localhost --admin-username admin {self.projname}"
)
code, output = exec_cmd(cmd, cwd=self.workdir)
print(output)
self.assertEqual(code, 0)