Skip to content

Commit e8ae022

Browse files
authored
feat: Add endpoint for remodel allowlist (#5576)
1 parent f8e05b6 commit e8ae022

3 files changed

Lines changed: 140 additions & 1 deletion

File tree

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ canonicalwebteam.discourse==7.0.0
66
canonicalwebteam.blog==6.6.0
77
canonicalwebteam.search==2.1.2
88
canonicalwebteam.image-template==1.9.0
9-
canonicalwebteam.store-api==7.3.8
9+
canonicalwebteam.store-api==7.3.10
1010
canonicalwebteam.launchpad==0.9.0
1111
django-openid-auth==0.17
1212
Flask-OpenID==1.3.0

tests/endpoints/tests_models.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,103 @@ def test_model_not_found(self, mock_update_store_model):
162162
self.assertEqual(response.status_code, 500)
163163
self.assertFalse(data["success"])
164164
self.assertEqual(data["message"], "Model not found")
165+
166+
167+
class TestGetRemodelAllowlist(TestModelServiceEndpoints):
168+
@patch(
169+
"canonicalwebteam.store_api.publishergw.PublisherGW"
170+
+ ".get_remodel_allowlist"
171+
)
172+
def test_get_remodel_allowlist_success(self, mock_get_remodel_allowlist):
173+
mock_allowlist = {
174+
"allowlist": [
175+
{
176+
"created-at": "2026-02-03T11:31:06Z",
177+
"created-by": "test-user-id",
178+
"description": "Test description",
179+
"from-model": "test-from-model",
180+
"from-serial": "test-from-serial",
181+
"modified-at": None,
182+
"modified-by": None,
183+
"to-model": "test-to-model",
184+
}
185+
]
186+
}
187+
mock_get_remodel_allowlist.return_value = mock_allowlist
188+
189+
response = self.client.get("/api/store/1/models/remodel-allowlist")
190+
data = response.json
191+
192+
self.assertEqual(response.status_code, 200)
193+
self.assertTrue(data["success"])
194+
self.assertEqual(data["data"], mock_allowlist)
195+
196+
@patch(
197+
"canonicalwebteam.store_api.publishergw.PublisherGW"
198+
+ ".get_remodel_allowlist"
199+
)
200+
def test_get_remodel_allowlist_empty(self, mock_get_remodel_allowlist):
201+
mock_get_remodel_allowlist.return_value = {"allowlist": []}
202+
203+
response = self.client.get("/api/store/1/models/remodel-allowlist")
204+
data = response.json
205+
206+
self.assertEqual(response.status_code, 200)
207+
self.assertTrue(data["success"])
208+
self.assertEqual(data["data"]["allowlist"], [])
209+
210+
@patch(
211+
"canonicalwebteam.store_api.publishergw.PublisherGW"
212+
+ ".get_remodel_allowlist"
213+
)
214+
def test_get_remodel_allowlist_unauthorized(
215+
self, mock_get_remodel_allowlist
216+
):
217+
mock_get_remodel_allowlist.side_effect = StoreApiResponseErrorList(
218+
"unauthorized", 401, [{"message": "unauthorized"}]
219+
)
220+
221+
response = self.client.get("/api/store/1/models/remodel-allowlist")
222+
data = response.json
223+
224+
self.assertEqual(response.status_code, 500)
225+
self.assertFalse(data["success"])
226+
self.assertEqual(data["message"], "Store not found")
227+
228+
@patch(
229+
"canonicalwebteam.store_api.publishergw.PublisherGW"
230+
+ ".get_remodel_allowlist"
231+
)
232+
def test_get_remodel_allowlist_store_not_found(
233+
self, mock_get_remodel_allowlist
234+
):
235+
mock_get_remodel_allowlist.side_effect = StoreApiResponseErrorList(
236+
"Store not found", 404, [{"message": "Store not found"}]
237+
)
238+
239+
response = self.client.get("/api/store/999/models/remodel-allowlist")
240+
data = response.json
241+
242+
self.assertEqual(response.status_code, 500)
243+
self.assertFalse(data["success"])
244+
self.assertEqual(data["message"], "Store not found")
245+
246+
@patch(
247+
"canonicalwebteam.store_api.publishergw.PublisherGW"
248+
+ ".get_remodel_allowlist"
249+
)
250+
def test_get_remodel_allowlist_general_error(
251+
self, mock_get_remodel_allowlist
252+
):
253+
mock_get_remodel_allowlist.side_effect = StoreApiResponseErrorList(
254+
"Internal server error",
255+
500,
256+
[{"message": "Internal server error"}],
257+
)
258+
259+
response = self.client.get("/api/store/1/models/remodel-allowlist")
260+
data = response.json
261+
262+
self.assertEqual(response.status_code, 500)
263+
self.assertFalse(data["success"])
264+
self.assertEqual(data["message"], "Internal server error")

webapp/endpoints/models.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,42 @@ def update_model(store_id: str, model_name: str):
262262
if res["success"]:
263263
return make_response(res, 200)
264264
return make_response(res, 500)
265+
266+
267+
@models.route("/api/store/<store_id>/models/remodel-allowlist")
268+
@login_required
269+
@exchange_required
270+
def get_remodel_allowlist(store_id: str):
271+
"""
272+
Retrieves remodels associated with a given store ID.
273+
274+
Args:
275+
store_id (int): The ID of the store for which to retrieve remodels.
276+
277+
Returns:
278+
dict: A dictionary containing the response message, success status,
279+
and data.
280+
"""
281+
282+
res = {}
283+
try:
284+
allowlist = publisher_gateway.get_remodel_allowlist(
285+
flask.session, store_id
286+
)
287+
res["success"] = True
288+
res["data"] = allowlist
289+
response = make_response(res, 200)
290+
response.cache_control.max_age = "3600"
291+
except StoreApiResponseErrorList as error_list:
292+
error_messages = [
293+
f"{error.get('message', 'An error occurred')}"
294+
for error in error_list.errors
295+
]
296+
if "unauthorized" in error_messages:
297+
res["message"] = "Store not found"
298+
else:
299+
res["message"] = " ".join(error_messages)
300+
res["success"] = False
301+
response = make_response(res, 500)
302+
303+
return response

0 commit comments

Comments
 (0)