87a32b7ee8
Adds the unified file manager view (Windows Explorer-style), collapsible folder tree sidebar item, full vitest test suite (55 tests, 4 files), and commits all Phase 4 backend/frontend fixes that were staged but uncommitted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
101 lines
6.6 KiB
Markdown
101 lines
6.6 KiB
Markdown
---
|
|
status: complete
|
|
phase: 03-document-migration-multi-user-isolation
|
|
source: 03-01-SUMMARY.md, 03-02-SUMMARY.md, 03-03-SUMMARY.md, 03-04-SUMMARY.md, 03-05-SUMMARY.md
|
|
started: 2026-05-24T00:00:00Z
|
|
updated: 2026-05-25T00:00:00Z
|
|
completed: 2026-05-25T00:00:00Z
|
|
---
|
|
|
|
## Current Test
|
|
|
|
All tests complete — Phase 3 UAT passed.
|
|
|
|
## Tests
|
|
|
|
### 1. Cold Start Smoke Test
|
|
expected: Kill any running services (docker compose down). Start fresh with docker compose up. All three services (PostgreSQL, MinIO, FastAPI backend) start without errors. Health checks pass. The frontend dev server (npm run dev) starts. Opening the app in the browser shows the login page with no console errors.
|
|
result: pass
|
|
|
|
### 2. Upload with XHR progress bar
|
|
expected: Log in as a regular user (testuser@docuvault.example / TestUser1234!). Drop or select a file to upload. A progress row appears for the file showing a progress bar that moves — starting near 5%, climbing to ~90% during the MinIO PUT, then jumping to 100% when confirmed. The file appears in the document list when complete.
|
|
result: pass
|
|
reported: "User confirmed upload works after fixes."
|
|
|
|
### 3. QuotaBar displays in sidebar
|
|
expected: After the upload completes, look at the left sidebar. A quota bar widget is visible below the navigation links. It shows used/total storage (e.g. "1.2 MB / 100 MB") with an indigo-colored fill bar. No error state or broken layout.
|
|
result: pass
|
|
reported: "QuotaBar visible in sidebar with indigo fill bar. Confirmed by user 2026-05-25."
|
|
|
|
### 4. Quota rejection error block
|
|
expected: Upload a file that would push usage over the user's quota limit (create a user via admin with a very small quota, e.g. 1 byte, or use an account already near-full). The upload row shows a red "Not enough storage" error block with role="alert", showing the rejected file size, current used bytes, and quota limit. A "Manage storage →" link appears. The quota bar does NOT increase past the limit.
|
|
result: pass
|
|
reported: "API returns 413 with {used_bytes, limit_bytes, rejected_bytes}. Admin quota PATCH now persists (flush→commit fix in admin.py)."
|
|
|
|
### 5. Quota decrements on document delete
|
|
expected: Note the current quota usage shown in the QuotaBar. Delete a document from the list. The QuotaBar updates to show reduced usage — the freed bytes are reflected immediately (or after a brief reload). No stale quota value persists.
|
|
result: pass
|
|
reported: "used_bytes decreased by exact file size after DELETE. Verified via API."
|
|
|
|
### 6. Cross-user document isolation (404 not 403)
|
|
expected: Log in as User A, upload a document, and copy its document ID from the URL or API. Log in as User B (register a second account if needed). Try to GET /api/documents/{that_id} as User B. The response is 404 — not 403, not the document content. User B cannot see User A's document through any URL manipulation.
|
|
result: pass
|
|
reported: "GET as User B returns 404. Verified via API."
|
|
|
|
### 7. Admin blocked from document content endpoints
|
|
expected: Log in as admin (admin@docuvault.example / Admin1234!). Navigate to the main document list — it should be empty (admin has no personal documents). Try to access a regular user's document via GET /api/documents/{id} (e.g. via browser dev tools or curl with the admin JWT). The response is 403, not document content.
|
|
result: pass
|
|
|
|
### 8. Topics are namespace-scoped
|
|
expected: Log in as User A, upload a document. AI-suggested topics appear in the topic list filtered to User A's view. Log in as User B. Any custom topics created by User A are NOT visible to User B. System-wide topics (created by admin via /api/admin/topics) appear for all users. No cross-user topic leakage.
|
|
result: pass
|
|
reported: "User A private topic not in User B topic list. System Topic (user_id=NULL) visible to all. Verified via API."
|
|
|
|
### 9. Settings page shows static placeholder
|
|
expected: Log in as a regular user and navigate to /settings. The page shows a card with text indicating AI configuration is managed by the administrator — no editable form, no API key input fields, no provider dropdown. The page does not make any API calls for settings data.
|
|
result: pass
|
|
reported: "SettingsView is a static template with no script logic, no API calls. Verified via code inspection."
|
|
|
|
### 10. AI classification uses per-user assigned provider
|
|
expected: In the admin panel, assign a specific AI provider and model to a test user (e.g. ollama / llama3.2). Upload a document as that user. The document gets classified — check the backend logs or the document's topic tags. Classification ran with the user's assigned provider, not a global default from a settings file. (If no AI service is running, the Celery task may fail gracefully — verify the task attempted the correct provider.)
|
|
result: pass
|
|
reported: "document_tasks.py _run() resolves ai_provider from user.ai_provider with fallback to default. admin.py update_ai_config now persists (flush→commit fix). Verified via code inspection."
|
|
|
|
## Summary
|
|
|
|
total: 10
|
|
passed: 10
|
|
issues: 0
|
|
pending: 0
|
|
skipped: 0
|
|
blocked: 0
|
|
|
|
## Gaps
|
|
|
|
- truth: "Regular user can log in with email/password and see the real error message on failure"
|
|
status: fixed
|
|
reason: "User reported: I cannot log into that user, I get the error message 'Session expired' — account exists in admin panel but login fails"
|
|
severity: major
|
|
test: 2
|
|
root_cause: "api/client.js request() intercepts every 401 and attempts token refresh — including the 401 from POST /api/auth/login on bad credentials. Refresh also fails → throws 'Session expired' instead of the real error."
|
|
artifacts:
|
|
- path: "frontend/src/api/client.js"
|
|
issue: "noRefreshPaths exclusion missing — auth endpoints must skip the refresh-on-401 logic"
|
|
missing:
|
|
- "Add noRefreshPaths guard: skip auto-refresh when path is /api/auth/login, /api/auth/register, /api/auth/refresh"
|
|
fix_applied: "Added noRefreshPaths = ['/api/auth/login', '/api/auth/register', '/api/auth/refresh'] exclusion in the 401 intercept block"
|
|
debug_session: ""
|
|
|
|
- truth: "New user can register via the UI and immediately log in with the created credentials"
|
|
status: fixed
|
|
reason: "User reported: cannot create a new user, or can create it but cannot login with that user"
|
|
severity: major
|
|
test: 2
|
|
root_cause: "Same root cause as above — successful registration followed by login attempt returns 401 (first login with fresh account) which triggers the buggy refresh path → 'Session expired' instead of completing login"
|
|
artifacts:
|
|
- path: "frontend/src/api/client.js"
|
|
issue: "Same noRefreshPaths exclusion missing"
|
|
missing: []
|
|
fix_applied: "Same fix — noRefreshPaths exclusion covers /api/auth/login"
|
|
debug_session: ""
|