Skip to content
Closed
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
36 changes: 36 additions & 0 deletions tests/store/tests_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"version": "1.0",
"confinement": "conf",
"download": {"size": 100000},
"revision": "rev-123",
}
],
}
Expand All @@ -55,6 +56,8 @@ class GetDetailsPageTest(BaseFlaskTestCase):
def setUp(self):
super().setUp()
self.snap_name = "toto"
self.snap_id = "id"
self.revision = "rev-123"
self.api_url = "".join(
[
"https://api.snapcraft.io/v2/",
Expand All @@ -81,6 +84,7 @@ def setUp(self):
"trending",
"unlisted",
"links",
"revision",
]
)
}
Expand All @@ -97,6 +101,13 @@ def setUp(self):
urlencode({"fields": ",".join(["aliases"])}),
]
)
self.sbom_url = "".join(
[
"https://api.snapcraft.io/api/v1/",
"sboms/download/",
f"sbom_snap_{self.snap_id}_{self.revision}.spdx2.3.json",
]
)

def create_app(self):
app = create_app(testing=True)
Expand Down Expand Up @@ -159,6 +170,11 @@ def test_extra_details_error(self):
status=404,
)
)
responses.add(
responses.Response(
method="HEAD", url=self.sbom_url, json={}, status=200
)
)
metrics_url = "https://api.snapcraft.io/api/v1/snaps/metrics"
responses.add(
responses.Response(
Expand Down Expand Up @@ -260,6 +276,11 @@ def test_user_connected(self):
status=200,
)
)
responses.add(
responses.Response(
method="HEAD", url=self.sbom_url, json={}, status=200
)
)

metrics_url = "https://api.snapcraft.io/api/v1/snaps/metrics"
responses.add(
Expand Down Expand Up @@ -298,6 +319,11 @@ def test_user_not_connected(self):
status=200,
)
)
responses.add(
responses.Response(
method="HEAD", url=self.sbom_url, json={}, status=200
)
)

metrics_url = "https://api.snapcraft.io/api/v1/snaps/metrics"
responses.add(
Expand Down Expand Up @@ -328,6 +354,11 @@ def test_user_connected_on_not_own_snap(self):
status=200,
)
)
responses.add(
responses.Response(
method="HEAD", url=self.sbom_url, json={}, status=200
)
)

metrics_url = "https://api.snapcraft.io/api/v1/snaps/metrics"
responses.add(
Expand Down Expand Up @@ -374,6 +405,11 @@ def test_extra_details(self):
status=200,
)
)
responses.add(
responses.Response(
method="HEAD", url=self.sbom_url, json={}, status=200
)
)
metrics_url = "https://api.snapcraft.io/api/v1/snaps/metrics"
responses.add(
responses.Response(
Expand Down
2 changes: 2 additions & 0 deletions tests/store/tests_distro_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class GetDistroPageTest(BaseFlaskTestCase):
"version": "1.0",
"confinement": "conf",
"download": {"size": 100000},
"revision": "rev-123",
}
],
}
Expand Down Expand Up @@ -71,6 +72,7 @@ def setUp(self):
"trending",
"unlisted",
"links",
"revision",
]
)
}
Expand Down
2 changes: 2 additions & 0 deletions tests/store/tests_embedded_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class GetEmbeddedCardTest(BaseFlaskTestCase):
"version": "1.0",
"confinement": "conf",
"download": {"size": 100000},
"revision": "rev-123",
}
],
}
Expand Down Expand Up @@ -71,6 +72,7 @@ def setUp(self):
"trending",
"unlisted",
"links",
"revision",
]
)
}
Expand Down
3 changes: 3 additions & 0 deletions tests/store/tests_github_badge.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class GetGitHubBadgeTest(BaseFlaskTestCase):
"version": "1.0",
"confinement": "conf",
"download": {"size": 100000},
"revision": "rev-123",
},
{
"channel": {
Expand All @@ -51,6 +52,7 @@ class GetGitHubBadgeTest(BaseFlaskTestCase):
"version": "1.0",
"confinement": "conf",
"download": {"size": 100000},
"revision": "rev-123",
},
],
}
Expand Down Expand Up @@ -84,6 +86,7 @@ def setUp(self):
"trending",
"unlisted",
"links",
"revision",
]
)
}
Expand Down
10 changes: 10 additions & 0 deletions tests/store/tests_public_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def test_one_track_channel_map(self):
"confinement": "confinement",
"download": {"size": "size"},
"version": "version",
"revision": "revision",
}
]

Expand All @@ -42,6 +43,7 @@ def test_one_track_channel_map(self):
"size": "size",
"risk": "risk",
"version": "version",
"revision": "revision",
}
]
}
Expand All @@ -63,6 +65,7 @@ def test_multiple_track_same_arch_channel_map(self):
"confinement": "confinement",
"download": {"size": "size"},
"version": "version",
"revision": "revision",
},
{
"channel": {
Expand All @@ -76,6 +79,7 @@ def test_multiple_track_same_arch_channel_map(self):
"confinement": "confinement",
"download": {"size": "size"},
"version": "version",
"revision": "revision",
},
]
result = logic.convert_channel_maps(channel_maps_list)
Expand All @@ -89,6 +93,7 @@ def test_multiple_track_same_arch_channel_map(self):
"size": "size",
"risk": "risk",
"version": "version",
"revision": "revision",
}
],
"track1": [
Expand All @@ -99,6 +104,7 @@ def test_multiple_track_same_arch_channel_map(self):
"size": "size",
"risk": "risk",
"version": "version",
"revision": "revision",
}
],
}
Expand All @@ -120,6 +126,7 @@ def test_multiple_track_different_arch_channel_map(self):
"confinement": "confinement",
"download": {"size": "size"},
"version": "version",
"revision": "revision",
},
{
"channel": {
Expand All @@ -133,6 +140,7 @@ def test_multiple_track_different_arch_channel_map(self):
"confinement": "confinement",
"download": {"size": "size"},
"version": "version",
"revision": "revision",
},
]

