Skip to content

Commit

Permalink
Store known error codes as events on the DB
Browse files Browse the repository at this point in the history
Extend the mechanism we already use for `canvas_invalid_scope` to other
error codes.
  • Loading branch information
marcospri committed Mar 25, 2024
1 parent 2d36462 commit b5f3f46
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
10 changes: 10 additions & 0 deletions lms/views/api/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
view_defaults,
)

from lms.events import LTIEvent
from lms.services import (
CanvasAPIPermissionError,
EventService,
ExternalAsyncRequestError,
ExternalRequestError,
OAuth2TokenError,
Expand Down Expand Up @@ -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),
Expand Down
20 changes: 18 additions & 2 deletions tests/unit/lms/views/api/exceptions_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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,
Expand All @@ -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:
Expand All @@ -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(
Expand Down

0 comments on commit b5f3f46

Please sign in to comment.