Skip to content

Commit a980d66

Browse files
committed
feat: Add endpoints to update and delete remodel allowlists
1 parent 042ea5b commit a980d66

3 files changed

Lines changed: 365 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.2.0
66
canonicalwebteam.blog==6.8.4
77
canonicalwebteam.search==2.1.2
88
canonicalwebteam.image-template==1.9.0
9-
canonicalwebteam.store-api==7.7.0
9+
canonicalwebteam.store-api==7.8.1
1010
canonicalwebteam.launchpad==0.9.0
1111
django-openid-auth==0.17
1212
Flask-OpenID==1.3.1

tests/endpoints/tests_models.py

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,276 @@ def test_create_remodel_allowlist_general_error(
344344
self.assertEqual(data["message"], "An error occurred")
345345

346346

347+
class TestUpdateRemodelAllowlist(TestModelServiceEndpoints):
348+
@patch(
349+
"canonicalwebteam.store_api.publishergw.PublisherGW"
350+
+ ".update_remodel_allowlist"
351+
)
352+
def test_update_remodel_allowlist_success(
353+
self, mock_update_remodel_allowlist
354+
):
355+
mock_update_remodel_allowlist.return_value = None
356+
357+
payload = {
358+
"description": "Updated remodel allowlist",
359+
"from-model": "updated-from-model",
360+
"from-serial": "updated-from-serial",
361+
"to-model": "updated-to-model",
362+
}
363+
364+
response = self.client.patch(
365+
"/api/store/1/models/remodel-allowlist", json=payload
366+
)
367+
data = response.json
368+
369+
self.assertEqual(response.status_code, 200)
370+
self.assertTrue(data["success"])
371+
mock_update_remodel_allowlist.assert_called_once()
372+
373+
@patch(
374+
"canonicalwebteam.store_api.publishergw.PublisherGW"
375+
+ ".update_remodel_allowlist"
376+
)
377+
def test_update_remodel_allowlist_store_not_found(
378+
self, mock_update_remodel_allowlist
379+
):
380+
mock_update_remodel_allowlist.side_effect = StoreApiResponseErrorList(
381+
"Store not found", 404, [{"message": "Store not found"}]
382+
)
383+
384+
payload = {
385+
"description": "Updated remodel allowlist",
386+
"from-model": "updated-from-model",
387+
"to-model": "updated-to-model",
388+
}
389+
390+
response = self.client.patch(
391+
"/api/store/999/models/remodel-allowlist", json=payload
392+
)
393+
data = response.json
394+
395+
self.assertEqual(response.status_code, 404)
396+
self.assertFalse(data["success"])
397+
self.assertEqual(data["message"], "Store not found")
398+
399+
@patch(
400+
"canonicalwebteam.store_api.publishergw.PublisherGW"
401+
+ ".update_remodel_allowlist"
402+
)
403+
def test_update_remodel_allowlist_models_not_found(
404+
self, mock_update_remodel_allowlist
405+
):
406+
mock_update_remodel_allowlist.side_effect = StoreApiResourceNotFound(
407+
"Remodel allowlist not found",
408+
404,
409+
[{"message": "Remodel allowlist not found"}],
410+
)
411+
412+
payload = {
413+
"description": "Updated remodel allowlist",
414+
"from-model": "updated-from-model",
415+
"to-model": "updated-to-model",
416+
}
417+
418+
response = self.client.patch(
419+
"/api/store/1/models/remodel-allowlist", json=payload
420+
)
421+
data = response.json
422+
423+
self.assertEqual(response.status_code, 404)
424+
self.assertFalse(data["success"])
425+
self.assertEqual(data["message"], "Remodel allowlist not found")
426+
427+
@patch(
428+
"canonicalwebteam.store_api.publishergw.PublisherGW"
429+
+ ".update_remodel_allowlist"
430+
)
431+
def test_update_remodel_allowlist_api_error(
432+
self, mock_update_remodel_allowlist
433+
):
434+
mock_update_remodel_allowlist.side_effect = StoreApiResponseErrorList(
435+
"Internal server error",
436+
500,
437+
[{"message": "An error occurred"}],
438+
)
439+
440+
payload = {
441+
"description": "Updated remodel allowlist",
442+
"from-model": "updated-from-model",
443+
"to-model": "updated-to-model",
444+
}
445+
446+
response = self.client.patch(
447+
"/api/store/1/models/remodel-allowlist", json=payload
448+
)
449+
data = response.json
450+
451+
self.assertEqual(response.status_code, 500)
452+
self.assertFalse(data["success"])
453+
self.assertEqual(data["message"], "An error occurred")
454+
455+
@patch(
456+
"canonicalwebteam.store_api.publishergw.PublisherGW"
457+
+ ".update_remodel_allowlist"
458+
)
459+
def test_update_remodel_allowlist_general_exception(
460+
self, mock_update_remodel_allowlist
461+
):
462+
mock_update_remodel_allowlist.side_effect = Exception(
463+
"Unexpected error"
464+
)
465+
466+
payload = {
467+
"description": "Updated remodel allowlist",
468+
"from-model": "updated-from-model",
469+
"to-model": "updated-to-model",
470+
"from-serial": "test-serial",
471+
}
472+
473+
response = self.client.patch(
474+
"/api/store/1/models/remodel-allowlist", json=payload
475+
)
476+
data = response.json
477+
478+
self.assertEqual(response.status_code, 500)
479+
self.assertFalse(data["success"])
480+
self.assertEqual(data["message"], "An error occurred")
481+
482+
483+
class TestDeleteRemodelAllowlist(TestModelServiceEndpoints):
484+
@patch(
485+
"canonicalwebteam.store_api.publishergw.PublisherGW"
486+
+ ".delete_remodel_allowlist"
487+
)
488+
def test_delete_remodel_allowlist_success(
489+
self, mock_delete_remodel_allowlist
490+
):
491+
mock_delete_remodel_allowlist.return_value = None
492+
493+
payload = {
494+
"from-model": "test-from-model",
495+
"from-serial": "test-from-serial",
496+
"to-model": "test-to-model",
497+
}
498+
499+
response = self.client.delete(
500+
"/api/store/1/models/remodel-allowlist", json=payload
501+
)
502+
data = response.json
503+
504+
self.assertEqual(response.status_code, 200)
505+
self.assertTrue(data["success"])
506+
mock_delete_remodel_allowlist.assert_called_once()
507+
508+
@patch(
509+
"canonicalwebteam.store_api.publishergw.PublisherGW"
510+
+ ".delete_remodel_allowlist"
511+
)
512+
def test_delete_remodel_allowlist_store_not_found(
513+
self, mock_delete_remodel_allowlist
514+
):
515+
mock_delete_remodel_allowlist.side_effect = StoreApiResponseErrorList(
516+
"Store not found", 404, [{"message": "Store not found"}]
517+
)
518+
519+
payload = {
520+
"from-model": "test-from-model",
521+
"from-serial": "test-from-serial",
522+
"to-model": "test-to-model",
523+
}
524+
525+
response = self.client.delete(
526+
"/api/store/999/models/remodel-allowlist", json=payload
527+
)
528+
data = response.json
529+
530+
self.assertEqual(response.status_code, 404)
531+
self.assertFalse(data["success"])
532+
self.assertEqual(data["message"], "Store not found")
533+
534+
@patch(
535+
"canonicalwebteam.store_api.publishergw.PublisherGW"
536+
+ ".delete_remodel_allowlist"
537+
)
538+
def test_delete_remodel_allowlist_allowlist_not_found(
539+
self, mock_delete_remodel_allowlist
540+
):
541+
mock_delete_remodel_allowlist.side_effect = StoreApiResourceNotFound(
542+
"Remodel allowlist not found",
543+
404,
544+
[{"message": "Remodel allowlist not found"}],
545+
)
546+
547+
payload = {
548+
"from-model": "test-from-model",
549+
"from-serial": "test-from-serial",
550+
"to-model": "test-to-model",
551+
}
552+
553+
response = self.client.delete(
554+
"/api/store/1/models/remodel-allowlist", json=payload
555+
)
556+
data = response.json
557+
558+
self.assertEqual(response.status_code, 404)
559+
self.assertFalse(data["success"])
560+
self.assertEqual(data["message"], "Remodel allowlist not found")
561+
562+
@patch(
563+
"canonicalwebteam.store_api.publishergw.PublisherGW"
564+
+ ".delete_remodel_allowlist"
565+
)
566+
def test_delete_remodel_allowlist_api_error(
567+
self, mock_delete_remodel_allowlist
568+
):
569+
mock_delete_remodel_allowlist.side_effect = StoreApiResponseErrorList(
570+
"Internal server error",
571+
500,
572+
[{"message": "An error occurred"}],
573+
)
574+
575+
payload = {
576+
"from-model": "test-from-model",
577+
"from-serial": "test-from-serial",
578+
"to-model": "test-to-model",
579+
}
580+
581+
response = self.client.delete(
582+
"/api/store/1/models/remodel-allowlist", json=payload
583+
)
584+
data = response.json
585+
586+
self.assertEqual(response.status_code, 500)
587+
self.assertFalse(data["success"])
588+
self.assertEqual(data["message"], "An error occurred")
589+
590+
@patch(
591+
"canonicalwebteam.store_api.publishergw.PublisherGW"
592+
+ ".delete_remodel_allowlist"
593+
)
594+
def test_delete_remodel_allowlist_general_exception(
595+
self, mock_delete_remodel_allowlist
596+
):
597+
mock_delete_remodel_allowlist.side_effect = Exception(
598+
"Unexpected error"
599+
)
600+
601+
payload = {
602+
"from-model": "test-from-model",
603+
"from-serial": "test-serial",
604+
"to-model": "test-to-model",
605+
}
606+
607+
response = self.client.delete(
608+
"/api/store/1/models/remodel-allowlist", json=payload
609+
)
610+
data = response.json
611+
612+
self.assertEqual(response.status_code, 500)
613+
self.assertFalse(data["success"])
614+
self.assertEqual(data["message"], "An error occurred")
615+
616+
347617
class TestGetSerialLog(TestModelServiceEndpoints):
348618
@patch(
349619
"canonicalwebteam.store_api.publishergw.PublisherGW"

webapp/endpoints/models.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,100 @@ def create_remodel_allowlist(store_id: str):
349349
return make_response(res, 500)
350350

351351

352+
@models.route(
353+
"/api/store/<store_id>/models/remodel-allowlist", methods=["PATCH"]
354+
)
355+
@login_required
356+
@exchange_required
357+
def update_remodel_allowlist(store_id: str):
358+
"""
359+
Update a remodel allowlist for a given store.
360+
361+
Args:
362+
store_id (str): The ID of the store.
363+
364+
Returns:
365+
dict: A dictionary containing the response message and success
366+
status.
367+
"""
368+
res = {}
369+
370+
try:
371+
allowlist = flask.request.json
372+
publisher_gateway.update_remodel_allowlist(
373+
flask.session, store_id, [allowlist]
374+
)
375+
376+
res["success"] = True
377+
return make_response(res, 200)
378+
except StoreApiResponseErrorList as error_list:
379+
res["success"] = False
380+
messages = [
381+
f"{error.get('message', 'An error occurred')}"
382+
for error in error_list.errors
383+
]
384+
res["message"] = " ".join(messages)
385+
return make_response(res, error_list.status_code)
386+
387+
except StoreApiResourceNotFound:
388+
res["success"] = False
389+
res["message"] = "Remodel allowlist not found"
390+
return make_response(res, 404)
391+
392+
except Exception:
393+
res["success"] = False
394+
res["message"] = "An error occurred"
395+
396+
return make_response(res, 500)
397+
398+
399+
@models.route(
400+
"/api/store/<store_id>/models/remodel-allowlist", methods=["DELETE"]
401+
)
402+
@login_required
403+
@exchange_required
404+
def delete_remodel_allowlist(store_id: str):
405+
"""
406+
Delete a remodel allowlist for a given store.
407+
408+
Args:
409+
store_id (str): The ID of the store.
410+
411+
Returns:
412+
dict: A dictionary containing the response message and success
413+
status.
414+
"""
415+
res = {}
416+
417+
try:
418+
allowlist = flask.request.json
419+
publisher_gateway.delete_remodel_allowlist(
420+
flask.session, store_id, [allowlist]
421+
)
422+
423+
res["success"] = True
424+
return make_response(res, 200)
425+
except StoreApiResponseErrorList as error_list:
426+
res["success"] = False
427+
messages = [
428+
f"{error.get('message', 'An error occurred')}"
429+
for error in error_list.errors
430+
]
431+
res["message"] = " ".join(messages)
432+
return make_response(res, error_list.status_code)
433+
434+
except StoreApiResourceNotFound:
435+
res["success"] = False
436+
res["message"] = "Remodel allowlist not found"
437+
return make_response(res, 404)
438+
439+
except Exception:
440+
res["success"] = False
441+
res["message"] = "An error occurred"
442+
443+
return make_response(res, 500)
444+
445+
352446
@models.route("/api/store/<store_id>/models/<model_name>/serial-log")
353447
@login_required
354448
@exchange_required

0 commit comments

Comments
 (0)