38 lines
2.0 KiB
Python
38 lines
2.0 KiB
Python
"""Генерация номера и постоянной ссылки конференции (ADR-001, п.4).
|
||
|
||
Оба идентификатора неизменны всё время жизни конференции и не переиспользуются;
|
||
уникальность в БД обеспечивают constraint'ы `conferences.number`/`conferences.slug`,
|
||
коллизии (крайне маловероятные при выбранной энтропии) обрабатываются повторной
|
||
генерацией на уровне репозитория/сервиса, создающего конференцию.
|
||
"""
|
||
|
||
import secrets
|
||
|
||
# Длина номера конференции в десятичных цифрах.
|
||
NUMBER_LENGTH = 9
|
||
|
||
# Длина slug в байтах энтропии (до base64url-кодирования); 8 байт = 64 бита,
|
||
# что даёт 11 символов base64url без padding.
|
||
SLUG_ENTROPY_BYTES = 8
|
||
|
||
|
||
def generate_number() -> str:
|
||
"""Сгенерировать 9-значный номер конференции.
|
||
|
||
Первая цифра — 1..9 (число не начинается с нуля), остальные 8 — 0..9.
|
||
Используется `secrets.randbelow` — криптографически стойкий генератор,
|
||
подбор номера должен быть неугадываем (оценка энтропии — ADR-001, п.4).
|
||
"""
|
||
first_digit = str(secrets.randbelow(9) + 1)
|
||
rest_digits = "".join(str(secrets.randbelow(10)) for _ in range(NUMBER_LENGTH - 1))
|
||
return first_digit + rest_digits
|
||
|
||
|
||
def generate_slug() -> str:
|
||
"""Сгенерировать slug постоянной ссылки конференции (`/j/{slug}`).
|
||
|
||
`secrets.token_urlsafe(8)` — 8 байт (64 бита) энтропии, 11 символов
|
||
base64url; также используется как имя LiveKit-комнаты.
|
||
"""
|
||
return secrets.token_urlsafe(SLUG_ENTROPY_BYTES)
|