From 033cbee5a97c52cdf796dc14b3abc4eb0303e199 Mon Sep 17 00:00:00 2001 From: 0x29a Date: Fri, 10 Nov 2023 15:03:06 +0100 Subject: [PATCH] feat: per-user secured Algolia API keys --- enterprise/api/v1/views.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/enterprise/api/v1/views.py b/enterprise/api/v1/views.py index bcca5cdc2d..bb7793f20a 100644 --- a/enterprise/api/v1/views.py +++ b/enterprise/api/v1/views.py @@ -8,6 +8,7 @@ from urllib.parse import quote_plus, unquote import jwt +from algoliasearch.search_client import SearchClient from django_filters.rest_framework import DjangoFilterBackend from edx_rbac.decorators import permission_required from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication @@ -525,6 +526,39 @@ def unlink_users(self, request, pk=None): # pylint: disable=unused-argument return Response(status=HTTP_200_OK) + @action(detail=False) + def algolia_key(self, request, *args, **kwargs): + """ + Returns an Algolia API key that is secured to only allow searching for + objects associated with enterprise customers that the user is linked to. + """ + + if not settings.ENTERPRISE_ALGOLIA_SEARCH_API_KEY: + raise ValidationError("Algolia API key not configured.", code=HTTP_500_INTERNAL_SERVER_ERROR) + + queryset = self.queryset.filter( + **{ + self.USER_ID_FILTER: request.user.id, + "enterprise_customer_users__linked": True + } + ).values_list("uuid", flat=True) + + if len(queryset) == 0: + raise ValidationError("User is not linked to any enterprise customers.", code=HTTP_404_NOT_FOUND) + + secured_key = SearchClient.generate_secured_api_key( + settings.ENTERPRISE_ALGOLIA_SEARCH_API_KEY, + { + "filters": " OR ".join( + f"enterprise_customer_uuids:{str(enterprise_customer_uuid)}" + for enterprise_customer_uuid + in queryset + ), + } + ) + + return Response({"key": secured_key}, status=HTTP_200_OK) + class EnterpriseCourseEnrollmentViewSet(EnterpriseReadWriteModelViewSet): """