diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19ed18c78..bfe6998e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,7 +90,6 @@ jobs: MITXPRO_ADMIN_EMAIL: example@localhost OPENEDX_API_CLIENT_ID: fake_client_id OPENEDX_API_CLIENT_SECRET: fake_client_secret # pragma: allowlist secret - OPENEDX_API_KEY: test-openedx-api-key # pragma: allowlist secret - name: Tests run: | @@ -120,7 +119,6 @@ jobs: OPENEDX_API_BASE_URL: http://localhost:18000 OPENEDX_API_CLIENT_ID: fake_client_id OPENEDX_API_CLIENT_SECRET: fake_client_secret # pragma: allowlist secret - OPENEDX_API_KEY: test-openedx-api-key # pragma: allowlist secret SECRET_KEY: local_unsafe_key # pragma: allowlist secret - name: Upload coverage to CodeCov diff --git a/.secrets.baseline b/.secrets.baseline index 606f8678d..70560a3d2 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -213,13 +213,6 @@ "hashed_secret": "b235838f76594bf21886c6eec9c06a207e9ec5ce", "is_verified": false, "line_number": 35 - }, - { - "type": "Secret Keyword", - "filename": "pytest.ini", - "hashed_secret": "e035cdf1f57666859ec5949ee389d479d03ea1e3", - "is_verified": false, - "line_number": 36 } ], "sheets/dev-setup.md": [ @@ -284,5 +277,5 @@ } ] }, - "generated_at": "2024-05-15T07:35:56Z" + "generated_at": "2024-05-22T09:32:37Z" } diff --git a/app.json b/app.json index ef3b892e7..4a345feab 100644 --- a/app.json +++ b/app.json @@ -442,10 +442,6 @@ "description": "The OAuth2 client secret to connect to Open edX with", "required": true }, - "OPENEDX_API_KEY": { - "description": "edX API key (EDX_API_KEY setting in Open edX)", - "required": true - }, "OPENEDX_BASE_REDIRECT_URL": { "description": "The base redirect URL for an OAuth Application for the Open edX API", "required": false diff --git a/courseware/api.py b/courseware/api.py index e8eb714ab..3fd4dbcf5 100644 --- a/courseware/api.py +++ b/courseware/api.py @@ -62,7 +62,6 @@ ACCESS_TOKEN_HEADER_NAME = "X-Access-Token" # noqa: S105 AUTH_TOKEN_HEADER_NAME = "Authorization" # noqa: S105 -API_KEY_HEADER_NAME = "X-EdX-Api-Key" # pragma: allowlist secret @dataclass(frozen=True) @@ -127,10 +126,7 @@ def get_existing_openedx_user(user): raise ImproperlyConfigured("OPENEDX_SERVICE_WORKER_API_TOKEN is not set") # noqa: EM101 req_session = requests.Session() req_session.headers.update( - { - AUTH_TOKEN_HEADER_NAME: f"Bearer {settings.OPENEDX_SERVICE_WORKER_API_TOKEN}", - API_KEY_HEADER_NAME: settings.OPENEDX_API_KEY, - } + {AUTH_TOKEN_HEADER_NAME: f"Bearer {settings.OPENEDX_SERVICE_WORKER_API_TOKEN}"} ) response = req_session.get( edx_url(f"{OPENEDX_USER_ACCOUNT_DETAIL_PATH}"), params={"email": user.email} @@ -515,7 +511,7 @@ def get_edx_api_client(user, ttl_in_seconds=OPENEDX_AUTH_DEFAULT_TTL_IN_SECONDS) "{} does not have an associated OpenEdxApiAuth".format(str(user)) # noqa: EM103, UP032 ) return EdxApi( - {"access_token": auth.access_token, "api_key": settings.OPENEDX_API_KEY}, + {"access_token": auth.access_token}, settings.OPENEDX_API_BASE_URL, timeout=settings.EDX_API_CLIENT_TIMEOUT, ) @@ -532,10 +528,7 @@ def get_edx_api_service_client(): raise ImproperlyConfigured("OPENEDX_SERVICE_WORKER_API_TOKEN is not set") # noqa: EM101 return EdxApi( - { - "access_token": settings.OPENEDX_SERVICE_WORKER_API_TOKEN, - "api_key": settings.OPENEDX_API_KEY, - }, + {"access_token": settings.OPENEDX_SERVICE_WORKER_API_TOKEN}, settings.OPENEDX_API_BASE_URL, timeout=settings.EDX_API_CLIENT_TIMEOUT, ) @@ -630,6 +623,7 @@ def enroll_in_edx_course_runs(user, course_runs, force_enrollment=True): # noqa UnknownEdxApiEnrollException: Raised if an unknown error was encountered during the edX API request """ edx_client = get_edx_api_service_client() + username = user.username results = [] for course_run in course_runs: @@ -745,10 +739,10 @@ def unenroll_edx_course_run(run_enrollment): EdxApiEnrollErrorException: Raised if the underlying edX API HTTP request fails UnknownEdxApiEnrollException: Raised if an unknown error was encountered during the edX API request """ - edx_client = get_edx_api_client(run_enrollment.user) + edx_client = get_edx_api_service_client() try: deactivated_enrollment = edx_client.enrollments.deactivate_enrollment( - run_enrollment.run.courseware_id + run_enrollment.run.courseware_id, username=run_enrollment.user.username ) except HTTPError as exc: raise EdxApiEnrollErrorException(run_enrollment.user, run_enrollment.run, exc) # noqa: B904, TRY200 diff --git a/courseware/api_test.py b/courseware/api_test.py index a80bbed87..ada5d7112 100644 --- a/courseware/api_test.py +++ b/courseware/api_test.py @@ -716,14 +716,19 @@ def test_unenroll_edx_course_run(mocker): mock_client = mocker.MagicMock() run_enrollment = CourseRunEnrollmentFactory.create(edx_enrolled=True) courseware_id = run_enrollment.run.courseware_id - enroll_return_value = mocker.Mock(json={"course_id": courseware_id}) + username = run_enrollment.user.username + enroll_return_value = mocker.Mock( + json={"course_id": courseware_id, "user": username} + ) mock_client.enrollments.deactivate_enrollment = mocker.Mock( return_value=enroll_return_value ) - mocker.patch("courseware.api.get_edx_api_client", return_value=mock_client) + mocker.patch("courseware.api.get_edx_api_service_client", return_value=mock_client) deactivated_enrollment = unenroll_edx_course_run(run_enrollment) - mock_client.enrollments.deactivate_enrollment.assert_called_once_with(courseware_id) + mock_client.enrollments.deactivate_enrollment.assert_called_once_with( + courseware_id, username=username + ) assert deactivated_enrollment == enroll_return_value @@ -744,7 +749,7 @@ def test_unenroll_edx_course_run_failure( mock_client.enrollments.deactivate_enrollment = mocker.Mock( side_effect=client_exception_raised ) - mocker.patch("courseware.api.get_edx_api_client", return_value=mock_client) + mocker.patch("courseware.api.get_edx_api_service_client", return_value=mock_client) with pytest.raises(expected_exception): unenroll_edx_course_run(run_enrollment) diff --git a/docker-compose.yml b/docker-compose.yml index 374eb7903..00f33bb77 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,6 @@ x-environment: &py-environment REDIS_URL: redis://redis:6379/4 DOCKER_HOST: ${DOCKER_HOST:-missing} WEBPACK_DEV_SERVER_HOST: ${WEBPACK_DEV_SERVER_HOST:-localhost} - OPENEDX_API_KEY: ${OPENEDX_API_KEY:-PUT_YOUR_API_KEY_HERE} x-extra-hosts: &default-extra-hosts - "edx.odl.local:${OPENEDX_IP:-172.22.0.1}" diff --git a/mitxpro/settings.py b/mitxpro/settings.py index 876ca2426..44da09723 100644 --- a/mitxpro/settings.py +++ b/mitxpro/settings.py @@ -1045,12 +1045,6 @@ description="The OAuth2 client secret to connect to Open edX with", required=True, ) -OPENEDX_API_KEY = get_string( - name="OPENEDX_API_KEY", - default=None, - description="edX API key (EDX_API_KEY setting in Open edX)", - required=True, -) MITXPRO_REGISTRATION_ACCESS_TOKEN = get_string( name="MITXPRO_REGISTRATION_ACCESS_TOKEN", diff --git a/poetry.lock b/poetry.lock index 056faafd1..52951355a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "amqp" @@ -1242,13 +1242,13 @@ files = [ [[package]] name = "edx-api-client" -version = "1.8.0" +version = "1.9.0" description = "Python interface to the edX REST APIs" optional = false python-versions = "*" files = [ - {file = "edx-api-client-1.8.0.tar.gz", hash = "sha256:cbf9af4d466cbea465054d78688e6f335a3e485a4e2f90dc82e050202af29ba1"}, - {file = "edx_api_client-1.8.0-py2.py3-none-any.whl", hash = "sha256:050f0622c2c3a0d4f24902bf6218b2a554b86a5e84800b71d1fefd0bddf3ad13"}, + {file = "edx-api-client-1.9.0.tar.gz", hash = "sha256:75006eb9d2540da3960993a3050372e52557b2c4c28d1d6f02cc2d6c46e72f57"}, + {file = "edx_api_client-1.9.0-py2.py3-none-any.whl", hash = "sha256:10d2f1d0a33cf5c3bf77bdabb4862d9724e41d3f1d9084d5545b292383d60acf"}, ] [package.dependencies] @@ -4089,4 +4089,4 @@ xmlsec = ["xmlsec (>=0.6.1)"] [metadata] lock-version = "2.0" python-versions = "3.9.15" -content-hash = "37f393dfd4949325481056512f91def2894865cf71a6345f53538ba135885074" +content-hash = "315a2f6add7e1a53b25cc80aeee9fa6301b6c9a51d227958e05b4c9c64ba390e" diff --git a/pyproject.toml b/pyproject.toml index 0d21843e0..b8e767aa5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ django-user-agents = "0.4.0" django-webpack-loader = "0.7.0" djangorestframework = "3.15.1" drf-flex-fields = "0.9.9" -edx-api-client = "1.8.0" +edx-api-client = "1.9.0" flaky = "3.8.1" google-api-python-client = "1.12.11" google-auth = "1.35.0" diff --git a/pytest.ini b/pytest.ini index bca581c5a..1faddffcd 100644 --- a/pytest.ini +++ b/pytest.ini @@ -33,7 +33,6 @@ env = OPENEDX_API_BASE_URL=http://localhost:18000 OPENEDX_API_CLIENT_ID=fake_client_id OPENEDX_API_CLIENT_SECRET=fake_client_secret - OPENEDX_API_KEY=test-openedx-api-key SENTRY_DSN= WAGTAIL_CACHE_BACKEND=django.core.cache.backends.dummy.DummyCache WAGTAIL_CACHE_URL=