fix: generalize internal services

This commit is contained in:
Jade Olivier
2024-08-06 11:18:52 +02:00
parent 77ca0f754a
commit e8f9db428d
6 changed files with 52 additions and 29 deletions

View File

@@ -4996,6 +4996,8 @@ RETIREMENT_STATES = [
'COMPLETE',
]
EXTRA_SERVICES_TO_RETIRE_FROM = {}
USERNAME_REPLACEMENT_WORKER = "REPLACE WITH VALID USERNAME"
############## Settings for Microfrontends #########################

View File

@@ -662,6 +662,8 @@ SUBSCRIPTIONS_TRIAL_LENGTH = 7
CSRF_TRUSTED_ORIGINS = ['.example.com']
CSRF_TRUSTED_ORIGINS_WITH_SCHEME = ['https://*.example.com']
EXTRA_SERVICES_TO_RETIRE_FROM = {}
# values are already updated above with default CSRF_TRUSTED_ORIGINS values but in
# case of new django version these values will override.
if django.VERSION[0] >= 4: # for greater than django 3.2 use with schemes.

View File

@@ -4,6 +4,8 @@ Test the retire_one_learner.py script
from unittest.mock import DEFAULT, patch
from click.testing import CliRunner
from django.conf import settings
from django.test.utils import override_settings
from scripts.user_retirement.retire_one_learner import (
END_STATES,
@@ -19,6 +21,13 @@ from scripts.user_retirement.tests.retirement_helpers import fake_config_file, g
from scripts.user_retirement.utils.exception import HttpDoesNotExistException
@override_settings(EXTRA_SERVICES_TO_RETIRE_FROM=[
{
'name': 'MOCK_SERVICE',
'service_base_url': 'http://fake_service_base_url',
'retirement_url_path': 'fake_retirement_url_path'
}
])
def _call_script(username, fetch_ecom_segment_id=False):
"""
Call the retired learner script with the given username and a generic, temporary config file.

View File

@@ -544,9 +544,9 @@ class TestLicenseManagerApi(OAuth2Mixin, unittest.TestCase):
)
class TestCommerceCoordinatorApi(OAuth2Mixin, unittest.TestCase):
class TestGenericApi(OAuth2Mixin, unittest.TestCase):
"""
Test the edX Commerce-Coordinator API client.
Test the Generic API client.
"""
@responses.activate(registry=OrderedRegistry)
@@ -554,15 +554,17 @@ class TestCommerceCoordinatorApi(OAuth2Mixin, unittest.TestCase):
super().setUp()
self.mock_access_token_response()
self.lms_base_url = 'http://localhost:18000/'
self.commerce_coordinator_base_url = 'http://localhost:8140/'
self.commerce_coordinator_api = edx_api.CommerceCoordinatorApi(
self.service_api_base_url = 'http://mock_service_url/'
self.retirement_url = 'mock/retirement_url'
self.generic_api = edx_api.GenericRetirementApi(
self.lms_base_url,
self.commerce_coordinator_base_url,
self.service_api_base_url,
'the_client_id',
'the_client_secret'
'the_client_secret',
self.retirement_url
)
@patch.object(edx_api.CommerceCoordinatorApi, '_request')
@patch.object(edx_api.GenericRetirementApi, '_request')
def test_retire_learner(self, mock_request):
learner_data = get_fake_user_retirement()
json_data = {
@@ -570,14 +572,14 @@ class TestCommerceCoordinatorApi(OAuth2Mixin, unittest.TestCase):
}
responses.add(
POST,
urljoin(self.commerce_coordinator_base_url, 'lms/user_retirement'),
urljoin(self.service_api_base_url, 'mock/retirement_url'),
match=[matchers.json_params_matcher(json_data)]
)
self.commerce_coordinator_api.retire_learner(learner=learner_data)
self.generic_api.retire_learner(learner=learner_data)
mock_request.assert_called_once_with(
'POST',
urljoin(self.commerce_coordinator_base_url, 'lms/user_retirement/'),
urljoin(self.service_api_base_url, 'mock/retirement_url/'),
json=json_data
)

View File

@@ -492,16 +492,19 @@ class LicenseManagerApi(BaseApiClient):
return True
class CommerceCoordinatorApi(BaseApiClient):
class GenericRetirementApi(BaseApiClient):
"""
Commerce-Coordinator API client.
Generic API client.
"""
def __init__(self, lms_base_url, api_base_url, client_id, client_secret, retirement_url_path):
super().__init__(lms_base_url, api_base_url, client_id, client_secret)
self.retirement_url_path = retirement_url_path
@_retry_lms_api()
def retire_learner(self, learner):
"""
Performs the learner retirement step for Commerce-Coordinator.
Passes the learner's LMS User Id instead of username.
Performs the learner retirement step for additonal services.
"""
data = {'edx_lms_user_id': learner['user']['id']}
api_url = self.get_api_url('lms/user_retirement')
api_url = self.get_api_url(self.retirement_url_path)
return self._request('POST', api_url, json=data)

View File

@@ -16,9 +16,10 @@ import unicodedata
import yaml
from six import text_type
from django.conf import settings
from scripts.user_retirement.utils.edx_api import LmsApi # pylint: disable=wrong-import-position
from scripts.user_retirement.utils.edx_api import CommerceCoordinatorApi, CredentialsApi, EcommerceApi, \
from scripts.user_retirement.utils.edx_api import CredentialsApi, EcommerceApi, GenericRetirementApi, \
LicenseManagerApi
from scripts.user_retirement.utils.thirdparty_apis.amplitude_api import \
AmplitudeApi # pylint: disable=wrong-import-position
@@ -155,7 +156,6 @@ def _setup_all_apis_or_exit(fail_func, fail_code, config):
credentials_base_url = config['base_urls'].get('credentials', None)
segment_base_url = config['base_urls'].get('segment', None)
license_manager_base_url = config['base_urls'].get('license_manager', None)
commerce_coordinator_base_url = config['base_urls'].get('commerce_coordinator', None)
client_id = config['client_id']
client_secret = config['client_secret']
braze_api_key = config.get('braze_api_key', None)
@@ -174,16 +174,19 @@ def _setup_all_apis_or_exit(fail_func, fail_code, config):
hubspot_from_address = config.get('hubspot_from_address', None)
hubspot_alert_email = config.get('hubspot_alert_email', None)
required_services = [
('BRAZE', braze_api_key),
('AMPLITUDE', amplitude_api_key),
('ECOMMERCE', ecommerce_base_url),
('CREDENTIALS', credentials_base_url),
('SEGMENT', segment_base_url),
('HUBSPOT', hubspot_api_key),
]
extra_services = [(service['name'], service['service_base_url']) for service in settings.EXTRA_SERVICES_TO_RETIRE_FROM]
all_services = required_services + extra_services
for state in config['retirement_pipeline']:
for service, service_url in (
('BRAZE', braze_api_key),
('AMPLITUDE', amplitude_api_key),
('ECOMMERCE', ecommerce_base_url),
('CREDENTIALS', credentials_base_url),
('SEGMENT', segment_base_url),
('HUBSPOT', hubspot_api_key),
('COMMERCE_COORDINATOR', commerce_coordinator_base_url),
):
for service, service_url in (all_services):
if state[2] == service and service_url is None:
fail_func(fail_code, 'Service URL is not configured, but required for state {}'.format(state))
@@ -239,12 +242,14 @@ def _setup_all_apis_or_exit(fail_func, fail_code, config):
segment_workspace_slug
)
if commerce_coordinator_base_url:
config['COMMERCE_COORDINATOR'] = CommerceCoordinatorApi(
for service_config in extra_services:
service_name = service_config['name']
config[service_name] = GenericRetirementApi(
lms_base_url,
commerce_coordinator_base_url,
service_config['service_base_url'],
client_id,
client_secret,
service_config['retirement_url_path']
)
except Exception as exc: # pylint: disable=broad-except
fail_func(fail_code, 'Unexpected error occurred!', exc)