Expand All @@ -147,6 +155,7 @@ def test_multiple_track_different_arch_channel_map(self):
"size": "size",
"risk": "risk",
"version": "version",
"revision": "revision",
}
]
},
Expand All @@ -159,6 +168,7 @@ def test_multiple_track_different_arch_channel_map(self):
"size": "size",
"risk": "risk",
"version": "version",
"revision": "revision",
}
]
},
Expand Down
1 change: 1 addition & 0 deletions webapp/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"www.facebook.com",
"px.ads.linkedin.com",
"*.snapcraft.io",
"*.snapcraftcontent.com",
],
"frame-src": [
"'self'",
Expand Down
9 changes: 9 additions & 0 deletions webapp/store/logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def convert_channel_maps(channel_map):
"risk": channel["channel"].get("risk"),
"confinement": channel.get("confinement"),
"size": channel["download"].get("size"),
"revision": channel["revision"],
}

channel_map_restruct[arch][track].append(info)
Expand Down Expand Up @@ -314,6 +315,14 @@ def get_latest_versions(
return default_stable, other


def get_revisions(channel_maps: list) -> list:
revisions = []
for channel_map in channel_maps:
revisions.append(channel_map["revision"])

return list(reversed(sorted(revisions)))


def get_last_updated_versions(channel_maps):
"""Get all channels in order of updates

Expand Down
40 changes: 37 additions & 3 deletions webapp/store/snap_details_views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import flask
from flask import Response
import requests

import logging
import humanize
Expand All @@ -22,8 +23,11 @@
from pybadges import badge

device_gateway = DeviceGW("snap", helpers.api_session)
device_gateway_sbom = DeviceGW("sbom", helpers.api_session)

logger = logging.getLogger(__name__)


FIELDS = [
"title",
"summary",
Expand All @@ -41,6 +45,7 @@
"trending",
"unlisted",
"links",
"revision",
]

FIELDS_EXTRA_DETAILS = [
Expand Down Expand Up @@ -87,6 +92,8 @@ def _get_context_snap_details(snap_name, supported_architectures=None):
details.get("channel-map")
)

revisions = logic.get_revisions(details.get("channel-map"))

default_track = (
details.get("default-track")
if details.get("default-track")
Expand Down Expand Up @@ -163,7 +170,7 @@ def _get_context_snap_details(snap_name, supported_architectures=None):
developer = logic.get_snap_developer(details["name"])

context = {
"snap-id": details.get("snap-id"),
"snap_id": details.get("snap-id"),
# Data direct from details API
"snap_title": details["snap"]["title"],
"package_name": details["name"],
Expand Down Expand Up @@ -206,9 +213,32 @@ def _get_context_snap_details(snap_name, supported_architectures=None):
},
"links": details["snap"].get("links"),
"updates": updates,
"revisions": revisions,
}
return context

def snap_has_sboms(revisions, snap_id):
sbom_path = f"download/sbom_snap_{snap_id}_{revisions[0]}.spdx2.3.json"
endpoint = device_gateway_sbom.get_endpoint_url(sbom_path)

res = requests.head(endpoint)

# backend returns 302 instead of 200 for a successful request
# adding the check for 200 in case this is changed without us knowing
if res.status_code == 200 or res.status_code == 302:
return True

return False

@store.route("/sbom/<snap_id>/<revision>")
def get_sbom(snap_id, revision):
sbom_path = f"download/sbom_snap_{snap_id}_{revision}.spdx2.3.json"
endpoint = device_gateway_sbom.get_endpoint_url(sbom_path)

res = requests.get(endpoint)

return res.json()

@store.route('/<regex("' + snap_regex + '"):snap_name>')
def snap_details(snap_name):
"""
Expand Down Expand Up @@ -251,13 +281,13 @@ def snap_details(snap_name):
metrics_query_json = [
metrics_helper.get_filter(
metric_name=country_metric_name,
snap_id=context["snap-id"],
snap_id=context["snap_id"],
start=end,
end=end,
),
metrics_helper.get_filter(
metric_name=os_metric_name,
snap_id=context["snap-id"],
snap_id=context["snap_id"],
start=end,
end=end,
),
Expand Down Expand Up @@ -289,6 +319,8 @@ def snap_details(snap_name):
private=False,
)

has_sboms = snap_has_sboms(context["revisions"], context["snap_id"])

context.update(
{
"countries": (
Expand All @@ -305,6 +337,8 @@ def snap_details(snap_name):
}
)

context["has_sboms"] = has_sboms

return (
flask.render_template("store/snap-details.html", **context),
status_code,
Expand Down