chore: add changelog and documentation updates
All checks were successful
CI / lint-and-test (push) Successful in 17s
All checks were successful
CI / lint-and-test (push) Successful in 17s
- Created a new `CHANGELOG.md` file to document all notable changes to the project, adhering to the Keep a Changelog format. - Updated `CONTRIBUTING.md` to include instructions for building and previewing documentation using MkDocs. - Added `mkdocs.yml` configuration for documentation generation, including navigation structure and theme settings. - Enhanced various documentation files, including API reference, architecture overview, configuration reference, and runbook, to provide comprehensive guidance for users and developers. - Included new sections in the README for changelog and documentation links, improving accessibility to project information.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""FastAPI dependencies: DB session, auth, date validation."""
|
||||
"""FastAPI dependencies: DB session, Miniapp auth (initData/allowlist), date validation."""
|
||||
|
||||
import logging
|
||||
import re
|
||||
@@ -22,7 +22,14 @@ _ACCEPT_LANG_TAG_RE = re.compile(r"^([a-zA-Z]{2,3})(?:-[a-zA-Z0-9]+)?\s*(?:;|,|$
|
||||
|
||||
|
||||
def _lang_from_accept_language(header: str | None) -> str:
|
||||
"""Normalize Accept-Language to 'ru' or 'en'; fallback to config.DEFAULT_LANGUAGE."""
|
||||
"""Normalize Accept-Language header to 'ru' or 'en'; fallback to config.DEFAULT_LANGUAGE.
|
||||
|
||||
Args:
|
||||
header: Raw Accept-Language header value (e.g. "ru-RU,ru;q=0.9,en;q=0.8").
|
||||
|
||||
Returns:
|
||||
'ru' or 'en'.
|
||||
"""
|
||||
if not header or not header.strip():
|
||||
return config.DEFAULT_LANGUAGE
|
||||
first = header.strip().split(",")[0].strip()
|
||||
@@ -58,13 +65,26 @@ def get_validated_dates(
|
||||
from_date: str = Query(..., description="ISO date YYYY-MM-DD", alias="from"),
|
||||
to_date: str = Query(..., description="ISO date YYYY-MM-DD", alias="to"),
|
||||
) -> tuple[str, str]:
|
||||
"""Validate from/to dates; lang from Accept-Language for error messages."""
|
||||
"""Validate from/to date query params; use Accept-Language for error messages.
|
||||
|
||||
Args:
|
||||
request: FastAPI request (for Accept-Language).
|
||||
from_date: Start date YYYY-MM-DD.
|
||||
to_date: End date YYYY-MM-DD.
|
||||
|
||||
Returns:
|
||||
(from_date, to_date) as strings.
|
||||
|
||||
Raises:
|
||||
HTTPException: 400 if format invalid or from_date > to_date.
|
||||
"""
|
||||
lang = _lang_from_accept_language(request.headers.get("Accept-Language"))
|
||||
_validate_duty_dates(from_date, to_date, lang)
|
||||
return (from_date, to_date)
|
||||
|
||||
|
||||
def get_db_session() -> Generator[Session, None, None]:
|
||||
"""Yield a DB session for the request; closed automatically by FastAPI."""
|
||||
with session_scope(config.DATABASE_URL) as session:
|
||||
yield session
|
||||
|
||||
@@ -76,6 +96,11 @@ def require_miniapp_username(
|
||||
] = None,
|
||||
session: Session = Depends(get_db_session),
|
||||
) -> str:
|
||||
"""FastAPI dependency: require valid Miniapp auth; return username/identifier.
|
||||
|
||||
Raises:
|
||||
HTTPException: 403 if initData missing/invalid or user not in allowlist.
|
||||
"""
|
||||
return get_authenticated_username(request, x_telegram_init_data, session)
|
||||
|
||||
|
||||
@@ -100,7 +125,20 @@ def get_authenticated_username(
|
||||
x_telegram_init_data: str | None,
|
||||
session: Session,
|
||||
) -> str:
|
||||
"""Return identifier for miniapp auth (username or full_name or id:...); empty if skip-auth."""
|
||||
"""Return identifier for miniapp auth (username or full_name or id:...); empty if skip-auth.
|
||||
|
||||
Args:
|
||||
request: FastAPI request (client host for private-IP bypass).
|
||||
x_telegram_init_data: Raw X-Telegram-Init-Data header value.
|
||||
session: DB session (for phone allowlist lookup).
|
||||
|
||||
Returns:
|
||||
Username, full_name, or "id:<telegram_id>"; empty string if MINI_APP_SKIP_AUTH
|
||||
or private IP and no initData.
|
||||
|
||||
Raises:
|
||||
HTTPException: 403 if initData missing/invalid or user not in allowlist.
|
||||
"""
|
||||
if config.MINI_APP_SKIP_AUTH:
|
||||
log.warning("allowing without any auth check (MINI_APP_SKIP_AUTH is set)")
|
||||
return ""
|
||||
@@ -142,6 +180,16 @@ def get_authenticated_username(
|
||||
def fetch_duties_response(
|
||||
session: Session, from_date: str, to_date: str
|
||||
) -> list[DutyWithUser]:
|
||||
"""Load duties in range and return as DutyWithUser list for API response.
|
||||
|
||||
Args:
|
||||
session: DB session.
|
||||
from_date: Start date YYYY-MM-DD.
|
||||
to_date: End date YYYY-MM-DD.
|
||||
|
||||
Returns:
|
||||
List of DutyWithUser (id, user_id, start_at, end_at, full_name, event_type).
|
||||
"""
|
||||
rows = get_duties(session, from_date=from_date, to_date=to_date)
|
||||
return [
|
||||
DutyWithUser(
|
||||
|
||||
Reference in New Issue
Block a user