Skip to content

Commit 72b99a2

Browse files
committed
Add API endpoint to check snap CVEs data availability
1 parent 8c42f8d commit 72b99a2

3 files changed

Lines changed: 83 additions & 29 deletions

File tree

webapp/publisher/cve/cve_helper.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ def _fetch_file_content(snap_name, revision, file_metadata):
109109
else:
110110
raise NotFound
111111

112+
@staticmethod
113+
def has_cve_data(snap_name):
114+
file_metadata = CveHelper._get_cve_file_metadata(
115+
"snap-cves/{}.json".format(snap_name)
116+
)
117+
118+
return bool(file_metadata)
119+
112120
@staticmethod
113121
def get_cve_with_revision(snap_name, revision):
114122
file_metadata = CveHelper._get_cve_file_metadata(

webapp/publisher/cve/cve_views.py

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,84 @@
11
import flask
22
from canonicalwebteam.store_api.dashboard import Dashboard
3-
3+
from canonicalwebteam.exceptions import StoreApiResourceNotFound, StoreApiError
44
from webapp.helpers import api_publisher_session
55
from webapp.decorators import login_required
66
from webapp.publisher.cve.cve_helper import CveHelper
77

88
dashboard = Dashboard(api_publisher_session)
99

1010

11+
def can_user_access_cve_data(snap_name):
12+
"""
13+
Check if the user has access to CVE data for the given snap.
14+
15+
:return: A tuple containing:
16+
has_access (bool): True if the user has access, False otherwise.
17+
error_message (str): Error message if access is denied.
18+
status_code (int): HTTP status code for the response.
19+
"""
20+
is_user_canonical = flask.session["publisher"].get("is_canonical", False)
21+
22+
# TODO: in future with brand store support we will need more specific
23+
# checks, such as those implemented in CveHelper.can_user_access_cve_data
24+
# For now, we only check if user is Canonical member and has
25+
# publisher access to the snap.
26+
if not is_user_canonical:
27+
return (False, "User is not allowed to see snap's CVE data.", 403)
28+
29+
try:
30+
snap_details = dashboard.get_snap_info(flask.session, snap_name)
31+
except StoreApiResourceNotFound:
32+
return (False, f"CVEs data for '{snap_name}' snap not found.", 404)
33+
except StoreApiError:
34+
return (False, f"Error fetching '{snap_name}' snap details.", 500)
35+
36+
if not snap_details:
37+
return (False, f"CVEs data for '{snap_name}' snap not found.", 404)
38+
39+
return (True, None, 200)
40+
41+
42+
@login_required
43+
def has_cves(snap_name):
44+
45+
# Check if the user has access to CVE data for the given snap
46+
has_access, error_message, status_code = can_user_access_cve_data(
47+
snap_name
48+
)
49+
if not has_access:
50+
return (
51+
flask.jsonify({"success": False, "error": error_message}),
52+
status_code,
53+
)
54+
55+
snap_has_cves = CveHelper.has_cve_data(snap_name)
56+
if snap_has_cves:
57+
return flask.jsonify({"success": True, "has_cves": True})
58+
else:
59+
return (
60+
flask.jsonify(
61+
{
62+
"success": True,
63+
"has_cves": False,
64+
"error": f"No CVEs data available for '{snap_name}' snap.",
65+
}
66+
),
67+
404,
68+
)
69+
70+
1171
@login_required
1272
def get_cves(snap_name, revision):
73+
# Check if the user has access to CVE data for the given snap
74+
has_access, error_message, status_code = can_user_access_cve_data(
75+
snap_name
76+
)
77+
if not has_access:
78+
return (
79+
flask.jsonify({"success": False, "error": error_message}),
80+
status_code,
81+
)
1382

1483
# Filtering params
1584
usn_ids = flask.request.args.getlist("usn_id")
@@ -59,34 +128,6 @@ def get_cves(snap_name, revision):
59128
# Pagination params
60129
page = flask.request.args.get("page", default=1, type=int)
61130
page_size = flask.request.args.get("page_size", default=10, type=int)
62-
is_user_canonical = flask.session["publisher"].get("is_canonical", False)
63-
64-
# TODO: in future with brand store support we will need more specific
65-
# checks, such as those implemented in CveHelper.can_user_access_cve_data
66-
# For now, we only check if user is Canonical member and has
67-
# publisher access to the snap.
68-
if not is_user_canonical:
69-
return (
70-
flask.jsonify(
71-
{
72-
"success": False,
73-
"error": "User is not allowed to see snap's CVE data.",
74-
}
75-
),
76-
403,
77-
)
78-
79-
snap_details = dashboard.get_snap_info(flask.session, snap_name)
80-
if not snap_details:
81-
return (
82-
flask.jsonify(
83-
{
84-
"success": False,
85-
"error": f"Snap '{snap_name}' not found.",
86-
}
87-
),
88-
404,
89-
)
90131

91132
cves = CveHelper.get_cve_with_revision(snap_name, revision)
92133
cves = CveHelper.filter_cve_data(

webapp/publisher/snaps/views.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@
285285
view_func=cve_views.get_cves,
286286
)
287287

288+
publisher_snaps.add_url_rule(
289+
"/api/snaps/cve/<snap_name>",
290+
view_func=cve_views.has_cves,
291+
)
292+
288293

289294
@publisher_snaps.route("/account/snaps")
290295
@login_required

0 commit comments

Comments
 (0)