Skip to content

Commit

Permalink
fix: Accept SVG as avatar_url
Browse files Browse the repository at this point in the history
Make download_avatar task to accept .svg up to 3MB

Issue: AAH-2836
  • Loading branch information
rochacbruno committed Feb 27, 2024
1 parent d0bf488 commit 36c7fd6
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGES/2836.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support SVG avatar image on namespaces
11 changes: 10 additions & 1 deletion galaxy_ng/app/management/commands/download-namespace-logos.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ def handle(self, *args, **options):
self.echo(f"Task failed with error: {task.error}", self.style.ERROR)
sys.exit(1)

# Report if any namespace are still inconsistent.
namespaces_with_avatar_but_not_sha = Namespace.objects.filter(
_avatar_url__isnull=False,
last_created_pulp_metadata__avatar_sha256__isnull=True
)
if namespaces_with_avatar_but_not_sha:
self.echo("Namespaces with avatar_url set but missing sha_256")
self.echo(", ".join(namespaces_with_avatar_but_not_sha.values_list("name", flat=True)))


def download_all_logos(namespace_name=None):
if namespace_name:
Expand All @@ -62,4 +71,4 @@ def download_all_logos(namespace_name=None):
if namespace._avatar_url:
download_logo = True

_create_pulp_namespace(namespace.pk, download_logo=download_logo)
_create_pulp_namespace(namespace.pk, download_logo=download_logo)
31 changes: 24 additions & 7 deletions galaxy_ng/app/tasks/namespaces.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import aiohttp
import asyncio
import contextlib
import xml.etree.cElementTree as et

from django.db import transaction
from django.forms.fields import ImageField
Expand All @@ -15,6 +17,9 @@
from galaxy_ng.app.models import Namespace


MAX_AVATAR_SIZE = 3 * 1024 * 1024 # 3MB


def dispatch_create_pulp_namespace_metadata(galaxy_ns, download_logo):

dispatch(
Expand All @@ -27,10 +32,15 @@ def dispatch_create_pulp_namespace_metadata(galaxy_ns, download_logo):


def _download_avatar(url):
# User-Agent needs to be added to avoid timing out on throtled servers.
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0)' # +
' Gecko/20100101 Firefox/71.0'
}
timeout = aiohttp.ClientTimeout(total=None, sock_connect=600, sock_read=600)
conn = aiohttp.TCPConnector(force_close=True)
session = aiohttp.ClientSession(
connector=conn, timeout=timeout, headers=None, requote_redirect_url=False
connector=conn, timeout=timeout, headers=headers, requote_redirect_url=False
)

try:
Expand All @@ -41,19 +51,26 @@ def _download_avatar(url):
finally:
asyncio.get_event_loop().run_until_complete(session.close())

try:
# Limit size of the avatar to avoid memory issues when validating it
if img.artifact_attributes["size"] > MAX_AVATAR_SIZE:
raise ValidationError(f"Avatar size is larger than {MAX_AVATAR_SIZE / 1024 / 1024}MB")

with contextlib.suppress(Artifact.DoesNotExist):
return Artifact.objects.get(sha256=img.artifact_attributes["sha256"])
except Artifact.DoesNotExist:
pass

with open(img.path, "rb") as f:
tf = PulpTemporaryUploadedFile.from_file(f)

try:
ImageField().to_python(tf)
except ValidationError:
print("file is not an image")
return
# Not a PIL valid image lets handle SVG case
tag = None
with contextlib.suppress(et.ParseError):
f.seek(0)
tag = et.parse(f).find(".").tag
if tag != '{http://www.w3.org/2000/svg}svg':
print("file is not an image or svg file")
return

# the artifact has to be saved before the file is closed, or s3transfer
# will throw an error.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def test_namespace_edit_logo(galaxy_client):
wait_for_all_tasks_gk(gc)
updated_again_namespace = gc.get(f"_ui/v1/my-namespaces/{name}/")
assert updated_namespace["avatar_url"] != updated_again_namespace["avatar_url"]
assert updated_namespace["avatar_sha256"] is not None

# verify no additional namespaces are created
resp = gc.get("_ui/v1/my-namespaces/")
Expand Down

0 comments on commit 36c7fd6

Please sign in to comment.