django-configurations/configurations/example_generators.py
2022-03-24 14:57:35 +01:00

59 lines
2.1 KiB
Python

from typing import Callable
import secrets
import base64
import django
from django.core.management.utils import get_random_secret_key
from django.utils.crypto import get_random_string
if django.VERSION[0] > 3 or \
(django.VERSION[0] == 3 and django.VERSION[1] >= 2):
# RANDOM_STRING_CHARS was only introduced in django 3.2
from django.utils.crypto import RANDOM_STRING_CHARS
else:
RANDOM_STRING_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" # pragma: no cover
def gen_django_secret_key() -> str:
"""
Generate a cryptographically secure random string that can safely be used as a SECRET_KEY in django
"""
return get_random_secret_key()
def gen_random_string(length: int, allowed_chars: str = RANDOM_STRING_CHARS) -> Callable[[], str]:
"""
Create a parameterized generator which generates a cryptographically secure random string of the given length
containing the given characters.
"""
def _gen_random_string() -> str:
return get_random_string(length, allowed_chars)
return _gen_random_string
def gen_bytes(length: int, encoding: str) -> Callable[[], str]:
"""
Create a parameterized generator which generates a cryptographically secure random assortments of bytes of the given
length and encoded in the given format
:param length: How many bytes should be generated. Not how long the encoded string will be.
:param encoding: How the generated bytes should be encoded.
Accepted values are "base64", "base64_urlsafe" and "hex" (case is ignored)
"""
encoding = encoding.lower()
if encoding not in ("base64", "base64_urlsafe", "hex"):
raise ValueError(f"Cannot gen_bytes with encoding '{encoding}'. Valid encodings are 'base64', 'base64_urlsafe'"
f" and 'hex'")
def _gen_bytes() -> str:
b = secrets.token_bytes(length)
if encoding == "base64":
return base64.standard_b64encode(b).decode("ASCII")
elif encoding == "base64_urlsafe":
return base64.urlsafe_b64encode(b).decode("ASCII")
elif encoding == "hex":
return b.hex().upper()
return _gen_bytes