fix(projects): keep paginated flow visibility scoped to current user#12484
fix(projects): keep paginated flow visibility scoped to current user#12484haimingZZ wants to merge 6 commits intolangflow-ai:mainfrom
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThe changes add user-specific filtering to project flow pagination in the API layer, add a unit test to verify the filtering behavior, and update the Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes 🚥 Pre-merge checks | ✅ 5 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/backend/tests/unit/api/v1/test_projects.py`:
- Around line 1548-1550: The test function
test_read_project_paginated_flows_match_current_user_visibility has an unused
fixture parameter active_user; remove active_user from the async def signature
so the test only accepts (self, client: AsyncClient, logged_in_headers,
basic_case) and update any references if present—this eliminates the unused
fixture warning while leaving the test's authentication via logged_in_headers
and the uuid4-generated other-user flow intact.
In `@src/lfx/src/lfx/_assets/component_index.json`:
- Line 73434: The component metadata extractor is emitting an invalid dependency
"google==2.8.0"; update the dependency resolution logic (functions like
extract_dependencies(), resolve_import_to_distribution(), and
parse_imports()/map_import_to_dist()) so imports under the google namespace map
to their real distributions (e.g., google.auth -> google-auth,
google.cloud.bigquery -> google-cloud-bigquery) instead of a standalone
"google", and validate resolved package versions against PyPI (use or add a
helper such as validate_version_on_pypi() or fallback_to_known_versions()) so
invalid versions are replaced with a known available version or omitted;
add/update unit tests for imports like from google.auth import ... to assert the
correct distribution and version are emitted rather than "google==2.8.0".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b059f858-2203-4bc8-a242-d7feed0fd40a
📒 Files selected for processing (3)
src/backend/base/langflow/api/v1/projects.pysrc/backend/tests/unit/api/v1/test_projects.pysrc/lfx/src/lfx/_assets/component_index.json
| async def test_read_project_paginated_flows_match_current_user_visibility( | ||
| self, client: AsyncClient, logged_in_headers, basic_case, active_user | ||
| ): |
There was a problem hiding this comment.
Remove unused active_user argument.
The static analysis correctly identifies that active_user is unused. The test authenticates via logged_in_headers and uses a random uuid4() for the other user's flow, so this fixture isn't needed.
🔧 Proposed fix
async def test_read_project_paginated_flows_match_current_user_visibility(
- self, client: AsyncClient, logged_in_headers, basic_case, active_user
+ self, client: AsyncClient, logged_in_headers, basic_case
):🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)
[failure] 1549-1549: Ruff (ARG002)
src/backend/tests/unit/api/v1/test_projects.py:1549:67: ARG002 Unused method argument: active_user
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/tests/unit/api/v1/test_projects.py` around lines 1548 - 1550, The
test function test_read_project_paginated_flows_match_current_user_visibility
has an unused fixture parameter active_user; remove active_user from the async
def signature so the test only accepts (self, client: AsyncClient,
logged_in_headers, basic_case) and update any references if present—this
eliminates the unused fixture warning while leaving the test's authentication
via logged_in_headers and the uuid4-generated other-user flow intact.
| { | ||
| "name": "google", | ||
| "version": "2.30.0" | ||
| "version": "2.8.0" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== All google versions in component_index.json =="
rg -n '"name":\s*"google"|"version":\s*"[0-9]+\.[0-9]+\.[0-9]+"' src/lfx/src/lfx/_assets/component_index.json -A1 -B1
echo
echo "== Find canonical dependency files (lock/pyproject/requirements) =="
fd -HI 'pyproject.toml|poetry.lock|requirements.*\.txt|Pipfile|Pipfile.lock|uv.lock'
echo
echo "== Any explicit google pins in repo =="
rg -nP '(^|\b)(google)\s*([<>=!~]=?)\s*[0-9]+\.[0-9]+\.[0-9]|\bgoogle==[0-9]+\.[0-9]+\.[0-9]' \
--iglob '*pyproject.toml' --iglob '*requirements*.txt' --iglob '*Pipfile*' --iglob '*lock*' || true
echo
echo "== Scripts/utilities that generate component_index.json =="
rg -n 'component_index\.json|sha256|build.*index|generate.*index'Repository: langflow-ai/langflow
Length of output: 50378
🏁 Script executed:
# Find all dependency/lock files in repo
find . -maxdepth 3 -type f \( -name "pyproject.toml" -o -name "requirements*.txt" -o -name "poetry.lock" -o -name "uv.lock" -o -name "Pipfile*" \) 2>/dev/null | head -20Repository: langflow-ai/langflow
Length of output: 115
🏁 Script executed:
# Search for scripts/code that generate or reference component_index.json
rg -l "component_index\.json" --type py --type sh | head -10Repository: langflow-ai/langflow
Length of output: 221
🏁 Script executed:
# Look for google package version specifications in canonical files
find . -maxdepth 3 -type f \( -name "pyproject.toml" -o -name "requirements*.txt" \) -exec grep -l "google" {} \; 2>/dev/null | head -10Repository: langflow-ai/langflow
Length of output: 80
🏁 Script executed:
# Read the build script to understand how component_index.json is generated
cat scripts/build_component_index.py | head -100Repository: langflow-ai/langflow
Length of output: 3612
🏁 Script executed:
# Check pyproject.toml for google version specification
rg "google" ./pyproject.toml -B2 -A2 | head -30Repository: langflow-ai/langflow
Length of output: 523
🏁 Script executed:
# Check src/lfx/pyproject.toml for google version
rg "google" ./src/lfx/pyproject.toml -B2 -A2 | head -30Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check uv.lock for the actual pinned google version
rg "name = \"google\"" ./uv.lock -A5 | head -20Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check uv.lock for google with a broader search
grep -n "google" ./uv.lock | grep -i "^.*name.*google\|^.*version.*2\.8" | head -20Repository: langflow-ai/langflow
Length of output: 862
🏁 Script executed:
# Look at the actual structure in uv.lock around google package
rg '\[\[package\]\]' ./uv.lock -A20 | grep -A15 'name = "google"' | head -40Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check what the current version of google is (pinned version in uv.lock)
rg 'name = "google"' ./uv.lock -A10 | head -20Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Search for where 'google' as a package (not google-*) appears in uv.lock
rg '^name = "google"$' ./uv.lock -A5 -B2Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check if there's a git diff or recent changes showing what changed in component_index.json
git log --oneline -20 -- src/lfx/src/lfx/_assets/component_index.json 2>/dev/null | head -10Repository: langflow-ai/langflow
Length of output: 107
🏁 Script executed:
# Search the codebase for where google==2.8.0 might be coming from (component requirements)
rg -r '"google".*"2\.8\.0"' src/lfx/src/lfx/components --type json | head -10Repository: langflow-ai/langflow
Length of output: 2198
🏁 Script executed:
# Check if google is imported/required by any components
rg "google.*2\.8" src/lfx/src/lfx/components --type py -B2 -A2 | head -30Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Look at more of the build_component_index.py script to see how dependencies are extracted
tail -n +100 scripts/build_component_index.py | head -150Repository: langflow-ai/langflow
Length of output: 3581
🏁 Script executed:
# Check what components might have google as a dependency
rg "google" src/lfx/src/lfx/components --type py -l | head -20Repository: langflow-ai/langflow
Length of output: 1078
🏁 Script executed:
# Look at actual component files that use google to see their dependency declarations
find src/lfx/src/lfx/components -name "*.py" -path "*google*" | head -10Repository: langflow-ai/langflow
Length of output: 641
🏁 Script executed:
# Check if google is listed as a dependency anywhere in component metadata
rg -r '"google"' src/lfx/src/lfx/components --type json | head -10Repository: langflow-ai/langflow
Length of output: 2028
🏁 Script executed:
# Look at a google component to see how dependencies are declared
cat src/lfx/src/lfx/components/google/google_drive.py | head -80Repository: langflow-ai/langflow
Length of output: 2933
🏁 Script executed:
# Check how components declare their dependencies - look for a pattern
rg "dependencies|requires" src/lfx/src/lfx/components/google --type py -B5 -A5 | head -50Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Look at the interface/components.py to see how dependencies are extracted
grep -n "import_langflow_components\|dependencies" src/lfx/src/lfx/interface/components.py | head -30Repository: langflow-ai/langflow
Length of output: 286
🏁 Script executed:
# Check component base class or metadata structure
find src/lfx/src/lfx/components -name "*.py" -path "*base*" -o -name "__init__.py" | xargs grep -l "dependencies" 2>/dev/null | head -5Repository: langflow-ai/langflow
Length of output: 199
🏁 Script executed:
# Look at src/lfx/pyproject.toml to see all dependencies
cat src/lfx/pyproject.toml | head -200Repository: langflow-ai/langflow
Length of output: 2996
🏁 Script executed:
# Search for where google package (not google-*) appears in dependencies
rg '^google' src/lfx/pyproject.tomlRepository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check the full dependencies section of src/lfx/pyproject.toml
sed -n '/dependencies/,/^\[/p' src/lfx/pyproject.toml | head -100Repository: langflow-ai/langflow
Length of output: 1275
🏁 Script executed:
# Check if there's a google package (not google-cloud-*, google-api-*, etc) in the project
pip list 2>/dev/null | grep -i "^google " || echo "Checking in requirements..."
rg "^google\s*=" src/lfx/pyproject.tomlRepository: langflow-ai/langflow
Length of output: 91
🏁 Script executed:
# Check if there's a package called 'google' in PyPI and what it is
pip index versions google 2>/dev/null | head -20 || echo "Checking alternative..."Repository: langflow-ai/langflow
Length of output: 132
🏁 Script executed:
# Search uv.lock more carefully for any 'google' entry
rg -E '^\[\[package\]\]' uv.lock -A25 | grep -B5 -A20 '^name = "google"' | head -50Repository: langflow-ai/langflow
Length of output: 117
🏁 Script executed:
# Check what modules are imported with 'google' in the google components
rg "^from google|^import google" src/lfx/src/lfx/components/google --type py -h | sort -uRepository: langflow-ai/langflow
Length of output: 9339
🏁 Script executed:
# Verify: google.auth comes from google-auth package, not standalone google
python3 << 'EOF'
import subprocess
import sys
# Check which package provides google.auth
result = subprocess.run([sys.executable, "-m", "pip", "show", "google-auth"],
capture_output=True, text=True)
if result.returncode == 0:
print("google-auth package info:")
print(result.stdout)
# Now check if there's a standalone 'google' package
result2 = subprocess.run([sys.executable, "-m", "pip", "show", "google"],
capture_output=True, text=True)
if result2.returncode == 0:
print("\nStandalone 'google' package info:")
print(result2.stdout)
else:
print("\nNo standalone 'google' package found")
EOFRepository: langflow-ai/langflow
Length of output: 101
🏁 Script executed:
# Let's find where google==2.8.0 is coming from by checking component metadata
# Look at one of the google components to see how it specifies dependencies
cat src/lfx/src/lfx/components/google/__init__.py | head -150Repository: langflow-ai/langflow
Length of output: 708
🏁 Script executed:
# Check if components have metadata that includes dependencies
rg "google.*2\.8|version.*2\.8" src/lfx/src/lfx/components --type py | head -20Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Look for `@component` decorators or metadata that might specify dependencies
rg "@component|dependencies\s*=" src/lfx/src/lfx/components/google --type py -B5 -A10 | head -100Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Search the entire components directory for where google 2.8.0 might be sourced
rg "google" src/lfx/src/lfx/components --type py -l | xargs grep -l "2\.8\|dependencies" | head -5Repository: langflow-ai/langflow
Length of output: 102
🏁 Script executed:
# Look at the main components __init__.py to see how dependencies are extracted
cat src/lfx/src/lfx/components/__init__.py | head -200Repository: langflow-ai/langflow
Length of output: 4827
🏁 Script executed:
# Check the Component base class to see if it has a dependencies attribute
find src/lfx/src/lfx -name "component.py" -o -name "base.py" | xargs grep -l "class Component" | head -3Repository: langflow-ai/langflow
Length of output: 156
🏁 Script executed:
# Let's trace through one component to see how dependencies are declared
cat src/lfx/src/lfx/components/google/google_generative_ai.py | grep -A50 "class GoogleGenerativeAI"Repository: langflow-ai/langflow
Length of output: 2025
🏁 Script executed:
# Check if there's a metadata or decorator system that declares dependencies
rg "dependencies|requires|import_" src/lfx/src/lfx/custom/custom_component --type py | head -20Repository: langflow-ai/langflow
Length of output: 315
🏁 Script executed:
# Look at the Component base class to see if it has a dependencies property
cat src/lfx/src/lfx/custom/custom_component/component.py | grep -i "dependencies\|import_requirement" -A5 -B5 | head -100Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Search for where dependencies might be extracted from component metadata
rg "dependencies|get_dependencies|import_requirement" src/lfx/src/lfx/interface/components.py -B3 -A3 | head -80Repository: langflow-ai/langflow
Length of output: 502
🏁 Script executed:
# Look at how the component metadata is built
rg "metadata\s*=" src/lfx/src/lfx/interface/components.py -B5 -A20 | head -100Repository: langflow-ai/langflow
Length of output: 2149
🏁 Script executed:
# Check if there's a tool or function that extracts requirements from Python source
rg "requirements\|google\|dependencies" scripts/build_component_index.py -B5 -A5Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check the full component_index.json structure around one of the google==2.8.0 entries
sed -n '73420,73445p' src/lfx/src/lfx/_assets/component_index.jsonRepository: langflow-ai/langflow
Length of output: 821
🏁 Script executed:
# Look for where these dependencies are coming from - check if there's a dependency resolver
rg "resolve|dependencies|requirements" src/lfx/src/lfx/interface/components.py | head -20Repository: langflow-ai/langflow
Length of output: 136
🏁 Script executed:
# Check what the 'google' entry might be - look at context around it
sed -n '73400,73460p' src/lfx/src/lfx/_assets/component_index.jsonRepository: langflow-ai/langflow
Length of output: 1745
🏁 Script executed:
# Verify: is 'google' coming from langchain or another package's dependencies?
python3 << 'EOF'
import subprocess
import sys
import json
# Try to understand where google==2.8.0 might come from
# Check if langchain-google-genai or other packages depend on it
result = subprocess.run(
[sys.executable, "-m", "pip", "show", "langchain-google-genai"],
capture_output=True, text=True
)
if result.returncode == 0:
print("langchain-google-genai package info:")
print(result.stdout)
# Check langchain-google-community
result2 = subprocess.run(
[sys.executable, "-m", "pip", "show", "langchain-google-community"],
capture_output=True, text=True
)
if result2.returncode == 0:
print("\nlangchain-google-community package info:")
print(result2.stdout)
EOFRepository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Look at the google_bq_sql_executor.py component to see where google==2.8.0 comes from
head -100 src/lfx/src/lfx/components/google/google_bq_sql_executor.pyRepository: langflow-ai/langflow
Length of output: 3515
🏁 Script executed:
# Check what's being imported from google in that file
grep -n "^from google\|^import google" src/lfx/src/lfx/components/google/google_bq_sql_executor.pyRepository: langflow-ai/langflow
Length of output: 205
🏁 Script executed:
# Look for a dependency extraction mechanism in the codebase
rg "def.*dependencies\|extract.*dependencies\|get.*requirements" src/lfx/src/lfx --type py | head -20Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check if there's an __init__.py in google that might define dependencies
cat src/lfx/src/lfx/components/google/google_bq_sql_executor.pyRepository: langflow-ai/langflow
Length of output: 6072
🏁 Script executed:
# Verify: does google==2.8.0 actually exist on PyPI?
python3 << 'EOF'
import subprocess
import sys
# Try to get info about google package and specifically version 2.8.0
result = subprocess.run(
[sys.executable, "-m", "pip", "index", "versions", "google"],
capture_output=True, text=True
)
print("Available versions of 'google' package on PyPI:")
print(result.stdout)
print(result.stderr)
# Try to install google==2.8.0 to see if it exists
print("\n\nAttempting to find google==2.8.0:")
result2 = subprocess.run(
[sys.executable, "-m", "pip", "install", "--dry-run", "google==2.8.0"],
capture_output=True, text=True
)
print("STDOUT:", result2.stdout[:500])
print("STDERR:", result2.stderr[:500])
print("Return code:", result2.returncode)
EOFRepository: langflow-ai/langflow
Length of output: 639
🏁 Script executed:
# Check where the dependency extraction happens in the build script
grep -r "dependencies\|get_requirement\|import" scripts/build_component_index.py | head -20Repository: langflow-ai/langflow
Length of output: 924
🏁 Script executed:
# Look at how Component base class or interface extracts dependencies
find src/lfx/src/lfx -name "*.py" -exec grep -l "dependencies.*=" {} \; | head -10Repository: langflow-ai/langflow
Length of output: 246
🏁 Script executed:
# Check the dependency_analyzer.py file
cat src/lfx/src/lfx/custom/dependency_analyzer.pyRepository: langflow-ai/langflow
Length of output: 5437
🏁 Script executed:
# Also check if there's a specific version check or parsing
grep -n "2\.8\|google" src/lfx/src/lfx/custom/dependency_analyzer.pyRepository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Check git history to see if google version recently changed
git log --all --oneline -- src/lfx/src/lfx/_assets/component_index.json | head -5Repository: langflow-ai/langflow
Length of output: 480
🏁 Script executed:
# Check the previous version of the component_index.json to see what google version was before
git show HEAD~1:src/lfx/src/lfx/_assets/component_index.json 2>/dev/null | grep -A2 -B2 '"name": "google"' | head -40 || echo "Previous version not available"Repository: langflow-ai/langflow
Length of output: 46
🏁 Script executed:
# Verify that google==2.8.0 truly doesn't exist
python3 << 'EOF'
# Check if there's perhaps a pre-release or something
import subprocess
result = subprocess.run(
["pip", "install", "--dry-run", "--pre", "google==2.8.0"],
capture_output=True, text=True
)
print("With --pre flag:")
print("STDERR:", result.stderr[:500])
print("Return code:", result.returncode)
EOFRepository: langflow-ai/langflow
Length of output: 288
🏁 Script executed:
# Check what the actual installed google package version is (if any)
python3 -c "import pkg_resources; print(pkg_resources.get_distribution('google').version)" 2>/dev/null || echo "google package not installed"Repository: langflow-ai/langflow
Length of output: 92
Non-existent dependency version in component metadata requires immediate correction.
The component index lists google==2.8.0 across multiple Google components (lines 73434, 73582, 73743, 73872, 74001, 74291, 74651), but this version does not exist on PyPI. Available versions are 1.9.3, 2.0.1, 2.0.2, 2.0.3, and 3.0.0 only. This appears to be a dependency resolution bug in the component metadata extraction system—the analyzer is incorrectly identifying google as a standalone package when imports like from google.auth import ... should resolve to their actual distributions (google-auth, google-cloud-bigquery). Correct the dependency extraction logic before merge to prevent runtime failures.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lfx/src/lfx/_assets/component_index.json` at line 73434, The component
metadata extractor is emitting an invalid dependency "google==2.8.0"; update the
dependency resolution logic (functions like extract_dependencies(),
resolve_import_to_distribution(), and parse_imports()/map_import_to_dist()) so
imports under the google namespace map to their real distributions (e.g.,
google.auth -> google-auth, google.cloud.bigquery -> google-cloud-bigquery)
instead of a standalone "google", and validate resolved package versions against
PyPI (use or add a helper such as validate_version_on_pypi() or
fallback_to_known_versions()) so invalid versions are replaced with a known
available version or omitted; add/update unit tests for imports like from
google.auth import ... to assert the correct distribution and version are
emitted rather than "google==2.8.0".
eb3271f to
a848c29
Compare
a28541c to
bed4619
Compare
|
Follow-up update: I removed the unrelated That asset change was not part of the backend bugfix and was pulling in the invalid Commit: |
6219369 to
d3c744b
Compare
|
Author follow-up: the remaining failing checks currently look repo-side rather than caused by the paginated flow visibility fix itself. The two failing jobs are (frontend timeout in ) and (Docker build failing during 15 packages are looking for funding |
|
Author follow-up: the remaining failing checks currently look repo-side rather than caused by the paginated flow visibility fix itself. The two failing jobs are:
The PR diff is now reduced to the intended backend change plus regression test only. |
|
Author follow-up with failed job details: I pulled the raw logs for the two remaining failed jobs, and both failures appear unrelated to the backend pagination visibility fix in this PR.
The PR diff itself is already reduced to the intended backend change plus its regression test:
CodeRabbit’s actionable comments on this PR were already addressed earlier, and the remaining failures look like repo-side CI / test-environment issues rather than regressions introduced by this change. |
|
Follow-up update after checking the current upstream I verified the current |
|
Closing this PR because the fix it carried is now already present on current I rechecked the current upstream branch and confirmed that paginated project flow reads are already scoped to the current user, with regression coverage for only returning the current user's flows. Keeping this stale branch open would mostly preserve old check noise rather than add a new change for maintainers to merge. Thanks for the earlier review and CI signal here. |
Summary
current_user.idfilter in the paginatedread_projectquery that the non-paginated branch already usespage/sizeresponses from exposing flows owned by another user in the same project folderTesting
test_projects.pyand left for repo CISummary by CodeRabbit
Release Notes
Bug Fixes
Tests
Chores