• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

esnet-security / SCRAM / 15737761040

18 Jun 2025 03:58PM UTC coverage: 95.004% (-0.7%) from 95.666%
15737761040

push

github

web-flow
fix(user model): Fix default password generation. (#158)

Django is deprecating the make_random_password() method so we need to
roll our own eventually, might as well now. Also we need to change the
allowed characters for the DB secret as it keeps killing the django env
library.

58 of 61 branches covered (95.08%)

Branch coverage included in aggregate %.

15 of 25 new or added lines in 3 files covered. (60.0%)

1197 of 1260 relevant lines covered (95.0%)

0.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

64.29
/scram/shared/shared_code.py
1
"""A Module for defining shared code."""
2

3
import secrets
1✔
4
import string
1✔
5

6

7
def make_random_password(length: int = 20, min_digits: int = 5, max_attempts: int = 10000) -> str:
1✔
8
    """make_random_password replaces the deprecated django make_random_password function.
9

10
    Generates a random password of a specified length containing at least a specified number of digits using the
11
    official python best practices and some additional sanity checks. The python docs for this can be found at
12
    https://docs.python.org/3/library/secrets.html#recipes-and-best-practices. Note that generating long passwords
13
    with a high number of digits (>100) is inefficient and should be avoided. This password should only be used for
14
    temporary purposes, such as for a user to log in to the web interface and change their password.
15

16
    Args:
17
        length (int, optional): The total length of the password to generate. Defaults to 20.
18
        min_digits (int, optional): The minimum number of digits the password needs. Defaults to 5.
19
        max_attempts (int, optional): The maximum number of attempts to generate a valid password. Defaults to 10000.
20

21
    Raises:
22
        ValueError: Password length must be at least 1
23
        ValueError: min_digits cannot be negative
24
        ValueError: min_digits cannot exceed password length
25
        ValueError: For performance reasons, min_digits cannot exceed 30% of the password length
26
        RuntimeError: Failed to generate a valid password after max_attempts attempts
27

28
    Returns:
29
        password (str): The generated password.
30
    """
31
    if length < 1:
1✔
NEW
32
        message = "Password length must be at least 1"
×
NEW
33
        raise ValueError(message)
×
34
    if min_digits < 0:
1✔
NEW
35
        message = "min_digits cannot be negative"
×
NEW
36
        raise ValueError(message)
×
37
    if min_digits > length:
1✔
NEW
38
        message = "min_digits cannot exceed password length"
×
NEW
39
        raise ValueError(message)
×
40
    # Only allow a somewhat arbitrary threshold of 30% of the password length for min_digits, for performance reasons.
41
    if min_digits > length * 0.3:
1✔
NEW
42
        message = "For performance reasons, min_digits cannot exceed 30% of the password length"
×
NEW
43
        raise ValueError(message)
×
44

45
    alphabet = string.ascii_letters + string.digits
1✔
46

47
    for _attempt in range(max_attempts):
1✔
48
        password = "".join(secrets.choice(alphabet) for _i in range(length))
1✔
49
        if (
1✔
50
            any(c.islower() for c in password)
51
            and any(c.isupper() for c in password)
52
            and sum(c.isdigit() for c in password) >= min_digits
53
        ):
54
            return password
1✔
55

56
    # If we reached this point, we failed to generate a valid password after max_attempts attempts, likely due to the
57
    # required password length being very long and the min_digits being high.
NEW
58
    message = f"Failed to generate a valid password after {max_attempts} attempts"
×
NEW
59
    raise RuntimeError(message)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc