-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add bff handler context (#577)
- Loading branch information
1 parent
7aa0feb
commit ac5c9eb
Showing
6 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
""" App config for BFFs """ | ||
|
||
from django.apps import AppConfig | ||
|
||
|
||
class BffsConfig(AppConfig): | ||
default_auto_field = 'django.db.models.BigAutoField' | ||
name = 'enterprise_access.apps.bffs' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
""" | ||
HandlerContext for bffs app. | ||
""" | ||
from enterprise_access.apps.bffs import serializers | ||
|
||
|
||
class HandlerContext: | ||
""" | ||
A context object for managing the state throughout the lifecycle of a Backend-for-Frontend (BFF) request. | ||
The `HandlerContext` class stores request information, loaded data, and any errors and warnings | ||
that may occur during the request. | ||
Attributes: | ||
request: The original request object containing information about the incoming HTTP request. | ||
user: The original request user information about hte incoming HTTP request. | ||
data: A dictionary to store data loaded and processed by the handlers. | ||
errors: A list to store errors that occur during request processing. | ||
warnings: A list to store warnings that occur during the request processing. | ||
enterprise_customer_uuid: The enterprise customer the user is associated with. | ||
lms_user_id: The id associated with the authenticated user. | ||
""" | ||
|
||
def __init__(self, request): | ||
""" | ||
Initializes the HandlerContext with request information, route, and optional initial data. | ||
Args: | ||
request: The incoming HTTP request. | ||
""" | ||
self._request = request | ||
self.data = {} # Stores processed data for the response | ||
self.errors = [] # Stores any errors that occur during processing | ||
self.warnings = [] # Stores any warnings that occur during processing | ||
self.enterprise_customer_uuid = None | ||
self.lms_user_id = None | ||
|
||
@property | ||
def request(self): | ||
return self._request | ||
|
||
@property | ||
def user(self): | ||
return self._request.user | ||
|
||
def add_error(self, **kwargs): | ||
""" | ||
Adds an error to the context. | ||
Output fields determined by the ErrorSerializer | ||
""" | ||
serializer = serializers.ErrorSerializer(data=kwargs) | ||
serializer.is_valid(raise_exception=True) | ||
self.errors.append(serializer.data) | ||
|
||
def add_warning(self, **kwargs): | ||
""" | ||
Adds a warning to the context. | ||
Output fields determined by the WarningSerializer | ||
""" | ||
serializer = serializers.WarningSerializer(data=kwargs) | ||
serializer.is_valid(raise_exception=True) | ||
self.warnings.append(serializer.data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
""" | ||
Serializers for bffs. | ||
""" | ||
from rest_framework import serializers | ||
|
||
|
||
class BaseBFFMessageSerializer(serializers.Serializer): | ||
""" | ||
Base Serializer for BFF messages. | ||
Fields: | ||
user_message (str): A user-friendly message. | ||
developer_message (str): A more detailed message for debugging purposes. | ||
""" | ||
developer_message = serializers.CharField() | ||
user_message = serializers.CharField() | ||
|
||
def create(self, validated_data): | ||
return validated_data | ||
|
||
def update(self, instance, validated_data): | ||
return validated_data | ||
|
||
|
||
class ErrorSerializer(BaseBFFMessageSerializer): | ||
pass | ||
|
||
|
||
class WarningSerializer(BaseBFFMessageSerializer): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
""" | ||
Text for the BFF context | ||
""" | ||
from django.test import RequestFactory, TestCase | ||
from rest_framework.exceptions import ValidationError | ||
|
||
from enterprise_access.apps.api_client.tests.test_constants import DATE_FORMAT_ISO_8601 | ||
from enterprise_access.apps.bffs.context import HandlerContext | ||
from enterprise_access.apps.core.tests.factories import UserFactory | ||
from enterprise_access.utils import _curr_date | ||
|
||
|
||
class TestHandlerContext(TestCase): | ||
def setUp(self): | ||
super().setUp() | ||
self.factory = RequestFactory() | ||
self.mock_user = UserFactory() | ||
|
||
def test_handler_context_init(self): | ||
request = self.factory.get('sample/api/call') | ||
request.user = self.mock_user | ||
context = HandlerContext(request) | ||
|
||
self.assertEqual(context.request, request) | ||
self.assertEqual(context.user, self.mock_user) | ||
self.assertEqual(context.data, {}) | ||
self.assertEqual(context.errors, []) | ||
self.assertEqual(context.warnings, []) | ||
self.assertEqual(context.enterprise_customer_uuid, None) | ||
self.assertEqual(context.lms_user_id, None) | ||
|
||
def test_handler_context_add_error_serializer(self): | ||
request = self.factory.get('sample/api/call') | ||
request.user = self.mock_user | ||
context = HandlerContext(request) | ||
expected_output = { | ||
"developer_message": "No enterprise uuid associated to the user mock-uuid", | ||
"user_message": "You may not be associated with the enterprise.", | ||
} | ||
# Define kwargs for add_error | ||
arguments = { | ||
**expected_output, | ||
"status": 403 # Add an attribute that is not explicitly defined in the serializer to verify | ||
} | ||
context.add_error( | ||
**arguments | ||
) | ||
self.assertEqual(expected_output, context.errors[0]) | ||
|
||
def test_handler_context_add_error_serializer_is_valid(self): | ||
request = self.factory.get('sample/api/call') | ||
request.user = self.mock_user | ||
context = HandlerContext(request) | ||
malformed_output = { | ||
"developer_message": "No enterprise uuid associated to the user mock-uuid", | ||
} | ||
with self.assertRaises(ValidationError): | ||
context.add_error(**malformed_output) | ||
|
||
def test_handler_context_add_warning_serializer(self): | ||
request = self.factory.get('sample/api/call') | ||
request.user = self.mock_user | ||
context = HandlerContext(request) | ||
expected_output = { | ||
"developer_message": "Heuristic Expiration", | ||
"user_message": "The data received might be out-dated", | ||
} | ||
# Define kwargs for add_warning | ||
arguments = { | ||
**expected_output, | ||
"status": 113 # Add an attribute that is not explicitly defined in the serializer to verify | ||
} | ||
context.add_warning( | ||
**arguments | ||
) | ||
self.assertEqual(expected_output, context.warnings[0]) | ||
|
||
def test_handler_context_add_warning_serializer_is_valid(self): | ||
request = self.factory.get('sample/api/call') | ||
request.user = self.mock_user | ||
context = HandlerContext(request) | ||
malformed_output = { | ||
"user_message": "The data received might be out-dated", | ||
} | ||
with self.assertRaises(ValidationError): | ||
context.add_error(**malformed_output) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters