45 lines
1.6 KiB
Python
45 lines
1.6 KiB
Python
from collections.abc import Mapping
|
|
|
|
OTP_SETTING_KEYS = {
|
|
"otp.phone.max_send_attempts_per_24h",
|
|
"otp.phone.min_seconds_between_attempts",
|
|
"otp.phone.max_verify_attempts",
|
|
"otp.phone.code_length",
|
|
"otp.phone.ttl_seconds",
|
|
"otp.phone.sms_order_timeout_ms",
|
|
}
|
|
|
|
|
|
def validate_otp_settings(values: Mapping[str, str]) -> None:
|
|
parsed: dict[str, int] = {}
|
|
for key in OTP_SETTING_KEYS:
|
|
raw = values.get(key)
|
|
if raw is None:
|
|
continue
|
|
try:
|
|
value = int(raw)
|
|
except (TypeError, ValueError) as error:
|
|
raise ValueError(f"{key}: integer value expected") from error
|
|
if str(value) != raw:
|
|
raise ValueError(f"{key}: canonical integer value expected")
|
|
parsed[key] = value
|
|
|
|
positive = OTP_SETTING_KEYS - {"otp.phone.min_seconds_between_attempts"}
|
|
for key in positive:
|
|
if key in parsed and parsed[key] <= 0:
|
|
raise ValueError(f"{key}: value must be positive")
|
|
if parsed.get("otp.phone.min_seconds_between_attempts", 0) < 0:
|
|
raise ValueError("otp.phone.min_seconds_between_attempts: value must be non-negative")
|
|
|
|
code_length = parsed.get("otp.phone.code_length")
|
|
if code_length is not None and not 4 <= code_length <= 10:
|
|
raise ValueError("otp.phone.code_length: value must be between 4 and 10")
|
|
|
|
ttl_seconds = parsed.get("otp.phone.ttl_seconds")
|
|
if ttl_seconds is not None and (
|
|
not 60 <= ttl_seconds <= 900 or ttl_seconds % 60 != 0
|
|
):
|
|
raise ValueError(
|
|
"otp.phone.ttl_seconds: value must be between 60 and 900 and divisible by 60"
|
|
)
|