From 17cb93dd51cc8b33ca4fa1c5a954293e39cd967a Mon Sep 17 00:00:00 2001 From: bmedx Date: Fri, 12 Apr 2019 11:54:48 -0400 Subject: [PATCH] Re-adding django-simple-history for CourseEnrollment --- cms/envs/common.py | 3 ++ .../0021_historicalcourseenrollment.py | 44 +++++++++++++++++++ common/djangoapps/student/models.py | 9 ++++ .../django_comment_client/tests/test_utils.py | 22 +--------- lms/envs/common.py | 3 ++ 5 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 common/djangoapps/student/migrations/0021_historicalcourseenrollment.py diff --git a/cms/envs/common.py b/cms/envs/common.py index 3c3e6bb67e..3f1ac280e2 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -545,6 +545,9 @@ MIDDLEWARE_CLASSES = [ 'edx_rest_framework_extensions.auth.jwt.middleware.EnsureJWTAuthSettingsMiddleware', + # Handles automatically storing user ids in django-simple-history tables when possible. + 'simple_history.middleware.HistoryRequestMiddleware', + # This must be last so that it runs first in the process_response chain 'openedx.core.djangoapps.site_configuration.middleware.SessionCookieDomainOverrideMiddleware', ] diff --git a/common/djangoapps/student/migrations/0021_historicalcourseenrollment.py b/common/djangoapps/student/migrations/0021_historicalcourseenrollment.py new file mode 100644 index 0000000000..5d08cc5908 --- /dev/null +++ b/common/djangoapps/student/migrations/0021_historicalcourseenrollment.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-04-25 20:18 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import simple_history.models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('course_overviews', '0014_courseoverview_certificate_available_date'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('student', '0020_auto_20190227_2019'), + ] + + operations = [ + migrations.CreateModel( + name='HistoricalCourseEnrollment', + fields=[ + ('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=b'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)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('course', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='course_overviews.CourseOverview')), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ('-history_date', '-history_id'), + 'db_table': 'student_courseenrollment_history', + 'verbose_name': 'historical course enrollment', + 'get_latest_by': 'history_date', + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + ] diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index ba0536cb72..77da369d15 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -46,6 +46,7 @@ from model_utils.models import TimeStampedModel from opaque_keys.edx.django.models import CourseKeyField from opaque_keys.edx.keys import CourseKey from pytz import UTC +from simple_history.models import HistoricalRecords from six import text_type from slumber.exceptions import HttpClientError, HttpServerError from user_util import user_util @@ -1129,6 +1130,14 @@ class CourseEnrollment(models.Model): # list of possible values. mode = models.CharField(default=CourseMode.DEFAULT_MODE_SLUG, max_length=100) + # An audit row will be created for every change to a CourseEnrollment. This + # will create a new model behind the scenes - HistoricalCourseEnrollment and a + # table named 'student_courseenrollment_history'. + history = HistoricalRecords( + history_id_field=models.UUIDField(default=uuid.uuid4), + table_name='student_courseenrollment_history' + ) + objects = CourseEnrollmentManager() # cache key format e.g enrollment...mode = 'honor' diff --git a/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py b/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py index e6306f90e1..486fd68565 100644 --- a/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py +++ b/lms/djangoapps/discussion/django_comment_client/tests/test_utils.py @@ -1680,14 +1680,8 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase): # Create course, seed permissions roles, and create team self.course = CourseFactory.create() seed_permissions_roles(self.course.id) - verified_coursemode = CourseModeFactory.create( - course_id=self.course.id, - mode_slug=CourseMode.VERIFIED - ) - audit_coursemode = CourseModeFactory.create( - course_id=self.course.id, - mode_slug=CourseMode.AUDIT - ) + verified_coursemode = CourseMode.VERIFIED + audit_coursemode = CourseMode.AUDIT # Create four users: group_moderator (who is within the verified enrollment track and in the cohort), # verified_user (who is in the verified enrollment track but not the cohort), @@ -1781,18 +1775,6 @@ class GroupModeratorPermissionsTestCase(ModuleStoreTestCase): 'can_vote': True, 'can_report': True }) - RequestCache.clear_all_namespaces() - - set_discussion_division_settings(self.course.id, division_scheme=CourseDiscussionSettings.ENROLLMENT_TRACK) - content = {'user_id': self.verified_user.id, 'type': 'thread', 'username': self.verified_user.username} - self.assertEqual(utils.get_ability(self.course.id, content, self.group_moderator), { - 'editable': True, - 'can_reply': True, - 'can_delete': True, - 'can_openclose': True, - 'can_vote': True, - 'can_report': True - }) @mock.patch( 'lms.djangoapps.discussion.django_comment_client.permissions._check_condition', diff --git a/lms/envs/common.py b/lms/envs/common.py index 01c985b3fe..ee4397e243 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1324,6 +1324,9 @@ MIDDLEWARE_CLASSES = [ 'edx_rest_framework_extensions.auth.jwt.middleware.EnsureJWTAuthSettingsMiddleware', + # Handles automatically storing user ids in django-simple-history tables when possible. + 'simple_history.middleware.HistoryRequestMiddleware', + # This must be last 'openedx.core.djangoapps.site_configuration.middleware.SessionCookieDomainOverrideMiddleware', ]