Skip to content

Conversation

@erichare
Copy link
Collaborator

@erichare erichare commented Jan 2, 2026

This pull request introduces a new API endpoint for managing global storage settings, specifically for file components, and integrates it into the existing API router structure. The main focus is to provide secure, validated access to storage configuration (such as AWS and Google Drive) via new GET and PATCH endpoints. Additionally, the new router is registered with the API, and a code hash update is made in a starter project.

API Enhancements:

  • Added a new storage_settings_router to the API v2, exposing /storage-settings endpoints for retrieving and updating global storage settings. This includes secure masking of sensitive fields and validation for required credentials based on the selected storage provider. (src/backend/base/langflow/api/v2/storage_settings.py)
  • Registered the new storage_settings_router in the API v2 initialization and included it in the main API router, making the new endpoints accessible. (src/backend/base/langflow/api/v2/__init__.py, src/backend/base/langflow/api/router.py) [1] [2] [3]

Other updates:

  • Updated the code_hash in the News Aggregator starter project metadata. (src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json)

Summary by CodeRabbit

Release Notes

  • New Features
    • Added global storage configuration management for AWS S3, Google Drive, and local storage
    • New Storage page in Settings for managing default storage credentials and location
    • File components now support component-level storage overrides to use custom settings instead of global defaults

✏️ Tip: You can customize this high-level summary in your review settings.

@erichare erichare requested a review from HimavarshaVS January 2, 2026 02:28
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 2, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR implements global storage settings management, enabling centralized AWS S3 and Google Drive credential configuration. A new v2 API endpoint manages settings with credential masking, while file components gain optional per-component storage overrides. Tests verify credential validation, masking, and fallback behavior.

Changes

Cohort / File(s) Summary
Backend API Router & Initialization
src/backend/base/langflow/api/router.py, src/backend/base/langflow/api/v2/__init__.py
Import and register new storage settings router v2; expose storage settings endpoints in v2 API surface.
Backend API v2 Storage Settings
src/backend/base/langflow/api/v2/storage_settings.py
New module implementing two endpoints: GET /storage-settings (returns current settings with masked sensitive fields) and PATCH /storage-settings (validates credentials, updates fields selectively, masks secrets in response). Includes StorageSettingsResponse and StorageSettingsUpdate Pydantic models.
Backend Storage Settings Service
src/lfx/src/lfx/services/settings/base.py
Add global storage configuration fields: default_storage_location, AWS credentials (key ID, secret, bucket, region), and Google Drive credentials (service account key, folder ID). Alter settings_customise_sources source ordering.
Backend Tests - API Validation
src/backend/tests/unit/api/v2/test_storage_settings_validation.py
New test suite covering credential validation for storage location switching: AWS (key ID, secret, bucket required), Google Drive (service account key required), credential masking in responses, and Local storage (no credentials required).
Backend Tests - Component Integration
src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
Test suites for FileComponent and SaveToFileComponent verifying: use of global storage when custom override disabled, custom storage overrides global, UI toggle behavior, and global credential application (AWS S3, Google Drive).
Backend Tests - Settings
src/backend/tests/unit/test_storage_settings.py
Unit tests for Settings class: default location, credential handling, environment variable loading, and explicit parameter overrides.
File Components - Storage Override
src/lfx/src/lfx/components/files_and_knowledge/file.py, src/lfx/src/lfx/components/files_and_knowledge/save_file.py
Add use_custom_storage toggle input to enable per-component overrides. Conditionally show/hide storage fields. Extend read/write paths to support dual modes: component-level credentials when toggle enabled, or global defaults when disabled. Validate credentials and set region/folder defaults based on selected mode.
Frontend Starter Project
src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json
Add use_custom_storage BoolInput to SaveToFile component; update code_hash in metadata; conditionally toggle storage field visibility.
Frontend API Constants & Hooks
src/frontend/src/controllers/API/helpers/constants.ts, src/frontend/src/controllers/API/queries/storage-settings/...
Add STORAGE_SETTINGS URL constant; create useGetStorageSettings query hook (fetches settings with refetch-on-focus disabled) and useUpdateStorageSettings mutation hook (PATCH endpoint with refetch on settle). Re-export hooks in storage-settings index.
Frontend UI - Storage Settings Page
src/frontend/src/pages/SettingsPage/index.tsx, src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx
Add Storage settings sidebar item with HardDrive icon. Implement StorageSettingsPage component with location selector (Local/AWS S3/Google Drive), conditional config panels, form initialization from API, selective payload building (omit masked secrets), save action with success/error alerts.
Frontend Routing
src/frontend/src/routes.tsx
Import StorageSettingsPage; add route at "storage" under settings path.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend
    participant API as v2 API
    participant SettingsService

    rect rgb(220, 240, 255)
    Note over User,SettingsService: GET Storage Settings Flow
    User->>Frontend: Load Storage Settings page
    Frontend->>API: GET /storage-settings
    API->>SettingsService: Retrieve current settings
    SettingsService-->>API: Return settings (secrets masked)
    API-->>Frontend: StorageSettingsResponse (masked)
    Frontend->>Frontend: Initialize form fields
    Frontend-->>User: Display current settings
    end

    rect rgb(240, 255, 240)
    Note over User,SettingsService: PATCH Storage Settings Flow
    User->>Frontend: Update storage location & credentials
    Frontend->>Frontend: Build update payload (omit masked secrets)
    Frontend->>API: PATCH /storage-settings
    API->>API: Determine selected storage location
    API->>API: Validate required credentials
    alt AWS selected
        API->>API: Require Access Key ID, Secret, Bucket
    else Google Drive selected
        API->>API: Require Service Account Key
    else Local selected
        API->>API: No credentials required
    end
    API->>SettingsService: Update settings (selective fields only)
    SettingsService-->>API: Return updated settings
    API-->>Frontend: StorageSettingsResponse (masked)
    Frontend->>Frontend: Show success alert
    Frontend-->>User: Settings saved
    end
