Skip to content

Support file downloads from files table with drive-level access control - #330

Merged
2witstudios merged 2 commits into
masterfrom
claude/fix-channel-attachments-0sgPl
Feb 2, 2026
Merged

2witstudios merged 2 commits into
masterfrom
claude/fix-channel-attachments-0sgPl

Conversation

@2witstudios

@2witstudios 2witstudios commented Feb 2, 2026 •

Copy link
Copy Markdown
Owner

Summary

Extended the file download and view endpoints to support files stored in the files table (channel attachments) in addition to the existing pages table support. Added drive-level access control for files table entries using drive membership verification.

Key Changes

  • Dual file source support: Both endpoints now check for files in the pages table first (FILE-type pages), then fall back to the files table (channel attachments)
  • Drive-level access control: Files from the files table require the user to be a member of the associated drive
  • Service token generation: Uses createDriveServiceToken for files table entries instead of createPageServiceToken
  • Code refactoring: Extracted common file fetching logic into reusable helper functions (fetchAndDownloadFile and fetchAndServeFile)
  • Improved error handling: More detailed error logging with file/page IDs and content hashes for better debugging

Implementation Details

  • Files table entries use storagePath or id as the content hash (fallback to id if storagePath is not set)
  • Drive membership is verified using driveMembers table with both driveId and userId conditions
  • Helper functions handle processor communication, response validation, and header configuration
  • Maintains existing security headers and MIME type handling for dangerous file types
  • Both endpoints maintain backward compatibility with existing FILE-type page downloads

https://claude.ai/code/session_0168Mk63SNuLe88fpVhsueaZ

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling and logging for file download and view operations with better timeout protection and validation.
  • Refactor

    • Consolidated file access logic for both FILE-type pages and drive-based files, reducing code duplication and strengthening access control with membership verification.

… messages

The file view/download endpoints only supported FILE-type pages from the
pages table, but channel attachments are stored in the files table with
contentHash as the ID. This caused attachments to remain stuck in skeleton
loading state since the API returned 404 for file lookups.

Updated both endpoints to:
1. First check if ID matches a FILE-type page (existing behavior)
2. Fall back to files table lookup for channel attachments
3. Verify drive membership for authorization
4. Use createDriveServiceToken for processor authentication

https://claude.ai/code/session_0168Mk63SNuLe88fpVhsueaZ
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Feb 2, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@2witstudios has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 42 minutes and 38 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

These changes refactor the file download and view API routes to consolidate processor interactions into dedicated helper functions, implement dual authentication pathways (FILE-type pages and files table entries), and integrate service token-based authentication for secure processor access.

Changes

Cohort / File(s) Summary
File Download Route
apps/web/src/app/api/files/[id]/download/route.ts
Introduces fetchAndDownloadFile helper for processor communication. Implements dual pathways: FILE-type pages (using page service tokens) and files table entries (using drive service tokens). Validates authorization, derives contentHash, and manages download headers with security considerations. Enhanced error logging for both flows.
File View Route
apps/web/src/app/api/files/[id]/view/route.ts
Introduces fetchAndServeFile helper for processor streaming. Mirrors download route with dual pathways: FILE-type pages (page service tokens) and files table entries (drive service tokens). Validates user permissions, constructs response headers including CSP, and provides granular error handling with improved logging context.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as File Route
    participant DB as Database
    participant Auth as Auth Library
    participant Proc as Processor Service

    Client->>API: GET /files/[id]/download

    alt FILE-Type Page Path
        API->>DB: Look up page by ID
        DB-->>API: Page found (FILE type)
        API->>DB: Verify filePath exists
        API->>Auth: createPageServiceToken(pageId)
        Auth-->>API: Service token
        API->>Proc: GET file (token, contentHash)
        Proc-->>API: File bytes + metadata
    else Files Table Path
        API->>DB: Look up page by ID
        DB-->>API: Not found or non-FILE type
        API->>DB: Query files table
        DB-->>API: File entry
        API->>DB: Verify drive membership
        DB-->>API: Access granted
        API->>Auth: createDriveServiceToken(driveId)
        Auth-->>API: Service token
        API->>Proc: GET file (token, contentHash)
        Proc-->>API: File bytes + metadata
    else Not Found/Unauthorized
        API-->>Client: 404 or 403 error
    end

    API->>API: Assemble response headers
    API-->>Client: Download response with file content
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #170: Directly related refactor of the same file routes to implement service token-based authentication (createPageServiceToken/createDriveServiceToken) and consolidate processor fetch/serve helper logic.

Poem

🐰 Down the rabbit hole of files we go,
With tokens pure and pathways flow,
Pages and tables, both paths unite,
Service tokens shining bright,
Download and view, now sealed up tight! 🔐

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: enabling file downloads from the files table with drive-level access control, which is the core objective of this PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/fix-channel-attachments-0sgPl

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/web/src/app/api/files/`[id]/view/route.ts:
- Around line 25-29: The fetch call that builds fileResponse when requesting
`${PROCESSOR_URL}/cache/${contentHash}/original` lacks a timeout and can hang;
update the request to use an AbortSignal with a timeout (e.g.,
AbortSignal.timeout(30000)) and pass the signal in the fetch options (alongside
the existing headers and Authorization `serviceToken`), and handle the
abort/timeout case in the surrounding `fetchAndServeFile` logic (or where
fileResponse is processed) to return an appropriate error/timeout response
instead of hanging.
🧹 Nitpick comments (3)
apps/web/src/app/api/files/[id]/download/route.ts (2)

105-150: Consider extracting shared logic between view and download routes.

Both routes have nearly identical code for:

  1. Looking up FILE-type pages and verifying permissions
  2. Looking up files and checking drive membership
  3. Creating service tokens

This duplication could be consolidated into shared helper functions to reduce maintenance burden and ensure consistency.

💡 Suggested approach

Consider creating shared helpers in a common location:

// e.g., in `@/lib/file-access.ts`
export async function resolveFileAccess(
  id: string,
  userId: string
): Promise<
  | { type: 'page'; page: Page; contentHash: string }
  | { type: 'file'; file: File; contentHash: string }
  | { error: string; status: number }
> {
  // Shared lookup and authorization logic
}

This would reduce the ~50 lines of duplicated authorization logic in each route to a single function call.


136-142: Same UX issue: using contentHash as filename for files table entries.

As noted in the view route, using the content hash as the download filename provides poor UX. Users will download files named like abc123def456 rather than meaningful names.

apps/web/src/app/api/files/[id]/view/route.ts (1)

145-151: Consider storing original filename in files table to improve downloaded file UX.

When serving files from the files table, users download files with hash-based names like abc123def456. The files table currently lacks an original filename field. Consider adding originalName column to the schema to preserve and serve meaningful filenames, or derive names from related message attachments.

Comment thread apps/web/src/app/api/files/[id]/view/route.ts
- Add 30s timeout to fetch call in view/route.ts to prevent hanging
- Add proper timeout error handling (504 status) to both view and download routes
- Accept optional `filename` query parameter for meaningful download filenames
- Update ChannelView to pass original filename when viewing/downloading attachments

This improves UX by ensuring users download files with their original names
(e.g., "document.pdf") instead of content hashes.

https://claude.ai/code/session_0168Mk63SNuLe88fpVhsueaZ
@2witstudios
2witstudios merged commit 9bfeea6 into master Feb 2, 2026
3 checks passed
@2witstudios
2witstudios deleted the claude/fix-channel-attachments-0sgPl branch February 6, 2026 01:27
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.

2 participants