Files
fourge-portal/docs/file-sharing.md
T
Krao Hasanee 0b4705311b Session 2026-05-30: task detail page overhaul
- New TaskDetail replaces /tasks/:id (was v2 at /requests/:id/v2)
- Overview tab: R00 request info, Requested By/Date/Sign Count inline row, Notes, Sign Family, files, amendments
- Revisions tab: R01+ from submissions, newest first, same layout as overview, per-entry Amend button
- Comments tab: single-line input, post on Enter, delete own comments, Supabase task_comments table
- Folder tab: placeholder for file sharing
- Tab badges showing revision/comment counts
- Amend Request modal: drag-drop file zone, popupOverlayStyle/Surface, Save+Cancel buttons
- Request Revision modal for clients on approved/invoiced/paid tasks
- JSZip download-all with progress popup for submission files
- Upload progress popup for Add Task and amend file uploads
- FileAttachment drop zone: 8px radius, transparent bg, label style fix (no all-caps override)
- PageLoader on task detail load
- task_comments migration with RLS policies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 22:44:57 -04:00

4.6 KiB

File Sharing — How It Works

Overview

File sharing proxies all file operations through a Vercel serverless function (/api/filebrowser) to a self-hosted FileBrowser Quantum instance. The frontend never speaks directly to FBQ. Auth is validated server-side via Supabase on every request.


Infrastructure

Component Location
FBQ instance https://fourgebranding.krao.us (internal: 192.168.2.200:8082)
API proxy api/filebrowser.js (Vercel function)
Frontend src/pages/FileSharing.jsx

Auth Flow

  1. Frontend gets the current Supabase session access token (supabase.auth.getSession()).
  2. Every request to /api/filebrowser sends the token as both Authorization: Bearer <token> header and sb_access_token query param.
  3. The API function validates the token against Supabase and loads the caller's profiles row.
  4. If valid, the function uses its own server-side FBQ token (FILEBROWSER_TOKEN env var) to talk to FBQ — the frontend never sees the FBQ token.
  5. The FBQ token is a long-lived API token. If it expires or returns 401, the function falls back to admin username/password login (FILEBROWSER_ADMIN_USER / FILEBROWSER_ADMIN_PASS) to get a fresh token, cached in-memory for 30 minutes.

No JWT auth from the frontend to FBQ. That feature was removed — portal users authenticate via Supabase only.


Role-Based Access Control

The API function maps each portal role to a different FBQ root path:

Portal role FBQ root Notes
team FILEBROWSER_TEAM_ROOT (default /fourgebranding) Full access, sees everything under team root
client FILEBROWSER_CLIENT_ROOT/{company-name} (default /fourgebranding/Clients/{name}) Scoped to their company folder; multi-company clients get a virtual root listing their companies
external FILEBROWSER_SUBS_ROOT/{their-name} + assigned project folders Personal folder + read access to Projects/{project} folders they are members of via project_members table

Virtual directories (e.g. the multi-company root for clients, the Projects/ node for externals) are synthesised by the API and never hit FBQ.

Path traversal (..) is blocked at normalizePath() — throws before any FBQ call.


API Actions (/api/filebrowser?action=...)

Action Method What it does
list GET List folder contents; returns { entries, path, canGoUp, ... }
download GET Returns a signed FBQ download URL + token for direct browser download
download-blob GET Proxies the file bytes through Vercel (used for ZIP building)
upload-token POST Returns FBQ token + URL for direct upload from browser to FBQ
mkdir POST Creates a new folder
delete DELETE Deletes one file/folder
rename POST Renames a file/folder in place
move POST Moves or copies items; mode: 'copy' or mode: 'move'
archive-move POST Merge-moves a folder into a destination (merges contents if dest already exists)

Frontend (FileSharing.jsx)

All FBQ calls go through the fbqProxy() helper which injects the current Supabase access token on every call.

  • Single file download: download action → signed URL → hidden <a> click.
  • Multi-file / folder download: download-blob streams each file, then JSZip builds a ZIP client-side.
  • Upload: upload-token gets a short-lived FBQ token, then browser POSTs binary directly to ${fbqUrl}/api/resources?auth=${token}.
  • Root path per user is derived by rootPath() in FileSharing.jsx — team/external get /, clients with one company get /Clients/{name}, clients with multiple get /Clients.
  • Pinned folders are persisted in localStorage keyed by fbq_pins:{userId}.
  • Nav tree lazily loads folder children into a navCache ref; does not re-fetch already-loaded paths.
  • Drag-and-drop upload uses webkitGetAsEntry to walk dropped folder trees, creates missing directories first, then uploads files.
  • Context menu (right-click): Open, Download, Pin/Unpin, Copy, Cut, Paste here, Delete. Delete in context menu is restricted to role === 'team' (accessScope.canManage).

Required Env Vars

FILEBROWSER_URL=https://fourgebranding.krao.us
FILEBROWSER_TOKEN=<long-lived FBQ API token>
FILEBROWSER_ADMIN_USER=admin
FILEBROWSER_ADMIN_PASS=<password>
FILEBROWSER_TEAM_ROOT=/fourgebranding
FILEBROWSER_CLIENT_ROOT=/fourgebranding/Clients
FILEBROWSER_SUBS_ROOT=/fourgebranding/team
FILEBROWSER_CLIENTS_ROOT=/fourgebranding/Clients

FILEBROWSER_TOKEN is the primary auth method. ADMIN_USER/ADMIN_PASS are only used for auto-refresh when the token expires.