diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ee78fc..b482ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Documentation + +- Filled in remaining missing docstrings to reach 100% interrogate coverage + (up from 99.2%): module docstring for `python_libs.middleware`, docstring + + type annotations for the `mask_match` inner callback in + `cloudflare_auth.utils.mask_sensitive_data`, and docstring for the + `dependency` closure returned by `cloudflare_auth.middleware_enhanced.require_tier`. + ### Changed - Migrated `sonarcloud.yml` to use `python-sonarcloud.yml` reusable workflow diff --git a/packages/cloudflare-auth/src/cloudflare_auth/middleware_enhanced.py b/packages/cloudflare-auth/src/cloudflare_auth/middleware_enhanced.py index 6fc8b67..dfc8bd8 100644 --- a/packages/cloudflare-auth/src/cloudflare_auth/middleware_enhanced.py +++ b/packages/cloudflare-auth/src/cloudflare_auth/middleware_enhanced.py @@ -721,6 +721,22 @@ async def premium(user: CloudflareUser = Depends(require_full)): """ def dependency(request: Request) -> CloudflareUser: + """Validate that the current user meets minimum_tier. + + Resolved as a FastAPI dependency by require_tier. The user is loaded + from request state via get_current_user; tiers are ordered + LIMITED < FULL < ADMIN. + + Args: + request: Incoming FastAPI/Starlette request. + + Returns: + The authenticated CloudflareUser object. + + Raises: + HTTPException: 403 if the user's tier is below minimum_tier; 401 + (via get_current_user) if the request is unauthenticated. + """ user = get_current_user(request) tier_order = { diff --git a/packages/cloudflare-auth/src/cloudflare_auth/utils.py b/packages/cloudflare-auth/src/cloudflare_auth/utils.py index bd83c53..54d6b88 100644 --- a/packages/cloudflare-auth/src/cloudflare_auth/utils.py +++ b/packages/cloudflare-auth/src/cloudflare_auth/utils.py @@ -221,7 +221,19 @@ def mask_sensitive_data( 'Contact ***@***.*** for help' """ - def mask_match(match): + def mask_match(match: re.Match[str]) -> str: + """Replace a regex match with a masked representation. + + For email-like matches (containing '@'), masks the local and domain + parts separately. For all other matches, replaces every character + with '*'. + + Args: + match: Regex match object produced by re.sub. + + Returns: + Masked replacement string for the matched text. + """ matched = match.group(0) if "@" in matched: # Email-like pattern diff --git a/src/python_libs/middleware/__init__.py b/src/python_libs/middleware/__init__.py index e69de29..ac221c3 100644 --- a/src/python_libs/middleware/__init__.py +++ b/src/python_libs/middleware/__init__.py @@ -0,0 +1,6 @@ +"""Middleware components for Python Libs. + +This package is reserved for middleware modules (request/response hooks, +ASGI/WSGI middleware, instrumentation). It is currently empty; submodules will +be added here as middleware features are introduced. +"""