Skip to content

Commit b5dbf51

Browse files
committed
Replace availability API with getting list of revisions from folder contents
1 parent a81244b commit b5dbf51

5 files changed

Lines changed: 68 additions & 34 deletions

File tree

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,49 @@
11
import unittest
2-
from unittest.mock import patch, MagicMock
2+
from unittest.mock import patch
33

44
from webapp.publisher.cve.cve_helper import CveHelper
5+
from werkzeug.exceptions import NotFound
56

67

7-
class HasCvesTest(unittest.TestCase):
8+
class HasRevisionsWithCvesTest(unittest.TestCase):
89

9-
def setUp(self):
10-
self.file_metadata = {"download_url": "https://example.com/file.json"}
10+
@patch("webapp.publisher.cve.cve_helper.CveHelper._get_cve_file_metadata")
11+
def test_returns_revision_numbers(self, mock_get_metadata):
12+
mock_get_metadata.return_value = [
13+
{"name": "123.yaml"},
14+
{"name": "456.yaml"},
15+
{"name": "789.yaml"},
16+
]
1117

12-
@patch("requests.get")
13-
def test_has_cve_data(self, mock_get):
14-
mock_get.side_effect = [
15-
MagicMock(status_code=200, json=lambda: self.file_metadata),
18+
result = CveHelper.has_revisions_with_cves("my-snap")
19+
self.assertEqual(result, [123, 456, 789])
20+
21+
@patch("webapp.publisher.cve.cve_helper.CveHelper._get_cve_file_metadata")
22+
def test_ignores_non_yaml_files(self, mock_get_metadata):
23+
mock_get_metadata.return_value = [
24+
{"name": "README.md"},
25+
{"name": "123.yaml"},
26+
{"name": "abc.yaml"},
27+
{"name": "456.yaml"},
28+
{"name": "data.txt"},
1629
]
1730

18-
result = CveHelper.has_cve_data("my-snap")
19-
self.assertTrue(result)
31+
result = CveHelper.has_revisions_with_cves("my-snap")
32+
self.assertEqual(result, [123, 456])
2033

21-
@patch("requests.get")
22-
def test_has_cve_data_not_found(self, mock_get):
23-
mock_get.side_effect = [
24-
MagicMock(status_code=404, json=lambda: {}),
34+
@patch("webapp.publisher.cve.cve_helper.CveHelper._get_cve_file_metadata")
35+
def test_returns_empty_list_if_no_revision_files(self, mock_get_metadata):
36+
mock_get_metadata.return_value = [
37+
{"name": "README.md"},
38+
{"name": "notes.txt"},
2539
]
2640

27-
result = CveHelper.has_cve_data("my-snap")
28-
self.assertFalse(result)
41+
result = CveHelper.has_revisions_with_cves("my-snap")
42+
self.assertEqual(result, [])
43+
44+
@patch("webapp.publisher.cve.cve_helper.CveHelper._get_cve_file_metadata")
45+
def test_returns_empty_list_on_not_found(self, mock_get_metadata):
46+
mock_get_metadata.side_effect = NotFound()
47+
48+
result = CveHelper.has_revisions_with_cves("my-snap")
49+
self.assertEqual(result, [])

tests/publisher/cve/test_has_cve_api.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ def _set_user_is_canonical(self, value):
3131

3232
class TestModelServiceEndpoints(TestEndpoints):
3333
@patch(
34-
"webapp.publisher.cve.cve_helper.CveHelper.has_cve_data",
35-
return_value=True,
34+
"webapp.publisher.cve.cve_helper.CveHelper.has_revisions_with_cves",
35+
return_value=[123, 321],
3636
)
3737
@patch(
3838
"canonicalwebteam.store_api.dashboard.Dashboard.get_snap_info",
@@ -41,15 +41,15 @@ class TestModelServiceEndpoints(TestEndpoints):
4141
def test_has_cves_for_canonical_user(self, mock_get_snap_info, mock_get):
4242
self._set_user_is_canonical(True)
4343

44-
response = self.client.get("api/test/cves/available")
44+
response = self.client.get("api/test/cves")
4545
data = response.json
4646

4747
self.assertEqual(response.status_code, 200)
4848
self.assertEqual(data["success"], True)
4949

5050
@patch(
51-
"webapp.publisher.cve.cve_helper.CveHelper.has_cve_data",
52-
return_value=False,
51+
"webapp.publisher.cve.cve_helper.CveHelper.has_revisions_with_cves",
52+
return_value=[],
5353
)
5454
@patch(
5555
"canonicalwebteam.store_api.dashboard.Dashboard.get_snap_info",
@@ -58,14 +58,14 @@ def test_has_cves_for_canonical_user(self, mock_get_snap_info, mock_get):
5858
def test_has_cves_no_data(self, mock_get_snap_info, mock_get):
5959
self._set_user_is_canonical(True)
6060

61-
response = self.client.get("api/test/cves/available")
61+
response = self.client.get("api/test/cves")
6262
data = response.json
6363

6464
self.assertEqual(response.status_code, 404)
6565
self.assertEqual(data["success"], False)
6666

6767
def test_has_cves_for_non_canonical_user(self):
68-
response = self.client.get("api/test/cves/available")
68+
response = self.client.get("api/test/cves")
6969
data = response.json
7070

7171
self.assertEqual(response.status_code, 403)

webapp/publisher/cve/cve_helper.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
from os import getenv
33
import requests
4+
import re
45

56
from werkzeug.exceptions import NotFound
67

@@ -110,14 +111,24 @@ def _fetch_file_content(snap_name, revision, file_metadata):
110111
raise NotFound
111112

112113
@staticmethod
113-
def has_cve_data(snap_name):
114+
def has_revisions_with_cves(snap_name):
114115
try:
115-
CveHelper._get_cve_file_metadata(
116-
"snap-cves/{}.json".format(snap_name)
116+
contents = CveHelper._get_cve_file_metadata(
117+
f"snap-cves/{snap_name}"
117118
)
118-
return True
119+
120+
# find all revision YAML files in the folder
121+
# e.g., 123.yaml, 456.yaml, 789.yaml
122+
# and extract the revision numbers
123+
revision_files = [
124+
int(match.group(1))
125+
for item in contents
126+
if (match := re.match(r"(\d+)\.yaml$", item["name"]))
127+
]
128+
129+
return revision_files
119130
except NotFound:
120-
return False
131+
return []
121132

122133
@staticmethod
123134
def get_cve_with_revision(snap_name, revision):

webapp/publisher/cve/cve_views.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def can_user_access_cve_data(snap_name):
4040

4141

4242
@login_required
43-
def has_cves(snap_name):
43+
def get_revisions_with_cves(snap_name):
4444

4545
# Check if the user has access to CVE data for the given snap
4646
has_access, error_message, status_code = can_user_access_cve_data(
@@ -52,9 +52,11 @@ def has_cves(snap_name):
5252
status_code,
5353
)
5454

55-
snap_has_cves = CveHelper.has_cve_data(snap_name)
56-
if snap_has_cves:
57-
return flask.jsonify({"success": True})
55+
revisions_with_cves = CveHelper.has_revisions_with_cves(snap_name)
56+
if len(revisions_with_cves) > 0:
57+
return flask.jsonify(
58+
{"success": True, "revisions": revisions_with_cves}
59+
)
5860
else:
5961
return (
6062
flask.jsonify(

webapp/publisher/snaps/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,8 @@
286286
)
287287

288288
publisher_snaps.add_url_rule(
289-
"/api/<snap_name>/cves/available",
290-
view_func=cve_views.has_cves,
289+
"/api/<snap_name>/cves",
290+
view_func=cve_views.get_revisions_with_cves,
291291
)
292292

293293

0 commit comments

Comments
 (0)