diff --git a/license_manager/apps/api/v1/tests/test_views.py b/license_manager/apps/api/v1/tests/test_views.py index 38185625..bf879876 100644 --- a/license_manager/apps/api/v1/tests/test_views.py +++ b/license_manager/apps/api/v1/tests/test_views.py @@ -3111,7 +3111,8 @@ def test_bulk_revoke_no_valid_subscription_plan_superuser(self, mock_revoke_lice response = self.api_client.post(request_url, request_payload) assert response.status_code == status.HTTP_404_NOT_FOUND - expected_response_message = {'error_messages': [{'error': 'No SubscriptionPlan identified by {} exists'.format(non_existent_uuid)}]} + expected_response_message = {'error_messages': [ + {'error': 'No SubscriptionPlan identified by {} exists'.format(non_existent_uuid)}]} self.assertEqual(expected_response_message, response.json()) self.assertFalse(mock_revoke_license.called) @@ -3178,10 +3179,10 @@ def test_bulk_revoke_license_not_found(self, mock_revoke_license, mock_execute_p response_data = response.json() self.assertIn('revocation_results', response_data) self.assertIn('error_messages', response_data) - + self.assertEqual(len(response_data['revocation_results']), 1) self.assertIsInstance(response_data['revocation_results'][0]['user_email'], str) - + self.assertEqual(len(response_data['error_messages']), 1) self.assertIsInstance(response_data['error_messages'][0]['user_email'], str) self.assertEqual(response_data['error_messages'][0]['error'], expected_error_msg) diff --git a/license_manager/apps/api/v1/views.py b/license_manager/apps/api/v1/views.py index b9b306b2..79ea9e36 100644 --- a/license_manager/apps/api/v1/views.py +++ b/license_manager/apps/api/v1/views.py @@ -894,7 +894,11 @@ def _validate_data(self, data): """ serializer_class = self.get_serializer_class() serializer = serializer_class(data=data) - serializer.is_valid(raise_exception=True) + try: + serializer.is_valid(raise_exception=True) + except ValidationError: + logger.error("Received invalid input: %s", data) + raise def _trim_already_associated_emails(self, subscription_plan, user_emails): """ @@ -1313,7 +1317,8 @@ def bulk_revoke(self, request, subscription_uuid=None): Response: 200 OK - All revocations were successful. Returns a list of successful revocations. - 207 Multi-Status - Some revocations were successful, but others failed. Returns both successful and failed revocations. + 207 Multi-Status - Some revocations were successful, but others failed. + Returns both successful and failed revocations. 400 Bad Request - An error occurred when processing the request (e.g., invalid data format). 404 Not Found - The subscription plan was not found. @@ -1335,11 +1340,11 @@ def bulk_revoke(self, request, subscription_uuid=None): ] } - The revocation process attempts to revoke all requested licenses. If any revocations fail, - the successful revocations are still committed, and details of both successful and failed + The revocation process attempts to revoke all requested licenses. If any revocations fail, + the successful revocations are still committed, and details of both successful and failed revocations are returned in the response. - If the number of requested revocations exceeds the remaining revocations for the plan, + If the number of requested revocations exceeds the remaining revocations for the plan, a 400 Bad Request response is returned without processing any revocations. """ # to capture custom metrics diff --git a/license_manager/apps/subscriptions/api.py b/license_manager/apps/subscriptions/api.py index 6bf3ae34..a9413fdd 100644 --- a/license_manager/apps/subscriptions/api.py +++ b/license_manager/apps/subscriptions/api.py @@ -167,7 +167,7 @@ def _renew_all_licenses(original_licenses, future_plan, is_auto_renewed): original_license.renewed_to = future_license License.bulk_update( future_licenses, - ['status', 'user_email', 'lms_user_id', 'activation_date', 'assigned_date'], + ['status', 'user_email', 'lms_user_id', 'activation_key', 'activation_date', 'assigned_date'], ) License.bulk_update( original_licenses, diff --git a/license_manager/apps/subscriptions/tests/test_api.py b/license_manager/apps/subscriptions/tests/test_api.py index 8451ce6d..2a32423e 100644 --- a/license_manager/apps/subscriptions/tests/test_api.py +++ b/license_manager/apps/subscriptions/tests/test_api.py @@ -91,6 +91,7 @@ def _assert_all_licenses_renewed(self, future_plan): self.assertEqual(future_license.status, original_license.status) self.assertEqual(future_license.user_email, original_license.user_email) self.assertEqual(future_license.lms_user_id, original_license.lms_user_id) + self.assertEqual(future_license.activation_key, original_license.activation_key) if original_license.status == constants.ACTIVATED: self.assertEqual(future_license.activation_date, expected_activation_datetime) self.assertEqual(future_license.assigned_date, NOW) @@ -108,6 +109,7 @@ def test_renewal_processed_with_no_existing_future_plan(self): LicenseFactory.create( subscription_plan=prior_plan, status=constants.ASSIGNED, + activation_key=uuid.uuid4(), user_email='assigned_user_{}@example.com'.format(i) ) for i in range(5) ] diff --git a/requirements/base.txt b/requirements/base.txt index d4a91647..55cbf5c2 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -22,9 +22,9 @@ backoff==1.10.0 # analytics-python billiard==4.2.0 # via celery -boto3==1.34.158 +boto3==1.35.5 # via django-ses -botocore==1.34.158 +botocore==1.35.5 # via # boto3 # s3transfer @@ -117,7 +117,7 @@ django-model-utils==4.5.1 # -r requirements/base.in # edx-celeryutils # edx-rbac -django-ses==4.1.0 +django-ses==4.1.1 # via -r requirements/base.in django-simple-history==3.7.0 # via -r requirements/base.in @@ -165,13 +165,13 @@ edx-drf-extensions==10.3.0 # edx-rbac edx-opaque-keys==2.10.0 # via edx-drf-extensions -edx-rbac==1.9.0 +edx-rbac==1.10.0 # via -r requirements/base.in edx-rest-api-client==5.7.1 # via -r requirements/base.in edx-toggles==5.2.0 # via -r requirements/base.in -idna==3.7 +idna==3.8 # via requests inflection==0.5.1 # via drf-spectacular @@ -232,9 +232,7 @@ python-slugify==8.0.4 python3-openid==3.2.0 # via social-auth-core pytz==2024.1 - # via - # -r requirements/base.in - # django-ses + # via -r requirements/base.in pyyaml==6.0.2 # via # code-annotations @@ -265,7 +263,7 @@ s3transfer==0.10.2 # via boto3 semantic-version==2.10.0 # via edx-drf-extensions -simplejson==3.19.2 +simplejson==3.19.3 # via -r requirements/base.in six==1.16.0 # via @@ -283,7 +281,7 @@ social-auth-core==4.5.4 # social-auth-app-django sqlparse==0.5.1 # via django -stevedore==5.2.0 +stevedore==5.3.0 # via # code-annotations # edx-django-utils diff --git a/requirements/dev.txt b/requirements/dev.txt index 5e91940a..efe50b72 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -33,11 +33,11 @@ billiard==4.2.0 # via # -r requirements/validation.txt # celery -boto3==1.34.158 +boto3==1.35.5 # via # -r requirements/validation.txt # django-ses -botocore==1.34.158 +botocore==1.35.5 # via # -r requirements/validation.txt # boto3 @@ -185,7 +185,7 @@ django-model-utils==4.5.1 # -r requirements/validation.txt # edx-celeryutils # edx-rbac -django-ses==4.1.0 +django-ses==4.1.1 # via -r requirements/validation.txt django-simple-history==3.7.0 # via -r requirements/validation.txt @@ -237,21 +237,21 @@ edx-drf-extensions==10.3.0 # edx-rbac edx-i18n-tools==1.6.2 # via -r requirements/validation.txt -edx-lint==5.3.7 +edx-lint==5.4.0 # via -r requirements/validation.txt edx-opaque-keys==2.10.0 # via # -r requirements/validation.txt # edx-drf-extensions -edx-rbac==1.9.0 +edx-rbac==1.10.0 # via -r requirements/validation.txt edx-rest-api-client==5.7.1 # via -r requirements/validation.txt edx-toggles==5.2.0 # via -r requirements/validation.txt -factory-boy==3.3.0 +factory-boy==3.3.1 # via -r requirements/validation.txt -faker==26.3.0 +faker==28.0.0 # via # -r requirements/validation.txt # factory-boy @@ -259,7 +259,7 @@ freezegun==1.5.1 # via -r requirements/validation.txt gunicorn==23.0.0 # via -r requirements/dev.in -idna==3.7 +idna==3.8 # via # -r requirements/validation.txt # requests @@ -459,9 +459,7 @@ python3-openid==3.2.0 # -r requirements/validation.txt # social-auth-core pytz==2024.1 - # via - # -r requirements/validation.txt - # django-ses + # via -r requirements/validation.txt pywatchman==2.0.0 # via -r requirements/dev.in pyyaml==6.0.2 @@ -505,7 +503,7 @@ semantic-version==2.10.0 # via # -r requirements/validation.txt # edx-drf-extensions -simplejson==3.19.2 +simplejson==3.19.3 # via -r requirements/validation.txt six==1.16.0 # via @@ -538,7 +536,7 @@ sqlparse==0.5.1 # -r requirements/validation.txt # django # django-debug-toolbar -stevedore==5.2.0 +stevedore==5.3.0 # via # -r requirements/validation.txt # code-annotations @@ -548,7 +546,7 @@ text-unidecode==1.3 # via # -r requirements/validation.txt # python-slugify -tomlkit==0.13.0 +tomlkit==0.13.2 # via # -r requirements/validation.txt # pylint diff --git a/requirements/doc.txt b/requirements/doc.txt index 6796f8ad..d0db2582 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -43,11 +43,11 @@ billiard==4.2.0 # via # -r requirements/test.txt # celery -boto3==1.34.158 +boto3==1.35.5 # via # -r requirements/test.txt # django-ses -botocore==1.34.158 +botocore==1.35.5 # via # -r requirements/test.txt # boto3 @@ -177,7 +177,7 @@ django-model-utils==4.5.1 # -r requirements/test.txt # edx-celeryutils # edx-rbac -django-ses==4.1.0 +django-ses==4.1.1 # via -r requirements/test.txt django-simple-history==3.7.0 # via -r requirements/test.txt @@ -236,27 +236,27 @@ edx-drf-extensions==10.3.0 # via # -r requirements/test.txt # edx-rbac -edx-lint==5.3.7 +edx-lint==5.4.0 # via -r requirements/test.txt edx-opaque-keys==2.10.0 # via # -r requirements/test.txt # edx-drf-extensions -edx-rbac==1.9.0 +edx-rbac==1.10.0 # via -r requirements/test.txt edx-rest-api-client==5.7.1 # via -r requirements/test.txt edx-toggles==5.2.0 # via -r requirements/test.txt -factory-boy==3.3.0 +factory-boy==3.3.1 # via -r requirements/test.txt -faker==26.3.0 +faker==28.0.0 # via # -r requirements/test.txt # factory-boy freezegun==1.5.1 # via -r requirements/test.txt -idna==3.7 +idna==3.8 # via # -r requirements/test.txt # requests @@ -430,9 +430,7 @@ python3-openid==3.2.0 # -r requirements/test.txt # social-auth-core pytz==2024.1 - # via - # -r requirements/test.txt - # django-ses + # via -r requirements/test.txt pyyaml==6.0.2 # via # -r requirements/test.txt @@ -478,7 +476,7 @@ semantic-version==2.10.0 # via # -r requirements/test.txt # edx-drf-extensions -simplejson==3.19.2 +simplejson==3.19.3 # via -r requirements/test.txt six==1.16.0 # via @@ -503,7 +501,7 @@ social-auth-core==4.5.4 # -r requirements/test.txt # edx-auth-backends # social-auth-app-django -soupsieve==2.5 +soupsieve==2.6 # via beautifulsoup4 sphinx==8.0.2 # via @@ -528,7 +526,7 @@ sqlparse==0.5.1 # via # -r requirements/test.txt # django -stevedore==5.2.0 +stevedore==5.3.0 # via # -r requirements/test.txt # code-annotations @@ -539,7 +537,7 @@ text-unidecode==1.3 # via # -r requirements/test.txt # python-slugify -tomlkit==0.13.0 +tomlkit==0.13.2 # via # -r requirements/test.txt # pylint diff --git a/requirements/pip.txt b/requirements/pip.txt index 11fc3283..0d30cd74 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -10,5 +10,5 @@ wheel==0.44.0 # The following packages are considered to be unsafe in a requirements file: pip==24.2 # via -r requirements/pip.in -setuptools==72.1.0 +setuptools==73.0.1 # via -r requirements/pip.in diff --git a/requirements/production.txt b/requirements/production.txt index 282a525a..ce972210 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -28,11 +28,11 @@ billiard==4.2.0 # via # -r requirements/base.txt # celery -boto3==1.34.158 +boto3==1.35.5 # via # -r requirements/base.txt # django-ses -botocore==1.34.158 +botocore==1.35.5 # via # -r requirements/base.txt # boto3 @@ -143,7 +143,7 @@ django-model-utils==4.5.1 # -r requirements/base.txt # edx-celeryutils # edx-rbac -django-ses==4.1.0 +django-ses==4.1.1 # via -r requirements/base.txt django-simple-history==3.7.0 # via -r requirements/base.txt @@ -197,7 +197,7 @@ edx-opaque-keys==2.10.0 # via # -r requirements/base.txt # edx-drf-extensions -edx-rbac==1.9.0 +edx-rbac==1.10.0 # via -r requirements/base.txt edx-rest-api-client==5.7.1 # via -r requirements/base.txt @@ -209,7 +209,7 @@ greenlet==3.0.3 # via gevent gunicorn==23.0.0 # via -r requirements/production.in -idna==3.7 +idna==3.8 # via # -r requirements/base.txt # requests @@ -318,9 +318,7 @@ python3-openid==3.2.0 # -r requirements/base.txt # social-auth-core pytz==2024.1 - # via - # -r requirements/base.txt - # django-ses + # via -r requirements/base.txt pyyaml==6.0.2 # via # -r requirements/base.txt @@ -362,7 +360,7 @@ semantic-version==2.10.0 # via # -r requirements/base.txt # edx-drf-extensions -simplejson==3.19.2 +simplejson==3.19.3 # via -r requirements/base.txt six==1.16.0 # via @@ -388,7 +386,7 @@ sqlparse==0.5.1 # via # -r requirements/base.txt # django -stevedore==5.2.0 +stevedore==5.3.0 # via # -r requirements/base.txt # code-annotations diff --git a/requirements/quality.txt b/requirements/quality.txt index 945958b0..8120c878 100644 --- a/requirements/quality.txt +++ b/requirements/quality.txt @@ -32,11 +32,11 @@ billiard==4.2.0 # via # -r requirements/base.txt # celery -boto3==1.34.158 +boto3==1.35.5 # via # -r requirements/base.txt # django-ses -botocore==1.34.158 +botocore==1.35.5 # via # -r requirements/base.txt # boto3 @@ -154,7 +154,7 @@ django-model-utils==4.5.1 # -r requirements/base.txt # edx-celeryutils # edx-rbac -django-ses==4.1.0 +django-ses==4.1.1 # via -r requirements/base.txt django-simple-history==3.7.0 # via -r requirements/base.txt @@ -204,19 +204,19 @@ edx-drf-extensions==10.3.0 # via # -r requirements/base.txt # edx-rbac -edx-lint==5.3.7 +edx-lint==5.4.0 # via -r requirements/quality.in edx-opaque-keys==2.10.0 # via # -r requirements/base.txt # edx-drf-extensions -edx-rbac==1.9.0 +edx-rbac==1.10.0 # via -r requirements/base.txt edx-rest-api-client==5.7.1 # via -r requirements/base.txt edx-toggles==5.2.0 # via -r requirements/base.txt -idna==3.7 +idna==3.8 # via # -r requirements/base.txt # requests @@ -345,9 +345,7 @@ python3-openid==3.2.0 # -r requirements/base.txt # social-auth-core pytz==2024.1 - # via - # -r requirements/base.txt - # django-ses + # via -r requirements/base.txt pyyaml==6.0.2 # via # -r requirements/base.txt @@ -388,7 +386,7 @@ semantic-version==2.10.0 # via # -r requirements/base.txt # edx-drf-extensions -simplejson==3.19.2 +simplejson==3.19.3 # via -r requirements/base.txt six==1.16.0 # via @@ -417,7 +415,7 @@ sqlparse==0.5.1 # via # -r requirements/base.txt # django -stevedore==5.2.0 +stevedore==5.3.0 # via # -r requirements/base.txt # code-annotations @@ -427,7 +425,7 @@ text-unidecode==1.3 # via # -r requirements/base.txt # python-slugify -tomlkit==0.13.0 +tomlkit==0.13.2 # via pylint typing-extensions==4.12.2 # via diff --git a/requirements/test.txt b/requirements/test.txt index 862a4ae7..043cbcb2 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -32,11 +32,11 @@ billiard==4.2.0 # via # -r requirements/base.txt # celery -boto3==1.34.158 +boto3==1.35.5 # via # -r requirements/base.txt # django-ses -botocore==1.34.158 +botocore==1.35.5 # via # -r requirements/base.txt # boto3 @@ -163,7 +163,7 @@ django-model-utils==4.5.1 # -r requirements/base.txt # edx-celeryutils # edx-rbac -django-ses==4.1.0 +django-ses==4.1.1 # via -r requirements/base.txt django-simple-history==3.7.0 # via -r requirements/base.txt @@ -213,25 +213,25 @@ edx-drf-extensions==10.3.0 # via # -r requirements/base.txt # edx-rbac -edx-lint==5.3.7 +edx-lint==5.4.0 # via -r requirements/test.in edx-opaque-keys==2.10.0 # via # -r requirements/base.txt # edx-drf-extensions -edx-rbac==1.9.0 +edx-rbac==1.10.0 # via -r requirements/base.txt edx-rest-api-client==5.7.1 # via -r requirements/base.txt edx-toggles==5.2.0 # via -r requirements/base.txt -factory-boy==3.3.0 +factory-boy==3.3.1 # via -r requirements/test.in -faker==26.3.0 +faker==28.0.0 # via factory-boy freezegun==1.5.1 # via -r requirements/test.in -idna==3.7 +idna==3.8 # via # -r requirements/base.txt # requests @@ -370,9 +370,7 @@ python3-openid==3.2.0 # -r requirements/base.txt # social-auth-core pytz==2024.1 - # via - # -r requirements/base.txt - # django-ses + # via -r requirements/base.txt pyyaml==6.0.2 # via # -r requirements/base.txt @@ -413,7 +411,7 @@ semantic-version==2.10.0 # via # -r requirements/base.txt # edx-drf-extensions -simplejson==3.19.2 +simplejson==3.19.3 # via -r requirements/base.txt six==1.16.0 # via @@ -440,7 +438,7 @@ sqlparse==0.5.1 # via # -r requirements/base.txt # django -stevedore==5.2.0 +stevedore==5.3.0 # via # -r requirements/base.txt # code-annotations @@ -450,7 +448,7 @@ text-unidecode==1.3 # via # -r requirements/base.txt # python-slugify -tomlkit==0.13.0 +tomlkit==0.13.2 # via pylint typing-extensions==4.12.2 # via diff --git a/requirements/validation.txt b/requirements/validation.txt index b58852d9..53c07df3 100644 --- a/requirements/validation.txt +++ b/requirements/validation.txt @@ -41,12 +41,12 @@ billiard==4.2.0 # -r requirements/quality.txt # -r requirements/test.txt # celery -boto3==1.34.158 +boto3==1.35.5 # via # -r requirements/quality.txt # -r requirements/test.txt # django-ses -botocore==1.34.158 +botocore==1.35.5 # via # -r requirements/quality.txt # -r requirements/test.txt @@ -208,7 +208,7 @@ django-model-utils==4.5.1 # -r requirements/test.txt # edx-celeryutils # edx-rbac -django-ses==4.1.0 +django-ses==4.1.1 # via # -r requirements/quality.txt # -r requirements/test.txt @@ -284,7 +284,7 @@ edx-drf-extensions==10.3.0 # edx-rbac edx-i18n-tools==1.6.2 # via -r requirements/validation.in -edx-lint==5.3.7 +edx-lint==5.4.0 # via # -r requirements/quality.txt # -r requirements/test.txt @@ -293,7 +293,7 @@ edx-opaque-keys==2.10.0 # -r requirements/quality.txt # -r requirements/test.txt # edx-drf-extensions -edx-rbac==1.9.0 +edx-rbac==1.10.0 # via # -r requirements/quality.txt # -r requirements/test.txt @@ -305,15 +305,15 @@ edx-toggles==5.2.0 # via # -r requirements/quality.txt # -r requirements/test.txt -factory-boy==3.3.0 +factory-boy==3.3.1 # via -r requirements/test.txt -faker==26.3.0 +faker==28.0.0 # via # -r requirements/test.txt # factory-boy freezegun==1.5.1 # via -r requirements/test.txt -idna==3.7 +idna==3.8 # via # -r requirements/quality.txt # -r requirements/test.txt @@ -520,7 +520,6 @@ pytz==2024.1 # via # -r requirements/quality.txt # -r requirements/test.txt - # django-ses pyyaml==6.0.2 # via # -r requirements/quality.txt @@ -573,7 +572,7 @@ semantic-version==2.10.0 # -r requirements/quality.txt # -r requirements/test.txt # edx-drf-extensions -simplejson==3.19.2 +simplejson==3.19.3 # via # -r requirements/quality.txt # -r requirements/test.txt @@ -612,7 +611,7 @@ sqlparse==0.5.1 # -r requirements/quality.txt # -r requirements/test.txt # django -stevedore==5.2.0 +stevedore==5.3.0 # via # -r requirements/quality.txt # -r requirements/test.txt @@ -624,7 +623,7 @@ text-unidecode==1.3 # -r requirements/quality.txt # -r requirements/test.txt # python-slugify -tomlkit==0.13.0 +tomlkit==0.13.2 # via # -r requirements/quality.txt # -r requirements/test.txt