Merge branch 'master' into issue-35278-unpin-charset-normalizer

This commit is contained in:
Ram Chandra Bhavirisetty
2025-05-06 13:30:03 -06:00
committed by GitHub
18 changed files with 5486 additions and 5585 deletions

View File

@@ -123,6 +123,17 @@ from lms.envs.common import (
AUTH_PASSWORD_VALIDATORS
)
from lms.envs.common import (
# FIXME: The HIBP settings are only used in the LMS, but CMS unit tests fail
# without them. Perhaps moving some code would allow us to remove these from
# this file.
ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY,
ENABLE_AUTHN_LOGIN_NUDGE_HIBP_POLICY,
ENABLE_AUTHN_REGISTER_HIBP_POLICY,
ENABLE_AUTHN_RESET_PASSWORD_HIBP_POLICY,
HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD,
HIBP_LOGIN_NUDGE_PASSWORD_FREQUENCY_THRESHOLD,
HIBP_REGISTRATION_PASSWORD_FREQUENCY_THRESHOLD,
USE_EXTRACTED_WORD_CLOUD_BLOCK,
USE_EXTRACTED_ANNOTATABLE_BLOCK,
USE_EXTRACTED_POLL_QUESTION_BLOCK,
@@ -595,49 +606,6 @@ IDA_LOGOUT_URI_LIST = []
COURSE_AUTHORING_MICROFRONTEND_URL = None
DISCUSSIONS_MICROFRONTEND_URL = None
DISCUSSIONS_MFE_FEEDBACK_URL = None
# .. toggle_name: ENABLE_AUTHN_RESET_PASSWORD_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# HIBP Policy.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2021-12-03
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-666
ENABLE_AUTHN_RESET_PASSWORD_HIBP_POLICY = False
# .. toggle_name: ENABLE_AUTHN_REGISTER_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# HIBP Policy on Authn MFE's registration.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2022-03-25
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-669
ENABLE_AUTHN_REGISTER_HIBP_POLICY = False
HIBP_REGISTRATION_PASSWORD_FREQUENCY_THRESHOLD = 3
# .. toggle_name: ENABLE_AUTHN_LOGIN_NUDGE_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# on Authn MFE's login.
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2022-03-29
# .. toggle_target_removal_date: None
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-668
ENABLE_AUTHN_LOGIN_NUDGE_HIBP_POLICY = False
HIBP_LOGIN_NUDGE_PASSWORD_FREQUENCY_THRESHOLD = 3
# .. toggle_name: ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# on Authn MFE's login.
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2022-03-29
# .. toggle_target_removal_date: None
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-667
ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY = False
HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD = 5
# .. toggle_name: ENABLE_DYNAMIC_REGISTRATION_FIELDS
# .. toggle_implementation: DjangoSetting

View File

@@ -215,8 +215,8 @@ from openedx.core.release import RELEASE_LINE
// it will report the height of its contents to the parent window when the
// document loads, window resizes, or DOM mutates.
if (window !== window.parent) {
var lastHeight = window.parent[0].offsetHeight;
var lastWidth = window.parent[0].offsetWidth;
var lastHeight = window.offsetHeight;
var lastWidth = window.offsetWidth;
var contentElement = document.getElementById('content');
function dispatchResizeMessage(event) {

View File

@@ -1,7 +1,6 @@
"""Tests for util.db module."""
from io import StringIO
import unittest
import ddt
from django.core.management import call_command
@@ -121,7 +120,6 @@ class MigrationTests(TestCase):
Tests for migrations.
"""
@unittest.skip('Skipping temporarily to add a foreign key')
@override_settings(MIGRATION_MODULES={})
def test_migrations_are_in_sync(self):
"""

View File

@@ -7,7 +7,6 @@ from opaque_keys.edx.keys import CourseKey
from lms.djangoapps.courseware.courses import get_course_blocks_completion_summary
User = get_user_model()
@@ -28,9 +27,12 @@ def calculate_progress_for_learner_in_course(course_key: CourseKey, user: User)
# refactored in the future so that the calculation is handled solely on the backend, eliminating the need for it to
# be done in the frontend.
num_total_units = complete_count + incomplete_count + locked_count
complete_percentage = round(complete_count / num_total_units, 2)
locked_percentage = round(locked_count / num_total_units, 2)
incomplete_percentage = 1.00 - complete_percentage - locked_percentage
if num_total_units == 0:
complete_percentage = locked_percentage = incomplete_percentage = 0.0
else:
complete_percentage = round(complete_count / num_total_units, 2)
locked_percentage = round(locked_count / num_total_units, 2)
incomplete_percentage = 1.00 - complete_percentage - locked_percentage
return {
"complete_count": complete_count,

View File

@@ -13,17 +13,17 @@ class ProgressApiTests(TestCase):
"""
Tests for the progress calculation functions.
"""
@patch("lms.djangoapps.course_home_api.progress.api.get_course_blocks_completion_summary")
def test_calculate_progress_for_learner_in_course(self, mock_get_summary):
"""
A test to verify functionality of the function under test.
"""
get_summary_return_val = {
mock_get_summary.return_value = {
"complete_count": 5,
"incomplete_count": 2,
"locked_count": 1,
}
mock_get_summary.return_value = get_summary_return_val
expected_data = {
"complete_count": 5,
@@ -39,6 +39,31 @@ class ProgressApiTests(TestCase):
assert mock_get_summary.called_once_with("some_course", "some_user")
assert results == expected_data
@patch("lms.djangoapps.course_home_api.progress.api.get_course_blocks_completion_summary")
def test_handle_division_by_zero(self, mock_get_summary):
"""
A test to verify that we're avoiding division-by-zero errors if the total number of units is 0.
"""
mock_get_summary.return_value = {
"complete_count": 0,
"incomplete_count": 0,
"locked_count": 0,
}
expected_data = {
"complete_count": 0,
"incomplete_count": 0,
"locked_count": 0,
"total_count": 0,
"complete_percentage": 0.0,
"locked_percentage": 0.0,
"incomplete_percentage": 0.0,
}
results = calculate_progress_for_learner_in_course("some_course", "some_user")
assert mock_get_summary.called_once_with("some_course", "some_user")
assert results == expected_data
@patch("lms.djangoapps.course_home_api.progress.api.get_course_blocks_completion_summary")
def test_calculate_progress_for_learner_in_course_summary_empty(self, mock_get_summary):
"""

View File

@@ -37,12 +37,19 @@ def collect_progress_for_user_in_course(course_id: str, user_id: str) -> None:
log.warning(f"Could not retrieve a user with id {user_id}, aborting task.")
return
try:
enrollment = get_course_enrollment(user, course_key)
enrollment_mode = enrollment.mode
except AttributeError:
log.warning(f"Could not retrieve enrollment info for user {user.id} in course {course_id}")
return
progress = calculate_progress_for_learner_in_course(course_key, user)
enrollment = get_course_enrollment(user, course_key)
# add a few extra fields to the returned data to make the event payload a bit more usable
progress["user_id"] = user.id
progress["course_id"] = course_id
progress["enrollment_mode"] = enrollment.mode
progress["enrollment_mode"] = enrollment_mode
tracker.emit(
COURSE_COMPLETION_FOR_USER_EVENT_NAME,

View File

@@ -5,6 +5,7 @@ Tests for Celery tasks used by the `course_home_api` app.
from unittest.mock import patch
from opaque_keys.edx.keys import CourseKey
from testfixtures import LogCapture
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
@@ -14,6 +15,8 @@ from lms.djangoapps.course_home_api.tasks import (
)
from openedx.core.djangoapps.catalog.tests.factories import CourseFactory, CourseRunFactory
LOG_PATH = 'lms.djangoapps.course_home_api.tasks'
class CalculateCompletionTaskTests(ModuleStoreTestCase):
"""
@@ -67,6 +70,27 @@ class CalculateCompletionTaskTests(ModuleStoreTestCase):
expected_data,
)
@patch("lms.djangoapps.course_home_api.tasks.calculate_progress_for_learner_in_course")
@patch("lms.djangoapps.course_home_api.tasks.get_course_enrollment")
@patch("lms.djangoapps.course_home_api.tasks.tracker.emit")
def test_cannot_retrieve_enrollment_info(self, mock_tracker, mock_get_enrollment, mock_progress):
"""
Test to ensure the task is aborted if we cannot retrieve enrollment info for the user in the specified course.
"""
mock_get_enrollment.return_value = None
expected_message = (
f"Could not retrieve enrollment info for user {self.user.id} in course {self.course_run_key_string}"
)
with LogCapture() as log:
collect_progress_for_user_in_course(self.course_run_key_string, self.user.id)
mock_get_enrollment.assert_called_once_with(self.user, CourseKey.from_string(self.course_run_key_string))
log.check_present((LOG_PATH, "WARNING", expected_message),)
mock_progress.assert_not_called()
mock_tracker.assert_not_called()
@patch("lms.djangoapps.course_home_api.tasks.calculate_progress_for_learner_in_course")
@patch("lms.djangoapps.course_home_api.tasks.tracker.emit")
def test_aborted_task_user_dne(self, mock_tracker, mock_progress):

View File

@@ -5060,49 +5060,70 @@ DISCUSSIONS_MFE_FEEDBACK_URL = None
# .. setting_default: None
# .. setting_description: Base URL of the exams dashboard micro-frontend for instructors.
EXAMS_DASHBOARD_MICROFRONTEND_URL = None
# .. toggle_name: ENABLE_AUTHN_RESET_PASSWORD_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# HIBP Policy.
# .. toggle_description: When enabled, this toggle prevents the use of known-vulnerable passwords in
# the password reset flow.
# See ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY for more details.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2021-12-03
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-666
ENABLE_AUTHN_RESET_PASSWORD_HIBP_POLICY = False
# .. toggle_name: ENABLE_AUTHN_REGISTER_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# HIBP Policy on Authn MFE's registration.
# .. toggle_description: When enabled, this toggle prevents the use of known-vulnerable passwords in
# the registration flow if their frequency exceeds a threshold.
# See ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY for more details.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2022-03-25
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-669
ENABLE_AUTHN_REGISTER_HIBP_POLICY = False
HIBP_REGISTRATION_PASSWORD_FREQUENCY_THRESHOLD = 3
# .. setting_name: HIBP_REGISTRATION_PASSWORD_FREQUENCY_THRESHOLD
# .. setting_default: 3.0
# .. setting_description: Log10 threshold in effect for ENABLE_AUTHN_REGISTER_HIBP_POLICY.
# See ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY for more details.
HIBP_REGISTRATION_PASSWORD_FREQUENCY_THRESHOLD = 3.0
# .. toggle_name: ENABLE_AUTHN_LOGIN_NUDGE_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# on Authn MFE's login.
# .. toggle_use_cases: temporary
# .. toggle_description: When enabled, the login flow detects vulnerable passwords
# and prompts users to change their password if their frequency exceeds a threshold.
# See ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY for more details.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2022-03-29
# .. toggle_target_removal_date: None
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-668
ENABLE_AUTHN_LOGIN_NUDGE_HIBP_POLICY = False
HIBP_LOGIN_NUDGE_PASSWORD_FREQUENCY_THRESHOLD = 3
# .. setting_name: HIBP_LOGIN_NUDGE_PASSWORD_FREQUENCY_THRESHOLD
# .. setting_default: 3.0
# .. setting_description: Log10 threshold in effect for ENABLE_AUTHN_LOGIN_NUDGE_HIBP_POLICY.
# See ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY for more details.
HIBP_LOGIN_NUDGE_PASSWORD_FREQUENCY_THRESHOLD = 3.0
# .. toggle_name: ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: When enabled, this toggle activates the use of the password validation
# on Authn MFE's login.
# .. toggle_use_cases: temporary
# .. toggle_description: When enabled, this toggle prevents the use of known-vulnerable passwords in
# the login flow if their frequency exceeds a threshold. Passwords are assessed by calling the
# Pwned Passwords service using a k-anonymity method that does not expose the password. The
# service tells us whether the password has been seen in any data breaches, and if so, how
# often. This count is converted to a "frequency" by taking the logarithm base 10. The login flow
# can reject all vulnerable passwords, or only passwords with a frequency above a configured
# threshold. In existing deployments, the threshold should be set high and tightened
# gradually in order to avoid large spikes in password resets and support requests. For example,
# setting ``HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD`` to 5 would reject logins when the
# password has been seen 100,000 or more times in the Pwned Passwords dataset. The goal should be
# to gradually reduce this to 0, meaning even a single occurrence will cause a rejection. (The
# threshold can take any real-number value.)
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2022-03-29
# .. toggle_target_removal_date: None
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-667
ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY = False
HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD = 5
# .. setting_name: HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD
# .. setting_default: 5.0
# .. setting_description: Log10 threshold in effect for ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY.
# See ENABLE_AUTHN_LOGIN_BLOCK_HIBP_POLICY for more details.
HIBP_LOGIN_BLOCK_PASSWORD_FREQUENCY_THRESHOLD = 5.0
# .. toggle_name: ENABLE_DYNAMIC_REGISTRATION_FIELDS
# .. toggle_implementation: DjangoSetting

10828
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -46,7 +46,7 @@
"@edx/paragon": "2.6.4",
"@edx/studio-frontend": "^2.1.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^12.1.5",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^12.8.3",
"babel-loader": "^9.1.3",
"babel-plugin-transform-class-properties": "6.24.1",
@@ -78,10 +78,10 @@
"popper.js": "1.16.1",
"prop-types": "15.8.1",
"raw-loader": "0.5.1",
"react": "16.14.0",
"react-dom": "16.14.0",
"react-focus-lock": "^1.19.1",
"react-redux": "5.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-focus-lock": "^2.0.0",
"react-redux": "^7.0.0",
"react-router-dom": "5.3.4",
"react-slick": "0.30.3",
"redux": "3.7.2",
@@ -121,7 +121,7 @@
"karma-spec-reporter": "0.0.20",
"karma-webpack": "^5.0.1",
"plato": "1.7.0",
"react-test-renderer": "16.14.0",
"react-test-renderer": "18.0.0",
"selenium-webdriver": "4.30.0",
"sinon": "19.0.2",
"squirejs": "0.1.0",

View File

@@ -62,7 +62,7 @@ django-storages<1.14.4
# 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==5.13.0
edx-enterprise==5.13.3
# Date: 2024-05-09
# This has to be constrained as well because newer versions of edx-i18n-tools need the
@@ -91,11 +91,6 @@ libsass==0.10.0
# Issue for unpinning: https://github.com/openedx/edx-platform/issues/35271
markdown<3.4.0
# Date: 2024-04-24
# moto==5.0 contains breaking changes. Needs to be updated separately.
# Issue for unpinning: https://github.com/openedx/edx-platform/issues/35270
moto<5.0
# Date: 2024-07-16
# We need to upgrade the version of elasticsearch to atleast 7.15 before we can upgrade to Numpy 2.0.0
# Otherwise we see a failure while running the following command:

View File

@@ -414,7 +414,7 @@ edx-ccx-keys==2.0.2
# -r requirements/edx/kernel.in
# lti-consumer-xblock
# openedx-events
edx-celeryutils==1.3.0
edx-celeryutils==1.4.0
# via
# -r requirements/edx/kernel.in
# edx-name-affirmation
@@ -459,7 +459,7 @@ edx-drf-extensions==10.6.0
# edx-when
# edxval
# openedx-learning
edx-enterprise==5.13.0
edx-enterprise==5.13.3
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/kernel.in

View File

@@ -681,7 +681,7 @@ edx-ccx-keys==2.0.2
# -r requirements/edx/testing.txt
# lti-consumer-xblock
# openedx-events
edx-celeryutils==1.3.0
edx-celeryutils==1.4.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -736,7 +736,7 @@ edx-drf-extensions==10.6.0
# edx-when
# edxval
# openedx-learning
edx-enterprise==5.13.0
edx-enterprise==5.13.3
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt

View File

@@ -498,7 +498,7 @@ edx-ccx-keys==2.0.2
# -r requirements/edx/base.txt
# lti-consumer-xblock
# openedx-events
edx-celeryutils==1.3.0
edx-celeryutils==1.4.0
# via
# -r requirements/edx/base.txt
# edx-name-affirmation
@@ -543,7 +543,7 @@ edx-drf-extensions==10.6.0
# edx-when
# edxval
# openedx-learning
edx-enterprise==5.13.0
edx-enterprise==5.13.3
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt

View File

@@ -523,7 +523,7 @@ edx-ccx-keys==2.0.2
# -r requirements/edx/base.txt
# lti-consumer-xblock
# openedx-events
edx-celeryutils==1.3.0
edx-celeryutils==1.4.0
# via
# -r requirements/edx/base.txt
# edx-name-affirmation
@@ -568,7 +568,7 @@ edx-drf-extensions==10.6.0
# edx-when
# edxval
# openedx-learning
edx-enterprise==5.13.0
edx-enterprise==5.13.3
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt

View File

@@ -1,6 +1,6 @@
-r base.txt
moto<5.0 # moto==5.0 contains breaking changes. needs to be fixed separately.
moto
pytest
requests_mock
responses

View File

@@ -130,7 +130,7 @@ more-itertools==10.6.0
# via
# -r scripts/user_retirement/requirements/base.txt
# simple-salesforce
moto==4.2.14
moto==5.1.4
# via -r scripts/user_retirement/requirements/testing.in
newrelic==10.9.0
# via

View File

@@ -10,7 +10,7 @@ import boto3
import pytest
from botocore.exceptions import ClientError
from click.testing import CliRunner
from moto import mock_ec2, mock_s3
from moto import mock_aws
from scripts.user_retirement.retirement_archive_and_cleanup import (
ERR_ARCHIVING,
@@ -89,7 +89,7 @@ def fake_learners_to_retire():
get_learners_by_date_and_status=DEFAULT,
bulk_cleanup_retirements=DEFAULT
)
@mock_s3
@mock_aws
def test_successful(*args, **kwargs):
conn = boto3.resource('s3')
conn.create_bucket(Bucket=FAKE_BUCKET_NAME)
@@ -118,8 +118,7 @@ def test_successful(*args, **kwargs):
get_learners_by_date_and_status=DEFAULT,
bulk_cleanup_retirements=DEFAULT
)
@mock_ec2
@mock_s3
@mock_aws
def test_successful_with_batching(*args, **kwargs):
conn = boto3.resource('s3')
conn.create_bucket(Bucket=FAKE_BUCKET_NAME)
@@ -149,7 +148,7 @@ def test_successful_with_batching(*args, **kwargs):
get_learners_by_date_and_status=DEFAULT,
bulk_cleanup_retirements=DEFAULT
)
@mock_s3
@mock_aws
def test_successful_dry_run(*args, **kwargs):
mock_get_access_token = args[0]
mock_get_learners = kwargs['get_learners_by_date_and_status']
@@ -253,7 +252,7 @@ def test_conflicting_cool_off_date(*_):
assert 'End date cannot occur within the cool_off_days period' in result.output
@mock_s3
@mock_aws
def test_s3_upload_data():
"""
Test case to verify s3 upload and download.