Loading
sequenceDiagram
    participant Component as File Component
    participant SettingsService
    participant Storage as AWS/GDrive

    rect rgb(255, 240, 240)
    Note over Component,Storage: Component Using Global Storage (use_custom_storage=False)
    Component->>Component: use_custom_storage = False
    Component->>Component: Get selected storage location
    alt Default is AWS
        Component->>SettingsService: Fetch global AWS credentials
        SettingsService-->>Component: Access Key, Secret, Bucket, Region
        Component->>Storage: Initialize with global credentials
    else Default is Google Drive
        Component->>SettingsService: Fetch global Google Drive key
        SettingsService-->>Component: Service Account Key, Folder ID
        Component->>Storage: Initialize with global credentials
    else Default is Local
        Component->>Storage: Use local file system
    end
    Component->>Storage: Read/Write file
    Storage-->>Component: Success
    end

    rect rgb(240, 220, 255)
    Note over Component,Storage: Component Using Custom Storage (use_custom_storage=True)
    Component->>Component: use_custom_storage = True
    Component->>Component: Validate component-level credentials
    alt Component AWS configured
        Component->>Component: Validate s3_file_key, credentials
        Component->>Storage: Initialize with component credentials
    else Component Google Drive configured
        Component->>Component: Validate service_account_key, file_id
        Component->>Storage: Initialize with component credentials
    end
    Component->>Storage: Read/Write file
    Storage-->>Component: Success
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 3 warnings)
Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error PR includes backend tests but lacks GET endpoint tests, uses flaky os.getenv() assertions, has incomplete integration tests, and is missing all frontend tests for new React Query hooks and StorageSettingsPage component. Add GET endpoint tests with masked field verification, replace os.getenv() with hardcoded values, fix integration tests with proper try/except blocks, add component method invocations, and create frontend tests for React Query hooks and StorageSettingsPage.
Test Quality And Coverage ⚠️ Warning Pull request has critical test quality gaps including misuse of os.getenv() in assertions, flaky integration tests, and missing frontend unit tests for StorageSettingsPage component. Replace os.getenv() with hardcoded test values, refactor integration tests to invoke actual component methods, add frontend unit tests for StorageSettingsPage, and fix frontend mutation hook callback composition.
Test File Naming And Structure ⚠️ Warning Test implementation violates pytest structure with os.getenv() in assertions, contextlib.suppress() misuse, tests not invoking component methods, and trivial assertions. Replace os.getenv() calls with hardcoded values, fix contextlib.suppress() with proper try/except, restructure tests to invoke component methods and verify behavior.
Excessive Mock Usage Warning ⚠️ Warning Test suite exhibits excessive mocking that obscures actual behavior testing, particularly in test_storage_settings_integration.py. Multiple tests patch external dependencies without invoking methods being tested, then assert on mock state rather than actual behavior. Refactor integration tests to invoke actual component methods instead of just checking mock setup. Replace trivial mock assertions with verification that components correctly retrieve and use global credentials. Use proper configured test doubles with return values rather than bare patches, or mock only at I/O boundary.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Complete refactor of storage locations' accurately captures the main objective of the PR, which is implementing a comprehensive storage settings management system with API endpoints, validation, and component integration.
Docstring Coverage ✅ Passed Docstring coverage is 89.58% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-storage-settings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
@erichare erichare requested a review from rodrigosnader January 2, 2026 02:32
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 2, 2026

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 17%
17.37% (4977/28637) 10.72% (2364/22033) 11.52% (722/6267)

Unit Test Results

Tests Skipped Failures Errors Time
1989 0 💤 0 ❌ 0 🔥 25.315s ⏱️

@codecov
Copy link

codecov bot commented Jan 2, 2026

Codecov Report

❌ Patch coverage is 40.86379% with 178 lines in your changes missing coverage. Please review.
✅ Project coverage is 34.08%. Comparing base (3006b13) to head (df09c4f).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...rc/lfx/src/lfx/base/data/storage_settings_mixin.py 21.59% 68 Missing and 1 partial ⚠️
...s/SettingsPage/pages/StorageSettingsPage/index.tsx 0.00% 64 Missing ⚠️
...c/backend/base/langflow/api/v2/storage_settings.py 81.30% 20 Missing ⚠️
...eries/storage-settings/use-get-storage-settings.ts 0.00% 11 Missing ⚠️
...es/storage-settings/use-update-storage-settings.ts 0.00% 11 Missing ⚠️
.../controllers/API/queries/storage-settings/index.ts 0.00% 2 Missing ⚠️
src/frontend/src/routes.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #11180      +/-   ##
==========================================
+ Coverage   34.03%   34.08%   +0.04%     
==========================================
  Files        1407     1413       +6     
  Lines       66661    66989     +328     
  Branches     9839     9890      +51     
