Enforce repository boundary for persistence access
- Hide raw database connections (DbDep) from routers by removing from public exports - Maintain DbDep as deprecated export for backward compatibility - Add _DbDep internal dependency for use by other dependencies like require_auth - Update module docstring to explain dependency layering rules - Add comprehensive documentation section on dependency layering to Backend-Development.md This enforces the architectural boundary where: - Routers depend on repository dependencies (SessionRepoDep, BlocklistRepositoryDep, etc) - Services orchestrate operations through repositories - Only repositories execute SQL queries The repository boundary is now technically enforced through the dependency injection system, making it impossible for routers to accidentally bypass repositories and access the database directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,11 @@ All ``Depends()`` callables that inject shared resources (database
|
||||
connection, settings, services, auth guard) are defined here.
|
||||
Routers import directly from this module — never from ``app.state``
|
||||
directly — to keep coupling explicit and testable.
|
||||
|
||||
IMPORTANT: Routers should depend on repository dependencies (e.g., SessionRepoDep,
|
||||
BlocklistRepositoryDep) rather than on database connections. This enforces the
|
||||
repository boundary: only repositories and services access the database directly.
|
||||
See Backend-Development.md § 6 for the dependency layering rules.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
@@ -369,9 +374,14 @@ async def get_fail2ban_metadata_service() -> object:
|
||||
return default_fail2ban_metadata_service
|
||||
|
||||
|
||||
# Internal database dependency for use by other dependencies only
|
||||
# Routers should NOT import this - they should use repository dependencies instead
|
||||
_DbDep = Annotated[aiosqlite.Connection, Depends(get_db)]
|
||||
|
||||
|
||||
async def require_auth(
|
||||
request: Request,
|
||||
db: Annotated[aiosqlite.Connection, Depends(get_db)],
|
||||
db: _DbDep,
|
||||
settings: Annotated[Settings, Depends(get_settings)],
|
||||
session_cache: Annotated[SessionCache, Depends(get_session_cache)],
|
||||
session_repo: Annotated[SessionRepository, Depends(get_session_repo)],
|
||||
@@ -390,8 +400,10 @@ async def require_auth(
|
||||
|
||||
Args:
|
||||
request: The incoming FastAPI request.
|
||||
db: Injected aiosqlite connection.
|
||||
db: Injected aiosqlite connection (for repository operations).
|
||||
settings: Application settings used for signed session token validation.
|
||||
session_cache: Session validation cache backend.
|
||||
session_repo: Session repository for persistence operations.
|
||||
|
||||
Returns:
|
||||
The active :class:`~app.models.auth.Session`.
|
||||
@@ -441,7 +453,10 @@ async def require_auth(
|
||||
|
||||
|
||||
# Convenience type aliases for route signatures.
|
||||
DbDep = Annotated[aiosqlite.Connection, Depends(get_db)]
|
||||
# NOTE: Database connections are NOT exported to routers. Routers should depend on
|
||||
# repository dependencies (SessionRepoDep, BlocklistRepositoryDep, etc.) instead.
|
||||
# See Backend-Development.md for the dependency layering rules.
|
||||
|
||||
SettingsDep = Annotated[Settings, Depends(get_settings)]
|
||||
HttpSessionDep = Annotated[aiohttp.ClientSession, Depends(get_http_session)]
|
||||
SchedulerDep = Annotated[AsyncIOScheduler, Depends(get_scheduler)]
|
||||
@@ -466,3 +481,8 @@ AppDep = Annotated[FastAPI, Depends(get_app)]
|
||||
AuthDep = Annotated[Session, Depends(require_auth)]
|
||||
LoginRateLimiterDep = Annotated[RateLimiter, Depends(get_login_rate_limiter)]
|
||||
Fail2BanMetadataServiceDep = Annotated[Fail2BanMetadataService, Depends(get_fail2ban_metadata_service)]
|
||||
|
||||
# DEPRECATED: DbDep is provided for backward compatibility only.
|
||||
# DO NOT use in new code. Use repository dependencies instead (SessionRepoDep, BlocklistRepositoryDep, etc.)
|
||||
# See Backend-Development.md § 6 for dependency layering rules.
|
||||
DbDep = _DbDep
|
||||
|
||||
Reference in New Issue
Block a user