Archived
- Backend: Django 5 + DRF with accounts, documents, collections, and reading apps - Custom User model with email-based auth, JWT via SimpleJWT - Full CRUD viewsets with ModelSerializer + DRF routers - pytest, Ruff, drf-spectacular (OpenAPI), whitenoise - Dockerfile for production deployment - Frontend: React 18 + TypeScript + Vite - Lazy-loaded routes with ProtectedRoute/PublicRoute guards - Auth context with useReducer, token refresh interceptor - Pages: Login, Register, Library, Document Detail, Reader, Collections, Settings - Dark theme, responsive grid layout, Vite proxy to Django backend - Mobile: Expo SDK 51 + React Native + Expo Router - File-based routing with login, register, and library screens - AsyncStorage for token persistence, token refresh interceptor - Shared API types via @cloud-reader/shared workspace package - Shared: TypeScript types (API responses, auth, documents, etc.) - CI/CD: 3 independent GitHub Actions pipelines (backend, frontend, mobile)
35 lines
1.3 KiB
Python
35 lines
1.3 KiB
Python
from rest_framework import permissions, viewsets
|
|
|
|
from .models import Document
|
|
from .serializers import DocumentDetailSerializer, DocumentListSerializer, DocumentUploadSerializer
|
|
|
|
|
|
class IsOwnerOrPublic(permissions.BasePermission):
|
|
"""Allow access if user is owner or the document is public."""
|
|
|
|
def has_object_permission(self, request, view, obj: Document) -> bool:
|
|
if request.method in permissions.SAFE_METHODS:
|
|
return obj.is_public or obj.owner == request.user
|
|
return obj.owner == request.user
|
|
|
|
|
|
class DocumentViewSet(viewsets.ModelViewSet):
|
|
"""CRUD for documents with owner-scoping."""
|
|
permission_classes = [permissions.IsAuthenticated, IsOwnerOrPublic]
|
|
|
|
def get_serializer_class(self):
|
|
if self.action == "create":
|
|
return DocumentUploadSerializer
|
|
if self.action in ("retrieve", "update", "partial_update"):
|
|
return DocumentDetailSerializer
|
|
return DocumentListSerializer
|
|
|
|
def get_queryset(self):
|
|
user = self.request.user
|
|
qs = Document.objects.select_related("owner")
|
|
if self.action == "list":
|
|
return qs.filter(owner=user) | qs.filter(is_public=True)
|
|
return qs
|
|
|
|
def perform_create(self, serializer):
|
|
serializer.save(owner=self.request.user) |