Merge branch 'master' into BOM-2374-entitlements
This commit is contained in:
@@ -5,8 +5,6 @@ Add and create new modes for running courses on this particular LMS
|
||||
|
||||
from collections import defaultdict, namedtuple
|
||||
from datetime import timedelta
|
||||
|
||||
import inspect # lint-amnesty, pylint: disable=unused-import
|
||||
import logging
|
||||
import six
|
||||
from config_models.models import ConfigurationModel
|
||||
@@ -21,7 +19,6 @@ from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from opaque_keys.edx.django.models import CourseKeyField
|
||||
from opaque_keys.edx.keys import CourseKey # lint-amnesty, pylint: disable=unused-import
|
||||
from simple_history.models import HistoricalRecords
|
||||
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
|
||||
@@ -21,7 +21,7 @@ from django.utils.translation import get_language, to_locale
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic.base import View
|
||||
from edx_django_utils.monitoring.utils import increment
|
||||
from ipware.ip import get_ip
|
||||
from ipware.ip import get_client_ip
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from six import text_type
|
||||
|
||||
@@ -90,7 +90,7 @@ class ChooseModeView(View):
|
||||
embargo_redirect = embargo_api.redirect_if_blocked(
|
||||
course_key,
|
||||
user=request.user,
|
||||
ip_address=get_ip(request),
|
||||
ip_address=get_client_ip(request)[0],
|
||||
url=request.path
|
||||
)
|
||||
if embargo_redirect:
|
||||
|
||||
@@ -17,7 +17,7 @@ import logging
|
||||
|
||||
import six
|
||||
from django.conf import settings
|
||||
from django.http import Http404, HttpResponse # lint-amnesty, pylint: disable=unused-import
|
||||
from django.http import HttpResponse # lint-amnesty, pylint: disable=unused-import
|
||||
from django.template import engines
|
||||
from django.urls import reverse, NoReverseMatch
|
||||
from six.moves.urllib.parse import urljoin
|
||||
@@ -26,7 +26,6 @@ from django.core.exceptions import ValidationError
|
||||
|
||||
from edx_django_utils.monitoring import set_custom_attribute
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site # lint-amnesty, pylint: disable=unused-import
|
||||
from xmodule.util.xmodule_django import get_current_request_hostname
|
||||
|
||||
from . import Engines
|
||||
|
||||
@@ -22,7 +22,6 @@ from common.djangoapps.student.tests.factories import TEST_PASSWORD, CourseEnrol
|
||||
from lms.djangoapps.courseware.models import DynamicUpgradeDeadlineConfiguration
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
||||
from openedx.core.djangoapps.user_api.models import UserOrgTag
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -485,7 +484,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True)
|
||||
course = CourseFactory.create(self_paced=True)
|
||||
course_uuid = uuid.uuid4()
|
||||
course_mode = CourseModeFactory(
|
||||
CourseModeFactory(
|
||||
course_id=course.id,
|
||||
mode_slug=CourseMode.VERIFIED,
|
||||
# This must be in the future to ensure it is returned by downstream code.
|
||||
@@ -499,11 +498,9 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
|
||||
# Add an audit course enrollment for user.
|
||||
enrollment = CourseEnrollment.enroll(self.user, course.id, mode=CourseMode.AUDIT)
|
||||
|
||||
# Set an upgrade schedule so that dynamic upgrade deadlines are used
|
||||
ScheduleFactory.create(
|
||||
enrollment=enrollment,
|
||||
upgrade_deadline=course_mode.expiration_datetime + timedelta(days=-3)
|
||||
)
|
||||
# Set an expired dynamic upgrade deadline
|
||||
enrollment.schedule.upgrade_deadline = now() + timedelta(days=-2)
|
||||
enrollment.schedule.save()
|
||||
|
||||
# The upgrade should complete and ignore the deadline
|
||||
response = self.client.post(
|
||||
|
||||
@@ -45,6 +45,11 @@ TRANSITION_STATES = (
|
||||
DEFAULT_TRANSITION_STATE,
|
||||
)
|
||||
|
||||
MANUAL_ENROLLMENT_ROLE_CHOICES = configuration_helpers.get_value(
|
||||
'MANUAL_ENROLLMENT_ROLE_CHOICES',
|
||||
settings.MANUAL_ENROLLMENT_ROLE_CHOICES
|
||||
)
|
||||
|
||||
COURSE_DASHBOARD_PLUGIN_VIEW_NAME = "course_dashboard"
|
||||
|
||||
|
||||
@@ -54,6 +59,7 @@ def create_manual_enrollment_audit(
|
||||
transition_state,
|
||||
reason,
|
||||
course_run_key=None,
|
||||
role=None
|
||||
):
|
||||
"""
|
||||
Creates an audit item for a manual enrollment.
|
||||
@@ -63,10 +69,13 @@ def create_manual_enrollment_audit(
|
||||
transition_state: <str> state of enrollment transition state from _TRANSITIONS_STATES
|
||||
reason: <str> Reason why user was manually enrolled
|
||||
course_run_key: <str> Used to link the audit enrollment to the actual enrollment
|
||||
role: <str> role of the enrolled user from MANUAL_ENROLLMENT_ROLE_CHOICES
|
||||
|
||||
Note: We purposefully *exclude* passing items like CourseEnrollment objects to prevent callers from needed to
|
||||
know about model level code.
|
||||
"""
|
||||
if role and role not in MANUAL_ENROLLMENT_ROLE_CHOICES:
|
||||
raise ValueError("Role `{}` not in allowed roles: `{}".format(role, MANUAL_ENROLLMENT_ROLE_CHOICES))
|
||||
if transition_state not in TRANSITION_STATES:
|
||||
raise ValueError("State `{}` not in allow states: `{}`".format(transition_state, TRANSITION_STATES))
|
||||
|
||||
@@ -86,7 +95,8 @@ def create_manual_enrollment_audit(
|
||||
user_email,
|
||||
transition_state,
|
||||
reason,
|
||||
enrollment
|
||||
enrollment,
|
||||
role
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -2,17 +2,10 @@
|
||||
Utility functions for validating forms
|
||||
"""
|
||||
|
||||
|
||||
import re # lint-amnesty, pylint: disable=unused-import
|
||||
from importlib import import_module # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user, unused-import
|
||||
from django.contrib.auth.tokens import default_token_generator
|
||||
from django.core.exceptions import ValidationError # lint-amnesty, pylint: disable=unused-import
|
||||
from django.urls import reverse
|
||||
from django.utils.http import int_to_base36
|
||||
from django.utils.translation import ugettext_lazy as _ # lint-amnesty, pylint: disable=unused-import
|
||||
from edx_ace import ace
|
||||
from edx_ace.recipient import Recipient
|
||||
|
||||
@@ -20,12 +13,9 @@ from openedx.core.djangoapps.ace_common.template_context import get_base_templat
|
||||
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.theming.helpers import get_current_site
|
||||
from openedx.core.djangoapps.user_api import accounts as accounts_settings # lint-amnesty, pylint: disable=unused-import
|
||||
from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled # lint-amnesty, pylint: disable=unused-import
|
||||
from openedx.core.djangoapps.user_authn.toggles import should_redirect_to_authn_microfrontend
|
||||
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
|
||||
from common.djangoapps.student.message_types import AccountRecovery as AccountRecoveryMessage
|
||||
from common.djangoapps.student.models import CourseEnrollmentAllowed, email_exists_or_retired # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
|
||||
def send_account_recovery_email_for_user(user, request, email=None):
|
||||
|
||||
@@ -4,7 +4,6 @@ Un-enroll Bulk users course wide as well as specified in csv
|
||||
import logging
|
||||
|
||||
import unicodecsv
|
||||
from django.core.exceptions import ObjectDoesNotExist # lint-amnesty, pylint: disable=unused-import
|
||||
from django.core.management.base import BaseCommand
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
@@ -18,6 +18,7 @@ from edx_ace import ace
|
||||
from edx_ace.recipient import Recipient
|
||||
|
||||
from common.djangoapps.student.models import AccountRecoveryConfiguration
|
||||
from openedx.core.djangoapps.user_authn.toggles import should_redirect_to_authn_microfrontend
|
||||
from openedx.core.djangoapps.ace_common.template_context import get_base_template_context
|
||||
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
@@ -104,12 +105,16 @@ class Command(BaseCommand):
|
||||
"""
|
||||
message_context = get_base_template_context(site)
|
||||
email = user.email
|
||||
if should_redirect_to_authn_microfrontend():
|
||||
site_url = settings.AUTHN_MICROFRONTEND_URL
|
||||
else:
|
||||
site_url = configuration_helpers.get_value('SITE_NAME', settings.SITE_NAME)
|
||||
message_context.update({
|
||||
'email': email,
|
||||
'platform_name': configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
|
||||
'reset_link': '{protocol}://{site}{link}?track=pwreset'.format(
|
||||
'reset_link': '{protocol}://{site_url}{link}?track=pwreset'.format(
|
||||
protocol='http',
|
||||
site=configuration_helpers.get_value('SITE_NAME', settings.SITE_NAME),
|
||||
site_url=site_url,
|
||||
link=reverse('password_reset_confirm', kwargs={
|
||||
'uidb36': int_to_base36(user.id),
|
||||
'token': default_token_generator.make_token(user),
|
||||
|
||||
@@ -7,17 +7,24 @@ import pytest
|
||||
import six
|
||||
|
||||
from django.core import mail
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management import call_command, CommandError
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase, RequestFactory
|
||||
from django.test import TestCase, RequestFactory, override_settings
|
||||
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
|
||||
from testfixtures import LogCapture
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
|
||||
from common.djangoapps.student.models import AccountRecoveryConfiguration
|
||||
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from openedx.core.djangoapps.user_authn.toggles import REDIRECT_TO_AUTHN_MICROFRONTEND
|
||||
|
||||
LOGGER_NAME = 'common.djangoapps.student.management.commands.recover_account'
|
||||
FEATURES_WITH_AUTHN_MFE_ENABLED = settings.FEATURES.copy()
|
||||
FEATURES_WITH_AUTHN_MFE_ENABLED['ENABLE_AUTHN_MICROFRONTEND'] = True
|
||||
|
||||
|
||||
class RecoverAccountTests(TestCase):
|
||||
@@ -65,6 +72,24 @@ class RecoverAccountTests(TestCase):
|
||||
# try to login with previous password
|
||||
assert not self.client.login(username=self.user.username, password='password')
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_AUTHN_MFE_ENABLED)
|
||||
@override_waffle_flag(REDIRECT_TO_AUTHN_MICROFRONTEND, active=True)
|
||||
@skip_unless_lms
|
||||
def test_authn_mfe_url_in_reset_link(self):
|
||||
"""
|
||||
send password reset link to learner with authn mfe.
|
||||
:return:
|
||||
"""
|
||||
|
||||
with NamedTemporaryFile() as csv:
|
||||
csv = self._write_test_csv(csv, lines=['amy,amy@edx.com,amy@newemail.com\n'])
|
||||
call_command("recover_account", "--csv_file_path={}".format(csv.name))
|
||||
|
||||
assert len(mail.outbox) == 1
|
||||
|
||||
authn_mfe_url = re.findall(settings.AUTHN_MICROFRONTEND_URL, mail.outbox[0].body)[0]
|
||||
self.assertEqual(authn_mfe_url, settings.AUTHN_MICROFRONTEND_URL)
|
||||
|
||||
def test_file_not_found_error(self):
|
||||
"""
|
||||
Test command error raised when csv path is invalid
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import django_countries.fields
|
||||
@@ -75,7 +72,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
('recent_enrollment_time_delta', models.PositiveIntegerField(default=0, help_text=u"The number of seconds in which a new enrollment is considered 'recent'. Used to display notifications.")),
|
||||
('recent_enrollment_time_delta', models.PositiveIntegerField(default=0, help_text="The number of seconds in which a new enrollment is considered 'recent'. Used to display notifications.")),
|
||||
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
|
||||
],
|
||||
options={
|
||||
@@ -141,9 +138,9 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
('company_identifier', models.TextField(help_text=u'The company identifier for the LinkedIn Add-to-Profile button e.g 0_0dPSPyS070e0HsE9HNz_13_d11_')),
|
||||
('dashboard_tracking_code', models.TextField(default=u'', blank=True)),
|
||||
('trk_partner_name', models.CharField(default=u'', help_text=u"Short identifier for the LinkedIn partner used in the tracking code. (Example: 'edx') If no value is provided, tracking codes will not be sent to LinkedIn.", max_length=10, blank=True)),
|
||||
('company_identifier', models.TextField(help_text='The company identifier for the LinkedIn Add-to-Profile button e.g 0_0dPSPyS070e0HsE9HNz_13_d11_')),
|
||||
('dashboard_tracking_code', models.TextField(default='', blank=True)),
|
||||
('trk_partner_name', models.CharField(default='', help_text="Short identifier for the LinkedIn partner used in the tracking code. (Example: 'edx') If no value is provided, tracking codes will not be sent to LinkedIn.", max_length=10, blank=True)),
|
||||
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
|
||||
],
|
||||
options={
|
||||
@@ -166,7 +163,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('enrolled_email', models.CharField(max_length=255, db_index=True)),
|
||||
('time_stamp', models.DateTimeField(auto_now_add=True, null=True)),
|
||||
('state_transition', models.CharField(max_length=255, choices=[(u'from unenrolled to allowed to enroll', u'from unenrolled to allowed to enroll'), (u'from allowed to enroll to enrolled', u'from allowed to enroll to enrolled'), (u'from enrolled to enrolled', u'from enrolled to enrolled'), (u'from enrolled to unenrolled', u'from enrolled to unenrolled'), (u'from unenrolled to enrolled', u'from unenrolled to enrolled'), (u'from allowed to enroll to enrolled', u'from allowed to enroll to enrolled'), (u'from unenrolled to unenrolled', u'from unenrolled to unenrolled'), (u'N/A', u'N/A')])),
|
||||
('state_transition', models.CharField(max_length=255, choices=[('from unenrolled to allowed to enroll', 'from unenrolled to allowed to enroll'), ('from allowed to enroll to enrolled', 'from allowed to enroll to enrolled'), ('from enrolled to enrolled', 'from enrolled to enrolled'), ('from enrolled to unenrolled', 'from enrolled to unenrolled'), ('from unenrolled to enrolled', 'from unenrolled to enrolled'), ('from allowed to enroll to enrolled', 'from allowed to enroll to enrolled'), ('from unenrolled to unenrolled', 'from unenrolled to unenrolled'), ('N/A', 'N/A')])),
|
||||
('reason', models.TextField(null=True)),
|
||||
('enrolled_by', models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
|
||||
('enrollment', models.ForeignKey(to='student.CourseEnrollment', null=True, on_delete=models.CASCADE)),
|
||||
@@ -186,7 +183,7 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('new_email', models.CharField(db_index=True, max_length=255, blank=True)),
|
||||
('activation_key', models.CharField(unique=True, max_length=32, verbose_name=u'activation key', db_index=True)),
|
||||
('activation_key', models.CharField(unique=True, max_length=32, verbose_name='activation key', db_index=True)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
],
|
||||
),
|
||||
@@ -203,7 +200,7 @@ class Migration(migrations.Migration):
|
||||
name='Registration',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('activation_key', models.CharField(unique=True, max_length=32, verbose_name=u'activation key', db_index=True)),
|
||||
('activation_key', models.CharField(unique=True, max_length=32, verbose_name='activation key', db_index=True)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
],
|
||||
options={
|
||||
@@ -216,12 +213,12 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('name', models.CharField(db_index=True, max_length=255, blank=True)),
|
||||
('meta', models.TextField(blank=True)),
|
||||
('courseware', models.CharField(default=u'course.xml', max_length=255, blank=True)),
|
||||
('courseware', models.CharField(default='course.xml', max_length=255, blank=True)),
|
||||
('language', models.CharField(db_index=True, max_length=255, blank=True)),
|
||||
('location', models.CharField(db_index=True, max_length=255, blank=True)),
|
||||
('year_of_birth', models.IntegerField(db_index=True, null=True, blank=True)),
|
||||
('gender', models.CharField(blank=True, max_length=6, null=True, db_index=True, choices=[(u'm', u'Male'), (u'f', u'Female'), (u'o', u'Other/Prefer Not to Say')])),
|
||||
('level_of_education', models.CharField(blank=True, max_length=6, null=True, db_index=True, choices=[(u'p', u'Doctorate'), (u'm', u"Master's or professional degree"), (u'b', u"Bachelor's degree"), (u'a', u'Associate degree'), (u'hs', u'Secondary/high school'), (u'jhs', u'Junior secondary/junior high/middle school'), (u'el', u'Elementary/primary school'), (u'none', u'No Formal Education'), (u'other', u'Other Education')])),
|
||||
('gender', models.CharField(blank=True, max_length=6, null=True, db_index=True, choices=[('m', 'Male'), ('f', 'Female'), ('o', 'Other/Prefer Not to Say')])),
|
||||
('level_of_education', models.CharField(blank=True, max_length=6, null=True, db_index=True, choices=[('p', 'Doctorate'), ('m', "Master's or professional degree"), ('b', "Bachelor's degree"), ('a', 'Associate degree'), ('hs', 'Secondary/high school'), ('jhs', 'Junior secondary/junior high/middle school'), ('el', 'Elementary/primary school'), ('none', 'No Formal Education'), ('other', 'Other Education')])),
|
||||
('mailing_address', models.TextField(null=True, blank=True)),
|
||||
('city', models.TextField(null=True, blank=True)),
|
||||
('country', django_countries.fields.CountryField(blank=True, max_length=2, null=True)),
|
||||
@@ -247,7 +244,7 @@ class Migration(migrations.Migration):
|
||||
name='UserStanding',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('account_status', models.CharField(blank=True, max_length=31, choices=[(u'disabled', u'Account Disabled'), (u'enabled', u'Account Enabled')])),
|
||||
('account_status', models.CharField(blank=True, max_length=31, choices=[('disabled', 'Account Disabled'), ('enabled', 'Account Enabled')])),
|
||||
('standing_last_changed_at', models.DateTimeField(auto_now=True)),
|
||||
('changed_by', models.ForeignKey(to=settings.AUTH_USER_MODEL, blank=True, on_delete=models.CASCADE)),
|
||||
('user', models.OneToOneField(related_name='standing', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
|
||||
@@ -269,22 +266,22 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseenrollmentallowed',
|
||||
unique_together=set([('email', 'course_id')]),
|
||||
unique_together={('email', 'course_id')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='languageproficiency',
|
||||
unique_together=set([('code', 'user_profile')]),
|
||||
unique_together={('code', 'user_profile')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='entranceexamconfiguration',
|
||||
unique_together=set([('user', 'course_id')]),
|
||||
unique_together={('user', 'course_id')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseenrollment',
|
||||
unique_together=set([('user', 'course_id')]),
|
||||
unique_together={('user', 'course_id')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseaccessrole',
|
||||
unique_together=set([('user', 'org', 'course_id', 'role')]),
|
||||
unique_together={('user', 'org', 'course_id', 'role')},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-04-13 17:34
|
||||
|
||||
|
||||
@@ -11,14 +10,13 @@ import opaque_keys.edx.django.models
|
||||
import simple_history.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
from lms.djangoapps.experiments.models import ExperimentData
|
||||
from common.djangoapps.student.models import CourseEnrollment, FBEEnrollmentExclusion
|
||||
|
||||
import openedx.core.djangolib.model_mixins
|
||||
from common.djangoapps.course_modes import models as course_modes_models
|
||||
from common.djangoapps.student.models import CourseEnrollment, FBEEnrollmentExclusion
|
||||
from lms.djangoapps.experiments.models import ExperimentData
|
||||
from openedx.features.course_duration_limits.config import EXPERIMENT_DATA_HOLDBACK_KEY, EXPERIMENT_ID
|
||||
|
||||
|
||||
# These data migrations do not require changes when building from scratch.
|
||||
# student.migrations.0029_add_data_researcher
|
||||
# student.migrations.0011_course_key_field_to_foreign_key
|
||||
@@ -287,15 +285,15 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseenrollmentallowed',
|
||||
unique_together=set([('email', 'course_id')]),
|
||||
unique_together={('email', 'course_id')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='languageproficiency',
|
||||
unique_together=set([('code', 'user_profile')]),
|
||||
unique_together={('code', 'user_profile')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='entranceexamconfiguration',
|
||||
unique_together=set([('user', 'course_id')]),
|
||||
unique_together={('user', 'course_id')},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='courseenrollment',
|
||||
@@ -304,11 +302,11 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseenrollment',
|
||||
unique_together=set([('user', 'course_id')]),
|
||||
unique_together={('user', 'course_id')},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseaccessrole',
|
||||
unique_together=set([('user', 'org', 'course_id', 'role')]),
|
||||
unique_together={('user', 'org', 'course_id', 'role')},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='UserAttribute',
|
||||
@@ -323,7 +321,7 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='userattribute',
|
||||
unique_together=set([('user', 'name')]),
|
||||
unique_together={('user', 'name')},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userattribute',
|
||||
@@ -364,7 +362,7 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseenrollment',
|
||||
unique_together=set([('user', 'course')]),
|
||||
unique_together={('user', 'course')},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SocialLink',
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -14,11 +11,11 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='courseenrollment',
|
||||
name='mode',
|
||||
field=models.CharField(default=u'audit', max_length=100),
|
||||
field=models.CharField(default='audit', max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalcourseenrollment',
|
||||
name='mode',
|
||||
field=models.CharField(default=u'audit', max_length=100),
|
||||
field=models.CharField(default='audit', max_length=100),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
from django.conf import settings
|
||||
@@ -28,6 +25,6 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='userattribute',
|
||||
unique_together=set([('user', 'name')]),
|
||||
unique_together={('user', 'name')},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -14,6 +11,6 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='level_of_education',
|
||||
field=models.CharField(blank=True, max_length=6, null=True, db_index=True, choices=[(u'p', u'Doctorate'), (u'm', u"Master's or professional degree"), (u'b', u"Bachelor's degree"), (u'a', u'Associate degree'), (u'hs', u'Secondary/high school'), (u'jhs', u'Junior secondary/junior high/middle school'), (u'el', u'Elementary/primary school'), (u'none', u'No formal education'), (u'other', u'Other education')]),
|
||||
field=models.CharField(blank=True, max_length=6, null=True, db_index=True, choices=[('p', 'Doctorate'), ('m', "Master's or professional degree"), ('b', "Bachelor's degree"), ('a', 'Associate degree'), ('hs', 'Secondary/high school'), ('jhs', 'Junior secondary/junior high/middle school'), ('el', 'Elementary/primary school'), ('none', 'No formal education'), ('other', 'Other education')]),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
from opaque_keys.edx.django.models import CourseKeyField
|
||||
@@ -71,6 +68,6 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='courseenrollment',
|
||||
unique_together=set([('user', 'course')]),
|
||||
unique_together={('user', 'course')},
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.14 on 2018-07-27 01:44
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.16 on 2018-12-10 12:15
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.16 on 2018-12-19 14:30
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.16 on 2018-12-21 10:40
|
||||
|
||||
|
||||
@@ -22,7 +21,7 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('new_secondary_email', models.CharField(blank=True, db_index=True, max_length=255)),
|
||||
('activation_key', models.CharField(db_index=True, max_length=32, unique=True, verbose_name=u'activation key')),
|
||||
('activation_key', models.CharField(db_index=True, max_length=32, unique=True, verbose_name='activation key')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
bases=(openedx.core.djangolib.model_mixins.DeletableByUserValue, models.Model),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-02-27 20:19
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-04-25 20:18
|
||||
|
||||
|
||||
@@ -25,7 +24,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.IntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('created', models.DateTimeField(blank=True, db_index=True, editable=False, null=True)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('mode', models.CharField(default=u'audit', max_length=100)),
|
||||
('mode', models.CharField(default='audit', max_length=100)),
|
||||
('history_id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('history_date', models.DateTimeField()),
|
||||
('history_change_reason', models.CharField(max_length=100, null=True)),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-06-24 19:01
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.24 on 2019-09-19 19:51
|
||||
|
||||
|
||||
from django.conf import settings
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
@@ -22,7 +21,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
|
||||
('csv_file', models.FileField(help_text='It expect that the data will be provided in a csv file format with first row being the header and columns will be as follows: user_id, username, email, course_id, is_verified, verification_date', upload_to=u'', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=[u'csv'])])),
|
||||
('csv_file', models.FileField(help_text='It expect that the data will be provided in a csv file format with first row being the header and columns will be as follows: user_id, username, email, course_id, is_verified, verification_date', upload_to='', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['csv'])])),
|
||||
('changed_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Changed by')),
|
||||
],
|
||||
options={
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.25 on 2019-11-01 15:56
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.25 on 2019-11-01 18:46
|
||||
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment, FBEEnrollmentExclusion
|
||||
from lms.djangoapps.experiments.models import ExperimentData
|
||||
from openedx.features.course_duration_limits.config import EXPERIMENT_DATA_HOLDBACK_KEY, EXPERIMENT_ID
|
||||
from common.djangoapps.student.models import CourseEnrollment, FBEEnrollmentExclusion
|
||||
|
||||
|
||||
def populate_fbeenrollmentexclusion(apps, schema_editor):
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.26 on 2019-11-14 14:12
|
||||
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.22 on 2019-07-19 13:06
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.27 on 2019-12-27 20:44
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.27 on 2020-01-27 19:02
|
||||
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from common.djangoapps.student.models import CourseAccessRole
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.28 on 2020-02-18 18:36
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-03-17 11:22
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-03-25 14:28
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Generated by Django 2.2.12 on 2020-06-08 15:12
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Generated by Django 2.2.14 on 2020-07-16 10:33
|
||||
|
||||
from django.conf import settings
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Generated by Django 2.2.16 on 2020-10-15 10:19
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#
|
||||
# This migration does not produce any changes at the database level.
|
||||
|
||||
from django.db import migrations
|
||||
import opaque_keys.edx.django.models
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Generated by Django 2.2.18 on 2021-02-18 22:49
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import model_utils.fields
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
@@ -76,7 +76,7 @@ from lms.djangoapps.courseware.models import (
|
||||
OrgDynamicUpgradeDeadlineConfiguration,
|
||||
)
|
||||
from lms.djangoapps.courseware.toggles import (
|
||||
courseware_mfe_streak_celebration_is_active,
|
||||
streak_celebration_is_active,
|
||||
COURSEWARE_PROCTORING_IMPROVEMENTS,
|
||||
)
|
||||
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
|
||||
@@ -2555,9 +2555,10 @@ def log_successful_logout(sender, request, user, **kwargs): # lint-amnesty, pyl
|
||||
"""Handler to log when logouts have occurred successfully."""
|
||||
if hasattr(request, 'user'):
|
||||
if settings.FEATURES['SQUELCH_PII_IN_LOGS']:
|
||||
AUDIT_LOG.info(u"Logout - user.id: {0}".format(request.user.id)) # pylint: disable=logging-format-interpolation
|
||||
AUDIT_LOG.info('Logout - user.id: {0}'.format(request.user.id)) # pylint: disable=logging-format-interpolation
|
||||
else:
|
||||
AUDIT_LOG.info(u"Logout - {0}".format(request.user)) # pylint: disable=logging-format-interpolation
|
||||
AUDIT_LOG.info('Logout - {0}'.format(request.user)) # pylint: disable=logging-format-interpolation
|
||||
segment.track(request.user.id, 'edx.bi.user.account.logout')
|
||||
|
||||
|
||||
@receiver(user_logged_in)
|
||||
@@ -3210,9 +3211,8 @@ class UserCelebration(TimeStampedModel):
|
||||
def _get_celebration(cls, user, course_key):
|
||||
""" Retrieve (or create) the celebration for the provided user and course_key """
|
||||
try:
|
||||
# The UI for celebrations is only supported on the MFE right now, so don't turn on
|
||||
# celebrations unless this enrollment's course is MFE-enabled and has milestones enabled.
|
||||
if not courseware_mfe_streak_celebration_is_active(course_key):
|
||||
# Only enable the streak if milestones and the streak are enabled for this course
|
||||
if not streak_celebration_is_active(course_key):
|
||||
return None
|
||||
return user.celebration
|
||||
except (cls.DoesNotExist, User.celebration.RelatedObjectDoesNotExist): # pylint: disable=no-member
|
||||
|
||||
@@ -35,7 +35,8 @@ def create_manual_enrollment_audit( # lint-amnesty, pylint: disable=missing-fun
|
||||
user_email,
|
||||
state_transition,
|
||||
reason,
|
||||
course_enrollment
|
||||
course_enrollment,
|
||||
role
|
||||
):
|
||||
_ManualEnrollmentAudit.create_manual_enrollment_audit(
|
||||
user=enrolled_by,
|
||||
@@ -43,6 +44,7 @@ def create_manual_enrollment_audit( # lint-amnesty, pylint: disable=missing-fun
|
||||
state_transition=state_transition,
|
||||
reason=reason,
|
||||
enrollment=course_enrollment,
|
||||
role=role,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import datetime
|
||||
import ddt
|
||||
import pytest
|
||||
import six
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=unused-import
|
||||
from django.contrib.admin.sites import AdminSite
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.forms import ValidationError
|
||||
|
||||
@@ -13,7 +13,7 @@ from django.test.client import Client
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from common.djangoapps.student.models import CourseEnrollment, DashboardConfiguration # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.student.models import CourseEnrollment # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.student.roles import GlobalStaff
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.student.views import get_course_enrollments
|
||||
|
||||
@@ -27,7 +27,6 @@ from lms.djangoapps.courseware.toggles import (
|
||||
)
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.schedules.models import Schedule
|
||||
from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory
|
||||
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from common.djangoapps.student.models import (
|
||||
@@ -139,8 +138,6 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
|
||||
self.assertListEqual([self.user, self.user_2], all_enrolled_users)
|
||||
|
||||
@skip_unless_lms
|
||||
# NOTE: We mute the post_save signal to prevent Schedules from being created for new enrollments
|
||||
@factory.django.mute_signals(signals.post_save)
|
||||
def test_upgrade_deadline(self):
|
||||
""" The property should use either the CourseMode or related Schedule to determine the deadline. """
|
||||
course = CourseFactory(self_paced=True)
|
||||
@@ -151,12 +148,10 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
|
||||
expiration_datetime=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
|
||||
)
|
||||
enrollment = CourseEnrollmentFactory(course_id=course.id, mode=CourseMode.AUDIT)
|
||||
assert Schedule.objects.all().count() == 0
|
||||
Schedule.objects.all().delete()
|
||||
assert enrollment.upgrade_deadline == course_mode.expiration_datetime
|
||||
|
||||
@skip_unless_lms
|
||||
# NOTE: We mute the post_save signal to prevent Schedules from being created for new enrollments
|
||||
@factory.django.mute_signals(signals.post_save)
|
||||
def test_upgrade_deadline_with_schedule(self):
|
||||
""" The property should use either the CourseMode or related Schedule to determine the deadline. """
|
||||
course = CourseFactory(self_paced=True)
|
||||
@@ -167,16 +162,17 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
|
||||
expiration_datetime=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=30),
|
||||
)
|
||||
course_overview = CourseOverview.load_from_module_store(course.id)
|
||||
enrollment = CourseEnrollmentFactory(
|
||||
CourseEnrollmentFactory(
|
||||
course_id=course.id,
|
||||
mode=CourseMode.AUDIT,
|
||||
course=course_overview,
|
||||
)
|
||||
Schedule.objects.update(upgrade_deadline=datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=5))
|
||||
enrollment = CourseEnrollment.objects.first()
|
||||
|
||||
# The schedule's upgrade deadline should be used if a schedule exists
|
||||
DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True)
|
||||
schedule = ScheduleFactory(enrollment=enrollment)
|
||||
assert enrollment.upgrade_deadline == schedule.upgrade_deadline
|
||||
assert enrollment.upgrade_deadline == enrollment.schedule.upgrade_deadline
|
||||
|
||||
@skip_unless_lms
|
||||
@ddt.data(*(set(CourseMode.ALL_MODES) - set(CourseMode.AUDIT_MODES)))
|
||||
@@ -197,7 +193,6 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
|
||||
)
|
||||
enrollment = CourseEnrollmentFactory(course_id=course.id, mode=CourseMode.AUDIT)
|
||||
DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True)
|
||||
ScheduleFactory(enrollment=enrollment)
|
||||
assert enrollment.schedule is not None
|
||||
assert enrollment.upgrade_deadline == course_upgrade_deadline
|
||||
|
||||
@@ -215,13 +210,10 @@ class CourseEnrollmentTests(SharedModuleStoreTestCase): # lint-amnesty, pylint:
|
||||
)
|
||||
enrollment = CourseEnrollmentFactory(course_id=course.id, mode=CourseMode.AUDIT)
|
||||
DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True)
|
||||
ScheduleFactory(enrollment=enrollment)
|
||||
assert enrollment.schedule is not None
|
||||
assert enrollment.upgrade_deadline is None
|
||||
|
||||
@skip_unless_lms
|
||||
# NOTE: We mute the post_save signal to prevent Schedules from being created for new enrollments
|
||||
@factory.django.mute_signals(signals.post_save)
|
||||
def test_enrollments_not_deleted(self):
|
||||
""" Recreating a CourseOverview with an outdated version should not delete the associated enrollment. """
|
||||
course = CourseFactory(self_paced=True)
|
||||
|
||||
@@ -5,15 +5,10 @@ This test file will verify proper password policy enforcement, which is an optio
|
||||
|
||||
|
||||
import json
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser # lint-amnesty, pylint: disable=unused-import
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from mock import patch # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.util.password_policy_validators import create_validator_config
|
||||
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ from pytz import UTC
|
||||
from six.moves import range, zip
|
||||
|
||||
from common.test.utils import XssTestMixin
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory # lint-amnesty, pylint: disable=unused-import
|
||||
from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.student.models import CourseEnrollment, DashboardConfiguration
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from common.djangoapps.student.views import get_course_enrollments
|
||||
|
||||
@@ -7,7 +7,7 @@ import itertools
|
||||
import json
|
||||
import re
|
||||
import unittest
|
||||
from datetime import datetime, timedelta # lint-amnesty, pylint: disable=unused-import
|
||||
from datetime import timedelta # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
import ddt
|
||||
import six
|
||||
@@ -17,7 +17,6 @@ from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
from mock import patch
|
||||
from opaque_keys import InvalidKeyError
|
||||
@@ -31,8 +30,6 @@ from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFact
|
||||
from openedx.core.djangoapps.catalog.tests.factories import ProgramFactory
|
||||
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_WAFFLE_FLAG
|
||||
from openedx.core.djangoapps.schedules.tests.factories import ScheduleFactory
|
||||
from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context
|
||||
from openedx.features.course_duration_limits.models import CourseDurationLimitConfig
|
||||
from openedx.features.course_experience.tests.views.helpers import add_course_mode
|
||||
@@ -755,7 +752,6 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin,
|
||||
assert resume_button_html in dashboard_html
|
||||
assert view_button_html not in dashboard_html
|
||||
|
||||
@override_waffle_flag(COURSE_UPDATE_WAFFLE_FLAG, True)
|
||||
def test_content_gating_course_card_changes(self):
|
||||
"""
|
||||
When a course is expired, the links on the course card should be removed.
|
||||
@@ -775,9 +771,6 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin,
|
||||
enrollment.created = self.THREE_YEARS_AGO + timedelta(days=1)
|
||||
enrollment.save()
|
||||
|
||||
# pylint: disable=unused-variable
|
||||
schedule = ScheduleFactory(enrollment=enrollment)
|
||||
|
||||
response = self.client.get(reverse('dashboard'))
|
||||
dashboard_html = self._remove_whitespace_from_response(response)
|
||||
access_expired_substring = 'Accessexpired'
|
||||
|
||||
@@ -418,7 +418,7 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
|
||||
|
||||
Note to future developers:
|
||||
If you break this test so that the "check_mongo_calls(0)" fails,
|
||||
please do NOT change it to "check_mongo_calls(n>1)". Instead, change
|
||||
please do NOT change it to "check_mongo_calls(n>=1)". Instead, change
|
||||
your code to not load courses from the module store. This may
|
||||
involve adding fields to CourseOverview so that loading a full
|
||||
CourseDescriptor isn't necessary.
|
||||
|
||||
@@ -29,7 +29,7 @@ from edx_ace import ace
|
||||
from edx_ace.recipient import Recipient
|
||||
from edx_django_utils import monitoring as monitoring_utils
|
||||
from eventtracking import tracker
|
||||
from ipware.ip import get_ip
|
||||
from ipware.ip import get_client_ip
|
||||
# Note that this lives in LMS, so this dependency should be refactored.
|
||||
from opaque_keys import InvalidKeyError
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
@@ -58,7 +58,7 @@ from common.djangoapps.student.message_types import AccountActivation, EmailChan
|
||||
from common.djangoapps.student.models import ( # lint-amnesty, pylint: disable=unused-import
|
||||
AccountRecovery,
|
||||
CourseEnrollment,
|
||||
PendingEmailChange,
|
||||
PendingEmailChange, # unimport:skip
|
||||
PendingSecondaryEmailChange,
|
||||
Registration,
|
||||
RegistrationCookieConfiguration,
|
||||
@@ -94,6 +94,7 @@ REGISTRATION_UTM_PARAMETERS = {
|
||||
'utm_content': 'registration_utm_content',
|
||||
}
|
||||
REGISTRATION_UTM_CREATED_AT = 'registration_utm_created_at'
|
||||
USER_ACCOUNT_ACTIVATED = 'edx.user.account.activated'
|
||||
|
||||
|
||||
def csrf_token(context):
|
||||
@@ -340,7 +341,7 @@ def change_enrollment(request, check_access=True):
|
||||
# or if the user is enrolling in a country in which the course
|
||||
# is not available.
|
||||
redirect_url = embargo_api.redirect_if_blocked(
|
||||
course_id, user=user, ip_address=get_ip(request),
|
||||
course_id, user=user, ip_address=get_client_ip(request)[0],
|
||||
url=request.path
|
||||
)
|
||||
if redirect_url:
|
||||
@@ -529,6 +530,13 @@ def activate_account(request, key):
|
||||
# Success message for logged in users.
|
||||
message = _('{html_start}Success{html_end} You have activated your account.')
|
||||
|
||||
tracker.emit(
|
||||
USER_ACCOUNT_ACTIVATED,
|
||||
{
|
||||
"user_id": registration.user.id,
|
||||
}
|
||||
)
|
||||
|
||||
if not request.user.is_authenticated:
|
||||
# Success message for logged out users
|
||||
message = _(
|
||||
|
||||
@@ -10,7 +10,6 @@ from django.conf import settings
|
||||
from django.test import RequestFactory, TestCase
|
||||
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
|
||||
from edx_rest_framework_extensions.auth.jwt.tests.utils import generate_jwt
|
||||
from mock import patch # lint-amnesty, pylint: disable=unused-import
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
@@ -6,12 +6,10 @@ Decorators that can be used to interact with third_party_auth.
|
||||
from functools import wraps
|
||||
|
||||
from django.conf import settings
|
||||
from django.shortcuts import redirect # lint-amnesty, pylint: disable=unused-import
|
||||
from django.utils.decorators import available_attrs
|
||||
from six.moves.urllib.parse import urlencode, urlparse # lint-amnesty, pylint: disable=unused-import
|
||||
from six.moves.urllib.parse import urlparse # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from common.djangoapps.third_party_auth.models import LTIProviderConfig
|
||||
from common.djangoapps.third_party_auth.provider import Registry # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
|
||||
def xframe_allow_whitelisted(view_func):
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""
|
||||
Tests for SAMLConfiguration endpoints
|
||||
"""
|
||||
|
||||
import unittest # lint-amnesty, pylint: disable=unused-import
|
||||
from django.urls import reverse
|
||||
from django.contrib.sites.models import Site
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
@@ -10,7 +8,6 @@ from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imp
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
from common.djangoapps.third_party_auth.models import SAMLConfiguration
|
||||
from common.djangoapps.third_party_auth.tests import testutil # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.third_party_auth.tests.utils import skip_unless_thirdpartyauth
|
||||
SAML_CONFIGURATIONS = [
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""
|
||||
Tests for SAMLProviderConfig endpoints
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import copy
|
||||
from uuid import uuid4
|
||||
from django.urls import reverse
|
||||
@@ -16,7 +14,6 @@ from enterprise.models import EnterpriseCustomerIdentityProvider, EnterpriseCust
|
||||
from enterprise.constants import ENTERPRISE_ADMIN_ROLE, ENTERPRISE_LEARNER_ROLE
|
||||
from common.djangoapps.third_party_auth.tests.samlutils import set_jwt_cookie
|
||||
from common.djangoapps.third_party_auth.models import SAMLProviderConfig, SAMLConfiguration
|
||||
from common.djangoapps.third_party_auth.tests import testutil
|
||||
from common.djangoapps.third_party_auth.tests.utils import skip_unless_thirdpartyauth
|
||||
from common.djangoapps.third_party_auth.utils import convert_saml_slug_provider_id
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import unittest
|
||||
import copy
|
||||
import pytz
|
||||
from uuid import uuid4
|
||||
@@ -12,8 +11,6 @@ from rest_framework.test import APITestCase
|
||||
|
||||
from enterprise.models import EnterpriseCustomer, EnterpriseCustomerIdentityProvider
|
||||
from enterprise.constants import ENTERPRISE_ADMIN_ROLE, ENTERPRISE_LEARNER_ROLE
|
||||
|
||||
from common.djangoapps.third_party_auth.tests import testutil
|
||||
from common.djangoapps.third_party_auth.models import SAMLProviderData, SAMLProviderConfig
|
||||
from common.djangoapps.third_party_auth.tests.samlutils import set_jwt_cookie
|
||||
from common.djangoapps.third_party_auth.tests.utils import skip_unless_thirdpartyauth
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"""
|
||||
Use the 'Dummy' auth provider for generic integration tests of third_party_auth.
|
||||
"""
|
||||
|
||||
|
||||
import unittest # lint-amnesty, pylint: disable=unused-import
|
||||
from common.djangoapps.third_party_auth.tests import testutil
|
||||
from common.djangoapps.third_party_auth.tests.utils import skip_unless_thirdpartyauth
|
||||
from .base import IntegrationTestMixin
|
||||
|
||||
@@ -7,7 +7,6 @@ import datetime
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import unittest # lint-amnesty, pylint: disable=unused-import
|
||||
from unittest import skip
|
||||
|
||||
import ddt
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
Tests third_party_auth admin views
|
||||
"""
|
||||
|
||||
|
||||
import unittest # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from django.contrib.admin.sites import AdminSite
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.forms import models
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
Tests for third_party_auth decorators.
|
||||
"""
|
||||
|
||||
|
||||
import unittest # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
import ddt
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=unused-import
|
||||
from django.http import HttpResponse
|
||||
from django.test import RequestFactory
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ Unit tests for the IdentityServer3 OAuth2 Backend
|
||||
"""
|
||||
import json
|
||||
import ddt
|
||||
import pytest # pylint: disable=unused-import
|
||||
|
||||
from common.djangoapps.third_party_auth.identityserver3 import IdentityServer3
|
||||
from common.djangoapps.third_party_auth.tests import testutil
|
||||
from common.djangoapps.third_party_auth.tests.utils import skip_unless_thirdpartyauth
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
|
||||
import json
|
||||
import unittest # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
"""Unit tests for settings.py."""
|
||||
|
||||
|
||||
import unittest # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from mock import patch
|
||||
from common.djangoapps.third_party_auth import provider, settings
|
||||
from common.djangoapps.third_party_auth.tests import testutil
|
||||
|
||||
@@ -36,7 +36,7 @@ class ThirdPartyOAuthTestMixin(ThirdPartyAuthTestMixin):
|
||||
def setUp(self): # lint-amnesty, pylint: disable=arguments-differ
|
||||
super(ThirdPartyOAuthTestMixin, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
|
||||
if self.CREATE_USER:
|
||||
self.user = UserFactory()
|
||||
self.user = UserFactory.create(password='secret')
|
||||
UserSocialAuth.objects.create(user=self.user, provider=self.BACKEND, uid=self.social_uid)
|
||||
self.oauth_client = self._create_client()
|
||||
if self.BACKEND == 'google-oauth2':
|
||||
|
||||
@@ -16,7 +16,7 @@ import six
|
||||
from django.conf import settings
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from eventtracking import tracker
|
||||
from ipware.ip import get_ip
|
||||
from ipware.ip import get_client_ip
|
||||
|
||||
from common.djangoapps.track import contexts, views
|
||||
|
||||
@@ -229,7 +229,7 @@ class TrackMiddleware(MiddlewareMixin):
|
||||
|
||||
def get_request_ip_address(self, request):
|
||||
"""Gets the IP address of the request"""
|
||||
ip_address = get_ip(request)
|
||||
ip_address = get_client_ip(request)[0]
|
||||
if ip_address is not None:
|
||||
return ip_address
|
||||
else:
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"""
|
||||
URLs for track app
|
||||
"""
|
||||
|
||||
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=unused-import
|
||||
from django.conf.urls import url
|
||||
|
||||
from . import views
|
||||
|
||||
@@ -6,7 +6,7 @@ import six
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.http import HttpResponse
|
||||
from eventtracking import tracker as eventtracker
|
||||
from ipware.ip import get_ip
|
||||
from ipware.ip import get_client_ip
|
||||
|
||||
from common.djangoapps.track import contexts, shim, tracker
|
||||
|
||||
@@ -22,7 +22,7 @@ def _get_request_header(request, header_name, default=''):
|
||||
def _get_request_ip(request, default=''):
|
||||
"""Helper method to get IP from a request's META dict, if present."""
|
||||
if request is not None and hasattr(request, 'META'):
|
||||
return get_ip(request)
|
||||
return get_client_ip(request)[0]
|
||||
else:
|
||||
return default
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ not migrating so as not to inconvenience users by logging them all out.
|
||||
from functools import wraps
|
||||
|
||||
import six
|
||||
from django.conf import settings # lint-amnesty, pylint: disable=unused-import
|
||||
from django.core import cache
|
||||
# If we can't find a 'general' CACHE defined in settings.py, we simply fall back
|
||||
# to returning the default cache. This will happen with dev machines.
|
||||
|
||||
@@ -8,9 +8,8 @@ import random
|
||||
# TransactionManagementError used below actually *does* derive from the standard "Exception" class.
|
||||
# lint-amnesty, pylint: disable=bad-option-value, nonstandard-exception
|
||||
from contextlib import contextmanager
|
||||
from functools import wraps # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from django.db import DEFAULT_DB_ALIAS, DatabaseError, Error, transaction # lint-amnesty, pylint: disable=unused-import
|
||||
from django.db import DEFAULT_DB_ALIAS, transaction # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from openedx.core.lib.cache_utils import get_cache
|
||||
|
||||
|
||||
@@ -5,10 +5,7 @@ so that we can cache any keys, not just ones that memcache would ordinarily acce
|
||||
|
||||
|
||||
import hashlib
|
||||
|
||||
import six.moves.urllib.error
|
||||
import six.moves.urllib.parse
|
||||
import six.moves.urllib.request
|
||||
from django.utils.encoding import smart_str
|
||||
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@ import unittest
|
||||
import ddt
|
||||
import mock
|
||||
from lxml import etree
|
||||
|
||||
# Changes formatting of empty elements; import here to avoid test order dependence
|
||||
import xmodule.modulestore.xml # pylint: disable=unused-import
|
||||
from capa.tests.helpers import new_loncapa_problem, test_capa_system
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
|
||||
|
||||
@@ -6,9 +6,6 @@ i.e. those with the <multiplechoiceresponse> element
|
||||
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
# Changes formatting of empty elements; import here to avoid test order dependence
|
||||
import xmodule.modulestore.xml # pylint: disable=unused-import
|
||||
from capa.tests.helpers import load_fixture, new_loncapa_problem, test_capa_system
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ import pytest
|
||||
|
||||
from safe_lxml import defuse_xml_libs
|
||||
|
||||
from openedx.core.pytest_hooks import pytest_configure # pylint: disable=unused-import
|
||||
|
||||
defuse_xml_libs()
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import unicodedata
|
||||
#import subprocess
|
||||
from copy import deepcopy
|
||||
from functools import reduce
|
||||
from xml.sax.saxutils import unescape # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
import six
|
||||
import sympy
|
||||
|
||||
@@ -6,7 +6,6 @@ Common code shared by course and library fixtures.
|
||||
import json
|
||||
|
||||
import requests
|
||||
import six # lint-amnesty, pylint: disable=unused-import
|
||||
from lazy import lazy
|
||||
|
||||
from common.test.acceptance.fixtures import STUDIO_BASE_URL
|
||||
|
||||
@@ -7,7 +7,7 @@ import logging
|
||||
|
||||
from bok_choy.javascript import js_defined, wait_for_js
|
||||
from bok_choy.page_object import PageObject
|
||||
from bok_choy.promise import EmptyPromise, Promise # lint-amnesty, pylint: disable=unused-import
|
||||
from bok_choy.promise import EmptyPromise # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
log = logging.getLogger('VideoPage')
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ Course Outline page in Studio.
|
||||
"""
|
||||
|
||||
|
||||
from bok_choy.javascript import js_defined, wait_for_js # lint-amnesty, pylint: disable=unused-import
|
||||
from bok_choy.javascript import js_defined # lint-amnesty, pylint: disable=unused-import
|
||||
from bok_choy.page_object import PageObject
|
||||
from bok_choy.promise import EmptyPromise
|
||||
from selenium.webdriver.support.ui import Select
|
||||
|
||||
@@ -7,17 +7,19 @@ from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc # lint-amnesty, pylint: disable=unused-import
|
||||
from common.test.acceptance.fixtures.course import CourseFixture # lint-amnesty, pylint: disable=unused-import
|
||||
from common.test.acceptance.fixtures.discussion import (
|
||||
Comment,
|
||||
Response,
|
||||
SingleThreadViewFixture,
|
||||
Thread,
|
||||
|
||||
)
|
||||
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
|
||||
from common.test.acceptance.pages.lms.discussion import (
|
||||
DiscussionTabHomePage,
|
||||
DiscussionTabSingleThreadPage,
|
||||
|
||||
)
|
||||
from common.test.acceptance.tests.discussion.helpers import BaseDiscussionMixin, BaseDiscussionTestCase
|
||||
from common.test.acceptance.tests.helpers import UniqueCourseTest
|
||||
|
||||
@@ -19,12 +19,12 @@ from bok_choy.promise import EmptyPromise, Promise
|
||||
from bok_choy.web_app_test import WebAppTest
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from path import Path as path
|
||||
from pymongo import ASCENDING, MongoClient # lint-amnesty, pylint: disable=unused-import
|
||||
from pymongo import MongoClient # lint-amnesty, pylint: disable=unused-import
|
||||
from selenium.common.exceptions import StaleElementReferenceException
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
from selenium.webdriver.support.select import Select
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from six.moves import range, zip # lint-amnesty, pylint: disable=unused-import
|
||||
from six.moves import range # lint-amnesty, pylint: disable=unused-import
|
||||
|
||||
from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
|
||||
from common.test.acceptance.fixtures.course import XBlockFixtureDesc
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
"""Code run by pylint before running any tests."""
|
||||
|
||||
# Patch the xml libs before anything else.
|
||||
|
||||
|
||||
from openedx.core.pytest_hooks import pytest_configure # pylint: disable=unused-import
|
||||
from safe_lxml import defuse_xml_libs
|
||||
|
||||
defuse_xml_libs()
|
||||
|
||||
@@ -1 +1 @@
|
||||
521f88f382acecc86fb7c9b5128d858a14313b07
|
||||
c4a7790413ee6ca1e3eabb9de0024a0b5c2a3ac7
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -967,7 +967,7 @@ CREATE TABLE `canvas_canvasenterprisecustomerconfiguration` (
|
||||
`catalogs_to_transmit` longtext,
|
||||
`client_id` varchar(255) DEFAULT NULL,
|
||||
`client_secret` varchar(255) DEFAULT NULL,
|
||||
`canvas_account_id` int(11) DEFAULT NULL,
|
||||
`canvas_account_id` bigint(20) DEFAULT NULL,
|
||||
`canvas_base_url` varchar(255) DEFAULT NULL,
|
||||
`enterprise_customer_id` char(32) NOT NULL,
|
||||
`refresh_token` varchar(255) NOT NULL,
|
||||
@@ -1028,7 +1028,7 @@ CREATE TABLE `canvas_historicalcanvasenterprisecustomerconfiguration` (
|
||||
`catalogs_to_transmit` longtext,
|
||||
`client_id` varchar(255) DEFAULT NULL,
|
||||
`client_secret` varchar(255) DEFAULT NULL,
|
||||
`canvas_account_id` int(11) DEFAULT NULL,
|
||||
`canvas_account_id` bigint(20) DEFAULT NULL,
|
||||
`canvas_base_url` varchar(255) DEFAULT NULL,
|
||||
`history_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`history_date` datetime(6) NOT NULL,
|
||||
@@ -2084,6 +2084,7 @@ CREATE TABLE `course_overviews_courseoverview` (
|
||||
`end_date` datetime(6) DEFAULT NULL,
|
||||
`start_date` datetime(6) DEFAULT NULL,
|
||||
`banner_image_url` longtext NOT NULL,
|
||||
`has_highlights` tinyint(1) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -2190,6 +2191,7 @@ CREATE TABLE `course_overviews_historicalcourseoverview` (
|
||||
`end_date` datetime(6) DEFAULT NULL,
|
||||
`start_date` datetime(6) DEFAULT NULL,
|
||||
`banner_image_url` longtext NOT NULL,
|
||||
`has_highlights` tinyint(1) DEFAULT NULL,
|
||||
PRIMARY KEY (`history_id`),
|
||||
KEY `course_overviews_his_history_user_id_e21063d9_fk_auth_user` (`history_user_id`),
|
||||
KEY `course_overviews_historicalcourseoverview_id_647043f0` (`id`),
|
||||
@@ -2994,7 +2996,7 @@ CREATE TABLE `django_migrations` (
|
||||
`name` varchar(255) NOT NULL,
|
||||
`applied` datetime(6) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=836 DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=839 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `django_openid_auth_association`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
|
||||
@@ -36,7 +36,7 @@ CREATE TABLE `django_migrations` (
|
||||
`name` varchar(255) NOT NULL,
|
||||
`applied` datetime(6) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=836 DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=839 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ General testing utilities.
|
||||
import functools
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
|
||||
import pytest # lint-amnesty, pylint: disable=unused-import
|
||||
from django.dispatch import Signal
|
||||
from markupsafe import escape
|
||||
from mock import Mock, patch
|
||||
|
||||
Reference in New Issue
Block a user