Skip to content

feat(files): persist uploaded files and associate them with conversations - #354

Open
Hustler490 wants to merge 1 commit into
AyinkxLab:mainfrom
Hustler490:feat/42-persist-uploaded-files
Open

Hustler490 wants to merge 1 commit into
AyinkxLab:mainfrom
Hustler490:feat/42-persist-uploaded-files

Conversation

@Hustler490

Copy link
Copy Markdown

Closes #42

What

Uploaded files are now persisted on disk and tracked in a files table, so the same file can be downloaded, attached to a conversation, and re-analyzed later without re-uploading.

Changes

  • app/models/stored_file.py - StoredFile (files table): id, workspace_id, user_id, original_name, stored_name, size, content_type, created_at (+ conversation_id for attachment). The stored name is random and never derived from user input.
  • app/files/ - new blueprint with:
    • POST /files upload (extension allowlist and size cap reused from /tools/analyze; optional workspace_id gated on active membership),
    • GET /files list (own files only),
    • GET /files/<id> metadata, GET /files/<id>/download,
    • POST /files/<id>/attach (own conversations only; null detaches),
    • POST /files/<id>/analyze (re-analyzes the stored bytes).
      Every read/download/attach/analyze is owner-scoped - another user gets a 404, never the file.
  • app/config.py - UPLOAD_FOLDER (configurable) and UPLOAD_MAX_BYTES.
  • Migration - creates the files table. It also merges the three pre-existing Alembic heads, which previously made flask db upgrade fail with "Multiple head revisions"; tests/test_migrations.py::test_head_is_latest_revision now asserts a single head.

Acceptance criteria

  • New files table with the required columns.
  • Uploads stored under UPLOAD_FOLDER with random stored names and validated extensions.
  • Files can be attached to a conversation and re-analyzed later.
  • File size/type checks reuse the /tools/analyze validation.
  • Tests cover upload, retrieval, download, and owner-only access.

Validation

  • pytest tests/test_files.py -> 8 passed.
  • ruff check and black --check clean on the changed files.
  • Full suite: only test_migrations.py::test_conversation_shares_table_upgraded fails, which is a pre-existing stale assertion (it expects the old conversation_shares columns while the migration/model add expires_at, token_hash, permission) and is unrelated to this change.

…ions

Add a files table plus upload/list/retrieve/download/attach/analyze routes so an uploaded file is stored once on disk and can be attached to a conversation and re-analyzed later without re-uploading.

Uploads reuse the /tools/analyze extension allowlist and size cap, are written under UPLOAD_FOLDER with a random stored name, and every read/download/attach/analyze is scoped to the owner (another user gets 404). The migration also merges the three pre-existing Alembic heads, which previously made \lask db upgrade\ fail outright, and the head test now asserts a single head.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Persist uploaded files and associate with conversations

1 participant