From b862bbeba66b1672301747e7e780470925811089 Mon Sep 17 00:00:00 2001 From: edX requirements bot <49161187+edx-requirements-bot@users.noreply.github.com> Date: Mon, 2 Oct 2023 08:10:01 -0400 Subject: [PATCH 01/17] chore: Updating Python Requirements (#33383) --- requirements/edx-sandbox/py38.txt | 8 +++--- requirements/edx/base.txt | 30 +++++++++++----------- requirements/edx/development.txt | 42 +++++++++++++++---------------- requirements/edx/doc.txt | 30 +++++++++++----------- requirements/edx/semgrep.txt | 8 +++--- requirements/edx/testing.txt | 38 ++++++++++++++-------------- requirements/pip-tools.txt | 2 +- scripts/xblock/requirements.txt | 2 +- 8 files changed, 80 insertions(+), 80 deletions(-) diff --git a/requirements/edx-sandbox/py38.txt b/requirements/edx-sandbox/py38.txt index 27138116fd..d1cc50e869 100644 --- a/requirements/edx-sandbox/py38.txt +++ b/requirements/edx-sandbox/py38.txt @@ -4,7 +4,7 @@ # # make upgrade # -cffi==1.15.1 +cffi==1.16.0 # via cryptography chem==1.2.0 # via -r requirements/edx-sandbox/py38.in @@ -20,9 +20,9 @@ cryptography==38.0.4 # via # -c requirements/edx-sandbox/../constraints.txt # -r requirements/edx-sandbox/py38.in -cycler==0.11.0 +cycler==0.12.0 # via matplotlib -fonttools==4.42.1 +fonttools==4.43.0 # via matplotlib importlib-resources==6.1.0 # via matplotlib @@ -57,7 +57,7 @@ numpy==1.22.4 # scipy openedx-calc==3.0.1 # via -r requirements/edx-sandbox/py38.in -packaging==23.1 +packaging==23.2 # via matplotlib pillow==9.5.0 # via diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 8b7d83aceb..f16deb7bb9 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -77,13 +77,13 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in -boto3==1.28.53 +boto3==1.28.57 # via # -r requirements/edx/kernel.in # django-ses # fs-s3fs # ora2 -botocore==1.31.53 +botocore==1.31.57 # via # -r requirements/edx/kernel.in # boto3 @@ -107,7 +107,7 @@ certifi==2023.7.22 # py2neo # requests # snowflake-connector-python -cffi==1.15.1 +cffi==1.16.0 # via # cryptography # pynacl @@ -406,7 +406,7 @@ drf-jwt==1.19.2 # via edx-drf-extensions drf-nested-routers==0.93.4 # via openedx-blockstore -drf-spectacular==0.26.4 +drf-spectacular==0.26.5 # via -r requirements/edx/kernel.in drf-yasg==1.21.5 # via @@ -492,7 +492,7 @@ edx-i18n-tools==1.2.0 # via ora2 edx-milestones==0.5.0 # via -r requirements/edx/kernel.in -edx-name-affirmation==2.3.6 +edx-name-affirmation==2.3.7 # via -r requirements/edx/kernel.in edx-opaque-keys[django]==2.5.1 # via @@ -599,7 +599,7 @@ html5lib==1.1 # via # -r requirements/edx/kernel.in # ora2 -icalendar==5.0.8 +icalendar==5.0.10 # via -r requirements/edx/kernel.in idna==3.4 # via @@ -735,7 +735,7 @@ mysqlclient==2.2.0 # via # -r requirements/edx/kernel.in # openedx-blockstore -newrelic==9.0.0 +newrelic==9.1.0 # via # -r requirements/edx/bundled.in # edx-django-utils @@ -758,7 +758,7 @@ oauthlib==3.2.2 # social-auth-core olxcleaner==0.2.1 # via -r requirements/edx/kernel.in -openai==0.28.0 +openai==0.28.1 # via edx-enterprise openedx-atlas==0.5.0 # via -r requirements/edx/kernel.in @@ -792,11 +792,11 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/kernel.in optimizely-sdk==4.1.1 # via -r requirements/edx/bundled.in -ora2==5.5.0 +ora2==5.5.1 # via -r requirements/edx/bundled.in oscrypto==1.3.0 # via snowflake-connector-python -packaging==23.1 +packaging==23.2 # via # drf-yasg # gunicorn @@ -977,7 +977,7 @@ random2==1.0.1 # via -r requirements/edx/kernel.in recommender-xblock==2.0.1 # via -r requirements/edx/bundled.in -redis==5.0.0 +redis==5.0.1 # via # -r requirements/edx/kernel.in # walrus @@ -1018,7 +1018,7 @@ rpds-py==0.10.3 # via # jsonschema # referencing -ruamel-yaml==0.17.32 +ruamel-yaml==0.17.33 # via drf-yasg ruamel-yaml-clib==0.2.7 # via ruamel-yaml @@ -1028,7 +1028,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.6.2 +s3transfer==0.7.0 # via boto3 sailthru-client==2.2.3 # via edx-ace @@ -1181,7 +1181,7 @@ walrus==0.9.3 # via edx-event-bus-redis watchdog==3.0.0 # via -r requirements/edx/paver.txt -wcwidth==0.2.6 +wcwidth==0.2.8 # via prompt-toolkit web-fragments==2.1.0 # via @@ -1204,7 +1204,7 @@ wrapt==1.15.0 # via # -r requirements/edx/paver.txt # deprecated -xblock[django]==1.7.0 +xblock[django]==1.8.0 # via # -r requirements/edx/kernel.in # acid-xblock diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 7566105dd4..080e3a1276 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -145,14 +145,14 @@ boto==2.39.0 # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -boto3==1.28.53 +boto3==1.28.57 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # django-ses # fs-s3fs # ora2 -botocore==1.31.53 +botocore==1.31.57 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -187,7 +187,7 @@ certifi==2023.7.22 # py2neo # requests # snowflake-connector-python -cffi==1.15.1 +cffi==1.16.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -655,7 +655,7 @@ drf-nested-routers==0.93.4 # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # openedx-blockstore -drf-spectacular==0.26.4 +drf-spectacular==0.26.5 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -774,7 +774,7 @@ edx-milestones==0.5.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -edx-name-affirmation==2.3.6 +edx-name-affirmation==2.3.7 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -897,7 +897,7 @@ faker==19.6.2 # via # -r requirements/edx/testing.txt # factory-boy -fastapi==0.103.1 +fastapi==0.103.2 # via # -r requirements/edx/testing.txt # pact-python @@ -984,7 +984,7 @@ httpx==0.23.3 # via # -r requirements/edx/testing.txt # pact-python -icalendar==5.0.8 +icalendar==5.0.10 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1002,7 +1002,7 @@ imagesize==1.4.1 # via # -r requirements/edx/doc.txt # sphinx -import-linter==1.11.1 +import-linter==1.12.0 # via -r requirements/edx/testing.txt importlib-metadata==6.8.0 # via @@ -1239,7 +1239,7 @@ mysqlclient==2.2.0 # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # openedx-blockstore -newrelic==9.0.0 +newrelic==9.1.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1274,7 +1274,7 @@ olxcleaner==0.2.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -openai==0.28.0 +openai==0.28.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1330,7 +1330,7 @@ optimizely-sdk==4.1.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -ora2==5.5.0 +ora2==5.5.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1339,7 +1339,7 @@ oscrypto==1.3.0 # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # snowflake-connector-python -packaging==23.1 +packaging==23.2 # via # -r requirements/edx/../pip-tools.txt # -r requirements/edx/doc.txt @@ -1475,11 +1475,11 @@ pycryptodomex==3.19.0 # lti-consumer-xblock # pyjwkest # snowflake-connector-python -pydantic==2.3.0 +pydantic==2.4.2 # via # -r requirements/edx/testing.txt # fastapi -pydantic-core==2.6.3 +pydantic-core==2.10.1 # via # -r requirements/edx/testing.txt # pydantic @@ -1713,7 +1713,7 @@ recommender-xblock==2.0.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -redis==5.0.0 +redis==5.0.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1771,7 +1771,7 @@ rpds-py==0.10.3 # -r requirements/edx/testing.txt # jsonschema # referencing -ruamel-yaml==0.17.32 +ruamel-yaml==0.17.33 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1788,7 +1788,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.6.2 +s3transfer==0.7.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -2054,11 +2054,11 @@ tqdm==4.66.1 # openai types-pytz==2023.3.1.1 # via django-stubs -types-pyyaml==6.0.12.11 +types-pyyaml==6.0.12.12 # via # django-stubs # djangorestframework-stubs -types-requests==2.31.0.3 +types-requests==2.31.0.6 # via djangorestframework-stubs types-urllib3==1.26.25.14 # via types-requests @@ -2156,7 +2156,7 @@ watchdog==3.0.0 # -r requirements/edx/development.in # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -wcwidth==0.2.6 +wcwidth==0.2.8 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -2192,7 +2192,7 @@ wrapt==1.15.0 # -r requirements/edx/testing.txt # astroid # deprecated -xblock[django]==1.7.0 +xblock[django]==1.8.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 90293ebd9e..6e9d767fcd 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -103,13 +103,13 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -boto3==1.28.53 +boto3==1.28.57 # via # -r requirements/edx/base.txt # django-ses # fs-s3fs # ora2 -botocore==1.31.53 +botocore==1.31.57 # via # -r requirements/edx/base.txt # boto3 @@ -133,7 +133,7 @@ certifi==2023.7.22 # py2neo # requests # snowflake-connector-python -cffi==1.15.1 +cffi==1.16.0 # via # -r requirements/edx/base.txt # cryptography @@ -481,7 +481,7 @@ drf-nested-routers==0.93.4 # via # -r requirements/edx/base.txt # openedx-blockstore -drf-spectacular==0.26.4 +drf-spectacular==0.26.5 # via -r requirements/edx/base.txt drf-yasg==1.21.5 # via @@ -570,7 +570,7 @@ edx-i18n-tools==1.2.0 # ora2 edx-milestones==0.5.0 # via -r requirements/edx/base.txt -edx-name-affirmation==2.3.6 +edx-name-affirmation==2.3.7 # via -r requirements/edx/base.txt edx-opaque-keys[django]==2.5.1 # via @@ -694,7 +694,7 @@ html5lib==1.1 # via # -r requirements/edx/base.txt # ora2 -icalendar==5.0.8 +icalendar==5.0.10 # via -r requirements/edx/base.txt idna==3.4 # via @@ -869,7 +869,7 @@ mysqlclient==2.2.0 # via # -r requirements/edx/base.txt # openedx-blockstore -newrelic==9.0.0 +newrelic==9.1.0 # via # -r requirements/edx/base.txt # edx-django-utils @@ -895,7 +895,7 @@ oauthlib==3.2.2 # social-auth-core olxcleaner==0.2.1 # via -r requirements/edx/base.txt -openai==0.28.0 +openai==0.28.1 # via # -r requirements/edx/base.txt # edx-enterprise @@ -932,13 +932,13 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/base.txt optimizely-sdk==4.1.1 # via -r requirements/edx/base.txt -ora2==5.5.0 +ora2==5.5.1 # via -r requirements/edx/base.txt oscrypto==1.3.0 # via # -r requirements/edx/base.txt # snowflake-connector-python -packaging==23.1 +packaging==23.2 # via # -r requirements/edx/base.txt # drf-yasg @@ -1158,7 +1158,7 @@ random2==1.0.1 # via -r requirements/edx/base.txt recommender-xblock==2.0.1 # via -r requirements/edx/base.txt -redis==5.0.0 +redis==5.0.1 # via # -r requirements/edx/base.txt # walrus @@ -1204,7 +1204,7 @@ rpds-py==0.10.3 # -r requirements/edx/base.txt # jsonschema # referencing -ruamel-yaml==0.17.32 +ruamel-yaml==0.17.33 # via # -r requirements/edx/base.txt # drf-yasg @@ -1218,7 +1218,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.6.2 +s3transfer==0.7.0 # via # -r requirements/edx/base.txt # boto3 @@ -1443,7 +1443,7 @@ walrus==0.9.3 # edx-event-bus-redis watchdog==3.0.0 # via -r requirements/edx/base.txt -wcwidth==0.2.6 +wcwidth==0.2.8 # via # -r requirements/edx/base.txt # prompt-toolkit @@ -1469,7 +1469,7 @@ wrapt==1.15.0 # via # -r requirements/edx/base.txt # deprecated -xblock[django]==1.7.0 +xblock[django]==1.8.0 # via # -r requirements/edx/base.txt # acid-xblock diff --git a/requirements/edx/semgrep.txt b/requirements/edx/semgrep.txt index ab6f0a120f..c53fe6f74c 100644 --- a/requirements/edx/semgrep.txt +++ b/requirements/edx/semgrep.txt @@ -52,7 +52,7 @@ markdown-it-py==3.0.0 # via rich mdurl==0.1.2 # via markdown-it-py -packaging==23.1 +packaging==23.2 # via semgrep peewee==3.16.3 # via semgrep @@ -68,17 +68,17 @@ referencing==0.30.2 # jsonschema-specifications requests==2.31.0 # via semgrep -rich==13.5.3 +rich==13.6.0 # via semgrep rpds-py==0.10.3 # via # jsonschema # referencing -ruamel-yaml==0.17.32 +ruamel-yaml==0.17.33 # via semgrep ruamel-yaml-clib==0.2.7 # via ruamel-yaml -semgrep==1.41.0 +semgrep==1.42.0 # via -r requirements/edx/semgrep.in tomli==2.0.1 # via semgrep diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 1bf4e7826d..9c95b05af7 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -110,13 +110,13 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -boto3==1.28.53 +boto3==1.28.57 # via # -r requirements/edx/base.txt # django-ses # fs-s3fs # ora2 -botocore==1.31.53 +botocore==1.31.57 # via # -r requirements/edx/base.txt # boto3 @@ -142,7 +142,7 @@ certifi==2023.7.22 # py2neo # requests # snowflake-connector-python -cffi==1.15.1 +cffi==1.16.0 # via # -r requirements/edx/base.txt # cryptography @@ -508,7 +508,7 @@ drf-nested-routers==0.93.4 # via # -r requirements/edx/base.txt # openedx-blockstore -drf-spectacular==0.26.4 +drf-spectacular==0.26.5 # via -r requirements/edx/base.txt drf-yasg==1.21.5 # via @@ -600,7 +600,7 @@ edx-lint==5.3.4 # via -r requirements/edx/testing.in edx-milestones==0.5.0 # via -r requirements/edx/base.txt -edx-name-affirmation==2.3.6 +edx-name-affirmation==2.3.7 # via -r requirements/edx/base.txt edx-opaque-keys[django]==2.5.1 # via @@ -691,7 +691,7 @@ factory-boy==3.3.0 # via -r requirements/edx/testing.in faker==19.6.2 # via factory-boy -fastapi==0.103.1 +fastapi==0.103.2 # via pact-python fastavro==1.8.3 # via @@ -748,7 +748,7 @@ httpretty==1.1.4 # via -r requirements/edx/testing.in httpx==0.23.3 # via pact-python -icalendar==5.0.8 +icalendar==5.0.10 # via -r requirements/edx/base.txt idna==3.4 # via @@ -759,7 +759,7 @@ idna==3.4 # rfc3986 # snowflake-connector-python # yarl -import-linter==1.11.1 +import-linter==1.12.0 # via -r requirements/edx/testing.in importlib-metadata==6.8.0 # via @@ -936,7 +936,7 @@ mysqlclient==2.2.0 # via # -r requirements/edx/base.txt # openedx-blockstore -newrelic==9.0.0 +newrelic==9.1.0 # via # -r requirements/edx/base.txt # edx-django-utils @@ -962,7 +962,7 @@ oauthlib==3.2.2 # social-auth-core olxcleaner==0.2.1 # via -r requirements/edx/base.txt -openai==0.28.0 +openai==0.28.1 # via # -r requirements/edx/base.txt # edx-enterprise @@ -999,13 +999,13 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/base.txt optimizely-sdk==4.1.1 # via -r requirements/edx/base.txt -ora2==5.5.0 +ora2==5.5.1 # via -r requirements/edx/base.txt oscrypto==1.3.0 # via # -r requirements/edx/base.txt # snowflake-connector-python -packaging==23.1 +packaging==23.2 # via # -r requirements/edx/base.txt # drf-yasg @@ -1108,9 +1108,9 @@ pycryptodomex==3.19.0 # lti-consumer-xblock # pyjwkest # snowflake-connector-python -pydantic==2.3.0 +pydantic==2.4.2 # via fastapi -pydantic-core==2.6.3 +pydantic-core==2.10.1 # via pydantic pygments==2.16.1 # via @@ -1290,7 +1290,7 @@ random2==1.0.1 # via -r requirements/edx/base.txt recommender-xblock==2.0.1 # via -r requirements/edx/base.txt -redis==5.0.0 +redis==5.0.1 # via # -r requirements/edx/base.txt # walrus @@ -1338,7 +1338,7 @@ rpds-py==0.10.3 # -r requirements/edx/base.txt # jsonschema # referencing -ruamel-yaml==0.17.32 +ruamel-yaml==0.17.33 # via # -r requirements/edx/base.txt # drf-yasg @@ -1352,7 +1352,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.6.2 +s3transfer==0.7.0 # via # -r requirements/edx/base.txt # boto3 @@ -1586,7 +1586,7 @@ walrus==0.9.3 # edx-event-bus-redis watchdog==3.0.0 # via -r requirements/edx/base.txt -wcwidth==0.2.6 +wcwidth==0.2.8 # via # -r requirements/edx/base.txt # prompt-toolkit @@ -1613,7 +1613,7 @@ wrapt==1.15.0 # -r requirements/edx/base.txt # astroid # deprecated -xblock[django]==1.7.0 +xblock[django]==1.8.0 # via # -r requirements/edx/base.txt # acid-xblock diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index f9aebfe766..ea283f4ad3 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -12,7 +12,7 @@ click==8.1.6 # pip-tools importlib-metadata==6.8.0 # via build -packaging==23.1 +packaging==23.2 # via build pip-tools==7.3.0 # via -r requirements/pip-tools.in diff --git a/scripts/xblock/requirements.txt b/scripts/xblock/requirements.txt index fcde0635a0..c66e31c37e 100644 --- a/scripts/xblock/requirements.txt +++ b/scripts/xblock/requirements.txt @@ -6,7 +6,7 @@ # certifi==2023.7.22 # via requests -charset-normalizer==3.2.0 +charset-normalizer==3.3.0 # via requests idna==3.4 # via requests From f5516e4716dcb29da23cca2e7667426309acbdd9 Mon Sep 17 00:00:00 2001 From: muhammad-ammar Date: Mon, 2 Oct 2023 12:38:10 +0000 Subject: [PATCH 02/17] feat: Upgrade Python dependency edx-enterprise Add the enable_pathways field for EnterpriseCustomer Commit generated by workflow `openedx/edx-platform/.github/workflows/upgrade-one-python-dependency.yml@refs/heads/master` --- requirements/constraints.txt | 2 +- requirements/edx/base.txt | 2 +- requirements/edx/development.txt | 2 +- requirements/edx/doc.txt | 2 +- requirements/edx/testing.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 9465159646..dab7f67f96 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -26,7 +26,7 @@ django-storages==1.14 # The team that owns this package will manually bump this package rather than having it pulled in automatically. # This is to allow them to better control its deployment and to do it in a process that works better # for them. -edx-enterprise==4.3.3 +edx-enterprise==4.4.0 # django-oauth-toolkit version >=2.0.0 has breaking changes. More details # mentioned on this issue https://github.com/openedx/edx-platform/issues/32884 diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index f16deb7bb9..15a4d519b6 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -480,7 +480,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.3.3 +edx-enterprise==4.4.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 080e3a1276..5fc5b9d44c 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -750,7 +750,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.3.3 +edx-enterprise==4.4.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 6e9d767fcd..2c7382687f 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -556,7 +556,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.3.3 +edx-enterprise==4.4.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 9c95b05af7..148e47411c 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -583,7 +583,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.3.3 +edx-enterprise==4.4.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt From 477da2c92ca01b5e4fd7c211823586e01d78194c Mon Sep 17 00:00:00 2001 From: jszewczulak <128841175+jszewczulak@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:47:07 -0400 Subject: [PATCH 03/17] chore: ORA bump to 5.5.2 (#33393) --- requirements/edx/base.txt | 2 +- requirements/edx/development.txt | 2 +- requirements/edx/doc.txt | 2 +- requirements/edx/testing.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 15a4d519b6..f83236699b 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -792,7 +792,7 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/kernel.in optimizely-sdk==4.1.1 # via -r requirements/edx/bundled.in -ora2==5.5.1 +ora2==5.5.2 # via -r requirements/edx/bundled.in oscrypto==1.3.0 # via snowflake-connector-python diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 5fc5b9d44c..a395eb7bc4 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -1330,7 +1330,7 @@ optimizely-sdk==4.1.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -ora2==5.5.1 +ora2==5.5.2 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 2c7382687f..869cc8434e 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -932,7 +932,7 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/base.txt optimizely-sdk==4.1.1 # via -r requirements/edx/base.txt -ora2==5.5.1 +ora2==5.5.2 # via -r requirements/edx/base.txt oscrypto==1.3.0 # via diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 148e47411c..06c6dcd3b8 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -999,7 +999,7 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/base.txt optimizely-sdk==4.1.1 # via -r requirements/edx/base.txt -ora2==5.5.1 +ora2==5.5.2 # via -r requirements/edx/base.txt oscrypto==1.3.0 # via From 9ddde642f8c086b70948e435d79b2ad1be9eddab Mon Sep 17 00:00:00 2001 From: edX requirements bot <49161187+edx-requirements-bot@users.noreply.github.com> Date: Tue, 3 Oct 2023 03:11:17 -0400 Subject: [PATCH 04/17] chore: Updating Python Requirements (#33397) --- requirements/edx/base.txt | 8 ++++---- requirements/edx/coverage.txt | 2 +- requirements/edx/development.txt | 10 +++++----- requirements/edx/doc.txt | 8 ++++---- requirements/edx/paver.txt | 2 +- requirements/edx/semgrep.txt | 2 +- requirements/edx/testing.txt | 10 +++++----- scripts/xblock/requirements.txt | 2 +- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index f83236699b..4170cb7675 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -77,13 +77,13 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in -boto3==1.28.57 +boto3==1.28.58 # via # -r requirements/edx/kernel.in # django-ses # fs-s3fs # ora2 -botocore==1.31.57 +botocore==1.31.58 # via # -r requirements/edx/kernel.in # boto3 @@ -288,7 +288,7 @@ django-filter==23.3 # edx-enterprise # lti-consumer-xblock # openedx-blockstore -django-ipware==5.0.0 +django-ipware==5.0.1 # via # -r requirements/edx/kernel.in # edx-enterprise @@ -1159,7 +1159,7 @@ uritemplate==4.1.1 # coreapi # drf-spectacular # drf-yasg -urllib3==1.26.16 +urllib3==1.26.17 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/paver.txt diff --git a/requirements/edx/coverage.txt b/requirements/edx/coverage.txt index 00f316f2b1..93af4c1f82 100644 --- a/requirements/edx/coverage.txt +++ b/requirements/edx/coverage.txt @@ -6,7 +6,7 @@ # chardet==5.2.0 # via diff-cover -coverage==7.3.1 +coverage==7.3.2 # via -r requirements/edx/coverage.in diff-cover==7.7.0 # via -r requirements/edx/coverage.in diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index a395eb7bc4..3f5d3695ba 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -145,14 +145,14 @@ boto==2.39.0 # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -boto3==1.28.57 +boto3==1.28.58 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # django-ses # fs-s3fs # ora2 -botocore==1.31.57 +botocore==1.31.58 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -275,7 +275,7 @@ coreschema==0.0.4 # -r requirements/edx/testing.txt # coreapi # drf-yasg -coverage[toml]==7.3.1 +coverage[toml]==7.3.2 # via # -r requirements/edx/testing.txt # pytest-cov @@ -474,7 +474,7 @@ django-filter==23.3 # edx-enterprise # lti-consumer-xblock # openedx-blockstore -django-ipware==5.0.0 +django-ipware==5.0.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -2108,7 +2108,7 @@ uritemplate==4.1.1 # coreapi # drf-spectacular # drf-yasg -urllib3==1.26.16 +urllib3==1.26.17 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 869cc8434e..5d08d03a5f 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -103,13 +103,13 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -boto3==1.28.57 +boto3==1.28.58 # via # -r requirements/edx/base.txt # django-ses # fs-s3fs # ora2 -botocore==1.31.57 +botocore==1.31.58 # via # -r requirements/edx/base.txt # boto3 @@ -345,7 +345,7 @@ django-filter==23.3 # edx-enterprise # lti-consumer-xblock # openedx-blockstore -django-ipware==5.0.0 +django-ipware==5.0.1 # via # -r requirements/edx/base.txt # edx-enterprise @@ -1416,7 +1416,7 @@ uritemplate==4.1.1 # coreapi # drf-spectacular # drf-yasg -urllib3==1.26.16 +urllib3==1.26.17 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt diff --git a/requirements/edx/paver.txt b/requirements/edx/paver.txt index 46af4d76cc..272e8a34a9 100644 --- a/requirements/edx/paver.txt +++ b/requirements/edx/paver.txt @@ -54,7 +54,7 @@ stevedore==5.1.0 # edx-opaque-keys typing-extensions==4.8.0 # via edx-opaque-keys -urllib3==1.26.16 +urllib3==1.26.17 # via # -c requirements/edx/../constraints.txt # requests diff --git a/requirements/edx/semgrep.txt b/requirements/edx/semgrep.txt index c53fe6f74c..fb696264ac 100644 --- a/requirements/edx/semgrep.txt +++ b/requirements/edx/semgrep.txt @@ -88,7 +88,7 @@ typing-extensions==4.8.0 # semgrep ujson==5.8.0 # via python-lsp-jsonrpc -urllib3==1.26.16 +urllib3==1.26.17 # via # -c requirements/edx/../constraints.txt # requests diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 06c6dcd3b8..a0e677a4e0 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -110,13 +110,13 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -boto3==1.28.57 +boto3==1.28.58 # via # -r requirements/edx/base.txt # django-ses # fs-s3fs # ora2 -botocore==1.31.57 +botocore==1.31.58 # via # -r requirements/edx/base.txt # boto3 @@ -212,7 +212,7 @@ coreschema==0.0.4 # -r requirements/edx/base.txt # coreapi # drf-yasg -coverage[toml]==7.3.1 +coverage[toml]==7.3.2 # via # -r requirements/edx/coverage.txt # pytest-cov @@ -378,7 +378,7 @@ django-filter==23.3 # edx-enterprise # lti-consumer-xblock # openedx-blockstore -django-ipware==5.0.0 +django-ipware==5.0.1 # via # -r requirements/edx/base.txt # edx-enterprise @@ -1553,7 +1553,7 @@ uritemplate==4.1.1 # coreapi # drf-spectacular # drf-yasg -urllib3==1.26.16 +urllib3==1.26.17 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt diff --git a/scripts/xblock/requirements.txt b/scripts/xblock/requirements.txt index c66e31c37e..b39be98983 100644 --- a/scripts/xblock/requirements.txt +++ b/scripts/xblock/requirements.txt @@ -12,5 +12,5 @@ idna==3.4 # via requests requests==2.31.0 # via -r scripts/xblock/requirements.in -urllib3==2.0.5 +urllib3==2.0.6 # via requests From 0611b12287ea8d554919626c183ae3d6b6a38fa3 Mon Sep 17 00:00:00 2001 From: Awais Qureshi Date: Tue, 3 Oct 2023 12:31:56 +0500 Subject: [PATCH 05/17] chore: enabling migrations tests for django4.2 (#33398) * chore: enabling migrations tests for django4.2 --- common/djangoapps/util/tests/test_db.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/common/djangoapps/util/tests/test_db.py b/common/djangoapps/util/tests/test_db.py index 77f2ac07f0..4a16c2a20a 100644 --- a/common/djangoapps/util/tests/test_db.py +++ b/common/djangoapps/util/tests/test_db.py @@ -1,10 +1,8 @@ """Tests for util.db module.""" -from importlib.metadata import version from io import StringIO import ddt -import pytest from django.core.management import call_command from django.db.transaction import TransactionManagementError, atomic from django.test import TestCase, TransactionTestCase @@ -12,8 +10,6 @@ from django.test.utils import override_settings from common.djangoapps.util.db import enable_named_outer_atomic, generate_int_id, outer_atomic -GET_DJANGO_VERSION = int(version('django').split('.')[0]) - def do_nothing(): """Just return.""" @@ -119,7 +115,6 @@ class GenerateIntIdTestCase(TestCase): assert int_id in list(set(range(minimum, (maximum + 1))) - used_ids) -@pytest.mark.skipif(GET_DJANGO_VERSION > 3, reason="django4.2 brings new migrations, so only run for dj32 for now.") class MigrationTests(TestCase): """ Tests for migrations. From 5eb7d4b8e2b31faddaeb3e82f5a4ce15642b6694 Mon Sep 17 00:00:00 2001 From: muhammad-ammar Date: Tue, 3 Oct 2023 09:04:34 +0000 Subject: [PATCH 06/17] feat: Upgrade Python dependency edx-enterprise Add the ``enable_programs`` field for EnterpriseCustomer Commit generated by workflow `openedx/edx-platform/.github/workflows/upgrade-one-python-dependency.yml@refs/heads/master` --- requirements/constraints.txt | 2 +- requirements/edx/base.txt | 2 +- requirements/edx/development.txt | 2 +- requirements/edx/doc.txt | 2 +- requirements/edx/testing.txt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements/constraints.txt b/requirements/constraints.txt index dab7f67f96..21e4c90bba 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -26,7 +26,7 @@ django-storages==1.14 # The team that owns this package will manually bump this package rather than having it pulled in automatically. # This is to allow them to better control its deployment and to do it in a process that works better # for them. -edx-enterprise==4.4.0 +edx-enterprise==4.5.0 # django-oauth-toolkit version >=2.0.0 has breaking changes. More details # mentioned on this issue https://github.com/openedx/edx-platform/issues/32884 diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 4170cb7675..1526563d4f 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -480,7 +480,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.4.0 +edx-enterprise==4.5.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 3f5d3695ba..b679702511 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -750,7 +750,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.4.0 +edx-enterprise==4.5.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 5d08d03a5f..c8c48bcafe 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -556,7 +556,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.4.0 +edx-enterprise==4.5.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index a0e677a4e0..dd192af90c 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -583,7 +583,7 @@ edx-drf-extensions==8.10.0 # edx-when # edxval # openedx-learning -edx-enterprise==4.4.0 +edx-enterprise==4.5.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt From ed48e9602763159c2402b25382ac9cc21a69b025 Mon Sep 17 00:00:00 2001 From: Rebecca Graber Date: Tue, 3 Oct 2023 08:29:15 -0400 Subject: [PATCH 07/17] feat: upgrade openedx-events (#33392) --- cms/envs/common.py | 4 ++++ lms/envs/common.py | 4 ++++ requirements/constraints.txt | 3 --- requirements/edx/base.txt | 3 +-- requirements/edx/development.txt | 3 +-- requirements/edx/doc.txt | 3 +-- requirements/edx/testing.txt | 3 +-- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cms/envs/common.py b/cms/envs/common.py index 2021d372bc..bcb7665210 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -2787,3 +2787,7 @@ SPECTACULAR_SETTINGS = { 'SERVE_INCLUDE_SCHEMA': False, 'PREPROCESSING_HOOKS': ['cms.lib.spectacular.cms_api_filter'], # restrict spectacular to CMS API endpoints } + +#### Event bus publishing #### +## Will be more filled out as part of https://github.com/edx/edx-arch-experiments/issues/381 +EVENT_BUS_PRODUCER_CONFIG = {} diff --git a/lms/envs/common.py b/lms/envs/common.py index 2c12037e92..90d5517fa4 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -5384,3 +5384,7 @@ EXPIRED_NOTIFICATIONS_DELETE_BATCH_SIZE = 10000 #### django-simple-history## # disable indexing on date field its coming from django-simple-history. SIMPLE_HISTORY_DATE_INDEX = False + +#### Event bus publishing #### +## Will be more filled out as part of https://github.com/edx/edx-arch-experiments/issues/381 +EVENT_BUS_PRODUCER_CONFIG = {} diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 21e4c90bba..77f60e9937 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -120,9 +120,6 @@ libsass==0.10.0 # greater version breaking upgrade builds click==8.1.6 -# openedx-events 8.6.0 introduces publishing via configuration. Ticket to unpin: https://github.com/edx/edx-arch-experiments/issues/381 -openedx-events<8.6.0 # Open edX Events from Hooks Extension Framework (OEP-50) - # pinning this version to avoid updates while the library is being developed openedx-learning==0.1.7 diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 1526563d4f..145741297e 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -774,9 +774,8 @@ openedx-django-require==2.1.0 # via -r requirements/edx/kernel.in openedx-django-wiki==2.0.3 # via -r requirements/edx/kernel.in -openedx-events==8.5.0 +openedx-events==8.6.0 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in # edx-event-bus-kafka # edx-event-bus-redis diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index b679702511..409432d4e5 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -1305,9 +1305,8 @@ openedx-django-wiki==2.0.3 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -openedx-events==8.5.0 +openedx-events==8.6.0 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # edx-event-bus-kafka diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index c8c48bcafe..ec4e862a1c 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -914,9 +914,8 @@ openedx-django-require==2.1.0 # via -r requirements/edx/base.txt openedx-django-wiki==2.0.3 # via -r requirements/edx/base.txt -openedx-events==8.5.0 +openedx-events==8.6.0 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt # edx-event-bus-kafka # edx-event-bus-redis diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index dd192af90c..c03e582434 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -981,9 +981,8 @@ openedx-django-require==2.1.0 # via -r requirements/edx/base.txt openedx-django-wiki==2.0.3 # via -r requirements/edx/base.txt -openedx-events==8.5.0 +openedx-events==8.6.0 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt # edx-event-bus-kafka # edx-event-bus-redis From e10ba22e51b10f7c48a314d209a366016017a35a Mon Sep 17 00:00:00 2001 From: Juliana Kang Date: Tue, 3 Oct 2023 10:51:57 -0400 Subject: [PATCH 08/17] fix: Remove rendering of the subs upsell on dashboard sidebar (#33324) REV-3705 --- .../spec/sidebar_view_spec.js | 27 +------------------ .../learner_dashboard/views/sidebar_view.js | 7 ----- .../learner_dashboard/sidebar.underscore | 3 --- 3 files changed, 1 insertion(+), 36 deletions(-) diff --git a/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js b/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js index c1f7e4734e..04c936908e 100644 --- a/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js @@ -32,35 +32,10 @@ describe('Sidebar View', () => { expect(view).toBeDefined(); }); - it('should not render the subscription upsell section if B2CSubscriptions are disabled', () => { - view.remove(); - view = new SidebarView({ - el: '.sidebar', - context: { - ...context, - isUserB2CSubscriptionsEnabled: false, - }, - }); - view.render(); + it('should not render the subscription upsell section', () => { expect(view.$('.js-subscription-upsell')[0]).not.toBeInDOM(); }); - it('should render the subscription upsell section', () => { - expect(view.$('.js-subscription-upsell')[0]).toBeInDOM(); - expect(view.$('.js-subscription-upsell .badge').html().trim()) - .toEqual('New'); - expect(view.$('.js-subscription-upsell h4').html().trim()) - .toMatch(/^Monthly program subscriptions . more flexible, more affordable$/); - expect(view.$('.js-subscription-upsell .advertise-message').html().trim()) - .toEqual( - 'Now available for many popular programs, affordable monthly subscription pricing can help you manage your budget more effectively. Subscriptions start at $39/month USD per program, after a 7-day full access free trial. Cancel at any time.', - ); - expect(view.$('.js-subscription-upsell a span:last').html().trim()) - .toEqual('Explore subscription options'); - expect(view.$('.js-subscription-upsell a').attr('href')) - .toEqual('https://www.example.org/program-subscriptions'); - }); - it('should load the exploration panel given a marketing URL', () => { expect(view.$('.program-advertise .advertise-message').html().trim()) .toEqual( diff --git a/lms/static/js/learner_dashboard/views/sidebar_view.js b/lms/static/js/learner_dashboard/views/sidebar_view.js index 9cc9245f20..3359eac1b4 100644 --- a/lms/static/js/learner_dashboard/views/sidebar_view.js +++ b/lms/static/js/learner_dashboard/views/sidebar_view.js @@ -3,7 +3,6 @@ import Backbone from 'backbone'; import HtmlUtils from 'edx-ui-toolkit/js/utils/html-utils'; import NewProgramsView from './explore_new_programs_view'; -import SubscriptionUpsellView from './subscription_upsell_view'; import sidebarTpl from '../../../templates/learner_dashboard/sidebar.underscore'; @@ -30,12 +29,6 @@ class SidebarView extends Backbone.View { } postRender() { - if (this.context.isUserB2CSubscriptionsEnabled) { - this.subscriptionUpsellView = new SubscriptionUpsellView({ - subscriptionUpsellData: this.context.subscriptionUpsellData, - }); - } - this.newProgramsView = new NewProgramsView({ context: this.context, }); diff --git a/lms/templates/learner_dashboard/sidebar.underscore b/lms/templates/learner_dashboard/sidebar.underscore index 8f8db1b97a..7f02d9862e 100644 --- a/lms/templates/learner_dashboard/sidebar.underscore +++ b/lms/templates/learner_dashboard/sidebar.underscore @@ -1,4 +1 @@ -<% if (isUserB2CSubscriptionsEnabled) { %> - -<% } %>
From 07ea8a207b2e1aeaadc7112b8a7f83dbebcf4c38 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 15:25:00 +0000 Subject: [PATCH 09/17] feat: Upgrade Python dependency openedx-events (#33401) feat: upgrade openedx-events definitions Commit generated by workflow `openedx/edx-platform/.github/workflows/upgrade-one-python-dependency.yml@refs/heads/master` Co-authored-by: Zacharis278 --- requirements/edx/base.txt | 2 +- requirements/edx/development.txt | 2 +- requirements/edx/doc.txt | 2 +- requirements/edx/testing.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 145741297e..c150d6dee3 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -774,7 +774,7 @@ openedx-django-require==2.1.0 # via -r requirements/edx/kernel.in openedx-django-wiki==2.0.3 # via -r requirements/edx/kernel.in -openedx-events==8.6.0 +openedx-events==8.8.0 # via # -r requirements/edx/kernel.in # edx-event-bus-kafka diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 409432d4e5..508a4261ae 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -1305,7 +1305,7 @@ openedx-django-wiki==2.0.3 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -openedx-events==8.6.0 +openedx-events==8.8.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index ec4e862a1c..8634ba1ee8 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -914,7 +914,7 @@ openedx-django-require==2.1.0 # via -r requirements/edx/base.txt openedx-django-wiki==2.0.3 # via -r requirements/edx/base.txt -openedx-events==8.6.0 +openedx-events==8.8.0 # via # -r requirements/edx/base.txt # edx-event-bus-kafka diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index c03e582434..c611bc9273 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -981,7 +981,7 @@ openedx-django-require==2.1.0 # via -r requirements/edx/base.txt openedx-django-wiki==2.0.3 # via -r requirements/edx/base.txt -openedx-events==8.6.0 +openedx-events==8.8.0 # via # -r requirements/edx/base.txt # edx-event-bus-kafka From 62cfe6f3a9f3cf502226b659d28d144691000677 Mon Sep 17 00:00:00 2001 From: Kaustav Banerjee Date: Tue, 3 Oct 2023 22:16:47 +0530 Subject: [PATCH 10/17] fix: fetch organizations list only for granted course creators (#33333) * fix: fetch organizations list only for granted course creators * fix: add ability for course instructors to create libraries same as course staff --- .../tests/test_course_create_rerun.py | 7 +++++++ cms/djangoapps/contentstore/views/course.py | 2 +- cms/djangoapps/contentstore/views/library.py | 3 ++- .../contentstore/views/tests/test_library.py | 21 +++++++++++++++---- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_course_create_rerun.py b/cms/djangoapps/contentstore/tests/test_course_create_rerun.py index 264d6de8ff..fcba8f6e1b 100644 --- a/cms/djangoapps/contentstore/tests/test_course_create_rerun.py +++ b/cms/djangoapps/contentstore/tests/test_course_create_rerun.py @@ -208,6 +208,10 @@ class TestCourseListing(ModuleStoreTestCase): self.assertEqual(response.status_code, 403) @override_settings(FEATURES={'ENABLE_CREATOR_GROUP': True}) + @mock.patch( + 'cms.djangoapps.course_creators.admin.render_to_string', + mock.Mock(side_effect=mock_render_to_string, autospec=True) + ) def test_course_creation_when_user_in_org_with_creator_role(self): """ Tests course creation with user having the organization content creation role. @@ -218,6 +222,9 @@ class TestCourseListing(ModuleStoreTestCase): 'description': 'Testing Organization Description', }) update_org_role(self.global_admin, OrgContentCreatorRole, self.user, [self.source_course_key.org]) + self.course_creator_entry.all_organizations = True + self.course_creator_entry.state = CourseCreator.GRANTED + self.creator_admin.save_model(self.request, self.course_creator_entry, None, True) self.assertIn(self.source_course_key.org, get_allowed_organizations(self.user)) response = self.client.ajax_post(self.course_create_rerun_url, { 'org': self.source_course_key.org, diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 4a70e5028c..a55bb3db9a 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -1786,7 +1786,7 @@ def get_organizations(user): Returns the list of organizations for which the user is allowed to create courses. """ course_creator = CourseCreator.objects.filter(user=user).first() - if not course_creator: + if not course_creator or course_creator.state != CourseCreator.GRANTED: return [] elif course_creator.all_organizations: organizations = Organization.objects.all().values_list('short_name', flat=True) diff --git a/cms/djangoapps/contentstore/views/library.py b/cms/djangoapps/contentstore/views/library.py index 2d1501d420..17aa24c571 100644 --- a/cms/djangoapps/contentstore/views/library.py +++ b/cms/djangoapps/contentstore/views/library.py @@ -83,8 +83,9 @@ def user_can_create_library(user, org=None): is_course_creator = get_course_creator_status(user) == 'granted' has_org_staff_role = OrgStaffRole().get_orgs_for_user(user).exists() has_course_staff_role = UserBasedRole(user=user, role=CourseStaffRole.ROLE).courses_with_role().exists() + has_course_admin_role = UserBasedRole(user=user, role=CourseInstructorRole.ROLE).courses_with_role().exists() - return is_course_creator or has_org_staff_role or has_course_staff_role + return is_course_creator or has_org_staff_role or has_course_staff_role or has_course_admin_role else: # EDUCATOR-1924: DISABLE_LIBRARY_CREATION overrides DISABLE_COURSE_CREATION, if present. disable_library_creation = settings.FEATURES.get('DISABLE_LIBRARY_CREATION', None) diff --git a/cms/djangoapps/contentstore/views/tests/test_library.py b/cms/djangoapps/contentstore/views/tests/test_library.py index bac450b3bd..f6b7a48a68 100644 --- a/cms/djangoapps/contentstore/views/tests/test_library.py +++ b/cms/djangoapps/contentstore/views/tests/test_library.py @@ -19,7 +19,7 @@ from organizations.exceptions import InvalidOrganizationException from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase, parse_json from cms.djangoapps.contentstore.utils import reverse_course_url, reverse_library_url from cms.djangoapps.course_creators.views import add_user_with_status_granted as grant_course_creator_status -from common.djangoapps.student.roles import LibraryUserRole, CourseStaffRole +from common.djangoapps.student.roles import LibraryUserRole, CourseStaffRole, CourseInstructorRole from xmodule.modulestore.tests.factories import LibraryFactory # lint-amnesty, pylint: disable=wrong-import-order from cms.djangoapps.course_creators.models import CourseCreator @@ -101,6 +101,14 @@ class UnitTestLibraries(CourseTestCase): auth.add_users(self.user, CourseStaffRole(self.course.id), nostaff_user) self.assertEqual(user_can_create_library(nostaff_user), True) + # When creator groups are enabled, course instructor members can create libraries + @mock.patch("cms.djangoapps.contentstore.views.library.LIBRARIES_ENABLED", True) + def test_library_creator_status_with_course_instructor_role_for_enabled_creator_group_setting(self): + _, nostaff_user = self.create_non_staff_authed_user_client() + with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): + auth.add_users(self.user, CourseInstructorRole(self.course.id), nostaff_user) + self.assertEqual(user_can_create_library(nostaff_user), True) + @ddt.data( (False, False, True), (False, True, False), @@ -480,9 +488,14 @@ class UnitTestLibraries(CourseTestCase): # Assert that the method returned the expected value self.assertEqual(organizations, []) with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): - organizations = get_allowed_organizations_for_libraries(self.user) - # Assert that the method returned the expected value - self.assertEqual(organizations, ['org1', 'org2']) + # Assert that correct org values are returned based on course creator state + for course_creator_state in CourseCreator.STATES: + course_creator.state = course_creator_state + organizations = get_allowed_organizations_for_libraries(self.user) + if course_creator_state != CourseCreator.GRANTED: + self.assertEqual(organizations, []) + else: + self.assertEqual(organizations, ['org1', 'org2']) with mock.patch.dict( 'django.conf.settings.FEATURES', {"ENABLE_ORGANIZATION_STAFF_ACCESS_FOR_CONTENT_LIBRARIES": True} From 96992e7b05f34f73796369ee873c35f76a0723b1 Mon Sep 17 00:00:00 2001 From: jszewczulak <128841175+jszewczulak@users.noreply.github.com> Date: Tue, 3 Oct 2023 16:29:06 -0400 Subject: [PATCH 11/17] chore: ORA bump to 5.5.3 (#33404) --- requirements/edx/base.txt | 2 +- requirements/edx/development.txt | 2 +- requirements/edx/doc.txt | 2 +- requirements/edx/testing.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index c150d6dee3..63dfd49229 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -791,7 +791,7 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/kernel.in optimizely-sdk==4.1.1 # via -r requirements/edx/bundled.in -ora2==5.5.2 +ora2==5.5.3 # via -r requirements/edx/bundled.in oscrypto==1.3.0 # via snowflake-connector-python diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 508a4261ae..d95bf65d1a 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -1329,7 +1329,7 @@ optimizely-sdk==4.1.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -ora2==5.5.2 +ora2==5.5.3 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 8634ba1ee8..2ccab0b634 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -931,7 +931,7 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/base.txt optimizely-sdk==4.1.1 # via -r requirements/edx/base.txt -ora2==5.5.2 +ora2==5.5.3 # via -r requirements/edx/base.txt oscrypto==1.3.0 # via diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index c611bc9273..1e854dda09 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -998,7 +998,7 @@ openedx-mongodbproxy==0.2.0 # via -r requirements/edx/base.txt optimizely-sdk==4.1.1 # via -r requirements/edx/base.txt -ora2==5.5.2 +ora2==5.5.3 # via -r requirements/edx/base.txt oscrypto==1.3.0 # via From 835a81c46625c71dc13b26427846b2440937a0ee Mon Sep 17 00:00:00 2001 From: Zachary Hancock Date: Tue, 3 Oct 2023 16:50:47 -0400 Subject: [PATCH 12/17] feat: handle exam events for credit state (#33402) Handles exam related events from the event bus that impact credit state. Functionally this will behave the same as the existing CreditService which is called by edx-proctoring. This enables edx-exams (an IDA) to have the same behavior. --- cms/djangoapps/contentstore/tasks.py | 2 +- .../contentstore/tests/test_tasks.py | 2 +- .../views/tests/test_credit_eligibility.py | 2 +- openedx/core/djangoapps/credit/apps.py | 2 +- .../djangoapps/credit/signals/__init__.py | 0 .../{signals.py => signals/handlers.py} | 108 +++++++++++ .../djangoapps/credit/tests/test_signals.py | 181 +++++++++++++++++- .../djangoapps/credit/tests/test_tasks.py | 2 +- 8 files changed, 284 insertions(+), 15 deletions(-) create mode 100644 openedx/core/djangoapps/credit/signals/__init__.py rename openedx/core/djangoapps/credit/{signals.py => signals/handlers.py} (54%) diff --git a/cms/djangoapps/contentstore/tasks.py b/cms/djangoapps/contentstore/tasks.py index b6861e4ddc..b7a249bfa5 100644 --- a/cms/djangoapps/contentstore/tasks.py +++ b/cms/djangoapps/contentstore/tasks.py @@ -256,7 +256,7 @@ def update_special_exams_and_publish(course_key_str): """ from cms.djangoapps.contentstore.exams import register_exams from cms.djangoapps.contentstore.proctoring import register_special_exams as register_exams_legacy - from openedx.core.djangoapps.credit.signals import on_course_publish + from openedx.core.djangoapps.credit.signals.handlers import on_course_publish course_key = CourseKey.from_string(course_key_str) LOGGER.info('Attempting to register exams for course %s', course_key_str) diff --git a/cms/djangoapps/contentstore/tests/test_tasks.py b/cms/djangoapps/contentstore/tests/test_tasks.py index d0fcd78210..cf82a6d165 100644 --- a/cms/djangoapps/contentstore/tests/test_tasks.py +++ b/cms/djangoapps/contentstore/tests/test_tasks.py @@ -195,7 +195,7 @@ class RegisterExamsTaskTestCase(CourseTestCase): # pylint: disable=missing-clas @mock.patch('cms.djangoapps.contentstore.proctoring.register_special_exams') def test_register_exams_failure(self, _mock_register_exams_proctoring, _mock_register_exams_service): """ credit requirements update signal fires even if exam registration fails """ - with mock.patch('openedx.core.djangoapps.credit.signals.on_course_publish') as course_publish: + with mock.patch('openedx.core.djangoapps.credit.signals.handlers.on_course_publish') as course_publish: _mock_register_exams_proctoring.side_effect = Exception('boom!') update_special_exams_and_publish(str(self.course.id)) course_publish.assert_called() diff --git a/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py b/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py index 3d6d2d9e81..5cfa2ded2b 100644 --- a/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py +++ b/cms/djangoapps/contentstore/views/tests/test_credit_eligibility.py @@ -9,7 +9,7 @@ from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.utils import reverse_course_url from openedx.core.djangoapps.credit.api import get_credit_requirements from openedx.core.djangoapps.credit.models import CreditCourse -from openedx.core.djangoapps.credit.signals import on_course_publish +from openedx.core.djangoapps.credit.signals.handlers import on_course_publish from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order diff --git a/openedx/core/djangoapps/credit/apps.py b/openedx/core/djangoapps/credit/apps.py index 6107d73de7..e057cc5cab 100644 --- a/openedx/core/djangoapps/credit/apps.py +++ b/openedx/core/djangoapps/credit/apps.py @@ -15,7 +15,7 @@ class CreditConfig(AppConfig): name = 'openedx.core.djangoapps.credit' def ready(self): - from . import signals # lint-amnesty, pylint: disable=unused-import + from .signals import handlers # lint-amnesty, pylint: disable=unused-import if settings.FEATURES.get('ENABLE_SPECIAL_EXAMS'): from .services import CreditService set_runtime_service('credit', CreditService()) diff --git a/openedx/core/djangoapps/credit/signals/__init__.py b/openedx/core/djangoapps/credit/signals/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openedx/core/djangoapps/credit/signals.py b/openedx/core/djangoapps/credit/signals/handlers.py similarity index 54% rename from openedx/core/djangoapps/credit/signals.py rename to openedx/core/djangoapps/credit/signals/handlers.py index de22fe42a8..3748f1cfba 100644 --- a/openedx/core/djangoapps/credit/signals.py +++ b/openedx/core/djangoapps/credit/signals/handlers.py @@ -5,15 +5,78 @@ This file contains receivers of course publication signals. import logging +from django.contrib.auth import get_user_model +from django.core.exceptions import ObjectDoesNotExist from django.dispatch import receiver from django.utils import timezone from opaque_keys.edx.keys import CourseKey +from openedx_events.learning.signals import ( + EXAM_ATTEMPT_ERRORED, + EXAM_ATTEMPT_REJECTED, + EXAM_ATTEMPT_RESET, + EXAM_ATTEMPT_SUBMITTED, + EXAM_ATTEMPT_VERIFIED +) +from openedx.core.djangoapps.credit.api.eligibility import ( + is_credit_course, + remove_credit_requirement_status, + set_credit_requirement_status +) from openedx.core.djangoapps.signals.signals import COURSE_GRADE_CHANGED +User = get_user_model() + log = logging.getLogger(__name__) +def handle_exam_event(signal, event_data, credit_status=None): + """ + update credit requirements based on exam event + """ + user_data = event_data.student_user + course_key = event_data.course_key + usage_key = event_data.usage_key + request_namespace = 'exam' + + # quick exit, if course is not credit enabled + if not is_credit_course(course_key): + return + + # log any activity to the credit requirements table + log.info( + f'Recieved {signal} signal, changing credit requirement for ' + f'user_id={user_data.id}, course_key_or_id={course_key} ' + f'content_id={usage_key}' + ) + + try: + user = User.objects.get(id=user_data.id) + except ObjectDoesNotExist: + log.error( + 'Error occurred while handling exam event for ' + f'{user_data.id} and content_id {usage_key}. ' + 'User does not exist!' + ) + return + + if signal == EXAM_ATTEMPT_RESET: + remove_credit_requirement_status( + user.username, + course_key, + request_namespace, + str(usage_key), + ) + else: + set_credit_requirement_status( + user.username, + course_key, + request_namespace, + str(usage_key), + credit_status + ) + + def on_course_publish(course_key): """ Will receive a delegated 'course_published' signal from cms/djangoapps/contentstore/signals.py @@ -94,3 +157,48 @@ def listen_for_grade_calculation(sender, user, course_grade, course_key, deadlin api.set_credit_requirement_status( user, course_id, 'grade', 'grade', status=status, reason=reason ) + + +@receiver(EXAM_ATTEMPT_RESET) +def listen_for_exam_reset(sender, signal, **kwargs): + """ + exam reset event from the event bus + """ + event_data = kwargs.get('exam_attempt') + handle_exam_event(signal, event_data) + + +@receiver(EXAM_ATTEMPT_SUBMITTED) +def listen_for_exam_submitted(sender, signal, **kwargs): + """ + exam submission event from the event bus + """ + event_data = kwargs.get('exam_attempt') + handle_exam_event(signal, event_data, credit_status='submitted') + + +@receiver(EXAM_ATTEMPT_VERIFIED) +def listen_for_exam_verified(sender, signal, **kwargs): + """ + exam verification event from the event bus + """ + event_data = kwargs.get('exam_attempt') + handle_exam_event(signal, event_data, credit_status='satisfied') + + +@receiver(EXAM_ATTEMPT_REJECTED) +def listen_for_exam_rejected(sender, signal, **kwargs): + """ + exam rejection event from the event bus + """ + event_data = kwargs.get('exam_attempt') + handle_exam_event(signal, event_data, credit_status='failed') + + +@receiver(EXAM_ATTEMPT_ERRORED) +def listen_for_exam_errored(sender, signal, **kwargs): + """ + exam error event from the event bus + """ + event_data = kwargs.get('exam_attempt') + handle_exam_event(signal, event_data, credit_status='failed') diff --git a/openedx/core/djangoapps/credit/tests/test_signals.py b/openedx/core/djangoapps/credit/tests/test_signals.py index 198f88e875..c3331c0ecf 100644 --- a/openedx/core/djangoapps/credit/tests/test_signals.py +++ b/openedx/core/djangoapps/credit/tests/test_signals.py @@ -1,23 +1,41 @@ """ -Tests for minimum grade requirement status +Tests for minimum grade and credit requirement status """ +from datetime import datetime, timedelta, timezone +from unittest import mock +from uuid import uuid4 -from datetime import datetime, timedelta - -from unittest.mock import MagicMock import ddt import pytz from django.test.client import RequestFactory +from opaque_keys.edx.keys import UsageKey +from openedx_events.data import EventsMetadata +from openedx_events.learning.data import ExamAttemptData, UserData, UserPersonalData +from openedx_events.learning.signals import ( + EXAM_ATTEMPT_ERRORED, + EXAM_ATTEMPT_REJECTED, + EXAM_ATTEMPT_RESET, + EXAM_ATTEMPT_SUBMITTED, + EXAM_ATTEMPT_VERIFIED +) from common.djangoapps.course_modes.models import CourseMode -from openedx.core.djangoapps.credit.api import get_credit_requirement_status, set_credit_requirements -from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider -from openedx.core.djangoapps.credit.signals import listen_for_grade_calculation -from openedx.core.djangolib.testing.utils import skip_unless_lms from common.djangoapps.student.models import CourseEnrollment from common.djangoapps.student.tests.factories import UserFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order +from openedx.core.djangoapps.credit.api import get_credit_requirement_status, set_credit_requirements +from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider +from openedx.core.djangoapps.credit.signals.handlers import ( + listen_for_exam_errored, + listen_for_exam_rejected, + listen_for_exam_reset, + listen_for_exam_submitted, + listen_for_exam_verified, + listen_for_grade_calculation +) +from openedx.core.djangolib.testing.utils import skip_unless_lms +from xmodule.modulestore.tests.django_utils import \ + ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order @@ -76,7 +94,7 @@ class TestMinGradedRequirementStatus(ModuleStoreTestCase): def assert_requirement_status(self, grade, due_date, expected_status): """ Verify the user's credit requirement status is as expected after simulating a grading calculation. """ - course_grade = MagicMock() + course_grade = mock.MagicMock() course_grade.percent = grade listen_for_grade_calculation(None, self.user, course_grade, self.course.id, due_date) req_status = get_credit_requirement_status(self.course.id, self.request.user.username, 'grade', 'grade') @@ -129,3 +147,146 @@ class TestMinGradedRequirementStatus(ModuleStoreTestCase): """Test with valid grades submitted before deadline with non-verified enrollment.""" self.enrollment.update_enrollment(mode, True) self.assert_requirement_status(0.8, self.VALID_DUE_DATE, None) + + +@skip_unless_lms +@ddt.ddt +class TestExamEvents(ModuleStoreTestCase): + """ + Test exam events + """ + HANDLERS = { + EXAM_ATTEMPT_ERRORED: listen_for_exam_errored, + EXAM_ATTEMPT_REJECTED: listen_for_exam_rejected, + EXAM_ATTEMPT_RESET: listen_for_exam_reset, + EXAM_ATTEMPT_SUBMITTED: listen_for_exam_submitted, + EXAM_ATTEMPT_VERIFIED: listen_for_exam_verified, + } + + def setUp(self): + super().setUp() + self.course = CourseFactory.create( + org='TestX', number='999', display_name='Test Course' + ) + self.subsection_key = UsageKey.from_string('block-v1:edX+TestX+Test_Course+type@sequential+block@subsection') + + self.user = UserFactory() + + # Enable the course for credit + CreditCourse.objects.create( + course_key=self.course.id, + enabled=True, + ) + + @staticmethod + def _get_exam_event_data(user, course, usage_key): + """ create ExamAttemptData object for user """ + return ExamAttemptData( + student_user=UserData( + id=user.id, + is_active=True, + pii=UserPersonalData( + username=user.username, + email=user.email, + ), + ), + course_key=course.id, + usage_key=usage_key, + exam_type='timed', + requesting_user=None, + ) + + @staticmethod + def _get_exam_event_metadata(event_signal): + """ create metadata object for event """ + return EventsMetadata( + event_type=event_signal.event_type, + id=uuid4(), + minorversion=0, + source='openedx/lms/web', + sourcehost='lms.test', + time=datetime.now(timezone.utc) + ) + + @mock.patch('openedx.core.djangoapps.credit.signals.handlers.remove_credit_requirement_status', autospec=True) + def test_exam_reset(self, mock_remove_credit_status): + """ + Test exam reset event + """ + event_data = self._get_exam_event_data(self.user, self.course, self.subsection_key) + event_metadata = self._get_exam_event_metadata(EXAM_ATTEMPT_RESET) + + listen_for_exam_reset(None, EXAM_ATTEMPT_RESET, event_metadata=event_metadata, exam_attempt=event_data) + + mock_remove_credit_status.assert_called_once_with( + self.user.username, self.course.id, 'exam', str(self.subsection_key) + ) + + @ddt.data( + (EXAM_ATTEMPT_ERRORED, 'failed'), + (EXAM_ATTEMPT_REJECTED, 'failed'), + (EXAM_ATTEMPT_VERIFIED, 'satisfied'), + (EXAM_ATTEMPT_SUBMITTED, 'submitted'), + ) + @ddt.unpack + @mock.patch('openedx.core.djangoapps.credit.signals.handlers.set_credit_requirement_status', autospec=True) + def test_exam_update_event(self, event_signal, expected_status, mock_set_credit_status): + """ + Test exam events that update credit status + """ + event_data = self._get_exam_event_data(self.user, self.course, self.subsection_key) + event_metadata = self._get_exam_event_metadata(event_signal) + + handler = self.HANDLERS.get(event_signal) + handler(None, event_signal, event_metadata=event_metadata, exam_attempt=event_data) + + mock_set_credit_status.assert_called_once_with( + self.user.username, self.course.id, 'exam', str(self.subsection_key), status=expected_status + ) + + @ddt.data( + EXAM_ATTEMPT_RESET, + EXAM_ATTEMPT_REJECTED, + EXAM_ATTEMPT_ERRORED, + EXAM_ATTEMPT_VERIFIED, + EXAM_ATTEMPT_SUBMITTED, + ) + def test_exam_event_bad_user(self, event_signal): + """ + Test exam event with a user that does not exist in the LMS + """ + self.user.id = 999 # don't save to db so user doesn't exist + event_data = self._get_exam_event_data(self.user, self.course, self.subsection_key) + event_metadata = self._get_exam_event_metadata(event_signal) + handler = self.HANDLERS.get(event_signal) + + with mock.patch('openedx.core.djangoapps.credit.signals.handlers.log.error') as mock_log: + handler(None, event_signal, event_metadata=event_metadata, exam_attempt=event_data) + mock_log.assert_called_once_with( + 'Error occurred while handling exam event for ' + f'{self.user.id} and content_id {self.subsection_key}. ' + 'User does not exist!' + ) + + @ddt.data( + EXAM_ATTEMPT_RESET, + EXAM_ATTEMPT_REJECTED, + EXAM_ATTEMPT_ERRORED, + EXAM_ATTEMPT_VERIFIED, + EXAM_ATTEMPT_SUBMITTED, + ) + @mock.patch('openedx.core.djangoapps.credit.signals.handlers.remove_credit_requirement_status', autospec=True) + @mock.patch('openedx.core.djangoapps.credit.signals.handlers.set_credit_requirement_status', autospec=True) + def test_exam_event_non_credit_course(self, event_signal, mock_remove_credit_status, mock_set_credit_status): + """ + Credit credit logic should not run on non-credit courses + """ + non_credit_course = CourseFactory.create() + event_data = self._get_exam_event_data(self.user, non_credit_course, self.subsection_key) + event_metadata = self._get_exam_event_metadata(event_signal) + handler = self.HANDLERS.get(event_signal) + + handler(None, event_signal, event_metadata=event_metadata, exam_attempt=event_data) + + mock_remove_credit_status.assert_not_called() + mock_set_credit_status.assert_not_called() diff --git a/openedx/core/djangoapps/credit/tests/test_tasks.py b/openedx/core/djangoapps/credit/tests/test_tasks.py index 7d520f22f3..47c4b50925 100644 --- a/openedx/core/djangoapps/credit/tests/test_tasks.py +++ b/openedx/core/djangoapps/credit/tests/test_tasks.py @@ -11,7 +11,7 @@ from edx_proctoring.api import create_exam from openedx.core.djangoapps.credit.api import get_credit_requirements from openedx.core.djangoapps.credit.exceptions import InvalidCreditRequirements from openedx.core.djangoapps.credit.models import CreditCourse -from openedx.core.djangoapps.credit.signals import on_course_publish +from openedx.core.djangoapps.credit.signals.handlers import on_course_publish from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory # lint-amnesty, pylint: disable=wrong-import-order From 8c071a30b4e84f48c67bf111ea5f999f294cb5d0 Mon Sep 17 00:00:00 2001 From: Maria Fernanda Magallanes Zubillaga Date: Tue, 3 Oct 2023 21:22:49 -0500 Subject: [PATCH 13/17] docs: fix the EnrollmentAllowedView doc to be right --- openedx/core/djangoapps/enrollments/views.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openedx/core/djangoapps/enrollments/views.py b/openedx/core/djangoapps/enrollments/views.py index 80f6df8531..f413cb761e 100644 --- a/openedx/core/djangoapps/enrollments/views.py +++ b/openedx/core/djangoapps/enrollments/views.py @@ -1066,7 +1066,9 @@ class EnrollmentAllowedView(APIView): **Example Request** - POST /api/enrollment/v1/enrollment_allowed + POST /api/enrollment/v1/enrollment_allowed/ + + Note: The URL for this request must finish with / Example request data: ``` @@ -1086,7 +1088,6 @@ class EnrollmentAllowedView(APIView): - `auto_enroll` (optional, bool: default=false, _body_) **Responses** - - 200: Success, enrollment allowed found. - 400: Bad request, missing data. - 403: Forbidden, you need to be staff. - 409: Conflict, enrollment allowed already exists. @@ -1122,7 +1123,9 @@ class EnrollmentAllowedView(APIView): **Example Request** - DELETE /api/enrollment/v1/enrollment_allowed + DELETE /api/enrollment/v1/enrollment_allowed/ + + Note: The URL for this request must finish with / Example request data: ``` From e003217d51b830836cad0dd5e5db0dbae7447174 Mon Sep 17 00:00:00 2001 From: IrfanUddinAhmad Date: Tue, 3 Oct 2023 13:52:09 +0500 Subject: [PATCH 14/17] fix: Added xblock skill tag verification waffle switch --- xmodule/tests/test_vertical.py | 14 ++++++--- xmodule/vertical_block.py | 56 +++++++++++++++++++++------------- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/xmodule/tests/test_vertical.py b/xmodule/tests/test_vertical.py index 1e8ababa91..223cf3889c 100644 --- a/xmodule/tests/test_vertical.py +++ b/xmodule/tests/test_vertical.py @@ -5,24 +5,26 @@ Tests for vertical block. # pylint: disable=protected-access +import json from collections import namedtuple from datetime import datetime, timedelta -import json from unittest.mock import Mock, patch -import pytz import ddt -from fs.memoryfs import MemoryFS +import pytz from django.contrib.auth.models import AnonymousUser from django.test import override_settings +from edx_toggles.toggles.testutils import override_waffle_switch +from fs.memoryfs import MemoryFS from openedx_filters import PipelineStep from openedx_filters.learning.filters import VerticalBlockChildRenderStarted, VerticalBlockRenderCompleted +from ..vertical_block import XBLOCK_SKILL_TAG_VERIFICATION_SWITCH +from ..x_module import AUTHOR_VIEW, PUBLIC_VIEW, STUDENT_VIEW from . import prepare_block_runtime from .helpers import StubUserService from .xml import XModuleXmlImportTest from .xml import factories as xml -from ..x_module import STUDENT_VIEW, AUTHOR_VIEW, PUBLIC_VIEW COMPLETION_DELAY = 9876 @@ -360,6 +362,7 @@ class VerticalBlockTestCase(BaseVerticalBlockTest): }, }, ) + @override_waffle_switch(XBLOCK_SKILL_TAG_VERIFICATION_SWITCH, True) def test_vertical_block_child_render_started_filter_execution(self): """ Test the VerticalBlockChildRenderStarted filter's effects on student view. @@ -382,6 +385,7 @@ class VerticalBlockTestCase(BaseVerticalBlockTest): }, }, ) + @override_waffle_switch(XBLOCK_SKILL_TAG_VERIFICATION_SWITCH, True) def test_vertical_block_child_render_is_skipped_on_filter_exception(self): """ Test VerticalBlockChildRenderStarted filter can be used to skip child blocks. @@ -405,6 +409,7 @@ class VerticalBlockTestCase(BaseVerticalBlockTest): }, }, ) + @override_waffle_switch(XBLOCK_SKILL_TAG_VERIFICATION_SWITCH, True) def test_vertical_block_render_completed_filter_execution(self): """ Test the VerticalBlockRenderCompleted filter's execution. @@ -427,6 +432,7 @@ class VerticalBlockTestCase(BaseVerticalBlockTest): }, }, ) + @override_waffle_switch(XBLOCK_SKILL_TAG_VERIFICATION_SWITCH, True) def test_vertical_block_render_output_is_changed_on_filter_exception(self): """ Test VerticalBlockRenderCompleted filter can be used to prevent vertical block from rendering. diff --git a/xmodule/vertical_block.py b/xmodule/vertical_block.py index d6a19353b2..10ff0a5408 100644 --- a/xmodule/vertical_block.py +++ b/xmodule/vertical_block.py @@ -9,17 +9,19 @@ from datetime import datetime from functools import reduce import pytz +from edx_toggles.toggles import WaffleSwitch from lxml import etree +from openedx_filters.learning.filters import VerticalBlockChildRenderStarted, VerticalBlockRenderCompleted from web_fragments.fragment import Fragment from xblock.core import XBlock # lint-amnesty, pylint: disable=wrong-import-order from xblock.fields import Boolean, Scope -from openedx_filters.learning.filters import VerticalBlockChildRenderStarted, VerticalBlockRenderCompleted + from xmodule.mako_block import MakoTemplateBlockBase from xmodule.progress import Progress from xmodule.seq_block import SequenceFields from xmodule.studio_editable import StudioEditableBlock -from xmodule.util.misc import is_xblock_an_assignment from xmodule.util.builtin_assets import add_webpack_js_to_fragment +from xmodule.util.misc import is_xblock_an_assignment from xmodule.x_module import PUBLIC_VIEW, STUDENT_VIEW, XModuleFields from xmodule.xml_block import XmlMixin @@ -32,6 +34,17 @@ _ = lambda text: text # HACK: This shouldn't be hard-coded to two types # OBSOLETE: This obsoletes 'type' CLASS_PRIORITY = ['video', 'problem'] +WAFFLE_NAMESPACE = 'xblocks' +# .. toggle_name: xblocks.xblock_skill_tag_verification' +# .. toggle_implementation: WaffleSwitch +# .. toggle_default: False +# .. toggle_description: Set to True to get learner verification of the skills associated with the xblock. +# .. toggle_use_cases: open_edx +# .. toggle_creation_date: 2023-10-04 +# .. toggle_target_removal_date: None +XBLOCK_SKILL_TAG_VERIFICATION_SWITCH = WaffleSwitch( # lint-amnesty, pylint: disable=toggle-missing-annotation + f'{WAFFLE_NAMESPACE}.xblock_skill_tag_verification', __name__ +) class VerticalFields: @@ -116,16 +129,16 @@ class VerticalBlock( child_block_context['wrap_xblock_data'] = { 'mark-completed-on-view-after-delay': complete_on_view_delay } - - try: - # .. filter_implemented_name: VerticalBlockChildRenderStarted - # .. filter_type: org.openedx.learning.vertical_block_child.render.started.v1 - child, child_block_context = VerticalBlockChildRenderStarted.run_filter( - block=child, context=child_block_context - ) - except VerticalBlockChildRenderStarted.PreventChildBlockRender as exc: - log.info("Skipping %s from vertical block. Reason: %s", child, exc.message) - continue + if XBLOCK_SKILL_TAG_VERIFICATION_SWITCH.is_enabled(): + try: + # .. filter_implemented_name: VerticalBlockChildRenderStarted + # .. filter_type: org.openedx.learning.vertical_block_child.render.started.v1 + child, child_block_context = VerticalBlockChildRenderStarted.run_filter( + block=child, context=child_block_context + ) + except VerticalBlockChildRenderStarted.PreventChildBlockRender as exc: + log.info("Skipping %s from vertical block. Reason: %s", child, exc.message) + continue rendered_child = child.render(view, child_block_context) fragment.add_fragment_resources(rendered_child) @@ -167,15 +180,16 @@ class VerticalBlock( add_webpack_js_to_fragment(fragment, 'VerticalStudentView') fragment.initialize_js('VerticalStudentView') - try: - # .. filter_implemented_name: VerticalBlockRenderCompleted - # .. filter_type: org.openedx.learning.vertical_block.render.completed.v1 - _, fragment, context, view = VerticalBlockRenderCompleted.run_filter( - block=self, fragment=fragment, context=context, view=view - ) - except VerticalBlockRenderCompleted.PreventVerticalBlockRender as exc: - log.info("VerticalBlock rendering stopped. Reason: %s", exc.message) - fragment.content = exc.message + if XBLOCK_SKILL_TAG_VERIFICATION_SWITCH.is_enabled(): + try: + # .. filter_implemented_name: VerticalBlockRenderCompleted + # .. filter_type: org.openedx.learning.vertical_block.render.completed.v1 + _, fragment, context, view = VerticalBlockRenderCompleted.run_filter( + block=self, fragment=fragment, context=context, view=view + ) + except VerticalBlockRenderCompleted.PreventVerticalBlockRender as exc: + log.info("VerticalBlock rendering stopped. Reason: %s", exc.message) + fragment.content = exc.message return fragment From e7f6d1c8f165be2829133f38e01ed30808b3c884 Mon Sep 17 00:00:00 2001 From: Syed Sajjad Hussain Shah <52817156+syedsajjadkazmii@users.noreply.github.com> Date: Wed, 4 Oct 2023 17:08:58 +0500 Subject: [PATCH 15/17] fix: null email in identify calls (#33410) --- openedx/core/djangoapps/user_authn/views/login.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openedx/core/djangoapps/user_authn/views/login.py b/openedx/core/djangoapps/user_authn/views/login.py index fa098c7237..4880e58a43 100644 --- a/openedx/core/djangoapps/user_authn/views/login.py +++ b/openedx/core/djangoapps/user_authn/views/login.py @@ -344,7 +344,7 @@ def _track_user_login(user, request): segment.identify( user.id, { - 'email': request.POST.get('email'), + 'email': user.email, 'username': user.username }, { From 70f6f5ad9e07d6f5c7c1e3b4f95c23353a1c4058 Mon Sep 17 00:00:00 2001 From: Zubair Shakoor <57657330+zubairshakoorarbisoft@users.noreply.github.com> Date: Wed, 4 Oct 2023 17:35:18 +0500 Subject: [PATCH 16/17] fix: replaced mysql57 hosts with mysql80 (#33147) --- .github/workflows/docker-compose.yml.mysqldbdump | 2 +- cms/envs/bok_choy_docker.auth.json | 4 ++-- cms/envs/bok_choy_docker.yml | 4 ++-- cms/envs/devstack-experimental.yml | 6 +++--- lms/envs/bok_choy_docker.yml | 4 ++-- lms/envs/devstack-experimental.yml | 6 +++--- scripts/reset-test-db.sh | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/docker-compose.yml.mysqldbdump b/.github/workflows/docker-compose.yml.mysqldbdump index 6affa8c788..87f0321374 100644 --- a/.github/workflows/docker-compose.yml.mysqldbdump +++ b/.github/workflows/docker-compose.yml.mysqldbdump @@ -2,7 +2,7 @@ version: '3' services: mysql: image: mysql:5.7 - container_name: edx.devstack.mysql57 + container_name: edx.devstack.mysql80 ports: - '3306:3306' environment: diff --git a/cms/envs/bok_choy_docker.auth.json b/cms/envs/bok_choy_docker.auth.json index fce8a970fe..9a187c05b1 100644 --- a/cms/envs/bok_choy_docker.auth.json +++ b/cms/envs/bok_choy_docker.auth.json @@ -24,7 +24,7 @@ "DATABASES": { "default": { "ENGINE": "django.db.backends.mysql", - "HOST": "edx.devstack.mysql57", + "HOST": "edx.devstack.mysql80", "NAME": "edxtest", "PASSWORD": "", "PORT": "3306", @@ -32,7 +32,7 @@ }, "student_module_history": { "ENGINE": "django.db.backends.mysql", - "HOST": "edx.devstack.mysql57", + "HOST": "edx.devstack.mysql80", "NAME": "student_module_history_test", "PASSWORD": "", "PORT": "3306", diff --git a/cms/envs/bok_choy_docker.yml b/cms/envs/bok_choy_docker.yml index bc9727d7cd..779751ecb6 100644 --- a/cms/envs/bok_choy_docker.yml +++ b/cms/envs/bok_choy_docker.yml @@ -75,9 +75,9 @@ CONTENTSTORE: host: [edx.devstack.mongo] port: 27017 DATABASES: - default: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql57, NAME: edxtest, + default: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql80, NAME: edxtest, PASSWORD: '', PORT: '3306', USER: root} - student_module_history: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql57, + student_module_history: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql80, NAME: student_module_history_test, PASSWORD: '', PORT: '3306', USER: root} DEFAULT_FEEDBACK_EMAIL: feedback@example.com DEFAULT_FROM_EMAIL: registration@example.com diff --git a/cms/envs/devstack-experimental.yml b/cms/envs/devstack-experimental.yml index 969e932937..e33c024b0f 100644 --- a/cms/envs/devstack-experimental.yml +++ b/cms/envs/devstack-experimental.yml @@ -208,7 +208,7 @@ DATABASES: ATOMIC_REQUESTS: true CONN_MAX_AGE: 0 ENGINE: django.db.backends.mysql - HOST: edx.devstack.mysql57 + HOST: edx.devstack.mysql80 NAME: edxapp OPTIONS: isolation_level: read committed @@ -218,7 +218,7 @@ DATABASES: read_replica: CONN_MAX_AGE: 0 ENGINE: django.db.backends.mysql - HOST: edx.devstack.mysql57 + HOST: edx.devstack.mysql80 NAME: edxapp OPTIONS: isolation_level: read committed @@ -228,7 +228,7 @@ DATABASES: student_module_history: CONN_MAX_AGE: 0 ENGINE: django.db.backends.mysql - HOST: edx.devstack.mysql57 + HOST: edx.devstack.mysql80 NAME: edxapp_csmh OPTIONS: isolation_level: read committed diff --git a/lms/envs/bok_choy_docker.yml b/lms/envs/bok_choy_docker.yml index afef10bb5d..f93063086a 100644 --- a/lms/envs/bok_choy_docker.yml +++ b/lms/envs/bok_choy_docker.yml @@ -75,9 +75,9 @@ CONTENTSTORE: host: [edx.devstack.mongo] port: 27017 DATABASES: - default: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql57, NAME: edxtest, + default: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql80, NAME: edxtest, PASSWORD: '', PORT: '3306', USER: root} - student_module_history: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql57, + student_module_history: {ENGINE: django.db.backends.mysql, HOST: edx.devstack.mysql80, NAME: student_module_history_test, PASSWORD: '', PORT: '3306', USER: root} DEFAULT_FEEDBACK_EMAIL: feedback@example.com DEFAULT_FROM_EMAIL: registration@example.com diff --git a/lms/envs/devstack-experimental.yml b/lms/envs/devstack-experimental.yml index 5ab37724ae..50958af4d6 100644 --- a/lms/envs/devstack-experimental.yml +++ b/lms/envs/devstack-experimental.yml @@ -228,7 +228,7 @@ DATABASES: ATOMIC_REQUESTS: true CONN_MAX_AGE: 0 ENGINE: django.db.backends.mysql - HOST: edx.devstack.mysql57 + HOST: edx.devstack.mysql80 NAME: edxapp OPTIONS: isolation_level: read committed @@ -238,7 +238,7 @@ DATABASES: read_replica: CONN_MAX_AGE: 0 ENGINE: django.db.backends.mysql - HOST: edx.devstack.mysql57 + HOST: edx.devstack.mysql80 NAME: edxapp OPTIONS: isolation_level: read committed @@ -248,7 +248,7 @@ DATABASES: student_module_history: CONN_MAX_AGE: 0 ENGINE: django.db.backends.mysql - HOST: edx.devstack.mysql57 + HOST: edx.devstack.mysql80 NAME: edxapp_csmh OPTIONS: isolation_level: read committed diff --git a/scripts/reset-test-db.sh b/scripts/reset-test-db.sh index b0573a8e13..fd751b75dd 100755 --- a/scripts/reset-test-db.sh +++ b/scripts/reset-test-db.sh @@ -31,7 +31,7 @@ if [[ -z "$BOK_CHOY_HOSTNAME" ]]; then MYSQL_HOST="" SETTINGS="bok_choy" else - MYSQL_HOST="--host=edx.devstack.mysql57" + MYSQL_HOST="--host=edx.devstack.mysql80" SETTINGS="bok_choy_docker" fi From 4d3ae9f665972cec9bcd29e27bf38f91cd220dc2 Mon Sep 17 00:00:00 2001 From: Juliana Kang Date: Wed, 4 Oct 2023 08:48:37 -0400 Subject: [PATCH 17/17] feat: Show active subscriptions on Program Details apart from eligibility (#33391) REV-3704 --- .../spec/program_details_view_spec.js | 30 ++++++++++++++++--- .../views/program_details_view.js | 6 +++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/lms/static/js/learner_dashboard/spec/program_details_view_spec.js b/lms/static/js/learner_dashboard/spec/program_details_view_spec.js index 795667d2de..2387ade00b 100644 --- a/lms/static/js/learner_dashboard/spec/program_details_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/program_details_view_spec.js @@ -544,6 +544,28 @@ describe('Program Details View', () => { .toContainText(body); }; + const testSubscriptionSunsetting = (state, heading, body) => { + const subscriptionData = { + ...options.subscriptionData[0], + subscription_state: state, + }; + // eslint-disable-next-line no-use-before-define + view = initView({ + // eslint-disable-next-line no-undef + programData: $.extend({}, options.programData, { + subscription_eligible: false, + }), + isUserB2CSubscriptionsEnabled: true, + subscriptionData: [subscriptionData], + }); + view.render(); + expect(view.$('.upgrade-subscription')[0]).not.toBeInDOM(); + expect(view.$('.upgrade-subscription .upgrade-button')).not + .toContainText(heading); + expect(view.$('.upgrade-subscription .subscription-info-brief')).not + .toContainText(body); + }; + const initView = (updates) => { // eslint-disable-next-line no-undef const viewOptions = $.extend({}, options, updates); @@ -709,8 +731,8 @@ describe('Program Details View', () => { ); }); - it('should render the get subscription link if program is subscription eligible', () => { - testSubscriptionState( + it('should not render the get subscription link if program is not active', () => { + testSubscriptionSunsetting( 'pre', 'Start 7-day free trial', '$100/month USD subscription after trial ends. Cancel anytime.', @@ -734,8 +756,8 @@ describe('Program Details View', () => { ); }); - it('should render appropriate subscription text when subscription is inactive', () => { - testSubscriptionState( + it('should not render appropriate subscription text when subscription is inactive', () => { + testSubscriptionSunsetting( 'inactive', 'Restart my subscription', '$100/month USD subscription. Cancel anytime.', diff --git a/lms/static/js/learner_dashboard/views/program_details_view.js b/lms/static/js/learner_dashboard/views/program_details_view.js index 8d6c418147..220840c182 100644 --- a/lms/static/js/learner_dashboard/views/program_details_view.js +++ b/lms/static/js/learner_dashboard/views/program_details_view.js @@ -215,9 +215,13 @@ class ProgramDetailsView extends Backbone.View { && this.remainingCourseCollection.length === 0 ); + const isSubscriptionActiveSunsetting = ( + this.subscriptionModel.get('subscriptionState') === 'active' + ) + return ( this.options.isUserB2CSubscriptionsEnabled - && this.options.programData.subscription_eligible + && isSubscriptionActiveSunsetting && !programPurchasedWithoutSubscription ); }