==========================================
+ Hits        22689    22832     +143     
- Misses      42787    42967     +180     
- Partials     1185     1190       +5     
Flag Coverage Δ
backend 53.40% <81.65%> (+0.24%) ⬆️
frontend 15.94% <0.00%> (-0.06%) ⬇️
lfx 40.58% <33.00%> (-0.05%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/backend/base/langflow/api/router.py 100.00% <100.00%> (ø)
.../frontend/src/controllers/API/helpers/constants.ts 60.00% <ø> (ø)
src/frontend/src/pages/SettingsPage/index.tsx 0.00% <ø> (ø)
src/lfx/src/lfx/services/settings/base.py 72.08% <100.00%> (+0.92%) ⬆️
src/frontend/src/routes.tsx 0.00% <0.00%> (ø)
.../controllers/API/queries/storage-settings/index.ts 0.00% <0.00%> (ø)
...eries/storage-settings/use-get-storage-settings.ts 0.00% <0.00%> (ø)
...es/storage-settings/use-update-storage-settings.ts 0.00% <0.00%> (ø)
...c/backend/base/langflow/api/v2/storage_settings.py 81.30% <81.30%> (ø)
...s/SettingsPage/pages/StorageSettingsPage/index.tsx 0.00% <0.00%> (ø)
... and 1 more

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/lfx/src/lfx/components/files_and_knowledge/save_file.py (1)

614-681: AWS env fallback conflicts with validation helper and prior security posture.

In _save_to_aws:

  • For use_custom_storage=True you fall back to AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars when component inputs are missing.
  • Later you call validate_aws_credentials(self), which inspects self.aws_access_key_id, self.aws_secret_access_key, and self.bucket_name, not the local variables.
  • In the env‑fallback path, those attributes are never updated, so validate_aws_credentials can still fail even when env vars are present.
  • Separately, prior AWS components in this repo have required explicit credentials rather than inheriting environment/machine credentials for security in hosted environments. Based on learnings, this fallback is inconsistent with that pattern and could accidentally bind flows to host‑level AWS creds.

You should either:

  1. Drop the env fallback and require explicit component/global credentials, or
  2. If you really want env fallback, set self.aws_access_key_id, self.aws_secret_access_key, and self.bucket_name in the custom path before calling validate_aws_credentials, and document the intended behavior.

Given the earlier security stance, option (1) is preferable.

[specify_refactor]

Safer, simpler option: remove env fallback
-        if use_custom:
-            # Get from component inputs or fall back to environment variables
-            aws_access_key_id = getattr(self, "aws_access_key_id", None)
-            if aws_access_key_id and hasattr(aws_access_key_id, "get_secret_value"):
-                aws_access_key_id = aws_access_key_id.get_secret_value()
-            if not aws_access_key_id:
-                aws_access_key_id = os.getenv("AWS_ACCESS_KEY_ID")
-
-            aws_secret_access_key = getattr(self, "aws_secret_access_key", None)
-            if aws_secret_access_key and hasattr(aws_secret_access_key, "get_secret_value"):
-                aws_secret_access_key = aws_secret_access_key.get_secret_value()
-            if not aws_secret_access_key:
-                aws_secret_access_key = os.getenv("AWS_SECRET_ACCESS_KEY")
-
-            bucket_name = getattr(self, "bucket_name", None)
-            if not bucket_name:
-                bucket_name = settings.object_storage_bucket_name
-
-            aws_region = getattr(self, "aws_region", None)
+        if use_custom:
+            # Use only explicit component inputs for credentials
+            aws_access_key_id = getattr(self, "aws_access_key_id", None)
+            if aws_access_key_id and hasattr(aws_access_key_id, "get_secret_value"):
+                aws_access_key_id = aws_access_key_id.get_secret_value()
+
+            aws_secret_access_key = getattr(self, "aws_secret_access_key", None)
+            if aws_secret_access_key and hasattr(aws_secret_access_key, "get_secret_value"):
+                aws_secret_access_key = aws_secret_access_key.get_secret_value()
+
+            bucket_name = getattr(self, "bucket_name", None)
+
+            aws_region = getattr(self, "aws_region", None)

This keeps _save_to_aws in line with the rest of the AWS components’ “explicit credentials only” policy and avoids the attribute vs local variable mismatch with validate_aws_credentials(self). Based on learnings, ...

src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json (1)

1640-1682: Starter flow now depends on global storage defaults; docs still assume Local.

The embedded SaveToFileComponent code now delegates storage selection to:

  • Global default_storage_location when use_custom_storage=False.
  • Per‑node storage_location when use_custom_storage=True.

However, the News Aggregator note still tells users the file will be written locally to news-aggregated.json. If an instance is configured with a non‑Local global storage (e.g., AWS or Google Drive), this starter will now save to that provider instead, and the doc string will be misleading.

Consider:

  • Updating the note to mention that the target storage is controlled by global Storage Settings (with an optional per‑node override), or
  • Defaulting use_custom_storage to True and storage_location to Local in this starter if you want it to stay strictly local regardless of global defaults.
🧹 Nitpick comments (5)
src/backend/tests/unit/test_storage_settings.py (1)

1-6: Consider removing unused os import after fixing assertions.

The os import is only used for the problematic os.getenv() calls in assertions. After fixing those to use hardcoded expected values, you can remove this import.

src/lfx/src/lfx/components/files_and_knowledge/file.py (1)

648-684: Consider potential side effects from mutating self with global credentials.

When use_custom_storage is False, the code sets credentials directly on self (lines 680-683). This mutates the component instance, which could cause issues if:

  1. The component is inspected after execution (credentials would be visible).
  2. The component is reused with different settings.

Consider using a local dictionary for the S3 client config instead of setting attributes on self.

Proposed approach
         else:
             # Use global settings
             if not settings.component_aws_access_key_id:
                 msg = "AWS Access Key ID not configured in global storage settings"
                 raise ValueError(msg)
             if not settings.component_aws_secret_access_key:
                 msg = "AWS Secret Access Key not configured in global storage settings"
                 raise ValueError(msg)
             if not settings.component_aws_default_bucket:
                 msg = "AWS Default Bucket not configured in global storage settings"
                 raise ValueError(msg)
             if not getattr(self, "s3_file_key", None):
                 msg = "S3 File Key is required"
                 raise ValueError(msg)

-            # Temporarily set credentials on self for create_s3_client
-            self.aws_access_key_id = settings.component_aws_access_key_id
-            self.aws_secret_access_key = settings.component_aws_secret_access_key
-            self.bucket_name = settings.component_aws_default_bucket
-            self.aws_region = settings.component_aws_default_region
-            s3_client = create_s3_client(self)
+            # Create a credentials object for the S3 client
+            from types import SimpleNamespace
+            creds = SimpleNamespace(
+                aws_access_key_id=settings.component_aws_access_key_id,
+                aws_secret_access_key=settings.component_aws_secret_access_key,
+                aws_region=settings.component_aws_default_region,
+            )
+            s3_client = create_s3_client(creds)
+            # Set bucket_name for download call
+            self.bucket_name = settings.component_aws_default_bucket

Note: This would require create_s3_client to work with any object having the required attributes, which it already does based on the relevant code snippet.

src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx (1)

55-77: Use a typed payload instead of any for updates.

The updates object is currently any, even though the hook is already typed with UpdateStorageSettingsParams. Using the concrete type here will:

  • Catch payload/field mismatches at compile time.
  • Keep the frontend aligned with backend API evolution.
Proposed typing tweak
-  const handleSave = () => {
-    const updates: any = {
+  const handleSave = () => {
+    const updates: UpdateStorageSettingsParams = {
       default_storage_location: storageLocation,
     };

(Import UpdateStorageSettingsParams from the storage‑settings query module or its shared types definition.)

src/backend/tests/unit/api/v2/test_storage_settings_validation.py (1)

32-185: Good AWS validation coverage; consider aligning Google Drive validation with runtime needs.

The AWS tests thoroughly exercise:

  • Missing credentials when switching to AWS.
  • Partial credentials (only key id).
  • Missing bucket.
  • Successful configuration and masking behavior.
  • Updates when AWS is already configured or when only some fields change.

For Google Drive, you only assert on the presence/absence of the service account key:

  • test_validation_fails_when_switching_to_google_drive_without_credentials
  • test_validation_passes_when_switching_to_google_drive_with_credentials

However, the runtime Google Drive path in SaveToFileComponent._save_to_google_drive (see src/lfx/src/lfx/components/files_and_knowledge/save_file.py) also requires a default folder ID when using global settings. Right now:

  • The API allows default_storage_location="Google Drive" with only a key configured.
  • SaveToFile will later fail with “Google Drive default folder ID not configured in global storage settings”.

It may be worth:

  • Extending update_storage_settings to also validate component_google_drive_default_folder_id when switching to Google Drive, and
  • Adding a corresponding failing test case here (and a passing one where both key and folder id are provided), so the API rejects incomplete Google Drive setups early instead of deferring to the component.
src/backend/base/langflow/api/v2/storage_settings.py (1)

65-133: PATCH handler’s AWS validation is solid; Google Drive could also validate folder id.

For AWS, update_storage_settings:

  • Derives final_storage_location from update/default.
  • Computes effective key id, secret, and bucket from the patch or existing settings.
  • Validates all three when final_storage_location == "AWS", mirroring component‑level requirements.

For Google Drive, it currently only:

  • Computes final_gdrive_key from update or existing settings.
  • Validates that the key is present when final_storage_location == "Google Drive".

Given _save_to_google_drive in SaveToFileComponent requires both a service account key and a default folder id when using global settings, you may want to also require a non‑empty component_google_drive_default_folder_id here when the final storage location is Google Drive. Otherwise the API will accept a configuration that still cannot be used by the file component.

Illustrative change for Google Drive validation
     if final_storage_location == "Google Drive":
         # Check if we're updating credentials or if they already exist
-        final_gdrive_key = settings.component_google_drive_service_account_key
+        final_gdrive_key = settings.component_google_drive_service_account_key
         if settings_update.component_google_drive_service_account_key is not None and not all(
             c == "*" for c in settings_update.component_google_drive_service_account_key
         ):
             final_gdrive_key = settings_update.component_google_drive_service_account_key
+
+        final_gdrive_folder = (
+            settings_update.component_google_drive_default_folder_id
+            if settings_update.component_google_drive_default_folder_id is not None
+            else settings.component_google_drive_default_folder_id
+        )
 
         # Validate required Google Drive fields
         if not final_gdrive_key:
             raise HTTPException(
                 status_code=400,
                 detail="Google Drive Service Account Key is required when Google Drive storage is selected",
             )
+        if not final_gdrive_folder:
+            raise HTTPException(
+                status_code=400,
+                detail="Google Drive Default Folder ID is required when Google Drive storage is selected",
+            )
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc2635e and bdae4fc.

📒 Files selected for processing (21)
  • src/backend/base/langflow/api/router.py
  • src/backend/base/langflow/api/v2/__init__.py
  • src/backend/base/langflow/api/v2/storage_settings.py
  • src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json
  • src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json
  • src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json
  • src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json
  • src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json
  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
  • src/backend/tests/unit/test_storage_settings.py
  • src/frontend/src/controllers/API/helpers/constants.ts
  • src/frontend/src/controllers/API/queries/storage-settings/index.ts
  • src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts
  • src/frontend/src/controllers/API/queries/storage-settings/use-update-storage-settings.ts
  • src/frontend/src/pages/SettingsPage/index.tsx
  • src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx
  • src/frontend/src/routes.tsx
  • src/lfx/src/lfx/components/files_and_knowledge/file.py
  • src/lfx/src/lfx/components/files_and_knowledge/save_file.py
  • src/lfx/src/lfx/services/settings/base.py
🧰 Additional context used
📓 Path-based instructions (7)
src/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

src/frontend/src/**/*.{ts,tsx}: Use React 18 with TypeScript for frontend development
Use Zustand for state management

Files:

  • src/frontend/src/controllers/API/queries/storage-settings/use-update-storage-settings.ts
  • src/frontend/src/controllers/API/helpers/constants.ts
  • src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts
  • src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx
  • src/frontend/src/routes.tsx
  • src/frontend/src/pages/SettingsPage/index.tsx
  • src/frontend/src/controllers/API/queries/storage-settings/index.ts
src/backend/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

src/backend/**/*.py: Use FastAPI async patterns with await for async operations in component execution methods
Use asyncio.create_task() for background tasks and implement proper cleanup with try/except for asyncio.CancelledError
Use queue.put_nowait() for non-blocking queue operations and asyncio.wait_for() with timeouts for controlled get operations

Files:

  • src/backend/base/langflow/api/v2/__init__.py
  • src/backend/base/langflow/api/v2/storage_settings.py
  • src/backend/base/langflow/api/router.py
  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/test_storage_settings.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
src/backend/base/langflow/api/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Backend API endpoints should be organized by version (v1/, v2/) under src/backend/base/langflow/api/ with specific modules for features (chat.py, flows.py, users.py, etc.)

Files:

  • src/backend/base/langflow/api/v2/__init__.py
  • src/backend/base/langflow/api/v2/storage_settings.py
  • src/backend/base/langflow/api/router.py
src/frontend/src/**/*.{tsx,jsx,css,scss}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

Use Tailwind CSS for styling

Files:

  • src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx
  • src/frontend/src/routes.tsx
  • src/frontend/src/pages/SettingsPage/index.tsx
src/frontend/src/**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/frontend_development.mdc)

src/frontend/src/**/*.{tsx,jsx}: Implement dark mode support using the useDarkMode hook and dark store
Use Lucide React for icon components in the application

Files:

  • src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx
  • src/frontend/src/routes.tsx
  • src/frontend/src/pages/SettingsPage/index.tsx
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Place backend unit tests in src/backend/tests/ directory, component tests in src/backend/tests/unit/components/ organized by component subdirectory, and integration tests accessible via make integration_tests
Use same filename as component with appropriate test prefix/suffix (e.g., my_component.pytest_my_component.py)
Use the client fixture (FastAPI Test Client) defined in src/backend/tests/conftest.py for API tests; it provides an async httpx.AsyncClient with automatic in-memory SQLite database and mocked environment variables. Skip client creation by marking test with @pytest.mark.noclient
Inherit from the correct ComponentTestBase family class located in src/backend/tests/base.py based on API access needs: ComponentTestBase (no API), ComponentTestBaseWithClient (needs API), or ComponentTestBaseWithoutClient (pure logic). Provide three required fixtures: component_class, default_kwargs, and file_names_mapping
Create comprehensive unit tests for all new backend components. If unit tests are incomplete, create a corresponding Markdown file documenting manual testing steps and expected outcomes
Test both sync and async code paths, mock external dependencies appropriately, test error handling and edge cases, validate input/output behavior, and test component initialization and configuration
Use @pytest.mark.asyncio decorator for async component tests and ensure async methods are properly awaited
Test background tasks using asyncio.create_task() and verify completion with asyncio.wait_for() with appropriate timeout constraints
Test queue operations using non-blocking queue.put_nowait() and asyncio.wait_for(queue.get(), timeout=...) to verify queue processing without blocking
Use @pytest.mark.no_blockbuster marker to skip the blockbuster plugin in specific tests
For database tests that may fail in batch runs, run them sequentially using uv run pytest src/backend/tests/unit/test_database.py r...

Files:

  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/test_storage_settings.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
**/test_*.py

📄 CodeRabbit inference engine (Custom checks)

**/test_*.py: Review test files for excessive use of mocks that may indicate poor test design - check if tests have too many mock objects that obscure what's actually being tested
Warn when mocks are used instead of testing real behavior and interactions, and suggest using real objects or test doubles when mocks become excessive
Ensure mocks are used appropriately for external dependencies only, not for core logic
Backend test files should follow the naming convention test_*.py with proper pytest structure
Test files should have descriptive test function names that explain what is being tested
Tests should be organized logically with proper setup and teardown
Consider including edge cases and error conditions for comprehensive test coverage
Verify tests cover both positive and negative scenarios where appropriate
For async functions in backend tests, ensure proper async testing patterns are used with pytest
For API endpoints, verify both success and error response testing

Files:

  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/test_storage_settings.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
🧠 Learnings (21)
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/**/*.{tsx,jsx} : Implement dark mode support using the useDarkMode hook and dark store

Applied to files:

  • src/frontend/src/controllers/API/queries/storage-settings/use-update-storage-settings.ts
  • src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/**/{hooks,services}/**/*.{ts,tsx} : Use the useApi hook for API calls with proper error handling, including loading state, error state, and exception throwing

Applied to files:

  • src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts
📚 Learning: 2025-09-21T09:46:44.276Z
Learnt from: iann0036
Repo: langflow-ai/langflow PR: 9935
File: src/lfx/src/lfx/components/amazon/aws_api_call.py:35-48
Timestamp: 2025-09-21T09:46:44.276Z
Learning: Amazon components in the Langflow bundle consistently require explicit AWS credentials (aws_access_key_id and aws_secret_access_key with required=True) rather than falling back to environment/machine credentials for security reasons in hosted environments.

Applied to files:

  • src/lfx/src/lfx/components/files_and_knowledge/save_file.py
📚 Learning: 2025-11-24T19:46:09.104Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:09.104Z
Learning: Applies to src/backend/base/langflow/api/**/*.py : Backend API endpoints should be organized by version (v1/, v2/) under `src/backend/base/langflow/api/` with specific modules for features (chat.py, flows.py, users.py, etc.)

Applied to files:

  • src/backend/base/langflow/api/v2/storage_settings.py
  • src/backend/base/langflow/api/router.py
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/stores/**/*.{ts,tsx} : Store state management code in stores/ directory using Zustand with typed state interfaces

Applied to files:

  • src/frontend/src/routes.tsx
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/**/*.{ts,tsx} : Use Zustand for state management

Applied to files:

  • src/frontend/src/routes.tsx
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test both sync and async code paths, mock external dependencies appropriately, test error handling and edge cases, validate input/output behavior, and test component initialization and configuration

Applied to files:

  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Create comprehensive unit tests for all new backend components. If unit tests are incomplete, create a corresponding Markdown file documenting manual testing steps and expected outcomes

Applied to files:

  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Use `aiofiles` and `anyio.Path` for async file operations in tests; create temporary test files using `tmp_path` fixture and verify file existence and content

Applied to files:

  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Place backend unit tests in `src/backend/tests/` directory, component tests in `src/backend/tests/unit/components/` organized by component subdirectory, and integration tests accessible via `make integration_tests`

Applied to files:

  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-12-19T18:04:08.938Z
Learnt from: Jkavia
Repo: langflow-ai/langflow PR: 11111
File: src/backend/tests/unit/api/v2/test_workflow.py:10-11
Timestamp: 2025-12-19T18:04:08.938Z
Learning: In the langflow-ai/langflow repository, pytest-asyncio is configured with asyncio_mode = 'auto' in pyproject.toml. This means you do not need to decorate test functions or classes with pytest.mark.asyncio; async tests are auto-detected and run by pytest-asyncio. When reviewing tests, ensure they rely on this configuration (i.e., avoid unnecessary pytest.mark.asyncio decorators) and that tests living under any tests/ path (e.g., src/.../tests/**/*.py) follow this convention. If a test explicitly requires a different asyncio policy, document it and adjust the config accordingly.

Applied to files:

  • src/backend/tests/unit/api/v2/test_storage_settings_validation.py
  • src/backend/tests/unit/test_storage_settings.py
  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test component versioning and backward compatibility using `file_names_mapping` fixture with `VersionComponentMapping` objects mapping component files across Langflow versions

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Inherit from the correct `ComponentTestBase` family class located in `src/backend/tests/base.py` based on API access needs: `ComponentTestBase` (no API), `ComponentTestBaseWithClient` (needs API), or `ComponentTestBaseWithoutClient` (pure logic). Provide three required fixtures: `component_class`, `default_kwargs`, and `file_names_mapping`

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Test component build config updates by calling `to_frontend_node()` to get the node template, then calling `update_build_config()` to apply configuration changes

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: Applies to src/backend/tests/**/*.py : Use same filename as component with appropriate test prefix/suffix (e.g., `my_component.py` → `test_my_component.py`)

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-08-05T22:51:27.961Z
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-08-05T22:51:27.961Z
Learning: The TestComposioComponentAuth test in src/backend/tests/unit/components/bundles/composio/test_base_composio.py demonstrates proper integration testing patterns for external API components, including real API calls with mocking for OAuth completion, comprehensive resource cleanup, and proper environment variable handling with pytest.skip() fallbacks.

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:46:09.104Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:09.104Z
Learning: Applies to tests/unit/components/**/*.py : Create unit tests in `src/backend/tests/unit/components/` mirroring the component directory structure, using `ComponentTestBaseWithClient` or `ComponentTestBaseWithoutClient` base classes

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:47:28.997Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-24T19:47:28.997Z
Learning: When adding a new component test, inherit from the correct `ComponentTestBase` class and provide the three required fixtures (`component_class`, `default_kwargs`, `file_names_mapping`) to greatly reduce boilerplate and enforce version compatibility

Applied to files:

  • src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/hooks/**/*.{ts,tsx} : Export hooks as custom hooks (useHookName) from the hooks/ directory

Applied to files:

  • src/frontend/src/controllers/API/queries/storage-settings/index.ts
📚 Learning: 2025-11-24T19:46:45.790Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-11-24T19:46:45.790Z
Learning: Applies to src/frontend/src/utils/**/*.{ts,tsx} : Use named exports for utility functions in the utils/ directory

Applied to files:

  • src/frontend/src/controllers/API/queries/storage-settings/index.ts
📚 Learning: 2025-06-23T12:46:42.048Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/frontend_development.mdc:0-0
Timestamp: 2025-06-23T12:46:42.048Z
Learning: Use Zustand for state management in React components within the frontend; stores should expose both state and setter functions, and be imported via hooks (e.g., useMyStore).

Applied to files:

  • src/frontend/src/controllers/API/queries/storage-settings/index.ts
🧬 Code graph analysis (10)
src/frontend/src/controllers/API/queries/storage-settings/use-update-storage-settings.ts (4)
src/frontend/src/types/api/index.ts (1)
  • useMutationFunctionType (291-309)
src/frontend/src/controllers/API/services/request-processor.ts (1)
  • UseRequestProcessor (14-54)
src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts (1)
  • StorageSettings (7-15)
src/frontend/src/controllers/API/helpers/constants.ts (1)
  • getURL (44-54)
src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts (3)
src/frontend/src/types/api/index.ts (1)
  • useQueryFunctionType (266-277)
src/frontend/src/controllers/API/services/request-processor.ts (1)
  • UseRequestProcessor (14-54)
src/frontend/src/controllers/API/helpers/constants.ts (1)
  • getURL (44-54)
src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx (3)
src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts (1)
  • useGetStorageSettings (17-38)
src/frontend/src/controllers/API/queries/storage-settings/use-update-storage-settings.ts (1)
  • useUpdateStorageSettings (18-44)
src/frontend/src/components/common/genericIconComponent/index.tsx (1)
  • ForwardedIconComponent (23-170)
src/lfx/src/lfx/components/files_and_knowledge/save_file.py (3)
src/lfx/src/lfx/inputs/inputs.py (1)
  • BoolInput (533-546)
src/lfx/src/lfx/services/interfaces.py (1)
  • settings (55-57)
src/lfx/src/lfx/base/data/cloud_storage_utils.py (2)
  • validate_aws_credentials (13-30)
  • create_google_drive_service (127-156)
src/backend/base/langflow/api/v2/storage_settings.py (2)
src/lfx/src/lfx/services/interfaces.py (1)
  • settings (55-57)
src/backend/tests/unit/api/v2/test_storage_settings_validation.py (1)
  • settings_service (14-19)
src/frontend/src/routes.tsx (1)
src/frontend/src/pages/SettingsPage/pages/StorageSettingsPage/index.tsx (1)
  • StorageSettingsPage (20-244)
src/frontend/src/pages/SettingsPage/index.tsx (1)
src/frontend/src/components/common/genericIconComponent/index.tsx (1)
  • ForwardedIconComponent (23-170)
src/backend/tests/unit/api/v2/test_storage_settings_validation.py (1)
src/backend/base/langflow/api/v2/storage_settings.py (2)
  • StorageSettingsUpdate (25-34)
  • update_storage_settings (66-179)
src/backend/tests/unit/test_storage_settings.py (1)
src/lfx/src/lfx/services/settings/base.py (1)
  • Settings (60-643)
src/lfx/src/lfx/components/files_and_knowledge/file.py (3)
src/lfx/src/lfx/inputs/inputs.py (1)
  • BoolInput (533-546)
src/backend/base/langflow/services/deps.py (1)
  • get_settings_service (125-138)
src/lfx/src/lfx/base/data/cloud_storage_utils.py (3)
  • validate_aws_credentials (13-30)
  • create_s3_client (33-59)
  • create_google_drive_service (127-156)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (60)
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 39/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 44/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 48/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 32/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 49/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 47/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 43/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 24/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 45/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 37/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 42/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 27/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 28/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 41/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 15/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 35/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 29/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 23/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 22/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 26/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 40/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 46/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 34/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 21/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 50/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 38/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 10/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 30/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 31/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 36/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 25/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 1/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 33/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 3/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 14/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 11/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 9/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 7/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 20/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 19/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 8/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 18/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 17/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 13/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 16/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 12/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 5/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 2/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 4/50
  • GitHub Check: Run Frontend Tests / Playwright Tests - Shard 6/50
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
  • GitHub Check: Test Docker Images / Test docker images
  • GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
  • GitHub Check: Test Starter Templates
  • GitHub Check: Run Ruff Check and Format
  • GitHub Check: test-starter-projects
🔇 Additional comments (22)
src/frontend/src/controllers/API/queries/storage-settings/use-update-storage-settings.ts (1)

18-29: LGTM!

The hook signature, interface, and mutation function are well-structured and follow the existing patterns in the codebase.

src/lfx/src/lfx/components/files_and_knowledge/file.py (3)

384-405: LGTM!

The update_build_config logic for the use_custom_storage toggle correctly shows/hides the storage location and related credential fields based on the toggle state.


586-605: LGTM!

The _get_selected_storage_location method correctly differentiates between component-level and global settings, with appropriate fallback to "Local" when component storage location is not specified.


718-744: LGTM!

The Google Drive credential handling correctly retrieves credentials from either component or global settings without unnecessary mutation of self.

src/backend/tests/unit/components/files_and_knowledge/test_storage_settings_integration.py (1)

12-37: LGTM!

These tests correctly verify that _get_selected_storage_location respects the use_custom_storage toggle and appropriately falls back to global settings or uses component-level overrides.

src/frontend/src/routes.tsx (1)

140-140: LGTM!

The storage settings route is correctly added under the settings path, following the same pattern as other settings pages like global-variables and api-keys.

Note: Unlike GeneralPage which is wrapped in AuthSettingsGuard, this route has no guard. Please verify this is intentional - if storage settings should be restricted based on user permissions, consider adding the appropriate guard.

src/frontend/src/pages/SettingsPage/index.tsx (1)

41-50: LGTM!

The Storage sidebar navigation item is correctly added with appropriate icon and href, following the existing pattern for settings navigation items.

src/frontend/src/controllers/API/helpers/constants.ts (1)

39-39: LGTM!

The STORAGE_SETTINGS URL constant is correctly added and follows the existing naming conventions. The kebab-case value aligns with REST API best practices.

src/frontend/src/controllers/API/queries/storage-settings/index.ts (1)

1-2: LGTM! Clean barrel export pattern.

The barrel export pattern appropriately aggregates the storage settings hooks, making them accessible from a single import path. This follows the established codebase conventions.

src/backend/base/langflow/api/router.py (1)

30-30: LGTM! Consistent v2 router integration.

The storage settings router is properly imported and registered following the established pattern for v2 API endpoints. The implementation aligns with the coding guidelines for organizing backend API endpoints by version.

Also applies to: 65-65

src/backend/base/langflow/api/v2/__init__.py (1)

4-4: LGTM! Proper public API export.

The storage settings router is correctly imported and added to __all__, following the established pattern for exposing v2 API routers. This ensures the router can be properly imported by consuming modules.

Also applies to: 10-10

src/lfx/src/lfx/services/settings/base.py (1)

202-216: LGTM! Well-structured storage settings fields.

The new global component storage settings are properly defined with clear naming, appropriate types, and helpful docstrings. The fields support both AWS S3 and Google Drive storage options with sensible defaults and nullable credentials.

Note: Sensitive fields like component_aws_secret_access_key and component_google_drive_service_account_key are stored as plain strings here, which is appropriate for a settings model that loads from environment variables. As per the PR summary, masking of these sensitive values is handled at the API endpoint level when returning settings to clients.

src/frontend/src/controllers/API/queries/storage-settings/use-get-storage-settings.ts (2)

7-15: LGTM! Interface matches backend settings model.

The StorageSettings interface properly mirrors the backend Settings model fields introduced in src/lfx/src/lfx/services/settings/base.py, with appropriate nullable types for optional credentials and a required default_storage_location field.


17-38: LGTM! Well-implemented query hook following established patterns.

The hook implementation properly follows the codebase conventions:

  • Uses UseRequestProcessor for standardized query behavior with retry logic and error handling
  • Disables refetchOnWindowFocus (appropriate for infrequently-changing settings)
  • Provides proper TypeScript typing throughout
  • Allows caller customization via options spread
  • Uses stable query key for effective caching

The hook depends on the STORAGE_SETTINGS URL constant referenced in the AI summary as being added to src/frontend/src/controllers/API/helpers/constants.ts. TypeScript's keyof typeof URLs type constraint ensures compile-time safety for this dependency.

Based on learnings, the use of UseRequestProcessor for API calls with proper error handling, loading state, and retry logic aligns with frontend development best practices.

src/lfx/src/lfx/components/files_and_knowledge/save_file.py (3)

55-187: Component/global storage override wiring looks consistent.

The new use_custom_storage toggle plus update_build_config logic cleanly separates:

  • Global default behavior (use_custom_storage=False → hide storage‑specific fields, rely on SettingsService).
  • Per‑component overrides (use_custom_storage=True → show location + provider‑specific fields).

Dynamic show/advanced flags for AWS and Google Drive fields match the storage choice and keep the UI constrained.


547-567: Global vs per‑component storage selection behavior is clear.

_get_selected_storage_location correctly:

  • Uses storage_location when use_custom_storage is enabled.
  • Falls back to get_settings_service().settings.default_storage_location otherwise.

This aligns SaveToFile with the new global storage settings, while preserving explicit per‑component overrides when requested.


724-813: Google Drive global/custom split and error messages look good.

_save_to_google_drive:

  • Enforces both service_account_key and folder_id for use_custom_storage=True.
  • For global mode, requires component_google_drive_service_account_key and component_google_drive_default_folder_id in settings before proceeding.
  • Reuses create_google_drive_service with full Drive scope and builds clear error messages when folder access fails.

This is consistent with the global storage model and provides helpful feedback when misconfigured.

src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json (1)

1663-2082: SaveToFile template and embedded code are aligned; added override input looks correct.

Within the SaveToFile-VVVVb node:

  • metadata.code_hash points to the updated SaveToFileComponent implementation that includes use_custom_storage.
  • The new use_custom_storage field is present in template with matching name, display name, info, and real_time_refresh=True.
  • Field ordering and options for storage_location, formats, and credential fields are consistent with the Python component.

This keeps the starter’s embedded component definition in sync with the runtime class and exposes the override toggle as expected.

src/backend/tests/unit/api/v2/test_storage_settings_validation.py (1)

13-30: SettingsService fixture and mock_user are appropriate for unit‑level API testing.

The settings_service fixture isolates settings into a tmp config dir, and mock_user is a simple MagicMock that satisfies the dependency without over‑mocking. This is a good balance for these pure validation tests.

src/backend/base/langflow/api/v2/storage_settings.py (3)

13-35: Models cleanly separate response vs update concerns.

StorageSettingsResponse and StorageSettingsUpdate provide:

  • A clear, minimal shape for what’s exposed to the client.
  • Optional fields in the update model so PATCH can be truly partial.

This mirrors how the handler logic uses “is not None” to decide when to apply updates and keeps masking handled only at the response layer.


37-62: GET handler correctly masks secrets while exposing non‑sensitive fields.

get_storage_settings:

  • Reads from settings_service.settings.
  • Replaces non‑empty component_aws_secret_access_key / component_google_drive_service_account_key with "********" before returning.
  • Leaves non‑secret fields (location, bucket, region, folder id) intact.

This matches the masking strategy used in the PATCH response and avoids leaking real secrets through the API.


134-179: Partial update + masking flow is well‑implemented.

The PATCH handler:

  • Applies only fields where the update model sets a non‑None value, allowing true partial updates.
  • Skips overwriting secrets when the client sends masked values (all *s).
  • Recomputes the masked secrets for the response from the stored settings rather than echoing back input.

This keeps the API ergonomic for clients while maintaining secrecy of credential material.

erichare and others added 2 commits January 1, 2026 19:13
…update-storage-settings.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…index.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
@github-actions github-actions bot removed the enhancement New feature or request label Jan 2, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 2, 2026
@diffray-bot
Copy link

Changes Summary

This PR introduces a comprehensive global storage settings management system for Langflow file components. It adds a new API v2 endpoint (/storage-settings) with GET and PATCH operations to manage credentials for AWS S3, Google Drive, and Local storage globally, along with a new Settings UI page. File components now support per-component storage overrides while defaulting to global settings.

Type: feature

Components Affected: API v2 Storage Settings Router, Frontend Storage Settings Page, File Component (Read File), Save File Component (Write File), Settings Service Configuration, Storage Settings Mixin (new), Frontend API Queries/Mutations

Files Changed
File Summary Change Impact
...ackend/base/langflow/api/v2/storage_settings.py New API endpoints for GET and PATCH storage settings with credential masking, validation, and database persistence 🔴
...ettingsPage/pages/StorageSettingsPage/index.tsx New React Settings page for managing global storage credentials with conditional AWS/Google Drive forms 🔴
...lfx/src/lfx/base/data/storage_settings_mixin.py Mixin class providing reusable storage settings inputs and methods for file components 🔴
src/lfx/src/lfx/services/settings/base.py Added 8 new settings fields for default storage location and credentials (AWS/Google Drive) ✏️ 🟡
.../src/lfx/components/files_and_knowledge/file.py Refactored to use StorageSettingsMixin, added use_custom_storage toggle and updated storage location selection logic ✏️ 🔴
...lfx/components/files_and_knowledge/save_file.py Refactored to use StorageSettingsMixin with per-component credential handling and dynamic field visibility ✏️ 🔴
...es/storage-settings/use-get-storage-settings.ts React Query hook for fetching global storage settings from API 🟡
...storage-settings/use-update-storage-settings.ts React Query mutation hook for updating global storage settings 🟡
src/backend/base/langflow/api/v2/__init__.py Exported new storage_settings_router ✏️ 🟢
src/backend/base/langflow/api/router.py Registered storage_settings_router in v2 API ✏️ 🟢
src/frontend/src/routes.tsx Added /storage route to Settings page navigation ✏️ 🟢
...unit/api/v2/test_storage_settings_validation.py Comprehensive tests for storage settings validation, credential persistence, and provider-specific requirements 🟡
src/backend/tests/unit/test_storage_settings.py Unit tests for Settings class storage configuration properties 🟡
..._knowledge/test_storage_settings_integration.py Integration tests for file components using global and custom storage settings 🟡
Architecture Impact
  • New Patterns: Mixin pattern for shared storage configuration across components, API credential masking pattern (masked secrets shown as asterisks), Database-persisted settings with fallback to in-memory configuration, Component-level override pattern for global settings
  • Dependencies: added: storage_settings_mixin.py for code reuse, added: new API v2 storage_settings router, added: React Query hooks for storage settings
  • Coupling: File and SaveToFileComponent now depend on StorageSettingsMixin and DatabaseVariableService. Settings are persisted in database as internal variables with '_storage' prefix. Frontend Settings page tightly coupled to API through React Query.
  • Breaking Changes: Settings.settings_sources() changed return tuple order (now includes init_settings and file_secret_settings), File components no longer have hardcoded storage_location input; now use mixin-provided input with use_custom_storage toggle

Risk Areas: Credential Security: Secret masking strategy (asterisks) could be bypassed if user re-sends masked value. Need validation to prevent sending masked-only credentials., Database Transaction Safety: Async session management in storage_settings.py with commit at end - potential for inconsistent state if update partially fails, Settings Source Priority Change: Modified settings_sources() tuple order could affect configuration loading precedence for all Settings fields, Field Visibility Toggle: Use_custom_storage field visibility toggle logic duplicated across file.py and save_file.py could cause inconsistencies, Credential Validation Logic: AWS and Google Drive credential validation happens both at API and component level - potential for inconsistent validation, Error Handling: HTTP 400 errors in PATCH endpoint for validation; no retry logic or detailed error reporting in frontend

Suggestions
  • Extract credential masking/validation logic into shared utility to prevent duplicating the asterisk-checking pattern
  • Add audit logging for credential updates to track who changed storage settings and when
  • Consider using database transactions with explicit rollback handling instead of relying on session.commit() at the end
  • Consolidate use_custom_storage toggle visibility logic from both file components into StorageSettingsMixin
  • Add type hints for TypeScript StorageSettings interface to match Python Pydantic models exactly
  • Document the '_update_build_config_for_storage_toggle' helper that's called but not defined in the components (should be in mixin)
  • Consider adding migration path for existing component configurations that have hardcoded credentials to use global settings instead

Full review in progress... | Powered by diffray

@diffray-bot
Copy link

Review Summary

Free public review - Want AI code reviews on your PRs? Check out diffray.ai

No validation results


Review ID: 960db2ec-0c2f-4800-8d9d-c1d019ca0900
Rate it 👍 or 👎 to improve future reviews | Powered by diffray

@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 5, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 9, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 9, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 9, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 9, 2026
@github-actions github-actions bot added enhancement New feature or request and removed enhancement New feature or request labels Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants