Production Login page passcode updates

This commit is contained in:
sriram
2026-08-24 22:55:06 +05:30
parent 2482fe43e3
commit 1b347f91db
11 changed files with 878 additions and 67 deletions

View File

@@ -27,6 +27,17 @@ from __future__ import annotations
import os
from pathlib import Path
# Snapshotted BEFORE load_dotenv, and that ordering is the entire point.
# load_dotenv() is called without override=True, so a variable already in the
# process environment silently beats the .env file and keeps beating it no
# matter how many times the file is corrected. That is not hypothetical here:
# the deployment platform injects its Environment tab into the container, so a
# stale value left in that tab overrides the credentials baked into the image
# (backend/Dockerfile copies .env.production to /app/.env) and the only symptom
# is a 401 that nothing explains. Comparing a name against this set answers
# "which of the two won?" - see config_source() below.
_PREEXISTING_ENV = frozenset(os.environ)
try:
from dotenv import load_dotenv
@@ -39,6 +50,45 @@ except ImportError:
pass
# Names whose raw value arrived wrapped in quotes or padded with whitespace.
# Recorded rather than merely fixed: stripping keeps the login working, but the
# only place the original shape is still visible is right here, before the value
# is normalised. A quoted hash is the signature of a value pasted into a web
# form, so surfacing it at startup is what stops the next person rediscovering
# it from a 401. See DB_PASSWORD in .env.production for the counter-case where
# the quotes ARE part of the secret - which is why this warns, and does not fail.
_ENV_NEEDED_CLEANUP = set()
def _clean(name: str, raw: str) -> str:
"""Strip surrounding quotes/whitespace off an env value, remembering if it mattered."""
cleaned = raw.strip().strip("'\"")
if cleaned != raw:
_ENV_NEEDED_CLEANUP.add(name)
return cleaned
def cleaned_env_names() -> list:
"""Which settings needed quote/whitespace stripping. Reported at startup."""
return sorted(_ENV_NEEDED_CLEANUP)
def config_source(name: str) -> str:
"""
Where a setting's value actually came from: the process environment, the
.env file, or this module's own default.
Reported at startup for the AUTH_* values (see app/main.py) so that an
override arriving from outside the image is visible in the logs instead of
being inferred from a failing login.
"""
if name in _PREEXISTING_ENV:
return "process-env"
if name in os.environ:
return "env-file"
return "default"
def _bool(name: str, default: str) -> bool:
return os.getenv(name, default).strip().lower() in {"1", "true", "yes"}
@@ -290,20 +340,29 @@ AUTH_TOKEN_TTL_MINUTES = int(os.getenv("AUTH_TOKEN_TTL_MINUTES", "720"))
# `make_auth_secrets.py` prints the lines ready to paste.
#
# `admin` is required whenever auth is on: without it nobody could sign in.
AUTH_ADMIN_USERNAME = os.getenv("AUTH_ADMIN_USERNAME", "admin").strip().strip("'\"")
AUTH_ADMIN_PASSWORD_HASH = (
_require("AUTH_ADMIN_PASSWORD_HASH", feature_flag="AUTH_ENABLED")
if AUTH_ENABLED
else os.getenv("AUTH_ADMIN_PASSWORD_HASH", "")
).strip().strip("'\"")
AUTH_ADMIN_USERNAME = _clean(
"AUTH_ADMIN_USERNAME", os.getenv("AUTH_ADMIN_USERNAME", "admin")
)
AUTH_ADMIN_PASSWORD_HASH = _clean(
"AUTH_ADMIN_PASSWORD_HASH",
(
_require("AUTH_ADMIN_PASSWORD_HASH", feature_flag="AUTH_ENABLED")
if AUTH_ENABLED
else os.getenv("AUTH_ADMIN_PASSWORD_HASH", "")
),
)
# The second `user` account is OPTIONAL, and left unset in this deployment.
# An empty hash is how the account is switched off: auth.py builds its account
# table from these values and omits any entry whose hash is blank, so there is
# nothing to sign in to. Setting the hash again re-enables it with no code
# change - which is exactly what the test suite does in tests/conftest.py.
AUTH_USER_USERNAME = os.getenv("AUTH_USER_USERNAME", "user").strip().strip("'\"")
AUTH_USER_PASSWORD_HASH = os.getenv("AUTH_USER_PASSWORD_HASH", "").strip().strip("'\"")
AUTH_USER_USERNAME = _clean(
"AUTH_USER_USERNAME", os.getenv("AUTH_USER_USERNAME", "user")
)
AUTH_USER_PASSWORD_HASH = _clean(
"AUTH_USER_PASSWORD_HASH", os.getenv("AUTH_USER_PASSWORD_HASH", "")
)
# Failed-login throttle, applied per username+client-IP. Prevents an exposed
# login endpoint from being a free password oracle.