Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow clients of customer content_metadata view to skip ent customer fetches #702

Merged
merged 1 commit into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions enterprise_catalog/apps/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,11 @@ def to_representation(self, instance):
"""
catalog_modified = None
customer_modified = None
if enterprise_catalog := self.context.get('enterprise_catalog'):
enterprise_catalog = self.context.get('enterprise_catalog')

if enterprise_catalog:
catalog_modified = enterprise_catalog.modified
if enterprise_catalog and not self.context.get('skip_customer_fetch'):
customer_modified = enterprise_catalog.enterprise_customer.last_modified_date

content_type = instance.content_type
Expand Down Expand Up @@ -255,7 +258,9 @@ def to_representation(self, instance):

if content_type in (COURSE, COURSE_RUN):
if enterprise_catalog:
json_metadata['enrollment_url'] = enterprise_catalog.get_content_enrollment_url(instance)
json_metadata['enrollment_url'] = None
if not self.context.get('skip_customer_fetch'):
json_metadata['enrollment_url'] = enterprise_catalog.get_content_enrollment_url(instance)
json_metadata['xapi_activity_id'] = enterprise_catalog.get_xapi_activity_id(
content_resource=content_type,
content_key=content_key,
Expand All @@ -267,7 +272,7 @@ def to_representation(self, instance):
# for exec-ed-2u content, because enrollment fulfillment for such content
# is controlled via Entitlements, which are tied directly to Courses
# (as opposed to Seats, which are tied to Course Runs).
if not instance.is_exec_ed_2u_course:
if not instance.is_exec_ed_2u_course and not self.context.get('skip_customer_fetch'):
self._add_course_run_enrollment_urls(instance, serialized_course_runs)
elif content_type == PROGRAM:
# We want this to be null, because we have no notion
Expand Down
19 changes: 16 additions & 3 deletions enterprise_catalog/apps/api/v1/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2175,20 +2175,33 @@ def setUp(self):

self.addCleanup(self.customer_details_patcher.stop)

def test_content_metadata_get_item_with_content_key(self):
@ddt.data(True, False)
def test_content_metadata_get_item_with_content_key(self, skip_customer_fetch):
"""
Test the base success case for the `content-metadata` view using a content key as an identifier
"""
response = self.client.get(urljoin(self.url, f"{self.content_key_1}/"))
self.mock_customer_details.reset_mock()
query_params = ''
if skip_customer_fetch:
query_params = '?skip_customer_fetch=1'
response = self.client.get(urljoin(self.url, f"{self.content_key_1}/") + query_params)
assert response.status_code == 200
expected_data = ContentMetadataSerializer(
self.first_content_metadata,
context={'enterprise_catalog': self.enterprise_catalog},
context={
'enterprise_catalog': self.enterprise_catalog,
'skip_customer_fetch': skip_customer_fetch,
},
).data
actual_data = response.json()
for payload_key in ['key', 'uuid']:
assert actual_data[payload_key] == expected_data[payload_key]

if skip_customer_fetch:
self.assertFalse(self.mock_customer_details.called)
else:
self.assertTrue(self.mock_customer_details.called)

def test_content_metadata_get_item_with_content_key_in_multiple_catalogs(self):
"""
Test the base success case for the `content-metadata` view using a content key as an identifier
Expand Down
18 changes: 15 additions & 3 deletions enterprise_catalog/apps/api/v1/views/enterprise_customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ def get_metadata_item_serializer(self):
enterprise_uuid=self.kwargs.get('enterprise_uuid')
))
content_identifier = self.kwargs.get('content_identifier')
serializer_context = {
'skip_customer_fetch': bool(self.request.query_params.get('skip_customer_fetch', '').lower()),
}

try:
# Search for matching metadata if the value of the requested
Expand All @@ -164,7 +167,7 @@ def get_metadata_item_serializer(self):
if content_with_uuid:
return ContentMetadataSerializer(
content_with_uuid.first(),
context={'enterprise_catalog': catalog},
context={'enterprise_catalog': catalog, **serializer_context},
)
except ValueError:
# Otherwise, search for matching metadata as a content key
Expand All @@ -173,7 +176,7 @@ def get_metadata_item_serializer(self):
if content_with_key:
return ContentMetadataSerializer(
content_with_key.first(),
context={'enterprise_catalog': catalog},
context={'enterprise_catalog': catalog, **serializer_context},
)
# If we've made it here without finding a matching ContentMetadata record,
# assume no matching record exists and raise a 404.
Expand All @@ -183,7 +186,16 @@ def get_metadata_item_serializer(self):
def content_metadata(self, customer_uuid, content_identifier, **kwargs): # pylint: disable=unused-argument
"""
Get endpoint for `/api/v1/enterprise-customer/{customer uuid}/content-metadata/{content identifier}`.
Accepts both content uuids and content keys for the specific content metadata record requested
Accepts both content uuids and content keys for the specific content metadata record requested.

Accepts an optional `skip_customer_fetch` query parameter.
If present and truthy, including this param will cause
the serialized content metadata to not fetch related enterprise customer
details from the edx-enterprise REST API. Thus the presence of this
query param means that the serialized 'content_last_modified' time
will not take into account the *customer* modified time. Additionally,
it means that no 'enrollment_url' fields will be present in the serialied
response.
"""
serializer = self.get_metadata_item_serializer()
return Response(serializer.data)
Loading