From b5f3f46794fd5a260396d01d5bea1d21770be372 Mon Sep 17 00:00:00 2001 From: Marcos Prieto Date: Thu, 21 Mar 2024 12:46:42 +0100 Subject: [PATCH] Store known error codes as events on the DB Extend the mechanism we already use for `canvas_invalid_scope` to other error codes. --- lms/views/api/exceptions.py | 10 ++++++++++ tests/unit/lms/views/api/exceptions_test.py | 20 ++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lms/views/api/exceptions.py b/lms/views/api/exceptions.py index 46be487160..4afeac7a7f 100644 --- a/lms/views/api/exceptions.py +++ b/lms/views/api/exceptions.py @@ -15,8 +15,10 @@ view_defaults, ) +from lms.events import LTIEvent from lms.services import ( CanvasAPIPermissionError, + EventService, ExternalAsyncRequestError, ExternalRequestError, OAuth2TokenError, @@ -200,6 +202,14 @@ def api_error(self): """ if hasattr(self.context, "error_code"): + EventService.queue_event( + LTIEvent( + request=self.request, + type=LTIEvent.Type.ERROR_CODE, + data={"code": self.context.error_code}, + ) + ) + return ErrorBody( error_code=self.context.error_code, message=getattr(self.context, "message", None), diff --git a/tests/unit/lms/views/api/exceptions_test.py b/tests/unit/lms/views/api/exceptions_test.py index ed6d26f41b..a5749a787b 100644 --- a/tests/unit/lms/views/api/exceptions_test.py +++ b/tests/unit/lms/views/api/exceptions_test.py @@ -11,7 +11,9 @@ from lms.views.api.exceptions import APIExceptionViews, ErrorBody, strip_queryparams from tests import factories -pytestmark = pytest.mark.usefixtures("oauth2_token_service") +pytestmark = pytest.mark.usefixtures( + "oauth2_token_service", "course_service", "assignment_service" +) class TestSchemaValidationError: @@ -139,7 +141,7 @@ def context(self): class TestAPIError: - def test_it_with_an_APIError(self, pyramid_request, views): + def test_it_with_an_APIError(self, pyramid_request, views, EventService, LTIEvent): views.context = SerializableError( error_code=sentinel.error_code, message=sentinel.message, @@ -154,6 +156,12 @@ def test_it_with_an_APIError(self, pyramid_request, views): message=sentinel.message, details=sentinel.details, ) + LTIEvent.assert_called_once_with( + request=pyramid_request, + type=LTIEvent.Type.ERROR_CODE, + data={"code": sentinel.error_code}, + ) + EventService.queue_event.assert_called_once_with(LTIEvent.return_value) def test_it_with_a_minimal_viable_error(self, pyramid_request, views): class MinimalError: @@ -179,6 +187,14 @@ def test_it_with_an_unexpected_error(self, pyramid_request, views): ) ) + @pytest.fixture(autouse=True) + def LTIEvent(self, patch): + return patch("lms.views.api.exceptions.LTIEvent") + + @pytest.fixture(autouse=True) + def EventService(self, patch): + return patch("lms.views.api.exceptions.EventService") + class TestErrorBody: @pytest.mark.parametrize(