Skip to content

fix: resolve cover_image relative URL validation error for self-hoste…#9294

Open
karthiksuki wants to merge 1 commit into
makeplane:previewfrom
karthiksuki:fix/9283-cover-image-url
Open

fix: resolve cover_image relative URL validation error for self-hoste…#9294
karthiksuki wants to merge 1 commit into
makeplane:previewfrom
karthiksuki:fix/9283-cover-image-url

Conversation

@karthiksuki

@karthiksuki karthiksuki commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

…d MinIO #9283

Description

Fixes a misleading 400 Bad Request error when a user updates their profile cover image or avatar

Depending on the preferred architecture design of the maintainers, this PR addresses the issue via:

  • Backend Fix: Updated the user profile serializer field for cover_image to handle relative paths gracefully (similar to avatar_url implementation) instead of utilizing standard strict Django URLField validation.
  • Frontend Alignment: Ensured the payload sent during the PATCH /api/users/me/ request provides a consistent schema that aligns with backend expectations.

Type of Change

  • [x ] Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Image

Test Scenarios

References

Summary by CodeRabbit

  • New Features

    • User avatar and cover image URLs are now available via API.
  • Bug Fixes

    • Improved cover image upload handling for better reliability with user-uploaded assets.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

S3Storage.__init__ gains an is_server flag to route MinIO signed URLs to the public endpoint (MINIO_PUBLIC_ENDPOINT_URL) for browser use or the internal endpoint for server-side calls. UserSerializer exposes avatar_url and cover_image_url as read-only fields. handleCoverImageChange adds an early-return guard for user-asset uploads that don't resolve to an HTTP URL.

Changes

MinIO Public Endpoint Routing

Layer / File(s) Summary
S3Storage is_server flag and endpoint selection
apps/api/plane/settings/storage.py, apps/api/plane/tests/unit/settings/test_storage.py
S3Storage.__init__ accepts is_server=False and reads MINIO_PUBLIC_ENDPOINT_URL from the environment. When USE_MINIO is enabled, endpoint_url is set to the public endpoint (non-server path) or the internal endpoint (server path) before constructing the boto3 client. A new unit test verifies the boto3 client receives the public endpoint URL.

User Asset URL Exposure and Upload Guard

Layer / File(s) Summary
UserSerializer read-only URL fields
apps/api/plane/app/serializers/user.py
avatar_url and cover_image_url are appended to fields and added to read_only_fields in UserSerializer.Meta.
Cover image upload early return for user assets
apps/web/helpers/cover-image.helper.ts
After uploadCoverImage runs, a new branch checks uploadConfig.isUserAsset and whether newImage starts with "http"; if it is a user asset without an HTTP URL, handleCoverImageChange returns immediately.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hoppin' through the storage lane,
Public endpoints, server plain,
Avatar URLs now shine in view,
Read-only fields, nothing askew.
Early return for assets fair—
A tidy warren, beyond compare! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title addresses the main bug fix for relative URL validation errors in self-hosted MinIO setups, which is accurately reflected in the changes across backend serializer configuration and frontend upload handling.
Description check ✅ Passed The description provides clear context about the bug fix, type of change is properly selected, and includes a screenshot. However, the Test Scenarios section is empty with only a placeholder comment.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/api/plane/tests/unit/settings/test_storage.py (1)

67-78: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add a companion test for the is_server=True branch.

The new test verifies only the public-endpoint path. Please add a second assertion/test that S3Storage(request=request, is_server=True) keeps endpoint_url on the internal endpoint, so the new contract is fully pinned.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/tests/unit/settings/test_storage.py` around lines 67 - 78, Add
a companion test method that verifies the behavior when S3Storage is initialized
with is_server=True parameter. The new test should follow the same setup pattern
as test_minio_uses_public_endpoint_for_request_signed_urls but pass
is_server=True to the S3Storage constructor, and assert that the endpoint_url in
the boto3 client call_kwargs uses the internal endpoint (not the public
localhost endpoint), ensuring the internal server branch of the endpoint
selection logic is fully covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/plane/settings/storage.py`:
- Around line 47-50: The issue is that browser-facing presigned URL generation
in asset.py is incorrectly instantiating S3Storage with is_server=True, which
causes presigned URLs to point to the internal MinIO endpoint instead of the
public endpoint that browsers need. Find the S3Storage instantiation in the
presigned upload flow (around line 337-349 in asset.py) and change
is_server=True to is_server=False so that the public endpoint URL is used for
presigned URLs returned to clients.

---

Nitpick comments:
In `@apps/api/plane/tests/unit/settings/test_storage.py`:
- Around line 67-78: Add a companion test method that verifies the behavior when
S3Storage is initialized with is_server=True parameter. The new test should
follow the same setup pattern as
test_minio_uses_public_endpoint_for_request_signed_urls but pass is_server=True
to the S3Storage constructor, and assert that the endpoint_url in the boto3
client call_kwargs uses the internal endpoint (not the public localhost
endpoint), ensuring the internal server branch of the endpoint selection logic
is fully covered.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: dbca2950-a059-4bda-bd8b-3774052424dc

📥 Commits

Reviewing files that changed from the base of the PR and between 4a0746b and d5c057d.

📒 Files selected for processing (4)
  • apps/api/plane/app/serializers/user.py
  • apps/api/plane/settings/storage.py
  • apps/api/plane/tests/unit/settings/test_storage.py
  • apps/web/helpers/cover-image.helper.ts

Comment thread apps/api/plane/settings/storage.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant