diff --git a/etebase_fastapi/dependencies.py b/etebase_fastapi/dependencies.py index fb9cec5..520d499 100644 --- a/etebase_fastapi/dependencies.py +++ b/etebase_fastapi/dependencies.py @@ -11,6 +11,7 @@ from django_etebase.token_auth.models import AuthToken, get_default_expiry from myauth.models import UserType, get_typed_user_model from .exceptions import AuthenticationFailed from .utils import get_object_or_404 +from .db_hack import django_db_cleanup_decorator User = get_typed_user_model() @@ -55,25 +56,30 @@ def __get_authenticated_user(api_token: str): return token.user, token +@django_db_cleanup_decorator def get_auth_data(api_token: str = Depends(token_scheme)) -> AuthData: user, token = __get_authenticated_user(api_token) return AuthData(user, token) +@django_db_cleanup_decorator def get_authenticated_user(api_token: str = Depends(token_scheme)) -> UserType: user, _ = __get_authenticated_user(api_token) return user +@django_db_cleanup_decorator def get_collection_queryset(user: UserType = Depends(get_authenticated_user)) -> QuerySet: default_queryset: QuerySet = models.Collection.objects.all() return default_queryset.filter(members__user=user) +@django_db_cleanup_decorator def get_collection(collection_uid: str, queryset: QuerySet = Depends(get_collection_queryset)) -> models.Collection: return get_object_or_404(queryset, uid=collection_uid) +@django_db_cleanup_decorator def get_item_queryset(collection: models.Collection = Depends(get_collection)) -> QuerySet: default_item_queryset: QuerySet = models.CollectionItem.objects.all() # XXX Potentially add this for performance: .prefetch_related('revisions__chunks') diff --git a/etebase_fastapi/msgpack.py b/etebase_fastapi/msgpack.py index 67627e1..a671e79 100644 --- a/etebase_fastapi/msgpack.py +++ b/etebase_fastapi/msgpack.py @@ -1,6 +1,5 @@ import typing as t -from fastapi import params from fastapi.routing import APIRoute, get_request_handler from pydantic import BaseModel from starlette.requests import Request @@ -38,21 +37,9 @@ class MsgpackRoute(APIRoute): # keep track of content-type -> response classes ROUTES_HANDLERS_CLASSES = {MsgpackResponse.media_type: MsgpackResponse} - def __init__( - self, - path: str, - endpoint: t.Callable[..., t.Any], - *args, - dependencies: t.Optional[t.Sequence[params.Depends]] = None, - **kwargs - ): - if dependencies is not None: - dependencies = [ - params.Depends(django_db_cleanup_decorator(dep.dependency), use_cache=dep.use_cache) - for dep in dependencies - ] + def __init__(self, path: str, endpoint: t.Callable[..., t.Any], *args, **kwargs): endpoint = django_db_cleanup_decorator(endpoint) - super().__init__(path, endpoint, *args, dependencies=dependencies, **kwargs) + super().__init__(path, endpoint, *args, **kwargs) def _get_media_type_route_handler(self, media_type): return get_request_handler( diff --git a/etebase_fastapi/routers/collection.py b/etebase_fastapi/routers/collection.py index 2041ce7..4dcb3c6 100644 --- a/etebase_fastapi/routers/collection.py +++ b/etebase_fastapi/routers/collection.py @@ -26,6 +26,7 @@ from ..utils import ( ) from ..dependencies import get_collection_queryset, get_item_queryset, get_collection from ..sendfile import sendfile +from ..db_hack import django_db_cleanup_decorator collection_router = APIRouter(route_class=MsgpackRoute, responses=permission_responses) item_router = APIRouter(route_class=MsgpackRoute, responses=permission_responses) @@ -222,6 +223,7 @@ def collection_list_common( # permissions +@django_db_cleanup_decorator def verify_collection_admin( collection: models.Collection = Depends(get_collection), user: UserType = Depends(get_authenticated_user) ): @@ -229,6 +231,7 @@ def verify_collection_admin( raise PermissionDenied("admin_access_required", "Only collection admins can perform this operation.") +@django_db_cleanup_decorator def has_write_access( collection: models.Collection = Depends(get_collection), user: UserType = Depends(get_authenticated_user) ): diff --git a/etebase_fastapi/routers/invitation.py b/etebase_fastapi/routers/invitation.py index aceb05d..cbe570b 100644 --- a/etebase_fastapi/routers/invitation.py +++ b/etebase_fastapi/routers/invitation.py @@ -19,6 +19,7 @@ from ..utils import ( PERMISSIONS_READ, PERMISSIONS_READWRITE, ) +from ..db_hack import django_db_cleanup_decorator User = get_typed_user_model() invitation_incoming_router = APIRouter(route_class=MsgpackRoute, responses=permission_responses) @@ -86,10 +87,12 @@ class InvitationListResponse(BaseModel): done: bool +@django_db_cleanup_decorator def get_incoming_queryset(user: UserType = Depends(get_authenticated_user)): return default_queryset.filter(user=user) +@django_db_cleanup_decorator def get_outgoing_queryset(user: UserType = Depends(get_authenticated_user)): return default_queryset.filter(fromMember__user=user) diff --git a/etebase_fastapi/routers/member.py b/etebase_fastapi/routers/member.py index 41393bf..38beb79 100644 --- a/etebase_fastapi/routers/member.py +++ b/etebase_fastapi/routers/member.py @@ -10,6 +10,7 @@ from .authentication import get_authenticated_user from ..msgpack import MsgpackRoute from ..utils import get_object_or_404, BaseModel, permission_responses, PERMISSIONS_READ, PERMISSIONS_READWRITE from ..stoken_handler import filter_by_stoken_and_limit +from ..db_hack import django_db_cleanup_decorator from .collection import get_collection, verify_collection_admin @@ -19,10 +20,12 @@ MemberQuerySet = QuerySet[models.CollectionMember] default_queryset: MemberQuerySet = models.CollectionMember.objects.all() +@django_db_cleanup_decorator def get_queryset(collection: models.Collection = Depends(get_collection)) -> MemberQuerySet: return default_queryset.filter(collection=collection) +@django_db_cleanup_decorator def get_member(username: str, queryset: MemberQuerySet = Depends(get_queryset)) -> models.CollectionMember: return get_object_or_404(queryset, user__username__iexact=username)