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).
This commit is contained in:
@@ -46,7 +46,14 @@ def assign_default_role(course_id, 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)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
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):
|
||||
@@ -7,14 +12,14 @@ class ThreadContext(object):
|
||||
COURSE = 'course'
|
||||
|
||||
|
||||
_STUDENT_ROLE_PERMISSIONS = ["vote", "update_thread", "follow_thread", "unfollow_thread",
|
||||
"update_comment", "create_sub_comment", "unvote", "create_thread",
|
||||
"follow_commentable", "unfollow_commentable", "create_comment", ]
|
||||
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"]
|
||||
MODERATOR_ROLE_PERMISSIONS = ["edit_content", "delete_thread", "openclose_thread",
|
||||
"endorse_comment", "delete_comment", "see_all_cohorts"]
|
||||
|
||||
_ADMINISTRATOR_ROLE_PERMISSIONS = ["manage_moderator"]
|
||||
ADMINISTRATOR_ROLE_PERMISSIONS = ["manage_moderator"]
|
||||
|
||||
|
||||
def _save_forum_role(course_key, name):
|
||||
@@ -34,18 +39,18 @@ def seed_permissions_roles(course_key):
|
||||
"""
|
||||
Create and assign permissions for forum roles
|
||||
"""
|
||||
administrator_role = _save_forum_role(course_key, "Administrator")
|
||||
moderator_role = _save_forum_role(course_key, "Moderator")
|
||||
community_ta_role = _save_forum_role(course_key, "Community TA")
|
||||
student_role = _save_forum_role(course_key, "Student")
|
||||
administrator_role = _save_forum_role(course_key, FORUM_ROLE_ADMINISTRATOR)
|
||||
moderator_role = _save_forum_role(course_key, FORUM_ROLE_MODERATOR)
|
||||
community_ta_role = _save_forum_role(course_key, FORUM_ROLE_COMMUNITY_TA)
|
||||
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)
|
||||
|
||||
for per in _MODERATOR_ROLE_PERMISSIONS:
|
||||
for per in MODERATOR_ROLE_PERMISSIONS:
|
||||
moderator_role.add_permission(per)
|
||||
|
||||
for per in _ADMINISTRATOR_ROLE_PERMISSIONS:
|
||||
for per in ADMINISTRATOR_ROLE_PERMISSIONS:
|
||||
administrator_role.add_permission(per)
|
||||
|
||||
moderator_role.inherit_permissions(student_role)
|
||||
@@ -62,21 +67,21 @@ def are_permissions_roles_seeded(course_id):
|
||||
the database
|
||||
"""
|
||||
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)
|
||||
administrator_role = Role.objects.get(name=FORUM_ROLE_ADMINISTRATOR, course_id=course_id)
|
||||
moderator_role = Role.objects.get(name=FORUM_ROLE_MODERATOR, course_id=course_id)
|
||||
student_role = Role.objects.get(name=FORUM_ROLE_STUDENT, course_id=course_id)
|
||||
except:
|
||||
return False
|
||||
|
||||
for per in _STUDENT_ROLE_PERMISSIONS:
|
||||
for per in STUDENT_ROLE_PERMISSIONS:
|
||||
if not student_role.has_permission(per):
|
||||
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):
|
||||
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):
|
||||
return False
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
# -*- 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
|
||||
from courseware.tests.helpers import LoginEnrollmentTestCase
|
||||
from courseware.tabs import get_course_tab_list
|
||||
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 (
|
||||
allow_access,
|
||||
list_with_level,
|
||||
@@ -423,6 +426,10 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
|
||||
list_staff_master_course = list_with_level(self.course, 'staff')
|
||||
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:
|
||||
list_staff_ccx_course = list_with_level(course_ccx, 'staff')
|
||||
self.assertEqual(len(list_staff_master_course), len(list_staff_ccx_course))
|
||||
|
||||
@@ -30,6 +30,8 @@ from courseware.access import has_access
|
||||
from courseware.courses import get_course_by_id
|
||||
|
||||
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 lms.djangoapps.grades.course_grades import iterate_grades_for
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
@@ -220,6 +222,11 @@ def create_ccx(request, course, ccx=None):
|
||||
|
||||
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})
|
||||
|
||||
# Enroll the coach in the course
|
||||
|
||||
@@ -14,7 +14,6 @@ import pystache_custom as pystache
|
||||
from opaque_keys.edx.locations import i4xEncoder
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
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_client.permissions import check_permissions_by_view, has_permission, get_team
|
||||
@@ -806,11 +805,8 @@ def is_commentable_cohorted(course_key, commentable_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')
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user