feat(file): conceal file resource existence from other users
- feat: cross-user file access returns not-found instead of permission-denied - fix: repository delete now only affects active rows and returns ErrNotFound when no row changes; repeated deletes yield not-found - feat: parent directory operations (list, upload, create-dir, move) conceal ownership of other user's directories - test: update handler, service, repository, and integration tests to assert not-found behavior for cross-user and missing file operations
This commit is contained in:
@@ -588,6 +588,16 @@ func TestFileHandler_Delete(t *testing.T) {
|
||||
t.Errorf("status = %d, want %d; body = %s", rec.Code, http.StatusNoContent, rec.Body.String())
|
||||
}
|
||||
|
||||
// Repeated deletes return not found.
|
||||
req = httptest.NewRequest(http.MethodDelete, "/api/v1/files/"+uploaded.ID, nil)
|
||||
req.Header.Set(testUserIDHeader, "user1")
|
||||
rec = httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusNotFound {
|
||||
t.Errorf("repeated delete status = %d, want %d; body = %s", rec.Code, http.StatusNotFound, rec.Body.String())
|
||||
}
|
||||
|
||||
// Verify gone.
|
||||
req = httptest.NewRequest(http.MethodGet, "/api/v1/files/"+uploaded.ID, nil)
|
||||
req.Header.Set(testUserIDHeader, "user1")
|
||||
@@ -599,7 +609,20 @@ func TestFileHandler_Delete(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileHandler_ForbiddenAccess(t *testing.T) {
|
||||
func TestFileHandler_DeleteMissingReturnsNotFound(t *testing.T) {
|
||||
r := setupFileRouter(t)
|
||||
|
||||
req := httptest.NewRequest(http.MethodDelete, "/api/v1/files/missing-file", nil)
|
||||
req.Header.Set(testUserIDHeader, "user1")
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusNotFound {
|
||||
t.Errorf("status = %d, want %d; body = %s", rec.Code, http.StatusNotFound, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileHandler_CrossUserAccessReturnsNotFound(t *testing.T) {
|
||||
r := setupFileRouter(t)
|
||||
|
||||
// Upload as user1.
|
||||
@@ -624,7 +647,13 @@ func TestFileHandler_ForbiddenAccess(t *testing.T) {
|
||||
rec = httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusForbidden {
|
||||
t.Errorf("status = %d, want %d", rec.Code, http.StatusForbidden)
|
||||
if rec.Code != http.StatusNotFound {
|
||||
t.Errorf("status = %d, want %d", rec.Code, http.StatusNotFound)
|
||||
}
|
||||
if !strings.Contains(rec.Body.String(), "file not found") {
|
||||
t.Errorf("body = %s, want file not found message", rec.Body.String())
|
||||
}
|
||||
if strings.Contains(rec.Body.String(), "access denied") {
|
||||
t.Errorf("body leaks authorization result: %s", rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user