Files
hub/.gral/prompt.md
T
2026-10-14 02:01:34 -05:00

3.9 KiB

The core break

Drives.vue builds the right target path and passes it to the upload helper as a third argument:

const path = dirPath ? `${dirPath}/${file.name}` : file.name;
await backend.uploadDriveFile(drive.name, file, path);

The backend only accepts uploads at POST /files/<drive>/<path:filename> (upload_file(user_id, drive_name, filename, stream, mime_type)), i.e. the composite name must be in the URL. Docs describe the helper as 2-arg (uploadDriveFile(driveName, file)) POSTing to /files/<drive>, which has no route. So the documented contract and the view disagree, and every upload (root or folder) fails. The view is right; the docs/wrapper are wrong. This is the same failure the doc already lists under "Known issues," but it's written as a bug report rather than as the correct interface.

Everything else in Drives.vue matches the documented REST API and shapes:

  • getDrives() → {id, name} ✓
  • getDriveFiles(name) → {id, name, size, mime, created}, consumed by buildTree ✓
  • deleteDriveFile(name, path) ✓
  • driveFileUrl(name, path) for both the <a download> and window.open ✓

So the view speaks the right API. The fix belongs in backend.js (accept the path, multipart-POST to /files/<drive>/<path>), and the "Frontend interface" section should document the 3-arg signature.

Docs vs. backend (drives.py)

  1. accessed_at claim is false. Docs: "Every resolve (download, metadata, delete) stamps accessed_at." Only resolve_file stamps it. get_metadata and delete_file never touch it.
  2. DELETE return value is wrong. Docs: returns {fileId}. delete_file returns the removed absolute disk path (abs_path).
  3. resolve_file returns the wrong second value. Docs say it serves bytes "with their stored mime type" and the docstring says it returns (path, mime). It actually returns (abs_path, file.id) — the file id, not the mime. So mime cannot come from resolve_file; the route must look it up. Fix the docstring too.
  4. Id- vs name-addressing is undocumented. The route table presents download/delete/metadata as drive+filename-addressed, but the functions are id-addressed: get_metadata(file_id) and delete_file(file_id). Only upload_file takes drive+filename. The docs should note the extra filename→id resolution step.
  5. Ownership checks don't match the claim. Docs: "Ownership ... is checked before any disk access." resolve_file checks it (badly — already noted for the None deref). But delete_file and get_metadata perform no ownership check at all; both work off a bare file_id. If the route doesn't guard them, that's a real authorization gap, and the doc overstates the protection.
  6. Listing routes aren't in drives.py. The table lists GET /files and GET /files/<drive> as backend routes, but no list_drives/list_files exists here — the doc says "logic in backend/src/drives.py," which is therefore inaccurate for those two.
  7. Minor identity mismatch in the doc's own text. It describes DriveFile(id char(64) pk ...) while _generate_file_id() is secrets.token_hex(8) → 16 hex chars. Harmless but the doc contradicts itself.

The already-listed "Known issues" (collision check querying Drive instead of DriveFile; resolve_file dereferencing a None drive) are accurate and match the code.

Suggested ordering

  • Fix backend.js upload (path arg + /files/<drive>/<path> POST); update the doc's frontend section to the 3-arg signature.
  • Correct the doc's accessed_at, DELETE-return, and resolve_file-return claims.
  • Decide whether delete_file/get_metadata need ownership checks (they currently have none) and document id-vs-name addressing accordingly.

Task

Apply the fixes documented in the prompt above. This task is bounded on the files: docs/drives.md, frontend/src/views/Drives.vue, backend/src/drives.py. You can only access those files, any read or exploration in another location is forbidden.