diff --git a/license_manager/apps/api/permissions.py b/license_manager/apps/api/permissions.py index 68971efa..0d6bef45 100644 --- a/license_manager/apps/api/permissions.py +++ b/license_manager/apps/api/permissions.py @@ -13,3 +13,18 @@ class CanRetireUser(permissions.BasePermission): def has_permission(self, request, view): return request.user.username == settings.RETIREMENT_SERVICE_WORKER_USERNAME or request.user.is_superuser + + +class IsInProvisioningAdminGroup(permissions.BasePermission): + """ + Grant access to those users only who are part of the license provisiioning django group + """ + ALLOWED_API_GROUPS = ['provisioning-admins-group'] + message = 'Access denied: You do not have the necessary permissions to access this.' + + def has_permission(self, request, view): + return ( + super().has_permission(request, view) and ( + request.user.groups.filter(name__in=self.ALLOWED_API_GROUPS).exists() + ) + ) diff --git a/license_manager/apps/api/v1/tests/constants.py b/license_manager/apps/api/v1/tests/constants.py index b1f2ba03..59b40e52 100644 --- a/license_manager/apps/api/v1/tests/constants.py +++ b/license_manager/apps/api/v1/tests/constants.py @@ -3,6 +3,7 @@ # Constants for subscriptions API tests SUBSCRIPTION_RENEWAL_DAYS_OFFSET = 500 +PROVISIONING_ADMINS_GROUP = "provisioning-admins-group" ADMIN_ROLES = { 'system_role': constants.SYSTEM_ENTERPRISE_ADMIN_ROLE, diff --git a/license_manager/apps/api/v1/tests/test_views.py b/license_manager/apps/api/v1/tests/test_views.py index d26f6bee..5c034236 100644 --- a/license_manager/apps/api/v1/tests/test_views.py +++ b/license_manager/apps/api/v1/tests/test_views.py @@ -12,6 +12,7 @@ import pytest from django.conf import settings from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group from django.core.exceptions import ObjectDoesNotExist from django.db import DatabaseError from django.http import QueryDict @@ -34,6 +35,7 @@ from license_manager.apps.api.v1.tests.constants import ( ADMIN_ROLES, LEARNER_ROLES, + PROVISIONING_ADMINS_GROUP, SUBSCRIPTION_RENEWAL_DAYS_OFFSET, ) from license_manager.apps.api.v1.views import ( @@ -242,14 +244,14 @@ def _subscriptions_list_request(api_client, user, enterprise_customer_uuid=None, return api_client.get(url) -def _subscription_create_request(api_client, user, params): +def _provision_license_create_request(api_client, user, params): """ Helper method that creates a SubscriptionPlan. """ if user: api_client.force_authenticate(user=user) - url = '/api/v1/subscriptions' + url = '/api/v1/provisioning-admins/subscriptions' return api_client.post(url, params) @@ -260,18 +262,18 @@ def _subscription_get_request(api_client, user, subscription_uuid): if user: api_client.force_authenticate(user=user) - url = f'/api/v1/subscriptions/{subscription_uuid}' + url = f'/api/v1/provisioning-admins/subscriptions/{subscription_uuid}' return api_client.get(url) -def _subscriptions_patch_request(api_client, user, params, subscription_uuid): +def _provision_license_patch_request(api_client, user, params, subscription_uuid): """ Helper method that updates a SubscriptionPlan. """ if user: api_client.force_authenticate(user=user) - url = f'/api/v1/subscriptions/{subscription_uuid}' + url = f'/api/v1/provisioning-admins/subscriptions/{subscription_uuid}' return api_client.patch(url, params) @@ -843,7 +845,7 @@ def test_subscription_plan_list_bad_enterprise_uuid_400(api_client, superuser): @pytest.mark.django_db -def test_subscription_plan_create_superuser_200(api_client, superuser, boolean_toggle): +def test_subscription_plan_create_staff_user_200(api_client, staff_user, boolean_toggle): """ Verify that the subcription POST endpoint creates new record and response includes all expected fields """ @@ -853,10 +855,11 @@ def test_subscription_plan_create_superuser_200(api_client, superuser, boolean_t ProductFactory.create_batch(1) params = _prepare_subscription_plan_payload(customer_agreement) _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + response = _provision_license_create_request( + api_client, staff_user, params=params) assert status.HTTP_201_CREATED == response.status_code expected_fields = { @@ -888,7 +891,65 @@ def test_subscription_plan_create_superuser_200(api_client, superuser, boolean_t @pytest.mark.django_db -def test_subscription_plan_create_superuser_customer_agreement_400(api_client, superuser, boolean_toggle): +def test_subscription_plan_create_staff_user_403(api_client, staff_user, boolean_toggle): + """ + Verify that the subcription POST endpoint is accessible to authorised users only + """ + enterprise_customer_uuid = uuid4() + customer_agreement = CustomerAgreementFactory.create( + enterprise_customer_uuid=enterprise_customer_uuid) + ProductFactory.create_batch(1) + params = _prepare_subscription_plan_payload(customer_agreement) + _assign_role_via_jwt_or_db( + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + + response = _provision_license_create_request( + api_client, staff_user, params=params) + assert status.HTTP_403_FORBIDDEN == response.status_code + + +@pytest.mark.django_db +def test_subscription_plan_update_staff_user_403(api_client, staff_user, boolean_toggle): + """ + Verify that the subcription update endpoint is accessible to authorised users only + """ + enterprise_customer_uuid = uuid4() + fake_uuid = uuid4() + customer_agreement = CustomerAgreementFactory.create( + enterprise_customer_uuid=enterprise_customer_uuid) + ProductFactory.create_batch(1) + params = _prepare_subscription_plan_payload(customer_agreement) + _assign_role_via_jwt_or_db( + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + + response = _provision_license_patch_request( + api_client, staff_user, params=params, subscription_uuid=fake_uuid) + + assert status.HTTP_403_FORBIDDEN == response.status_code + + +@pytest.mark.django_db +def test_subscription_plan_create_staff_user_201(api_client, staff_user, boolean_toggle): + """ + Verify that the subcription update endpoint is accessible to authorised users only + """ + enterprise_customer_uuid = uuid4() + customer_agreement = CustomerAgreementFactory.create( + enterprise_customer_uuid=enterprise_customer_uuid) + ProductFactory.create_batch(1) + params = _prepare_subscription_plan_payload(customer_agreement) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + + _assign_role_via_jwt_or_db( + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + response = _provision_license_create_request( + api_client, staff_user, params=params) + assert status.HTTP_201_CREATED == response.status_code + + +@pytest.mark.django_db +def test_subscription_plan_create_staff_user_customer_agreement_400(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns error if invalid customer_agreement is given """ @@ -901,16 +962,17 @@ def test_subscription_plan_create_superuser_customer_agreement_400(api_client, s params = _prepare_subscription_plan_payload(customer_agreement) params['customer_agreement'] = invalid_customer_agreement_uuid _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + response = _provision_license_create_request( + api_client, staff_user, params=params) assert status.HTTP_400_BAD_REQUEST == response.status_code assert response.json() == {'error': "An error occurred: Provided customer_agreement doesn't exist."} @pytest.mark.django_db -def test_subscription_plan_create_superuser_product_400(api_client, superuser, boolean_toggle): +def test_subscription_plan_create_staff_user_product_400(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns error if invalid Product is given """ @@ -922,10 +984,11 @@ def test_subscription_plan_create_superuser_product_400(api_client, superuser, b params = _prepare_subscription_plan_payload(customer_agreement) params['product'] = 2 # passing an invalid PK _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + response = _provision_license_create_request( + api_client, staff_user, params=params) assert status.HTTP_400_BAD_REQUEST == response.status_code assert response.json() == {'error': {'product': [ @@ -933,7 +996,7 @@ def test_subscription_plan_create_superuser_product_400(api_client, superuser, b @pytest.mark.django_db -def test_subscription_plan_create_superuser_salesforce_lineitem_400(api_client, superuser, boolean_toggle): +def test_subscription_plan_create_staff_user_salesforce_lineitem_400(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns error if invalid salesforce_lineitem is given """ @@ -946,10 +1009,11 @@ def test_subscription_plan_create_superuser_salesforce_lineitem_400(api_client, # passing a invalid string params['salesforce_opportunity_line_item'] = 'foo' _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + response = _provision_license_create_request( + api_client, staff_user, params=params) assert status.HTTP_400_BAD_REQUEST == response.status_code assert response.json() == \ @@ -957,7 +1021,7 @@ def test_subscription_plan_create_superuser_salesforce_lineitem_400(api_client, @pytest.mark.django_db -def test_subscription_plan_update_superuser_200(api_client, superuser, boolean_toggle): +def test_subscription_plan_update_staff_user_200(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns 200 on patch request """ @@ -968,13 +1032,14 @@ def test_subscription_plan_update_superuser_200(api_client, superuser, boolean_t params = _prepare_subscription_plan_payload(customer_agreement) _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - create_response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + create_response = _provision_license_create_request( + api_client, staff_user, params=params) params['title'] = 'bar' - patch_response = _subscriptions_patch_request( - api_client, superuser, params=params, subscription_uuid=create_response.json()['uuid']) + patch_response = _provision_license_patch_request( + api_client, staff_user, params=params, subscription_uuid=create_response.json()['uuid']) assert status.HTTP_201_CREATED == create_response.status_code assert status.HTTP_200_OK == patch_response.status_code expected_fields = { @@ -1007,7 +1072,7 @@ def test_subscription_plan_update_superuser_200(api_client, superuser, boolean_t @pytest.mark.django_db -def test_subscription_plan_update_superuser_invalid_product_id(api_client, superuser, boolean_toggle): +def test_subscription_plan_update_staff_user_invalid_product_id(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns 200 on patch request """ @@ -1018,19 +1083,20 @@ def test_subscription_plan_update_superuser_invalid_product_id(api_client, super params = _prepare_subscription_plan_payload(customer_agreement) _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - create_response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + create_response = _provision_license_create_request( + api_client, staff_user, params=params) params['product'] = 10 # set invalid ID - patch_response = _subscriptions_patch_request( - api_client, superuser, params=params, subscription_uuid=create_response.json()['uuid']) + patch_response = _provision_license_patch_request( + api_client, staff_user, params=params, subscription_uuid=create_response.json()['uuid']) assert status.HTTP_201_CREATED == create_response.status_code assert status.HTTP_400_BAD_REQUEST == patch_response.status_code @pytest.mark.django_db -def test_subscription_plan_update_superuser_invalid_payload(api_client, superuser, boolean_toggle): +def test_subscription_plan_update_staff_user_invalid_payload(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns 200 on patch request """ @@ -1041,20 +1107,21 @@ def test_subscription_plan_update_superuser_invalid_payload(api_client, superuse params = _prepare_subscription_plan_payload(customer_agreement) _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - create_response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + create_response = _provision_license_create_request( + api_client, staff_user, params=params) params['salesforce_opportunity_line_item'] = 'foo' # set invalid ID - patch_response = _subscriptions_patch_request( - api_client, superuser, params=params, subscription_uuid=create_response.json()['uuid']) + patch_response = _provision_license_patch_request( + api_client, staff_user, params=params, subscription_uuid=create_response.json()['uuid']) assert status.HTTP_201_CREATED == create_response.status_code assert status.HTTP_400_BAD_REQUEST == patch_response.status_code @pytest.mark.django_db -def test_subscription_plan_create_superuser_cataog_uuid_missing(api_client, superuser, boolean_toggle): +def test_subscription_plan_create_staff_user_cataog_uuid_missing(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint handles request gracefully if enterprise_catalog_uuid is missing """ @@ -1066,10 +1133,11 @@ def test_subscription_plan_create_superuser_cataog_uuid_missing(api_client, supe params = _prepare_subscription_plan_payload(customer_agreement) params['enterprise_catalog_uuid'] = None _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - create_response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + create_response = _provision_license_create_request( + api_client, staff_user, params=params) assert status.HTTP_201_CREATED == create_response.status_code @@ -1078,7 +1146,7 @@ def test_subscription_plan_create_superuser_cataog_uuid_missing(api_client, supe @pytest.mark.django_db -def test_subscription_plan_create_superuser_invalid_product_id(api_client, superuser, boolean_toggle): +def test_subscription_plan_create_staff_user_invalid_product_id(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns error if invalid product id is provided """ @@ -1090,10 +1158,11 @@ def test_subscription_plan_create_superuser_invalid_product_id(api_client, super params = _prepare_subscription_plan_payload(customer_agreement) params['product'] = 12 _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - create_response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + create_response = _provision_license_create_request( + api_client, staff_user, params=params) assert status.HTTP_400_BAD_REQUEST == create_response.status_code assert create_response.json( @@ -1101,7 +1170,7 @@ def test_subscription_plan_create_superuser_invalid_product_id(api_client, super @pytest.mark.django_db -def test_subscription_plan_create_superuser_db_integrity_error(api_client, superuser, boolean_toggle): +def test_subscription_plan_create_staff_user_db_integrity_error(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns error if invalid product id is provided """ @@ -1112,13 +1181,14 @@ def test_subscription_plan_create_superuser_db_integrity_error(api_client, super params = _prepare_subscription_plan_payload(customer_agreement) _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - first_create_response = _subscription_create_request( - api_client, superuser, params=params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + first_create_response = _provision_license_create_request( + api_client, staff_user, params=params) - second_create_response = _subscription_create_request( - api_client, superuser, params=params) + second_create_response = _provision_license_create_request( + api_client, staff_user, params=params) assert status.HTTP_201_CREATED == first_create_response.status_code assert status.HTTP_400_BAD_REQUEST == second_create_response.status_code @@ -1128,7 +1198,7 @@ def test_subscription_plan_create_superuser_db_integrity_error(api_client, super @pytest.mark.django_db -def test_subscription_plan_get_superuser_success(api_client, superuser, boolean_toggle): +def test_subscription_plan_get_staff_user_success(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns error if invalid product id is provided """ @@ -1139,21 +1209,22 @@ def test_subscription_plan_get_superuser_success(api_client, superuser, boolean_ params = _prepare_subscription_plan_payload(customer_agreement) _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) - - create_response = _subscription_create_request( - api_client, superuser, params) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) + create_response = _provision_license_create_request( + api_client, staff_user, params) created_uuid = str(create_response.json()['uuid']) retrieved_subscription = _subscription_get_request( - api_client, superuser, created_uuid) + api_client, staff_user, created_uuid) assert retrieved_subscription.json()['uuid'] == created_uuid assert status.HTTP_201_CREATED == create_response.status_code @pytest.mark.django_db -def test_subscription_plan_get_superuser_failure(api_client, superuser, boolean_toggle): +def test_subscription_plan_get_staff_user_failure(api_client, staff_user, boolean_toggle): """ Verify that the subscription create endpoint returns error if invalid product id is provided """ @@ -1161,9 +1232,11 @@ def test_subscription_plan_get_superuser_failure(api_client, superuser, boolean_ invalid_subscription_id = uuid4() _assign_role_via_jwt_or_db( - api_client, superuser, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + api_client, staff_user, enterprise_customer_uuid=enterprise_customer_uuid, assign_via_jwt=boolean_toggle) + allowed_group = Group.objects.create(name=PROVISIONING_ADMINS_GROUP) + staff_user.groups.add(allowed_group) response = _subscription_get_request( - api_client, superuser, invalid_subscription_id) + api_client, staff_user, invalid_subscription_id) assert status.HTTP_404_NOT_FOUND == response.status_code diff --git a/license_manager/apps/api/v1/urls.py b/license_manager/apps/api/v1/urls.py index 44bc8f0e..9617c509 100644 --- a/license_manager/apps/api/v1/urls.py +++ b/license_manager/apps/api/v1/urls.py @@ -71,6 +71,11 @@ class NestedSimpleRouter(NestedMixin, routers.SimpleRouter): viewset=views.CustomerAgreementViewSet, basename='customer-agreement', ) +router.register( + prefix='provisioning-admins/subscriptions', + viewset=views.SubscriptionPlanProvisioningAdminViewset, + basename='provisioning-admins', +) subscription_router = NestedSimpleRouter( parent_router=router, diff --git a/license_manager/apps/api/v1/views.py b/license_manager/apps/api/v1/views.py index 7733856c..99376be9 100644 --- a/license_manager/apps/api/v1/views.py +++ b/license_manager/apps/api/v1/views.py @@ -30,7 +30,10 @@ from license_manager.apps.api.filters import LicenseFilter from license_manager.apps.api.mixins import UserDetailsFromJwtMixin from license_manager.apps.api.models import BulkEnrollmentJob -from license_manager.apps.api.permissions import CanRetireUser +from license_manager.apps.api.permissions import ( + CanRetireUser, + IsInProvisioningAdminGroup, +) from license_manager.apps.api.tasks import ( create_braze_aliases_task, execute_post_revocation_tasks, @@ -382,25 +385,11 @@ def base_queryset(self): parameters=[serializers.SubscriptionPlanQueryParamsSerializer], ), ) -class SubscriptionViewSet( - LearnerSubscriptionViewSet, - mixins.CreateModelMixin, - mixins.RetrieveModelMixin, - mixins.ListModelMixin, - viewsets.GenericViewSet -): +class SubscriptionViewSet(LearnerSubscriptionViewSet): """ Viewset for Admin only read operations on SubscriptionPlans.""" permission_required = constants.SUBSCRIPTIONS_ADMIN_ACCESS_PERMISSION allowed_roles = [constants.SUBSCRIPTIONS_ADMIN_ROLE] - def get_serializer_class(self): - if self.action == 'create': - return serializers.SubscriptionPlanCreateSerializer - elif self.action == 'partial_update': - return serializers.SubscriptionPlanUpdateSerializer - else: - return serializers.SubscriptionPlanSerializer - @property def requested_current_plan(self): return self.request.query_params.get('current') == 'true' @@ -424,8 +413,7 @@ def base_queryset(self): try: if self.requested_enterprise_uuid is not None: # Use the class method to get the most recent plan - current_plan = SubscriptionPlan.get_current_plan( - self.requested_enterprise_uuid) + current_plan = SubscriptionPlan.get_current_plan(self.requested_enterprise_uuid) queryset = SubscriptionPlan.objects.filter(pk=current_plan.pk) if current_plan \ else SubscriptionPlan.objects.none() else: @@ -435,6 +423,34 @@ def base_queryset(self): return queryset.order_by('-start_date') + +class SubscriptionPlanProvisioningAdminViewset( + mixins.CreateModelMixin, + viewsets.GenericViewSet +): + """ Viewset for Provisioning Admins write operations.""" + authentication_classes = [JwtAuthentication, SessionAuthentication] + permission_classes = [permissions.IsAuthenticated, IsInProvisioningAdminGroup] + lookup_field = 'uuid' + lookup_url_kwarg = 'subscription_uuid' # URL keyword for the lookup field + + def get_serializer_class(self): + if self.action == 'create': + return serializers.SubscriptionPlanCreateSerializer + elif self.action == 'partial_update': + return serializers.SubscriptionPlanUpdateSerializer + else: + return serializers.SubscriptionPlanSerializer + + def get_queryset(self): + return SubscriptionPlan.objects.filter( + is_active=True + ).order_by('-start_date') + + @property + def requested_subscription_uuid(self): + return self.kwargs.get('subscription_uuid') + def create(self, request, *args, **kwargs): """ Creates a new SubscriptionPlan record @@ -461,13 +477,6 @@ def create(self, request, *args, **kwargs): logger.exception(error) return Response({'error': 'Unknown error.'}, status=status.HTTP_400_BAD_REQUEST) - def retrieve(self, request, *args, **kwargs): - """ - Returns a single SubscriptionPlan against given uuid - """ - result = super().retrieve(request, *args, **kwargs) - return Response(data=result.data, status=status.HTTP_200_OK) - def partial_update(self, request, *args, **kwargs): """ Updates SubscriptionPlan record against given uuid @@ -497,6 +506,18 @@ def partial_update(self, request, *args, **kwargs): logger.exception(error) return Response({'error': 'Unknown error.'}, status=status.HTTP_400_BAD_REQUEST) + def retrieve(self, request, *args, **kwargs): + """ + Returns a single SubscriptionPlan object against given uuid + """ + try: + subscription_plan = SubscriptionPlan.objects.get( + uuid=self.requested_subscription_uuid) + serializer = self.get_serializer(subscription_plan) + return Response(data=serializer.data, status=status.HTTP_200_OK) + except SubscriptionPlan.DoesNotExist: + return Response({'error': "No record found."}, status=status.HTTP_404_NOT_FOUND) + class LearnerLicensesViewSet( PermissionRequiredForListingMixin,