From 57eca325d2f170a3eb1f07aaa9f6cc4ef7693afb Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 15:59:35 -0400 Subject: [PATCH 01/18] move some files from lms/djangoapps/django_comment_client to common/djangoapps/django_comment_common --- .../django_comment_common}/__init__.py | 0 .../migrations/0001_initial.py | 0 .../migrations/__init__.py | 0 .../django_comment_common}/models.py | 0 .../djangoapps/django_comment_common/utils.py | 27 +++++++++++++++++++ 5 files changed, 27 insertions(+) rename {lms/djangoapps/django_comment_client/migrations => common/djangoapps/django_comment_common}/__init__.py (100%) rename {lms/djangoapps/django_comment_client => common/djangoapps/django_comment_common}/migrations/0001_initial.py (100%) create mode 100644 common/djangoapps/django_comment_common/migrations/__init__.py rename {lms/djangoapps/django_comment_client => common/djangoapps/django_comment_common}/models.py (100%) create mode 100644 common/djangoapps/django_comment_common/utils.py diff --git a/lms/djangoapps/django_comment_client/migrations/__init__.py b/common/djangoapps/django_comment_common/__init__.py similarity index 100% rename from lms/djangoapps/django_comment_client/migrations/__init__.py rename to common/djangoapps/django_comment_common/__init__.py diff --git a/lms/djangoapps/django_comment_client/migrations/0001_initial.py b/common/djangoapps/django_comment_common/migrations/0001_initial.py similarity index 100% rename from lms/djangoapps/django_comment_client/migrations/0001_initial.py rename to common/djangoapps/django_comment_common/migrations/0001_initial.py diff --git a/common/djangoapps/django_comment_common/migrations/__init__.py b/common/djangoapps/django_comment_common/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lms/djangoapps/django_comment_client/models.py b/common/djangoapps/django_comment_common/models.py similarity index 100% rename from lms/djangoapps/django_comment_client/models.py rename to common/djangoapps/django_comment_common/models.py diff --git a/common/djangoapps/django_comment_common/utils.py b/common/djangoapps/django_comment_common/utils.py new file mode 100644 index 0000000000..9753591c5c --- /dev/null +++ b/common/djangoapps/django_comment_common/utils.py @@ -0,0 +1,27 @@ +from django_comment_common.models import Role + + +def seed_permissions_roles(course_id): + administrator_role = Role.objects.get_or_create(name="Administrator", course_id=course_id)[0] + moderator_role = Role.objects.get_or_create(name="Moderator", course_id=course_id)[0] + community_ta_role = Role.objects.get_or_create(name="Community TA", course_id=course_id)[0] + student_role = Role.objects.get_or_create(name="Student", course_id=course_id)[0] + + for per in ["vote", "update_thread", "follow_thread", "unfollow_thread", + "update_comment", "create_sub_comment", "unvote", "create_thread", + "follow_commentable", "unfollow_commentable", "create_comment", ]: + student_role.add_permission(per) + + for per in ["edit_content", "delete_thread", "openclose_thread", + "endorse_comment", "delete_comment", "see_all_cohorts"]: + moderator_role.add_permission(per) + + for per in ["manage_moderator"]: + administrator_role.add_permission(per) + + moderator_role.inherit_permissions(student_role) + + # For now, Community TA == Moderator, except for the styling. + community_ta_role.inherit_permissions(moderator_role) + + administrator_role.inherit_permissions(moderator_role) \ No newline at end of file From 30d266b43088d65594339db5d7a89aa0f009503c Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 16:01:14 -0400 Subject: [PATCH 02/18] seed forum permissions when creating new courses --- cms/djangoapps/contentstore/views.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index caf3901e03..af31fb841b 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -64,6 +64,8 @@ from contentstore.utils import get_modulestore from django.shortcuts import redirect from models.settings.course_metadata import CourseMetadata +from django_comment_common.utils import seed_permissions_roles + # to install PIL on MacOSX: 'easy_install http://dist.repoze.org/PIL-1.1.6.tar.gz' log = logging.getLogger(__name__) @@ -1503,6 +1505,9 @@ def create_new_course(request): create_all_course_groups(request.user, new_course.location) + # seed the forums + seed_permissions_roles(new_course.location.course_id) + return HttpResponse(json.dumps({'id': new_course.location.url()})) From 3858f1b7063bda75ec6a1f44800afd291ad3fd4d Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 16:02:13 -0400 Subject: [PATCH 03/18] update cms envs --- cms/envs/common.py | 3 +++ cms/envs/dev.py | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cms/envs/common.py b/cms/envs/common.py index 8effc773e0..3d4f2d2e9d 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -263,4 +263,7 @@ INSTALLED_APPS = ( 'pipeline', 'staticfiles', 'static_replace', + + # comment common + 'django_comment_common', ) diff --git a/cms/envs/dev.py b/cms/envs/dev.py index dbf9c5574c..f3f972be42 100644 --- a/cms/envs/dev.py +++ b/cms/envs/dev.py @@ -118,8 +118,7 @@ PIPELINE_SASS_ARGUMENTS = '--debug-info --require {proj_dir}/static/sass/bourbon ################################ DEBUG TOOLBAR ################################# INSTALLED_APPS += ('debug_toolbar', 'debug_toolbar_mongo') -MIDDLEWARE_CLASSES += ('django_comment_client.utils.QueryCountDebugMiddleware', - 'debug_toolbar.middleware.DebugToolbarMiddleware',) +MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',) INTERNAL_IPS = ('127.0.0.1',) DEBUG_TOOLBAR_PANELS = ( From ae9d13b53aa01b918100a5064330ee8b1a8b1fdc Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 16:04:25 -0400 Subject: [PATCH 04/18] update comment models.py to not have the dependency on get_course_by_id (which is in LMS). Also explicitly set the db_table name because django auto generates table prefixes according to the djangoapp name --- common/djangoapps/django_comment_common/models.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/common/djangoapps/django_comment_common/models.py b/common/djangoapps/django_comment_common/models.py index e06aed1281..6688470753 100644 --- a/common/djangoapps/django_comment_common/models.py +++ b/common/djangoapps/django_comment_common/models.py @@ -8,7 +8,8 @@ from django.db.models.signals import post_save from student.models import CourseEnrollment -from courseware.courses import get_course_by_id +from xmodule.modulestore.django import modulestore +from xmodule.course_module import CourseDescriptor FORUM_ROLE_ADMINISTRATOR = 'Administrator' FORUM_ROLE_MODERATOR = 'Moderator' @@ -32,6 +33,9 @@ class Role(models.Model): users = models.ManyToManyField(User, related_name="roles") course_id = models.CharField(max_length=255, blank=True, db_index=True) + class Meta: + db_table = 'django_comment_client_role' + def __unicode__(self): return self.name + " for " + (self.course_id if self.course_id else "all courses") @@ -47,7 +51,8 @@ class Role(models.Model): self.permissions.add(Permission.objects.get_or_create(name=permission)[0]) def has_permission(self, permission): - course = get_course_by_id(self.course_id) + course_loc = CourseDescriptor.id_to_location(self.course_id) + course = modulestore().get_instance(self.course_id, course_loc) if self.name == FORUM_ROLE_STUDENT and \ (permission.startswith('edit') or permission.startswith('update') or permission.startswith('create')) and \ (not course.forum_posts_allowed): @@ -60,5 +65,8 @@ class Permission(models.Model): name = models.CharField(max_length=30, null=False, blank=False, primary_key=True) roles = models.ManyToManyField(Role, related_name="permissions") + class Meta: + db_table = 'django_comment_client_permission' + def __unicode__(self): return self.name From a92910db209a46848a5626a56d72994b9d73a651 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 16:23:32 -0400 Subject: [PATCH 05/18] update lms to reflect where comment models.py is now in common --- .../django_comment_client/base/views.py | 2 +- .../management/commands/assign_role.py | 2 +- .../commands/assign_roles_for_course.py | 2 +- .../commands/create_roles_for_existing.py | 2 +- .../commands/seed_permissions_roles.py | 21 ++----------------- .../management/commands/show_permissions.py | 2 +- .../django_comment_client/permissions.py | 2 +- lms/djangoapps/django_comment_client/tests.py | 2 +- .../tests/test_models.py | 2 +- .../django_comment_client/tests/test_utils.py | 2 +- lms/djangoapps/django_comment_client/utils.py | 2 +- lms/djangoapps/instructor/views.py | 2 +- lms/envs/common.py | 1 + 13 files changed, 14 insertions(+), 30 deletions(-) diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index 69609dcf01..39c38e70f3 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -26,7 +26,7 @@ from course_groups.cohorts import get_cohort_id, is_commentable_cohorted from django_comment_client.utils import JsonResponse, JsonError, extract, get_courseware_context from django_comment_client.permissions import check_permissions_by_view, cached_has_permission -from django_comment_client.models import Role +from django_comment_common.models import Role log = logging.getLogger(__name__) diff --git a/lms/djangoapps/django_comment_client/management/commands/assign_role.py b/lms/djangoapps/django_comment_client/management/commands/assign_role.py index 655631008f..65da1ea5b4 100644 --- a/lms/djangoapps/django_comment_client/management/commands/assign_role.py +++ b/lms/djangoapps/django_comment_client/management/commands/assign_role.py @@ -1,7 +1,7 @@ from optparse import make_option from django.core.management.base import BaseCommand, CommandError -from django_comment_client.models import Role +from django_comment_common.models import Role from django.contrib.auth.models import User diff --git a/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py b/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py index 72100738d9..9ef4f3d0b1 100644 --- a/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py +++ b/lms/djangoapps/django_comment_client/management/commands/assign_roles_for_course.py @@ -7,7 +7,7 @@ Enrollments. from django.core.management.base import BaseCommand, CommandError from student.models import CourseEnrollment -from django_comment_client.models import assign_default_role +from django_comment_common.models import assign_default_role class Command(BaseCommand): diff --git a/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py b/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py index d5ba0042fc..037bb292ec 100644 --- a/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py +++ b/lms/djangoapps/django_comment_client/management/commands/create_roles_for_existing.py @@ -7,7 +7,7 @@ Enrollments. from django.core.management.base import BaseCommand, CommandError from student.models import CourseEnrollment -from django_comment_client.models import assign_default_role +from django_comment_common.models import assign_default_role class Command(BaseCommand): diff --git a/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py b/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py index 9d6eefd11d..f944146906 100644 --- a/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py +++ b/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py @@ -1,5 +1,5 @@ from django.core.management.base import BaseCommand, CommandError -from django_comment_client.models import Role +from django_comment_common.utils import seed_permissions_roles class Command(BaseCommand): @@ -18,21 +18,4 @@ class Command(BaseCommand): community_ta_role = Role.objects.get_or_create(name="Community TA", course_id=course_id)[0] student_role = Role.objects.get_or_create(name="Student", course_id=course_id)[0] - for per in ["vote", "update_thread", "follow_thread", "unfollow_thread", - "update_comment", "create_sub_comment", "unvote", "create_thread", - "follow_commentable", "unfollow_commentable", "create_comment", ]: - student_role.add_permission(per) - - for per in ["edit_content", "delete_thread", "openclose_thread", - "endorse_comment", "delete_comment", "see_all_cohorts"]: - moderator_role.add_permission(per) - - for per in ["manage_moderator"]: - administrator_role.add_permission(per) - - moderator_role.inherit_permissions(student_role) - - # For now, Community TA == Moderator, except for the styling. - community_ta_role.inherit_permissions(moderator_role) - - administrator_role.inherit_permissions(moderator_role) + seed_permissions_roles(course_id) diff --git a/lms/djangoapps/django_comment_client/management/commands/show_permissions.py b/lms/djangoapps/django_comment_client/management/commands/show_permissions.py index ec3167aa0c..67fc29ea97 100644 --- a/lms/djangoapps/django_comment_client/management/commands/show_permissions.py +++ b/lms/djangoapps/django_comment_client/management/commands/show_permissions.py @@ -1,5 +1,5 @@ from django.core.management.base import BaseCommand, CommandError -from django_comment_client.models import Permission, Role +from django_comment_common.models import Permission, Role from django.contrib.auth.models import User diff --git a/lms/djangoapps/django_comment_client/permissions.py b/lms/djangoapps/django_comment_client/permissions.py index 7d21cc9783..456d5f01d2 100644 --- a/lms/djangoapps/django_comment_client/permissions.py +++ b/lms/djangoapps/django_comment_client/permissions.py @@ -1,4 +1,4 @@ -from .models import Role, Permission +from django_comment_common.models import Role, Permission from django.db.models.signals import post_save from django.dispatch import receiver from student.models import CourseEnrollment diff --git a/lms/djangoapps/django_comment_client/tests.py b/lms/djangoapps/django_comment_client/tests.py index a35df54cd9..dcfd29f3cd 100644 --- a/lms/djangoapps/django_comment_client/tests.py +++ b/lms/djangoapps/django_comment_client/tests.py @@ -6,7 +6,7 @@ from django.test import TestCase from student.models import CourseEnrollment from django_comment_client.permissions import has_permission -from django_comment_client.models import Role +from django_comment_common.models import Role class PermissionsTestCase(TestCase): diff --git a/lms/djangoapps/django_comment_client/tests/test_models.py b/lms/djangoapps/django_comment_client/tests/test_models.py index 6f90b3c4b8..e8083fe954 100644 --- a/lms/djangoapps/django_comment_client/tests/test_models.py +++ b/lms/djangoapps/django_comment_client/tests/test_models.py @@ -1,5 +1,5 @@ import django_comment_client.models as models -import django_comment_client.permissions as permissions +import django_comment_common.permissions as permissions from django.test import TestCase diff --git a/lms/djangoapps/django_comment_client/tests/test_utils.py b/lms/djangoapps/django_comment_client/tests/test_utils.py index 80b8419d5a..3687e169e7 100644 --- a/lms/djangoapps/django_comment_client/tests/test_utils.py +++ b/lms/djangoapps/django_comment_client/tests/test_utils.py @@ -2,7 +2,7 @@ from django.test import TestCase from factory import DjangoModelFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory -from django_comment_client.models import Role, Permission +from django_comment_common.models import Role, Permission import django_comment_client.utils as utils diff --git a/lms/djangoapps/django_comment_client/utils.py b/lms/djangoapps/django_comment_client/utils.py index 9bfb9a9d0d..6e5c6794c9 100644 --- a/lms/djangoapps/django_comment_client/utils.py +++ b/lms/djangoapps/django_comment_client/utils.py @@ -13,7 +13,7 @@ from django.core.urlresolvers import reverse from django.db import connection from django.http import HttpResponse from django.utils import simplejson -from django_comment_client.models import Role +from django_comment_common.models import Role from django_comment_client.permissions import check_permissions_by_view from xmodule.modulestore.exceptions import NoPathToItem diff --git a/lms/djangoapps/instructor/views.py b/lms/djangoapps/instructor/views.py index dd6748e691..00b1b918b3 100644 --- a/lms/djangoapps/instructor/views.py +++ b/lms/djangoapps/instructor/views.py @@ -27,7 +27,7 @@ from courseware.access import (has_access, get_access_group_name, course_beta_test_group_name) from courseware.courses import get_course_with_access from courseware.models import StudentModule -from django_comment_client.models import (Role, +from django_comment_common.models import (Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA) diff --git a/lms/envs/common.py b/lms/envs/common.py index b804ae2a7a..ba4ba75bfd 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -592,5 +592,6 @@ INSTALLED_APPS = ( # Discussion forums 'django_comment_client', + 'django_comment_common', ) From c20dd7d90373227402f8b75356455c7d693ffa47 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 16:40:25 -0400 Subject: [PATCH 06/18] forgot to remove enough stuff from the django admin path --- .../management/commands/seed_permissions_roles.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py b/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py index f944146906..1073d7dbcf 100644 --- a/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py +++ b/lms/djangoapps/django_comment_client/management/commands/seed_permissions_roles.py @@ -13,9 +13,4 @@ class Command(BaseCommand): raise CommandError("Too many arguments") course_id = args[0] - administrator_role = Role.objects.get_or_create(name="Administrator", course_id=course_id)[0] - moderator_role = Role.objects.get_or_create(name="Moderator", course_id=course_id)[0] - community_ta_role = Role.objects.get_or_create(name="Community TA", course_id=course_id)[0] - student_role = Role.objects.get_or_create(name="Student", course_id=course_id)[0] - seed_permissions_roles(course_id) From 40e3410121bc3e8548d9ed9d94b1a41b7aaa96b8 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 16:51:36 -0400 Subject: [PATCH 07/18] fix broken unit tests --- lms/djangoapps/django_comment_client/tests/test_models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/django_comment_client/tests/test_models.py b/lms/djangoapps/django_comment_client/tests/test_models.py index e8083fe954..1f7e52b0a0 100644 --- a/lms/djangoapps/django_comment_client/tests/test_models.py +++ b/lms/djangoapps/django_comment_client/tests/test_models.py @@ -1,5 +1,5 @@ -import django_comment_client.models as models -import django_comment_common.permissions as permissions +import django_comment_common.models as models +import django_comment_client.permissions as permissions from django.test import TestCase From 5ba22ec89b22fd254584372aa4529095199424e2 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 6 May 2013 16:56:37 -0400 Subject: [PATCH 08/18] fix another broken test --- lms/djangoapps/instructor/tests/test_forum_admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/djangoapps/instructor/tests/test_forum_admin.py b/lms/djangoapps/instructor/tests/test_forum_admin.py index d2d58fb61c..7b4e729867 100644 --- a/lms/djangoapps/instructor/tests/test_forum_admin.py +++ b/lms/djangoapps/instructor/tests/test_forum_admin.py @@ -9,7 +9,7 @@ from django.test.utils import override_settings from django.contrib.auth.models import Group from django.core.urlresolvers import reverse -from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, \ +from django_comment_common.models import Role, FORUM_ROLE_ADMINISTRATOR, \ FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT from django_comment_client.utils import has_forum_access From 81ecf0c5df4af24b7db0985a269d2a70b30e49e7 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Tue, 7 May 2013 11:18:15 -0400 Subject: [PATCH 09/18] add unit test to verify forum seeding occurs when creating new courses --- .../contentstore/tests/test_contentstore.py | 10 +++++++ .../djangoapps/django_comment_common/utils.py | 29 ++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index 07b7032e60..b4a9210a26 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -34,6 +34,8 @@ from xmodule.course_module import CourseDescriptor from xmodule.seq_module import SequenceDescriptor from xmodule.modulestore.exceptions import ItemNotFoundError +from django_comment_common.utils import are_permissions_roles_seeded + TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') @@ -598,6 +600,14 @@ class ContentStoreTest(ModuleStoreTestCase): data = parse_json(resp) self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') + def test_create_course_check_forum_seeding(self): + """Test new course creation and verify forum seeding """ + resp = self.client.post(reverse('create_new_course'), self.course_data) + self.assertEqual(resp.status_code, 200) + data = parse_json(resp) + self.assertEqual(data['id'], 'i4x://MITx/999/course/Robot_Super_Course') + self.assertTrue(are_permissions_roles_seeded('MITx/999/Robot_Super_Course')) + def test_create_course_duplicate_course(self): """Test new course creation - error path""" resp = self.client.post(reverse('create_new_course'), self.course_data) diff --git a/common/djangoapps/django_comment_common/utils.py b/common/djangoapps/django_comment_common/utils.py index 9753591c5c..747e7e2c46 100644 --- a/common/djangoapps/django_comment_common/utils.py +++ b/common/djangoapps/django_comment_common/utils.py @@ -24,4 +24,31 @@ def seed_permissions_roles(course_id): # For now, Community TA == Moderator, except for the styling. community_ta_role.inherit_permissions(moderator_role) - administrator_role.inherit_permissions(moderator_role) \ No newline at end of file + administrator_role.inherit_permissions(moderator_role) + + +def are_permissions_roles_seeded(course_id): + + try: + administrator_role = Role.objects.get(name="Administrator", course_id=course_id) + moderator_role = Role.objects.get(name="Moderator", course_id=course_id) + student_role = Role.objects.get(name="Student", course_id=course_id) + except: + return False + + for per in ["vote", "update_thread", "follow_thread", "unfollow_thread", + "update_comment", "create_sub_comment", "unvote", "create_thread", + "follow_commentable", "unfollow_commentable", "create_comment", ]: + if not student_role.has_permission(per): + return False + + for per in ["edit_content", "delete_thread", "openclose_thread", + "endorse_comment", "delete_comment", "see_all_cohorts"]: + if not moderator_role.has_permission(per): + return False + + for per in ["manage_moderator"]: + if not administrator_role.has_permission(per): + return False + + return True \ No newline at end of file From 3c747f0e6e3bccaeab27169b9950dae30fdc166e Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Tue, 7 May 2013 11:53:02 -0400 Subject: [PATCH 10/18] consolidate the list of permissions --- .../djangoapps/django_comment_common/utils.py | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/common/djangoapps/django_comment_common/utils.py b/common/djangoapps/django_comment_common/utils.py index 747e7e2c46..f74116d59f 100644 --- a/common/djangoapps/django_comment_common/utils.py +++ b/common/djangoapps/django_comment_common/utils.py @@ -1,5 +1,13 @@ from django_comment_common.models import Role +_STUDENT_ROLE_PERMISSIONS = ["vote", "update_thread", "follow_thread", "unfollow_thread", + "update_comment", "create_sub_comment", "unvote", "create_thread", + "follow_commentable", "unfollow_commentable", "create_comment", ] + +_MODERATOR_ROLE_PERMISSIONS = ["edit_content", "delete_thread", "openclose_thread", + "endorse_comment", "delete_comment", "see_all_cohorts"] + +_ADMINISTRATOR_ROLE_PERMISSIONS = ["manage_moderator"] def seed_permissions_roles(course_id): administrator_role = Role.objects.get_or_create(name="Administrator", course_id=course_id)[0] @@ -7,16 +15,13 @@ def seed_permissions_roles(course_id): community_ta_role = Role.objects.get_or_create(name="Community TA", course_id=course_id)[0] student_role = Role.objects.get_or_create(name="Student", course_id=course_id)[0] - for per in ["vote", "update_thread", "follow_thread", "unfollow_thread", - "update_comment", "create_sub_comment", "unvote", "create_thread", - "follow_commentable", "unfollow_commentable", "create_comment", ]: + for per in _STUDENT_ROLE_PERMISSIONS: student_role.add_permission(per) - for per in ["edit_content", "delete_thread", "openclose_thread", - "endorse_comment", "delete_comment", "see_all_cohorts"]: + for per in _MODERATOR_ROLE_PERMISSIONS: moderator_role.add_permission(per) - for per in ["manage_moderator"]: + for per in _ADMINISTRATOR_ROLE_PERMISSIONS: administrator_role.add_permission(per) moderator_role.inherit_permissions(student_role) @@ -36,19 +41,16 @@ def are_permissions_roles_seeded(course_id): except: return False - for per in ["vote", "update_thread", "follow_thread", "unfollow_thread", - "update_comment", "create_sub_comment", "unvote", "create_thread", - "follow_commentable", "unfollow_commentable", "create_comment", ]: + for per in _STUDENT_ROLE_PERMISSIONS: if not student_role.has_permission(per): return False - for per in ["edit_content", "delete_thread", "openclose_thread", - "endorse_comment", "delete_comment", "see_all_cohorts"]: + for per in _MODERATOR_ROLE_PERMISSIONS + _STUDENT_ROLE_PERMISSIONS: if not moderator_role.has_permission(per): return False - for per in ["manage_moderator"]: + for per in _ADMINISTRATOR_ROLE_PERMISSIONS + _MODERATOR_ROLE_PERMISSIONS + _STUDENT_ROLE_PERMISSIONS: if not administrator_role.has_permission(per): return False - return True \ No newline at end of file + return True From 11244107fd19b0894e056998549307f28c15cf77 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Thu, 9 May 2013 16:16:11 -0400 Subject: [PATCH 11/18] add an empty models.py file to django_comment_client --- lms/djangoapps/django_comment_client/models.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lms/djangoapps/django_comment_client/models.py diff --git a/lms/djangoapps/django_comment_client/models.py b/lms/djangoapps/django_comment_client/models.py new file mode 100644 index 0000000000..e69de29bb2 From d39d44ba492cdcb645d8a8a8e49512bef159dd74 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Fri, 10 May 2013 12:58:00 -0400 Subject: [PATCH 12/18] keep migrations in djangoapp_comment_client --- .../djangoapps/django_comment_client}/migrations/0001_initial.py | 0 .../djangoapps/django_comment_client}/migrations/__init__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {common/djangoapps/django_comment_common => lms/djangoapps/django_comment_client}/migrations/0001_initial.py (100%) rename {common/djangoapps/django_comment_common => lms/djangoapps/django_comment_client}/migrations/__init__.py (100%) diff --git a/common/djangoapps/django_comment_common/migrations/0001_initial.py b/lms/djangoapps/django_comment_client/migrations/0001_initial.py similarity index 100% rename from common/djangoapps/django_comment_common/migrations/0001_initial.py rename to lms/djangoapps/django_comment_client/migrations/0001_initial.py diff --git a/common/djangoapps/django_comment_common/migrations/__init__.py b/lms/djangoapps/django_comment_client/migrations/__init__.py similarity index 100% rename from common/djangoapps/django_comment_common/migrations/__init__.py rename to lms/djangoapps/django_comment_client/migrations/__init__.py From 5619306c6b96cf46dd03529dc25d5f090346abd3 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Fri, 10 May 2013 13:43:15 -0400 Subject: [PATCH 13/18] add comment that the models.py file has been moved --- lms/djangoapps/django_comment_client/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lms/djangoapps/django_comment_client/models.py b/lms/djangoapps/django_comment_client/models.py index e69de29bb2..76d27be3bf 100644 --- a/lms/djangoapps/django_comment_client/models.py +++ b/lms/djangoapps/django_comment_client/models.py @@ -0,0 +1 @@ +# This file is intentionally blank. It has been moved to common/djangoapps/django_comment_common From 155ad08b9eb316906d6cbd30f42e34857feb17e2 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 13 May 2013 16:04:20 -0400 Subject: [PATCH 14/18] create forums permissions on course create --- cms/djangoapps/contentstore/views/course.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index ecc271926a..cf642e8256 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -10,16 +10,12 @@ from django.core.urlresolvers import reverse from mitxmako.shortcuts import render_to_response from xmodule.modulestore.django import modulestore -from xmodule.modulestore.exceptions import ItemNotFoundError, \ - InvalidLocationError +from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError from xmodule.modulestore import Location -from contentstore.course_info_model import get_course_updates, \ - update_course_updates, delete_course_update -from contentstore.utils import get_lms_link_for_item, \ - add_open_ended_panel_tab, remove_open_ended_panel_tab -from models.settings.course_details import CourseDetails, \ - CourseSettingsEncoder +from contentstore.course_info_model import get_course_updates, update_course_updates, delete_course_update +from contentstore.utils import get_lms_link_for_item, add_open_ended_panel_tab, remove_open_ended_panel_tab +from models.settings.course_details import CourseDetails, CourseSettingsEncoder from models.settings.course_grading import CourseGradingModel from models.settings.course_metadata import CourseMetadata from auth.authz import create_all_course_groups @@ -30,6 +26,8 @@ from .requests import get_request_method from .tabs import initialize_course_tabs from .component import OPEN_ENDED_COMPONENT_TYPES, ADVANCED_COMPONENT_POLICY_KEY +from django_comment_common.utils import seed_permissions_roles + # TODO: should explicitly enumerate exports with __all__ @@ -124,6 +122,9 @@ def create_new_course(request): create_all_course_groups(request.user, new_course.location) + # seed the forums + seed_permissions_roles(new_course.location.course_id) + return HttpResponse(json.dumps({'id': new_course.location.url()})) From ef78c99f70fdc25b66d77f518e7f6acefad3a2c9 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Tue, 14 May 2013 10:53:10 -0400 Subject: [PATCH 15/18] pep8/pylint violations fixes --- .../contentstore/tests/test_contentstore.py | 36 +++++++++---------- .../xmodule/xmodule/modulestore/__init__.py | 28 ++++++--------- .../lib/xmodule/xmodule/modulestore/draft.py | 3 +- .../xmodule/modulestore/tests/factories.py | 1 - 4 files changed, 31 insertions(+), 37 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index b89de3b37b..848015a2e7 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -47,7 +47,7 @@ class MongoCollectionFindWrapper(object): self.counter = 0 def find(self, query, *args, **kwargs): - self.counter = self.counter+1 + self.counter = self.counter + 1 return self.original(query, *args, **kwargs) @@ -357,7 +357,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): clone_items = module_store.get_items(Location(['i4x', 'MITx', '999', 'vertical', None])) self.assertGreater(len(clone_items), 0) for descriptor in items: - new_loc = descriptor.location._replace(org='MITx', course='999') + new_loc = descriptor.location.replace(org='MITx', course='999') print "Checking {0} should now also be at {1}".format(descriptor.location.url(), new_loc.url()) resp = self.client.get(reverse('edit_unit', kwargs={'location': new_loc.url()})) self.assertEqual(resp.status_code, 200) @@ -380,15 +380,15 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): self.assertEqual(len(items), 0) def verify_content_existence(self, modulestore, root_dir, location, dirname, category_name, filename_suffix=''): - fs = OSFS(root_dir / 'test_export') - self.assertTrue(fs.exists(dirname)) + filesystem = OSFS(root_dir / 'test_export') + self.assertTrue(filesystem.exists(dirname)) query_loc = Location('i4x', location.org, location.course, category_name, None) items = modulestore.get_items(query_loc) for item in items: - fs = OSFS(root_dir / ('test_export/' + dirname)) - self.assertTrue(fs.exists(item.location.name + filename_suffix)) + filesystem = OSFS(root_dir / ('test_export/' + dirname)) + self.assertTrue(filesystem.exists(item.location.name + filename_suffix)) def test_export_course(self): module_store = modulestore('direct') @@ -420,7 +420,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): # add private to list of children sequential = module_store.get_item(Location(['i4x', 'edX', 'full', 'sequential', 'Administrivia_and_Circuit_Elements', None])) - private_location_no_draft = private_vertical.location._replace(revision=None) + private_location_no_draft = private_vertical.location.replace(revision=None) module_store.update_children(sequential.location, sequential.children + [private_location_no_draft.url()]) @@ -445,20 +445,20 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): self.verify_content_existence(module_store, root_dir, location, 'custom_tags', 'custom_tag_template') # check for graiding_policy.json - fs = OSFS(root_dir / 'test_export/policies/6.002_Spring_2012') - self.assertTrue(fs.exists('grading_policy.json')) + filesystem = OSFS(root_dir / 'test_export/policies/6.002_Spring_2012') + self.assertTrue(filesystem.exists('grading_policy.json')) course = module_store.get_item(location) # compare what's on disk compared to what we have in our course - with fs.open('grading_policy.json', 'r') as grading_policy: + with filesystem.open('grading_policy.json', 'r') as grading_policy: on_disk = loads(grading_policy.read()) self.assertEqual(on_disk, course.grading_policy) #check for policy.json - self.assertTrue(fs.exists('policy.json')) + self.assertTrue(filesystem.exists('policy.json')) # compare what's on disk to what we have in the course module - with fs.open('policy.json', 'r') as course_policy: + with filesystem.open('policy.json', 'r') as course_policy: on_disk = loads(course_policy.read()) self.assertIn('course/6.002_Spring_2012', on_disk) self.assertEqual(on_disk['course/6.002_Spring_2012'], own_metadata(course)) @@ -813,37 +813,37 @@ class ContentStoreTest(ModuleStoreTestCase): self.assertEqual(200, resp.status_code) # go look at a subsection page - subsection_location = loc._replace(category='sequential', name='test_sequence') + subsection_location = loc.replace(category='sequential', name='test_sequence') resp = self.client.get(reverse('edit_subsection', kwargs={'location': subsection_location.url()})) self.assertEqual(200, resp.status_code) # go look at the Edit page - unit_location = loc._replace(category='vertical', name='test_vertical') + unit_location = loc.replace(category='vertical', name='test_vertical') resp = self.client.get(reverse('edit_unit', kwargs={'location': unit_location.url()})) self.assertEqual(200, resp.status_code) # delete a component - del_loc = loc._replace(category='html', name='test_html') + del_loc = loc.replace(category='html', name='test_html') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") self.assertEqual(200, resp.status_code) # delete a unit - del_loc = loc._replace(category='vertical', name='test_vertical') + del_loc = loc.replace(category='vertical', name='test_vertical') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") self.assertEqual(200, resp.status_code) # delete a unit - del_loc = loc._replace(category='sequential', name='test_sequence') + del_loc = loc.replace(category='sequential', name='test_sequence') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") self.assertEqual(200, resp.status_code) # delete a chapter - del_loc = loc._replace(category='chapter', name='chapter_2') + del_loc = loc.replace(category='chapter', name='chapter_2') resp = self.client.post(reverse('delete_item'), json.dumps({'id': del_loc.url()}), "application/json") self.assertEqual(200, resp.status_code) diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py index ae04e3aac4..33c7b61251 100644 --- a/common/lib/xmodule/xmodule/modulestore/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/__init__.py @@ -9,7 +9,7 @@ import re from collections import namedtuple from .exceptions import InvalidLocationError, InsufficientSpecificationError -from xmodule.errortracker import ErrorLog, make_error_tracker +from xmodule.errortracker import make_error_tracker from bson.son import SON log = logging.getLogger('mitx.' + 'modulestore') @@ -64,7 +64,6 @@ class Location(_LocationBase): """ return re.sub('_+', '_', invalid.sub('_', value)) - @staticmethod def clean(value): """ @@ -72,7 +71,6 @@ class Location(_LocationBase): """ return Location._clean(value, INVALID_CHARS) - @staticmethod def clean_keeping_underscores(value): """ @@ -82,7 +80,6 @@ class Location(_LocationBase): """ return INVALID_CHARS.sub('_', value) - @staticmethod def clean_for_url_name(value): """ @@ -154,9 +151,7 @@ class Location(_LocationBase): to mean wildcard selection. """ - - if (org is None and course is None and category is None and - name is None and revision is None): + if (org is None and course is None and category is None and name is None and revision is None): location = loc_or_tag else: location = (loc_or_tag, org, course, category, name, revision) @@ -191,7 +186,7 @@ class Location(_LocationBase): match = MISSING_SLASH_URL_RE.match(location) if match is None: log.debug('location is instance of %s but no URL match' % basestring) - raise InvalidLocationError(location) + raise InvalidLocationError(location) groups = match.groupdict() check_dict(groups) return _LocationBase.__new__(_cls, **groups) @@ -233,7 +228,7 @@ class Location(_LocationBase): html id attributes """ s = "-".join(str(v) for v in self.list() - if v is not None) + if v is not None) return Location.clean_for_html(s) def dict(self): @@ -258,6 +253,12 @@ class Location(_LocationBase): at the location URL hierachy""" return "/".join([self.org, self.course, self.name]) + def replace(self, **kwargs): + ''' + Expose a public method for replacing location elements + ''' + return self._replace(**kwargs) + class ModuleStore(object): """ @@ -382,12 +383,6 @@ class ModuleStore(object): ''' raise NotImplementedError - def get_course(self, course_id): - ''' - Look for a specific course id. Returns the course descriptor, or None if not found. - ''' - raise NotImplementedError - def get_parent_locations(self, location, course_id): '''Find all locations that are the parents of this location in this course. Needed for path_to_location(). @@ -406,8 +401,7 @@ class ModuleStore(object): courses = [ course for course in self.get_courses() - if course.location.org == location.org - and course.location.course == location.course + if course.location.org == location.org and course.location.course == location.course ] return courses diff --git a/common/lib/xmodule/xmodule/modulestore/draft.py b/common/lib/xmodule/xmodule/modulestore/draft.py index c3f1b23688..9262c5e9d6 100644 --- a/common/lib/xmodule/xmodule/modulestore/draft.py +++ b/common/lib/xmodule/xmodule/modulestore/draft.py @@ -13,11 +13,12 @@ def as_draft(location): """ return Location(location)._replace(revision=DRAFT) + def as_published(location): """ Returns the Location that is the published version for `location` """ - return Location(location)._replace(revision=None) + return Location(location)._replace(revision=None) def wrap_draft(item): diff --git a/common/lib/xmodule/xmodule/modulestore/tests/factories.py b/common/lib/xmodule/xmodule/modulestore/tests/factories.py index 31237af7b9..8cf148f742 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/factories.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/factories.py @@ -3,7 +3,6 @@ from time import gmtime from uuid import uuid4 from xmodule.modulestore import Location from xmodule.modulestore.django import modulestore -from xmodule.timeparse import stringify_time from xmodule.modulestore.inheritance import own_metadata From a44e8168773749b9c70c587eb6c0ac9092cb4daf Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Mon, 20 May 2013 10:33:52 -0400 Subject: [PATCH 16/18] remove_open_ended_panel_tab() -> remove_extra_paneltab(). Also, update new forums test factors to use refactored Models.py --- cms/djangoapps/contentstore/views/course.py | 2 +- lms/djangoapps/django_comment_client/tests/factories.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 9cfe9c207a..07f6b9669c 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -18,7 +18,7 @@ from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationErr from xmodule.modulestore import Location from contentstore.course_info_model import get_course_updates, update_course_updates, delete_course_update -from contentstore.utils import get_lms_link_for_item, add_extra_panel_tab, remove_open_ended_panel_tab +from contentstore.utils import get_lms_link_for_item, add_extra_panel_tab, remove_extra_panel_tab from models.settings.course_details import CourseDetails, CourseSettingsEncoder from models.settings.course_grading import CourseGradingModel from models.settings.course_metadata import CourseMetadata diff --git a/lms/djangoapps/django_comment_client/tests/factories.py b/lms/djangoapps/django_comment_client/tests/factories.py index eb1d9477c3..4a82c8f1bb 100644 --- a/lms/djangoapps/django_comment_client/tests/factories.py +++ b/lms/djangoapps/django_comment_client/tests/factories.py @@ -1,5 +1,5 @@ from factory import DjangoModelFactory -from django_comment_client.models import Role, Permission +from django_comment_common.models import Role, Permission class RoleFactory(DjangoModelFactory): From 470569545d9e1afd2c2aaa619284e78736ccf2f0 Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Wed, 22 May 2013 13:32:32 -0400 Subject: [PATCH 17/18] add a migrations to the new django_comment_common to keep things a bit more consistent with our normal useage. --- .../migrations/0001_initial.py | 92 +++++++++++++++++++ .../migrations/__init__.py | 0 .../django_comment_common/models.py | 2 + 3 files changed, 94 insertions(+) create mode 100644 common/djangoapps/django_comment_common/migrations/0001_initial.py create mode 100644 common/djangoapps/django_comment_common/migrations/__init__.py diff --git a/common/djangoapps/django_comment_common/migrations/0001_initial.py b/common/djangoapps/django_comment_common/migrations/0001_initial.py new file mode 100644 index 0000000000..f2c3ca3aee --- /dev/null +++ b/common/djangoapps/django_comment_common/migrations/0001_initial.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +from south.v2 import SchemaMigration + + +class Migration(SchemaMigration): +# +# cdodge: This is basically an empty migration since everything has - up to now - managed in the django_comment_client app +# But going forward we should be using this migration +# + def forwards(self, orm): + pass + + def backwards(self, orm): + pass + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'consecutive_days_visit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'display_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'email_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ignored_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'interesting_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'show_country': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'django_comment_common.permission': { + 'Meta': {'object_name': 'Permission'}, + 'name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'}), + 'roles': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'permissions'", 'symmetrical': 'False', 'to': "orm['django_comment_common.Role']"}) + }, + 'django_comment_common.role': { + 'Meta': {'object_name': 'Role'}, + 'course_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'roles'", 'symmetrical': 'False', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['django_comment_common'] diff --git a/common/djangoapps/django_comment_common/migrations/__init__.py b/common/djangoapps/django_comment_common/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/djangoapps/django_comment_common/models.py b/common/djangoapps/django_comment_common/models.py index 6688470753..ec722b718a 100644 --- a/common/djangoapps/django_comment_common/models.py +++ b/common/djangoapps/django_comment_common/models.py @@ -34,6 +34,7 @@ class Role(models.Model): course_id = models.CharField(max_length=255, blank=True, db_index=True) class Meta: + # use existing table that was originally created from django_comment_client app db_table = 'django_comment_client_role' def __unicode__(self): @@ -66,6 +67,7 @@ class Permission(models.Model): roles = models.ManyToManyField(Role, related_name="permissions") class Meta: + # use existing table that was originally created from django_comment_client app db_table = 'django_comment_client_permission' def __unicode__(self): From 293d0a8645e348ff9ab0f7fa57da7067c7ff03fa Mon Sep 17 00:00:00 2001 From: Chris Dodge Date: Wed, 22 May 2013 21:58:29 -0400 Subject: [PATCH 18/18] special case the db setup for the cms acceptance tests. We need the comment client database tables to be created since we're creating the DB from scratch --- rakefiles/tests.rake | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rakefiles/tests.rake b/rakefiles/tests.rake index ebe8ea6375..2dbde6b692 100644 --- a/rakefiles/tests.rake +++ b/rakefiles/tests.rake @@ -25,6 +25,16 @@ def run_tests(system, report_dir, stop_on_failure=true) end def run_acceptance_tests(system, report_dir, harvest_args) + # HACK: Since now the CMS depends on the existence of some database tables + # that used to be in LMS (Role/Permissions for Forums) we need to make + # sure the acceptance tests create/migrate the database tables + # that are represented in the LMS. We might be able to address this by moving + # out the migrations from lms/django_comment_client, but then we'd have to + # repair all the existing migrations from the upgrade tables in the DB. + if system == :cms + sh(django_admin('lms', 'acceptance', 'syncdb', '--noinput')) + sh(django_admin('lms', 'acceptance', 'migrate', '--noinput')) + end sh(django_admin(system, 'acceptance', 'syncdb', '--noinput')) sh(django_admin(system, 'acceptance', 'migrate', '--noinput')) sh(django_admin(system, 'acceptance', 'harvest', '--debug-mode', '--tag -skip', harvest_args))