diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/hub_settings.py')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/hub_settings.py | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/hub_settings.py b/packages/meshbay-hub/src/meshbay_hub/hub_settings.py index 1c2d2c4..1dcff84 100644 --- a/packages/meshbay-hub/src/meshbay_hub/hub_settings.py +++ b/packages/meshbay-hub/src/meshbay_hub/hub_settings.py @@ -85,6 +85,37 @@ async def mail_limits(db: AsyncSession) -> dict[str, int]: return {k: await get_int(db, f"mail.{k}", mail_default(k)) for k in MAIL_KEYS} +# ── Sign-in lockout ────────────────────────────────────────────────────────── +# +# After `max_failures` wrong passphrases for one username, sign-in with a +# passphrase is refused for `lockout_minutes` (`login_throttle.py`). Zero +# failures turns the lockout off; a zero-minute lockout would be the same thing +# said less clearly, so the duration starts at one. + +LOGIN_KEYS = ("max_failures", "lockout_minutes") + +LOGIN_DEFAULTS: dict[str, int] = { + "max_failures": 4, + "lockout_minutes": 60, +} + +LOGIN_BOUNDS: dict[str, tuple[int, int]] = { + "max_failures": (0, 100), + "lockout_minutes": (1, 10_080), # a week +} + + +def clamp_login_value(key: str, value: int) -> int: + low, high = LOGIN_BOUNDS[key] + return max(low, min(high, int(value))) + + +async def login_limits(db: AsyncSession) -> dict[str, int]: + """Both lockout numbers, stored value or built-in default.""" + return {k: clamp_login_value(k, await get_int(db, f"login.{k}", LOGIN_DEFAULTS[k])) + for k in LOGIN_KEYS} + + async def get_raw(db: AsyncSession, key: str) -> str | None: row = await db.get(HubSetting, key) return row.value if row else None |