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 bybuildTree✓deleteDriveFile(name, path)✓driveFileUrl(name, path)for both the<a download>andwindow.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)
accessed_atclaim is false. Docs: "Every resolve (download, metadata, delete) stampsaccessed_at." Onlyresolve_filestamps it.get_metadataanddelete_filenever touch it.- DELETE return value is wrong. Docs: returns
{fileId}.delete_filereturns the removed absolute disk path (abs_path). resolve_filereturns 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 fromresolve_file; the route must look it up. Fix the docstring too.- 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)anddelete_file(file_id). Onlyupload_filetakes drive+filename. The docs should note the extra filename→id resolution step. - Ownership checks don't match the claim. Docs: "Ownership ... is checked before any disk access."
resolve_filechecks it (badly — already noted for theNonederef). Butdelete_fileandget_metadataperform no ownership check at all; both work off a barefile_id. If the route doesn't guard them, that's a real authorization gap, and the doc overstates the protection. - Listing routes aren't in
drives.py. The table listsGET /filesandGET /files/<drive>as backend routes, but nolist_drives/list_filesexists here — the doc says "logic inbackend/src/drives.py," which is therefore inaccurate for those two. - Minor identity mismatch in the doc's own text. It describes
DriveFile(id char(64) pk ...)while_generate_file_id()issecrets.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.jsupload (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, andresolve_file-return claims. - Decide whether
delete_file/get_metadataneed 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.