Commit 8dc84bec by Matjaz Gregoric

Enable discussions on CCX courses.

Discussion is restricted to the CCX course (there is no sharing of
discussions with the parent course or other CCX instances).
parent 2251097c
...@@ -46,7 +46,14 @@ def assign_default_role(course_id, user): ...@@ -46,7 +46,14 @@ def assign_default_role(course_id, user):
""" """
Assign forum default role 'Student' to user Assign forum default role 'Student' to user
""" """
role, __ = Role.objects.get_or_create(course_id=course_id, name=FORUM_ROLE_STUDENT) assign_role(course_id, user, FORUM_ROLE_STUDENT)
def assign_role(course_id, user, rolename):
"""
Assign forum role `rolename` to user
"""
role, __ = Role.objects.get_or_create(course_id=course_id, name=rolename)
user.roles.add(role) user.roles.add(role)
......
from django_comment_common.models import Role """
Common comment client utility functions.
"""
from django_comment_common.models import Role, FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, \
FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT
class ThreadContext(object): class ThreadContext(object):
...@@ -7,14 +12,14 @@ class ThreadContext(object): ...@@ -7,14 +12,14 @@ class ThreadContext(object):
COURSE = 'course' COURSE = 'course'
_STUDENT_ROLE_PERMISSIONS = ["vote", "update_thread", "follow_thread", "unfollow_thread", STUDENT_ROLE_PERMISSIONS = ["vote", "update_thread", "follow_thread", "unfollow_thread",
"update_comment", "create_sub_comment", "unvote", "create_thread", "update_comment", "create_sub_comment", "unvote", "create_thread",
"follow_commentable", "unfollow_commentable", "create_comment", ] "follow_commentable", "unfollow_commentable", "create_comment", ]
_MODERATOR_ROLE_PERMISSIONS = ["edit_content", "delete_thread", "openclose_thread", MODERATOR_ROLE_PERMISSIONS = ["edit_content", "delete_thread", "openclose_thread",
"endorse_comment", "delete_comment", "see_all_cohorts"] "endorse_comment", "delete_comment", "see_all_cohorts"]
_ADMINISTRATOR_ROLE_PERMISSIONS = ["manage_moderator"] ADMINISTRATOR_ROLE_PERMISSIONS = ["manage_moderator"]
def _save_forum_role(course_key, name): def _save_forum_role(course_key, name):
...@@ -34,18 +39,18 @@ def seed_permissions_roles(course_key): ...@@ -34,18 +39,18 @@ def seed_permissions_roles(course_key):
""" """
Create and assign permissions for forum roles Create and assign permissions for forum roles
""" """
administrator_role = _save_forum_role(course_key, "Administrator") administrator_role = _save_forum_role(course_key, FORUM_ROLE_ADMINISTRATOR)
moderator_role = _save_forum_role(course_key, "Moderator") moderator_role = _save_forum_role(course_key, FORUM_ROLE_MODERATOR)
community_ta_role = _save_forum_role(course_key, "Community TA") community_ta_role = _save_forum_role(course_key, FORUM_ROLE_COMMUNITY_TA)
student_role = _save_forum_role(course_key, "Student") student_role = _save_forum_role(course_key, FORUM_ROLE_STUDENT)
for per in _STUDENT_ROLE_PERMISSIONS: for per in STUDENT_ROLE_PERMISSIONS:
student_role.add_permission(per) student_role.add_permission(per)
for per in _MODERATOR_ROLE_PERMISSIONS: for per in MODERATOR_ROLE_PERMISSIONS:
moderator_role.add_permission(per) moderator_role.add_permission(per)
for per in _ADMINISTRATOR_ROLE_PERMISSIONS: for per in ADMINISTRATOR_ROLE_PERMISSIONS:
administrator_role.add_permission(per) administrator_role.add_permission(per)
moderator_role.inherit_permissions(student_role) moderator_role.inherit_permissions(student_role)
...@@ -62,21 +67,21 @@ def are_permissions_roles_seeded(course_id): ...@@ -62,21 +67,21 @@ def are_permissions_roles_seeded(course_id):
the database the database
""" """
try: try:
administrator_role = Role.objects.get(name="Administrator", course_id=course_id) administrator_role = Role.objects.get(name=FORUM_ROLE_ADMINISTRATOR, course_id=course_id)
moderator_role = Role.objects.get(name="Moderator", course_id=course_id) moderator_role = Role.objects.get(name=FORUM_ROLE_MODERATOR, course_id=course_id)
student_role = Role.objects.get(name="Student", course_id=course_id) student_role = Role.objects.get(name=FORUM_ROLE_STUDENT, course_id=course_id)
except: except:
return False return False
for per in _STUDENT_ROLE_PERMISSIONS: for per in STUDENT_ROLE_PERMISSIONS:
if not student_role.has_permission(per): if not student_role.has_permission(per):
return False return False
for per in _MODERATOR_ROLE_PERMISSIONS + _STUDENT_ROLE_PERMISSIONS: for per in MODERATOR_ROLE_PERMISSIONS + STUDENT_ROLE_PERMISSIONS:
if not moderator_role.has_permission(per): if not moderator_role.has_permission(per):
return False return False
for per in _ADMINISTRATOR_ROLE_PERMISSIONS + _MODERATOR_ROLE_PERMISSIONS + _STUDENT_ROLE_PERMISSIONS: for per in ADMINISTRATOR_ROLE_PERMISSIONS + MODERATOR_ROLE_PERMISSIONS + STUDENT_ROLE_PERMISSIONS:
if not administrator_role.has_permission(per): if not administrator_role.has_permission(per):
return False return False
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import logging
from ccx_keys.locator import CCXLocator
from courseware.courses import get_course_by_id
from django.db import migrations
from django.http import Http404
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, \
FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT
from django_comment_common.utils import STUDENT_ROLE_PERMISSIONS, MODERATOR_ROLE_PERMISSIONS, \
ADMINISTRATOR_ROLE_PERMISSIONS
log = logging.getLogger("edx.ccx")
def seed_forum_roles_for_existing_ccx(apps, schema_editor):
"""
Seed forum roles and make CCX coach forum admin for respective CCX(s).
Arguments:
apps (Applications): Apps in edX platform.
schema_editor (SchemaEditor): For editing database schema i.e create, delete field (column)
"""
CustomCourseForEdX = apps.get_model("ccx", "CustomCourseForEdX")
Role = apps.get_model("django_comment_common", "Role")
Permission = apps.get_model("django_comment_common", "Permission")
db_alias = schema_editor.connection.alias
# This will need to be changed if ccx gets moved out of the default db for some reason.
if db_alias != 'default':
log.info("Skipping CCX migration on non-default database.")
return
for ccx in CustomCourseForEdX.objects.all():
if not ccx.course_id or ccx.course_id.deprecated:
# prevent migration for deprecated course ids or invalid ids.
log.warning(
"Skipping CCX %s due to invalid or deprecated course_id: %s.",
ccx.id,
ccx.course_id
)
continue
ccx_locator = CCXLocator.from_course_locator(ccx.course_id, unicode(ccx.id))
# Create forum roles.
admin_role, _ = Role.objects.get_or_create(name=FORUM_ROLE_ADMINISTRATOR, course_id=ccx_locator)
moderator_role, _ = Role.objects.get_or_create(name=FORUM_ROLE_MODERATOR, course_id=ccx_locator)
community_ta_role, _ = Role.objects.get_or_create(name=FORUM_ROLE_COMMUNITY_TA, course_id=ccx_locator)
student_role, _ = Role.objects.get_or_create(name=FORUM_ROLE_STUDENT, course_id=ccx_locator)
# Add permissions for each role.
for name in ADMINISTRATOR_ROLE_PERMISSIONS:
admin_role.permissions.add(Permission.objects.get_or_create(name=name)[0])
for name in MODERATOR_ROLE_PERMISSIONS:
moderator_role.permissions.add(Permission.objects.get_or_create(name=name)[0])
for name in STUDENT_ROLE_PERMISSIONS:
student_role.permissions.add(Permission.objects.get_or_create(name=name)[0])
for permission in student_role.permissions.all():
moderator_role.permissions.add(permission)
for permission in moderator_role.permissions.all():
community_ta_role.permissions.add(permission)
for permission in moderator_role.permissions.all():
admin_role.permissions.add(permission)
# Make CCX coach forum admin.
ccx.coach.roles.add(admin_role)
log.info("Seeded forum permissions for CCX %s", ccx_locator)
class Migration(migrations.Migration):
dependencies = [
('ccx', '0003_add_master_course_staff_in_ccx'),
('django_comment_common', '0002_forumsconfig'),
]
operations = [
migrations.RunPython(code=seed_forum_roles_for_existing_ccx, reverse_code=migrations.RunPython.noop)
]
...@@ -17,6 +17,9 @@ from courseware.tests.factories import StudentModuleFactory ...@@ -17,6 +17,9 @@ from courseware.tests.factories import StudentModuleFactory
from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.helpers import LoginEnrollmentTestCase
from courseware.tabs import get_course_tab_list from courseware.tabs import get_course_tab_list
from courseware.testutils import FieldOverrideTestMixin from courseware.testutils import FieldOverrideTestMixin
from django_comment_client.utils import has_forum_access
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR
from django_comment_common.utils import are_permissions_roles_seeded
from instructor.access import ( from instructor.access import (
allow_access, allow_access,
list_with_level, list_with_level,
...@@ -423,6 +426,10 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase): ...@@ -423,6 +426,10 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
list_staff_master_course = list_with_level(self.course, 'staff') list_staff_master_course = list_with_level(self.course, 'staff')
list_instructor_master_course = list_with_level(self.course, 'instructor') list_instructor_master_course = list_with_level(self.course, 'instructor')
# assert that forum roles are seeded
self.assertTrue(are_permissions_roles_seeded(course_key))
self.assertTrue(has_forum_access(self.coach.username, course_key, FORUM_ROLE_ADMINISTRATOR))
with ccx_course(course_key) as course_ccx: with ccx_course(course_key) as course_ccx:
list_staff_ccx_course = list_with_level(course_ccx, 'staff') list_staff_ccx_course = list_with_level(course_ccx, 'staff')
self.assertEqual(len(list_staff_master_course), len(list_staff_ccx_course)) self.assertEqual(len(list_staff_master_course), len(list_staff_ccx_course))
......
...@@ -30,6 +30,8 @@ from courseware.access import has_access ...@@ -30,6 +30,8 @@ from courseware.access import has_access
from courseware.courses import get_course_by_id from courseware.courses import get_course_by_id
from courseware.field_overrides import disable_overrides from courseware.field_overrides import disable_overrides
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR, assign_role
from django_comment_common.utils import seed_permissions_roles
from edxmako.shortcuts import render_to_response from edxmako.shortcuts import render_to_response
from lms.djangoapps.grades.course_grades import iterate_grades_for from lms.djangoapps.grades.course_grades import iterate_grades_for
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
...@@ -220,6 +222,11 @@ def create_ccx(request, course, ccx=None): ...@@ -220,6 +222,11 @@ def create_ccx(request, course, ccx=None):
ccx_id = CCXLocator.from_course_locator(course.id, unicode(ccx.id)) ccx_id = CCXLocator.from_course_locator(course.id, unicode(ccx.id))
# Create forum roles
seed_permissions_roles(ccx_id)
# Assign administrator forum role to CCX coach
assign_role(ccx_id, request.user, FORUM_ROLE_ADMINISTRATOR)
url = reverse('ccx_coach_dashboard', kwargs={'course_id': ccx_id}) url = reverse('ccx_coach_dashboard', kwargs={'course_id': ccx_id})
# Enroll the coach in the course # Enroll the coach in the course
......
...@@ -14,7 +14,6 @@ import pystache_custom as pystache ...@@ -14,7 +14,6 @@ import pystache_custom as pystache
from opaque_keys.edx.locations import i4xEncoder from opaque_keys.edx.locations import i4xEncoder
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from lms.djangoapps.ccx.overrides import get_current_ccx
from django_comment_common.models import Role, FORUM_ROLE_STUDENT from django_comment_common.models import Role, FORUM_ROLE_STUDENT
from django_comment_client.permissions import check_permissions_by_view, has_permission, get_team from django_comment_client.permissions import check_permissions_by_view, has_permission, get_team
...@@ -806,11 +805,8 @@ def is_commentable_cohorted(course_key, commentable_id): ...@@ -806,11 +805,8 @@ def is_commentable_cohorted(course_key, commentable_id):
def is_discussion_enabled(course_id): def is_discussion_enabled(course_id):
""" """
Return True if Discussion is enabled for a course; else False Return True if discussions are enabled; else False
""" """
if settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
if get_current_ccx(course_id):
return False
return settings.FEATURES.get('ENABLE_DISCUSSION_SERVICE') return settings.FEATURES.get('ENABLE_DISCUSSION_SERVICE')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment