Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion apps/api/plane/app/serializers/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ def validate_last_name(self, value):
class Meta:
model = User
# Exclude password field from the serializer
fields = [field.name for field in User._meta.fields if field.name != "password"]
fields = [field.name for field in User._meta.fields if field.name != "password"] + [
"avatar_url",
"cover_image_url",
]
# Make all system fields and email read only
read_only_fields = [
"id",
Expand All @@ -53,6 +56,8 @@ class Meta:
"is_email_verified",
"is_active",
"token_updated_at",
"avatar_url",
"cover_image_url",
]

# If the user has already filled first name or last name then he is onboarded
Expand Down
10 changes: 8 additions & 2 deletions apps/api/plane/settings/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def url(self, name, parameters=None, expire=None, http_method=None):

"""S3 storage class to generate presigned URLs for S3 objects"""

def __init__(self, request=None):
def __init__(self, request=None, is_server=False):
# Get the AWS credentials and bucket name from the environment
self.aws_access_key_id = os.environ.get("AWS_ACCESS_KEY_ID")
# Use the AWS_SECRET_ACCESS_KEY environment variable for the secret key
Expand All @@ -33,6 +33,7 @@ def __init__(self, request=None):
self.aws_region = os.environ.get("AWS_REGION")
# Use the AWS_S3_ENDPOINT_URL environment variable for the endpoint URL
self.aws_s3_endpoint_url = os.environ.get("AWS_S3_ENDPOINT_URL") or os.environ.get("MINIO_ENDPOINT_URL")
self.aws_s3_public_endpoint_url = os.environ.get("MINIO_PUBLIC_ENDPOINT_URL")
# Use the SIGNED_URL_EXPIRATION environment variable for the expiration time (default: 3600 seconds)
self.signed_url_expiration = int(os.environ.get("SIGNED_URL_EXPIRATION", "3600"))

Expand All @@ -42,13 +43,18 @@ def __init__(self, request=None):
endpoint_protocol = "https"
else:
endpoint_protocol = request.scheme if request else "http"
endpoint_url = self.aws_s3_endpoint_url
if not is_server:
endpoint_url = self.aws_s3_public_endpoint_url or (
f"{endpoint_protocol}://{request.get_host()}" if request else self.aws_s3_endpoint_url
)
Comment thread
karthiksuki marked this conversation as resolved.
# Create an S3 client for MinIO
self.s3_client = boto3.client(
"s3",
aws_access_key_id=self.aws_access_key_id,
aws_secret_access_key=self.aws_secret_access_key,
region_name=self.aws_region,
endpoint_url=(f"{endpoint_protocol}://{request.get_host()}" if request else self.aws_s3_endpoint_url),
endpoint_url=endpoint_url,
config=boto3.session.Config(signature_version="s3v4"),
)
else:
Expand Down
25 changes: 25 additions & 0 deletions apps/api/plane/tests/unit/settings/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,31 @@ def test_custom_expiration_multiple_values(self, mock_boto3):
# Assert expiration is 300
assert storage.signed_url_expiration == 300

@patch.dict(
os.environ,
{
"AWS_ACCESS_KEY_ID": "test-key",
"AWS_SECRET_ACCESS_KEY": "test-secret",
"AWS_S3_BUCKET_NAME": "test-bucket",
"AWS_S3_ENDPOINT_URL": "http://plane-minio:9000",
"MINIO_PUBLIC_ENDPOINT_URL": "http://localhost:9000",
"USE_MINIO": "1",
},
clear=True,
)
@patch("plane.settings.storage.boto3")
def test_minio_uses_public_endpoint_for_request_signed_urls(self, mock_boto3):
"""Test MinIO signed URLs use a browser-reachable endpoint when configured"""
mock_boto3.client.return_value = Mock()
request = Mock()
request.scheme = "http"
request.get_host.return_value = "localhost:8000"

S3Storage(request=request)

call_kwargs = mock_boto3.client.call_args[1]
assert call_kwargs["endpoint_url"] == "http://localhost:9000"

@patch.dict(
os.environ,
{
Expand Down
4 changes: 4 additions & 0 deletions apps/web/helpers/cover-image.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ export const handleCoverImageChange = async (
return;
}

if (uploadConfig.isUserAsset && !newImage.startsWith("http")) {
return;
}

return { cover_image: newImage };
};

Expand Down
Loading