diff --git a/AUTHORS b/AUTHORS index 4444ee16af..8c20814b13 100644 --- a/AUTHORS +++ b/AUTHORS @@ -209,6 +209,7 @@ answer newbie questions, and generally made Django that much better: Chris Wagner Chris Wesseling Chris Wilson + Ciaran McCormick Claude Paroz Clint Ecker colin@owlfish.com diff --git a/django/contrib/auth/base_user.py b/django/contrib/auth/base_user.py index f6de3b9317..5ee30bf59c 100644 --- a/django/contrib/auth/base_user.py +++ b/django/contrib/auth/base_user.py @@ -3,6 +3,7 @@ This module allows importing AbstractBaseUser even when django.contrib.auth is not in INSTALLED_APPS. """ import unicodedata +import warnings from django.contrib.auth import password_validation from django.contrib.auth.hashers import ( @@ -12,6 +13,7 @@ from django.contrib.auth.hashers import ( ) from django.db import models from django.utils.crypto import get_random_string, salted_hmac +from django.utils.deprecation import RemovedInDjango51Warning from django.utils.translation import gettext_lazy as _ @@ -40,6 +42,11 @@ class BaseUserManager(models.Manager): allowed_chars. The default value of allowed_chars does not have "I" or "O" or letters and digits that look similar -- just to avoid confusion. """ + warnings.warn( + "BaseUserManager.make_random_password() is deprecated.", + category=RemovedInDjango51Warning, + stacklevel=2, + ) return get_random_string(length, allowed_chars) def get_by_natural_key(self, username): diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 7bef5e7db5..5709b45865 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -15,6 +15,8 @@ about each item can often be found in the release notes of two versions prior. See the :ref:`Django 4.2 release notes ` for more details on these changes. +* The ``BaseUserManager.make_random_password()`` method will be removed. + .. _deprecation-removed-in-5.0: 5.0 diff --git a/docs/releases/4.2.txt b/docs/releases/4.2.txt index 0c80c5b103..b510eaa78f 100644 --- a/docs/releases/4.2.txt +++ b/docs/releases/4.2.txt @@ -250,4 +250,7 @@ Features deprecated in 4.2 Miscellaneous ------------- -* ... +* The ``BaseUserManager.make_random_password()`` method is deprecated. See + `recipes and best practices + `_ + for using Python's :py:mod:`secrets` module to generate passwords. diff --git a/docs/topics/auth/customizing.txt b/docs/topics/auth/customizing.txt index 38ee57240f..53db554baf 100644 --- a/docs/topics/auth/customizing.txt +++ b/docs/topics/auth/customizing.txt @@ -772,6 +772,8 @@ utility methods: .. method:: models.BaseUserManager.make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789') + .. deprecated:: 4.2 + Returns a random password with the given length and given string of allowed characters. Note that the default value of ``allowed_chars`` doesn't contain letters that can cause user confusion, including: diff --git a/tests/auth_tests/test_models.py b/tests/auth_tests/test_models.py index 2d75b607bf..01bb7981a4 100644 --- a/tests/auth_tests/test_models.py +++ b/tests/auth_tests/test_models.py @@ -18,6 +18,8 @@ from django.db import connection, migrations from django.db.migrations.state import ModelState, ProjectState from django.db.models.signals import post_save from django.test import SimpleTestCase, TestCase, TransactionTestCase, override_settings +from django.test.utils import ignore_warnings +from django.utils.deprecation import RemovedInDjango51Warning from .models import CustomEmailField, IntegerUsernameUser @@ -164,6 +166,7 @@ class UserManagerTestCase(TransactionTestCase): is_staff=False, ) + @ignore_warnings(category=RemovedInDjango51Warning) def test_make_random_password(self): allowed_chars = "abcdefg" password = UserManager().make_random_password(5, allowed_chars) @@ -171,6 +174,11 @@ class UserManagerTestCase(TransactionTestCase): for char in password: self.assertIn(char, allowed_chars) + def test_make_random_password_warning(self): + msg = "BaseUserManager.make_random_password() is deprecated." + with self.assertWarnsMessage(RemovedInDjango51Warning, msg): + UserManager().make_random_password() + def test_runpython_manager_methods(self): def forwards(apps, schema_editor): UserModel = apps.get_model("auth", "User")