Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
fd065c9e
Commit
fd065c9e
authored
Feb 24, 2016
by
Michael Katz
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11643 from edx/release
Release 2016-02-24
parents
a8094c39
44c27bb1
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
18 additions
and
258 deletions
+18
-258
cms/djangoapps/contentstore/views/course.py
+2
-11
lms/djangoapps/ccx/migrations/0002_add_master_course_staff_in_ccx.py
+0
-45
lms/djangoapps/ccx/tests/test_utils.py
+3
-64
lms/djangoapps/ccx/tests/test_views.py
+1
-31
lms/djangoapps/ccx/utils.py
+2
-83
lms/djangoapps/ccx/views.py
+1
-5
lms/djangoapps/courseware/access.py
+3
-0
lms/djangoapps/instructor/enrollment.py
+6
-19
No files found.
cms/djangoapps/contentstore/views/course.py
View file @
fd065c9e
...
...
@@ -27,7 +27,6 @@ from .component import (
)
from
.item
import
create_xblock_info
from
.library
import
LIBRARIES_ENABLED
from
ccx_keys.locator
import
CCXLocator
from
contentstore
import
utils
from
contentstore.course_group_config
import
(
COHORT_SCHEME
,
...
...
@@ -390,11 +389,6 @@ def _accessible_courses_list(request):
if
isinstance
(
course
,
ErrorDescriptor
):
return
False
# Custom Courses for edX (CCX) is an edX feature for re-using course content.
# CCXs cannot be edited in Studio (aka cms) and should not be shown in this dashboard.
if
isinstance
(
course
,
CCXLocator
):
return
False
# pylint: disable=fixme
# TODO remove this condition when templates purged from db
if
course
.
location
.
course
==
'templates'
:
...
...
@@ -439,11 +433,8 @@ def _accessible_courses_list_from_groups(request):
except
ItemNotFoundError
:
# If a user has access to a course that doesn't exist, don't do anything with that course
pass
# Custom Courses for edX (CCX) is an edX feature for re-using course content.
# CCXs cannot be edited in Studio (aka cms) and should not be shown in this dashboard.
if
course
is
not
None
and
not
isinstance
(
course
,
ErrorDescriptor
)
and
not
isinstance
(
course
.
id
,
CCXLocator
):
# ignore deleted, errored or ccx courses
if
course
is
not
None
and
not
isinstance
(
course
,
ErrorDescriptor
):
# ignore deleted or errored courses
courses_list
[
course_key
]
=
course
return
courses_list
.
values
(),
in_process_course_actions
...
...
lms/djangoapps/ccx/migrations/0002_add_master_course_staff_in_ccx.py
deleted
100644 → 0
View file @
a8094c39
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
ccx_keys.locator
import
CCXLocator
from
django.db
import
migrations
from
lms.djangoapps.ccx.models
import
CustomCourseForEdX
from
lms.djangoapps.ccx.utils
import
(
add_master_course_staff_to_ccx
,
reverse_add_master_course_staff_to_ccx
)
def
add_master_course_staff_to_ccx_for_existing_ccx
(
apps
,
schema_editor
):
"""
Add all staff and admin of master course to respective CCX(s).
"""
list_ccx
=
CustomCourseForEdX
.
objects
.
all
()
for
ccx
in
list_ccx
:
ccx_locator
=
CCXLocator
.
from_course_locator
(
ccx
.
course_id
,
unicode
(
ccx
.
id
))
add_master_course_staff_to_ccx
(
ccx
.
course
,
ccx_locator
,
ccx
.
display_name
)
def
reverse_add_master_course_staff_to_ccx_for_existing_ccx
(
apps
,
schema_editor
):
"""
Add all staff and admin of master course to respective CCX(s).
"""
list_ccx
=
CustomCourseForEdX
.
objects
.
all
()
for
ccx
in
list_ccx
:
ccx_locator
=
CCXLocator
.
from_course_locator
(
ccx
.
course_id
,
unicode
(
ccx
.
id
))
reverse_add_master_course_staff_to_ccx
(
ccx
.
course
,
ccx_locator
,
ccx
.
display_name
)
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'ccx'
,
'0001_initial'
),
]
operations
=
[
migrations
.
RunPython
(
add_master_course_staff_to_ccx_for_existing_ccx
,
reverse_code
=
reverse_add_master_course_staff_to_ccx_for_existing_ccx
)
]
lms/djangoapps/ccx/tests/test_utils.py
View file @
fd065c9e
...
...
@@ -3,30 +3,17 @@ test utils
"""
from
nose.plugins.attrib
import
attr
from
ccx_keys.locator
import
CCXLocator
from
student.roles
import
(
CourseCcxCoachRole
,
CourseInstructorRole
,
CourseStaffRole
,
)
from
lms.djangoapps.ccx.tests.factories
import
CcxFactory
from
student.roles
import
CourseCcxCoachRole
from
student.tests.factories
import
(
AdminFactory
,
CourseEnrollmentFactory
,
UserFactory
)
from
xmodule.modulestore.tests.django_utils
import
(
ModuleStoreTestCase
,
SharedModuleStoreTestCase
,
TEST_DATA_SPLIT_MODULESTORE
)
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.django
import
modulestore
from
lms.djangoapps.instructor.access
import
list_with_level
,
allow_access
from
lms.djangoapps.ccx.utils
import
add_master_course_staff_to_ccx
from
lms.djangoapps.ccx.views
import
ccx_course
from
lms.djangoapps.ccx.tests.factories
import
CcxFactory
from
lms.djangoapps.ccx.tests.utils
import
CcxTestCase
from
ccx_keys.locator
import
CCXLocator
@attr
(
'shard_1'
)
...
...
@@ -60,51 +47,3 @@ class TestGetCCXFromCCXLocator(ModuleStoreTestCase):
course_key
=
CCXLocator
.
from_course_locator
(
self
.
course
.
id
,
ccx
.
id
)
result
=
self
.
call_fut
(
course_key
)
self
.
assertEqual
(
result
,
ccx
)
class
TestStaffOnCCX
(
CcxTestCase
,
SharedModuleStoreTestCase
):
"""
Tests for staff on ccx courses.
"""
MODULESTORE
=
TEST_DATA_SPLIT_MODULESTORE
def
setUp
(
self
):
super
(
TestStaffOnCCX
,
self
)
.
setUp
()
# Create instructor account
self
.
client
.
login
(
username
=
self
.
coach
.
username
,
password
=
"test"
)
# create an instance of modulestore
self
.
mstore
=
modulestore
()
# adding staff to master course.
staff
=
UserFactory
()
allow_access
(
self
.
course
,
staff
,
'staff'
)
self
.
assertTrue
(
CourseStaffRole
(
self
.
course
.
id
)
.
has_user
(
staff
))
# adding instructor to master course.
instructor
=
UserFactory
()
allow_access
(
self
.
course
,
instructor
,
'instructor'
)
self
.
assertTrue
(
CourseInstructorRole
(
self
.
course
.
id
)
.
has_user
(
instructor
))
def
test_add_master_course_staff_to_ccx
(
self
):
"""
Test add staff of master course to ccx course
"""
self
.
make_coach
()
ccx
=
self
.
make_ccx
()
ccx_locator
=
CCXLocator
.
from_course_locator
(
self
.
course
.
id
,
ccx
.
id
)
add_master_course_staff_to_ccx
(
self
.
course
,
ccx_locator
,
ccx
.
display_name
)
# assert that staff and instructors of master course has staff and instructor roles on ccx
list_staff_master_course
=
list_with_level
(
self
.
course
,
'staff'
)
list_instructor_master_course
=
list_with_level
(
self
.
course
,
'instructor'
)
with
ccx_course
(
ccx_locator
)
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
))
self
.
assertEqual
(
list_staff_master_course
[
0
]
.
email
,
list_staff_ccx_course
[
0
]
.
email
)
list_instructor_ccx_course
=
list_with_level
(
course_ccx
,
'instructor'
)
self
.
assertEqual
(
len
(
list_instructor_ccx_course
),
len
(
list_instructor_master_course
))
self
.
assertEqual
(
list_instructor_ccx_course
[
0
]
.
email
,
list_instructor_master_course
[
0
]
.
email
)
lms/djangoapps/ccx/tests/test_views.py
View file @
fd065c9e
...
...
@@ -15,8 +15,6 @@ from courseware.courses import get_course_by_id
from
courseware.tests.factories
import
StudentModuleFactory
from
courseware.tests.helpers
import
LoginEnrollmentTestCase
from
courseware.tabs
import
get_course_tab_list
from
instructor.access
import
list_with_level
,
allow_access
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
,
resolve
from
django.utils.timezone
import
UTC
...
...
@@ -25,11 +23,7 @@ from django.test import RequestFactory
from
edxmako.shortcuts
import
render_to_response
from
request_cache.middleware
import
RequestCache
from
opaque_keys.edx.keys
import
CourseKey
from
student.roles
import
(
CourseCcxCoachRole
,
CourseInstructorRole
,
CourseStaffRole
,
)
from
student.roles
import
CourseCcxCoachRole
from
student.models
import
(
CourseEnrollment
,
CourseEnrollmentAllowed
,
...
...
@@ -54,7 +48,6 @@ from ccx_keys.locator import CCXLocator
from
lms.djangoapps.ccx.models
import
CustomCourseForEdX
from
lms.djangoapps.ccx.overrides
import
get_override_for_ccx
,
override_field_for_ccx
from
lms.djangoapps.ccx.views
import
ccx_course
from
lms.djangoapps.ccx.tests.factories
import
CcxFactory
from
lms.djangoapps.ccx.tests.utils
import
(
CcxTestCase
,
...
...
@@ -142,16 +135,6 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
# Login with the instructor account
self
.
client
.
login
(
username
=
self
.
coach
.
username
,
password
=
"test"
)
# adding staff to master course.
staff
=
UserFactory
()
allow_access
(
self
.
course
,
staff
,
'staff'
)
self
.
assertTrue
(
CourseStaffRole
(
self
.
course
.
id
)
.
has_user
(
staff
))
# adding instructor to master course.
instructor
=
UserFactory
()
allow_access
(
self
.
course
,
instructor
,
'instructor'
)
self
.
assertTrue
(
CourseInstructorRole
(
self
.
course
.
id
)
.
has_user
(
instructor
))
def
assert_elements_in_schedule
(
self
,
url
,
n_chapters
=
2
,
n_sequentials
=
4
,
n_verticals
=
8
):
"""
Helper function to count visible elements in the schedule
...
...
@@ -238,19 +221,6 @@ class TestCoachDashboard(CcxTestCase, LoginEnrollmentTestCase):
role
=
CourseCcxCoachRole
(
course_key
)
self
.
assertTrue
(
role
.
has_user
(
self
.
coach
,
refresh
=
True
))
# assert that staff and instructors of master course has staff and instructor roles on ccx
list_staff_master_course
=
list_with_level
(
self
.
course
,
'staff'
)
list_instructor_master_course
=
list_with_level
(
self
.
course
,
'instructor'
)
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
))
self
.
assertEqual
(
list_staff_master_course
[
0
]
.
email
,
list_staff_ccx_course
[
0
]
.
email
)
list_instructor_ccx_course
=
list_with_level
(
course_ccx
,
'instructor'
)
self
.
assertEqual
(
len
(
list_instructor_ccx_course
),
len
(
list_instructor_master_course
))
self
.
assertEqual
(
list_instructor_ccx_course
[
0
]
.
email
,
list_instructor_master_course
[
0
]
.
email
)
def
test_get_date
(
self
):
"""
Assert that get_date returns valid date.
...
...
lms/djangoapps/ccx/utils.py
View file @
fd065c9e
...
...
@@ -18,18 +18,17 @@ from courseware.model_data import FieldDataCache
from
courseware.module_render
import
get_module_for_descriptor
from
instructor.enrollment
import
(
enroll_email
,
get_email_params
,
unenroll_email
,
)
from
instructor.access
import
allow_access
,
list_with_level
,
revoke_access
from
instructor.access
import
allow_access
from
instructor.views.tools
import
get_student_from_identifier
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
student.models
import
CourseEnrollment
from
student.roles
import
CourseCcxCoachRole
from
lms.djangoapps.ccx.models
import
CustomCourseForEdX
from
lms.djangoapps.ccx.overrides
import
get_override_for_ccx
from
lms.djangoapps.ccx.custom_exception
import
CCXUserValidationException
from
lms.djangoapps.ccx.models
import
CustomCourseForEdX
log
=
logging
.
getLogger
(
"edx.ccx"
)
...
...
@@ -261,83 +260,3 @@ def is_email(identifier):
except
ValidationError
:
return
False
return
True
def
add_master_course_staff_to_ccx
(
master_course
,
ccx_key
,
display_name
):
"""
Added staff role on ccx to all the staff members of master course.
Arguments:
master_course (CourseDescriptorWithMixins): Master course instance
ccx_key (CCXLocator): CCX course key
display_name (str): ccx display name for email
"""
list_staff
=
list_with_level
(
master_course
,
'staff'
)
list_instructor
=
list_with_level
(
master_course
,
'instructor'
)
with
ccx_course
(
ccx_key
)
as
course_ccx
:
email_params
=
get_email_params
(
course_ccx
,
auto_enroll
=
True
,
course_key
=
ccx_key
,
display_name
=
display_name
)
for
staff
in
list_staff
:
# allow 'staff' access on ccx to staff of master course
allow_access
(
course_ccx
,
staff
,
'staff'
)
# Enroll the staff in the ccx
enroll_email
(
course_id
=
ccx_key
,
student_email
=
staff
.
email
,
auto_enroll
=
True
,
email_students
=
True
,
email_params
=
email_params
,
)
for
instructor
in
list_instructor
:
# allow 'instructor' access on ccx to instructor of master course
allow_access
(
course_ccx
,
instructor
,
'instructor'
)
# Enroll the instructor in the ccx
enroll_email
(
course_id
=
ccx_key
,
student_email
=
instructor
.
email
,
auto_enroll
=
True
,
email_students
=
True
,
email_params
=
email_params
,
)
def
reverse_add_master_course_staff_to_ccx
(
master_course
,
ccx_key
,
display_name
):
"""
Remove staff of ccx.
Arguments:
master_course (CourseDescriptorWithMixins): Master course instance
ccx_key (CCXLocator): CCX course key
display_name (str): ccx display name for email
"""
list_staff
=
list_with_level
(
master_course
,
'staff'
)
list_instructor
=
list_with_level
(
master_course
,
'instructor'
)
with
ccx_course
(
ccx_key
)
as
course_ccx
:
email_params
=
get_email_params
(
course_ccx
,
auto_enroll
=
True
,
course_key
=
ccx_key
,
display_name
=
display_name
)
for
staff
in
list_staff
:
# allow 'staff' access on ccx to staff of master course
revoke_access
(
course_ccx
,
staff
,
'staff'
)
# Enroll the staff in the ccx
unenroll_email
(
course_id
=
ccx_key
,
student_email
=
staff
.
email
,
email_students
=
True
,
email_params
=
email_params
,
)
for
instructor
in
list_instructor
:
# allow 'instructor' access on ccx to instructor of master course
revoke_access
(
course_ccx
,
instructor
,
'instructor'
)
# Enroll the instructor in the ccx
unenroll_email
(
course_id
=
ccx_key
,
student_email
=
instructor
.
email
,
email_students
=
True
,
email_params
=
email_params
,
)
lms/djangoapps/ccx/views.py
View file @
fd065c9e
...
...
@@ -52,7 +52,6 @@ from lms.djangoapps.ccx.overrides import (
bulk_delete_ccx_override_fields
,
)
from
lms.djangoapps.ccx.utils
import
(
add_master_course_staff_to_ccx
,
assign_coach_role_to_ccx
,
ccx_course
,
ccx_students_enrolling_center
,
...
...
@@ -147,9 +146,6 @@ def dashboard(request, course, ccx=None):
context
[
'grading_policy_url'
]
=
reverse
(
'ccx_set_grading_policy'
,
kwargs
=
{
'course_id'
:
ccx_locator
})
with
ccx_course
(
ccx_locator
)
as
course
:
context
[
'course'
]
=
course
else
:
context
[
'create_ccx_url'
]
=
reverse
(
'create_ccx'
,
kwargs
=
{
'course_id'
:
course
.
id
})
...
...
@@ -212,7 +208,7 @@ def create_ccx(request, course, ccx=None):
)
assign_coach_role_to_ccx
(
ccx_id
,
request
.
user
,
course
.
id
)
add_master_course_staff_to_ccx
(
course
,
ccx_id
,
ccx
.
display_name
)
return
redirect
(
url
)
...
...
lms/djangoapps/courseware/access.py
View file @
fd065c9e
...
...
@@ -132,6 +132,9 @@ def has_access(user, action, obj, course_key=None):
if
not
user
:
user
=
AnonymousUser
()
if
isinstance
(
course_key
,
CCXLocator
):
course_key
=
course_key
.
to_course_locator
()
# delegate the work to type-specific functions.
# (start with more specific types, then get more general)
if
isinstance
(
obj
,
CourseDescriptor
):
...
...
lms/djangoapps/instructor/enrollment.py
View file @
fd065c9e
...
...
@@ -219,8 +219,6 @@ def reset_student_attempts(course_id, student, module_state_key, delete_module=F
submissions.SubmissionError: unexpected error occurred while resetting the score in the submissions API.
"""
user_id
=
anonymous_id_for_user
(
student
,
course_id
)
submission_cleared
=
False
try
:
# A block may have children. Clear state on children first.
block
=
modulestore
()
.
get_item
(
module_state_key
)
...
...
@@ -231,27 +229,16 @@ def reset_student_attempts(course_id, student, module_state_key, delete_module=F
except
StudentModule
.
DoesNotExist
:
# If a particular child doesn't have any state, no big deal, as long as the parent does.
pass
if
delete_module
:
# Some blocks (openassessment) use StudentModule data as a key for internal submission data.
# Inform these blocks of the reset and allow them to handle their data.
clear_student_state
=
getattr
(
block
,
"clear_student_state"
,
None
)
if
callable
(
clear_student_state
):
clear_student_state
(
user_id
=
user_id
,
course_id
=
unicode
(
course_id
),
item_id
=
unicode
(
module_state_key
)
)
submission_cleared
=
True
except
ItemNotFoundError
:
log
.
warning
(
"Could not find
%
s in modulestore when attempting to reset attempts."
,
module_state_key
)
# Reset the student's score in the submissions API
, if xblock.clear_student_state has not done so already.
#
TODO: Remove this once we've finalized and communicated how xblocks should handle clear_student_state
#
and made sure that other xblocks relying on the submission api understand this is going away.
#
We need to do this before retrieving the `StudentModule` model, because a score may exist with no student module
.
if
delete_module
and
not
submission_cleared
:
# Reset the student's score in the submissions API
#
Currently this is used only by open assessment (ORA 2)
#
We need to do this *before* retrieving the `StudentModule` model,
#
because it's possible for a score to exist even if no student module exists
.
if
delete_module
:
sub_api
.
reset_score
(
user_id
,
anonymous_id_for_user
(
student
,
course_id
)
,
course_id
.
to_deprecated_string
(),
module_state_key
.
to_deprecated_string
(),
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment