Large uncommitted body of work accumulated across sessions on this branch -- committing as a checkpoint so it's tracked and future worktree-isolated agents see the real codebase instead of a stale ancestor commit. Covers the management app's dedicated Tailwind theme and templates, the club onboarding requirement/signup workflow (club/services/onboarding.py, requirement/status models, sign-up dashboard), fee/status auto-activation decoupling, referee management, and the new events calendar grid service layer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
40 lines
2.2 KiB
Python
40 lines
2.2 KiB
Python
"""Private file storage -- for uploads that must never be reachable by a guessable
|
|
URL, unlike everything in MEDIA_ROOT (club logos, sponsor logos, team photos, news
|
|
photos), which is deliberately public and served straight off disk by Caddy in
|
|
production (see deploy/caddy/Caddyfile's `/media/*` block -- it reads from the same
|
|
shared volume as Django's own MEDIA_ROOT, so anything placed there is public
|
|
regardless of what a Django view's own permission check says).
|
|
|
|
`PRIVATE_MEDIA_ROOT` is a completely separate directory, on a separate Docker volume
|
|
(see compose.yaml) that only the `web` container mounts -- Caddy never sees it. The
|
|
only way to read a file stored here is through an authenticated Django view that
|
|
streams it explicitly (see management.views.MemberRequirementDocumentView, the one
|
|
current use: MemberRequirementStatus.document, e.g. an uploaded medical certificate).
|
|
|
|
Deliberately local disk only, not S3, regardless of AWS_STORAGE_BUCKET_NAME -- unlike
|
|
the default storage's public/private split (which follows whether a bucket is
|
|
configured), this one is a fixed choice: local disk today, revisit if/when
|
|
multi-server deployment needs it (see DEPLOYMENT.md's own local-disk caveat for
|
|
MEDIA_ROOT -- the same one applies here until then).
|
|
"""
|
|
|
|
from django.conf import settings
|
|
from django.core.files.storage import FileSystemStorage
|
|
|
|
|
|
class PrivateStorage(FileSystemStorage):
|
|
"""FileSystemStorage with .url() permanently disabled.
|
|
|
|
Passing base_url=None to the parent class does NOT do this -- FileSystemStorage
|
|
treats None as "unset" and falls back to settings.MEDIA_URL, so it would happily
|
|
hand back a `/media/...` link for a file that was never written under MEDIA_ROOT
|
|
in the first place (wrong and broken, but not obviously so -- it looks like a
|
|
normal URL until something tries to fetch it). Overriding .url() to always raise
|
|
is the only way to make "this storage has no URL" fail loudly instead."""
|
|
|
|
def url(self, name):
|
|
raise ValueError("PrivateStorage has no URL -- read a file through an authenticated view instead, e.g. management.views.MemberRequirementDocumentView.")
|
|
|
|
|
|
private_storage = PrivateStorage(location=str(settings.PRIVATE_MEDIA_ROOT))
|