Skip to content

file_storage: StoredFile is not tenant scoped #361

Closed as not planned
Closed as not planned

Description

@antosubash

Summary

file_storage.StoredFile doesn't use MultiTenantMixin, so on a multi-tenant host any file id is readable and reusable across every tenant. A module that stores a StoredFile id in a MultiTenantMixin-protected row (e.g. a media reference on a tenant-scoped record) inherits this hole: tenant A can reference — and, depending on the endpoint, read — a file id that belongs to tenant B, because the file table itself never filters.

Observed

file_storage/models.py:18:

class StoredFile(Base, AuditMixin, SoftDeleteMixin, table=True):
    ...

MultiTenantMixin is absent — compare to users/models/user.py, which does have a nullable tenant_id column even without the mixin. StoredFile has neither.

Minimal reproduction (SQLite), showing the table participates in none of the framework's tenant filtering because it isn't a MultiTenantMixin subclass at all:

from simple_module_db.mixins import MultiTenantMixin
from file_storage.models import StoredFile

assert not issubclass(StoredFile, MultiTenantMixin)
print("StoredFile carries no tenant_id column; any file id is valid under any current_tenant_id")

This mirrors the read-path gap already measured for mapper-scoped tables (see the sibling read/flush issues from this batch): even once those are fixed, file_storage cannot benefit, because there is no tenant_id column for a loader-criteria filter to attach to in the first place.

Expected

StoredFile isolates files per tenant the same way a MultiTenantMixin table isolates any other row: upload under tenant A is invisible to (and cannot be referenced successfully by) tenant B.

Why a module cannot work around it

records (and any module storing media references) does not own file_storage's table or upload/serve endpoints; it can validate that a referenced file id exists, but has no way to also assert it belongs to the caller's tenant, because the file row carries no tenant information to check against.

Proposed API

MultiTenantMixin on file_storage.StoredFile, with the storage key/path also tenant-scoped so two tenants' otherwise-identical filenames don't collide on the same backend key.

Context

Found while making the records module (antosubash/smpy_modules#37) multi-tenant; design doc docs/plans/2026-09-23-records-multitenancy.md there.

Activity

  1. antosubash commented on Oct 1, 2026

    @antosubash
    OwnerAuthor

    Closing: filed before #370 (fail-closed tenancy + tenants module) landed, so the premise is stale. Module tenancy adoption is being re-tracked with fresh per-module issues in the post-#370 format (see #371–#377); any remaining gap here gets a new issue and lands in the tenancy adoption PR stack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions