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
4c95078e
Commit
4c95078e
authored
Aug 06, 2013
by
Christina Roberts
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #578 from edx/christina/autoenroll
Auto-enroll course staff to fix "View Live".
parents
147f7ed9
3732d418
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
124 additions
and
3 deletions
+124
-3
CHANGELOG.rst
+3
-0
cms/djangoapps/contentstore/tests/test_contentstore.py
+13
-2
cms/djangoapps/contentstore/tests/test_users.py
+65
-0
cms/djangoapps/contentstore/views/course.py
+5
-0
cms/djangoapps/contentstore/views/user.py
+7
-0
common/djangoapps/student/tests/tests.py
+13
-0
common/djangoapps/student/views.py
+18
-1
No files found.
CHANGELOG.rst
View file @
4c95078e
...
@@ -5,6 +5,9 @@ These are notable changes in edx-platform. This is a rolling list of changes,
...
@@ -5,6 +5,9 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
the top. Include a label indicating the component affected.
Studio: Studio course authors (both instructors and staff) will be auto-enrolled
for their courses so that "View Live" works.
Common: Added ratelimiting to our authentication backend.
Common: Added ratelimiting to our authentication backend.
Common: Add additional logging to cover login attempts and logouts.
Common: Add additional logging to cover login attempts and logouts.
...
...
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
4c95078e
...
@@ -49,7 +49,7 @@ import datetime
...
@@ -49,7 +49,7 @@ import datetime
from
pytz
import
UTC
from
pytz
import
UTC
from
uuid
import
uuid4
from
uuid
import
uuid4
from
pymongo
import
MongoClient
from
pymongo
import
MongoClient
from
student.views
import
is_enrolled_in_course
TEST_DATA_CONTENTSTORE
=
copy
.
deepcopy
(
settings
.
CONTENTSTORE
)
TEST_DATA_CONTENTSTORE
=
copy
.
deepcopy
(
settings
.
CONTENTSTORE
)
TEST_DATA_CONTENTSTORE
[
'OPTIONS'
][
'db'
]
=
'test_xcontent_
%
s'
%
uuid4
()
.
hex
TEST_DATA_CONTENTSTORE
[
'OPTIONS'
][
'db'
]
=
'test_xcontent_
%
s'
%
uuid4
()
.
hex
...
@@ -1041,12 +1041,18 @@ class ContentStoreTest(ModuleStoreTestCase):
...
@@ -1041,12 +1041,18 @@ class ContentStoreTest(ModuleStoreTestCase):
data
=
parse_json
(
resp
)
data
=
parse_json
(
resp
)
self
.
assertNotIn
(
'ErrMsg'
,
data
)
self
.
assertNotIn
(
'ErrMsg'
,
data
)
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/{0}/course/2013_Spring'
.
format
(
test_course_data
[
'number'
]))
self
.
assertEqual
(
data
[
'id'
],
'i4x://MITx/{0}/course/2013_Spring'
.
format
(
test_course_data
[
'number'
]))
# Verify that the creator is now registered in the course.
self
.
assertTrue
(
is_enrolled_in_course
(
self
.
user
,
self
.
_get_course_id
(
test_course_data
)))
return
test_course_data
return
test_course_data
def
test_create_course_check_forum_seeding
(
self
):
def
test_create_course_check_forum_seeding
(
self
):
"""Test new course creation and verify forum seeding """
"""Test new course creation and verify forum seeding """
test_course_data
=
self
.
assert_created_course
(
number_suffix
=
uuid4
()
.
hex
)
test_course_data
=
self
.
assert_created_course
(
number_suffix
=
uuid4
()
.
hex
)
self
.
assertTrue
(
are_permissions_roles_seeded
(
'MITx/{0}/2013_Spring'
.
format
(
test_course_data
[
'number'
])))
self
.
assertTrue
(
are_permissions_roles_seeded
(
self
.
_get_course_id
(
test_course_data
)))
def
_get_course_id
(
self
,
test_course_data
):
"""Returns the course ID (org/number/run)."""
return
"{org}/{number}/{run}"
.
format
(
**
test_course_data
)
def
test_create_course_duplicate_course
(
self
):
def
test_create_course_duplicate_course
(
self
):
"""Test new course creation - error path"""
"""Test new course creation - error path"""
...
@@ -1057,10 +1063,15 @@ class ContentStoreTest(ModuleStoreTestCase):
...
@@ -1057,10 +1063,15 @@ class ContentStoreTest(ModuleStoreTestCase):
"""
"""
Checks that the course did not get created
Checks that the course did not get created
"""
"""
course_id
=
self
.
_get_course_id
(
self
.
course_data
)
initially_enrolled
=
is_enrolled_in_course
(
self
.
user
,
course_id
)
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
resp
=
self
.
client
.
post
(
reverse
(
'create_new_course'
),
self
.
course_data
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
data
=
parse_json
(
resp
)
data
=
parse_json
(
resp
)
self
.
assertEqual
(
data
[
'ErrMsg'
],
error_message
)
self
.
assertEqual
(
data
[
'ErrMsg'
],
error_message
)
# One test case involves trying to create the same course twice. Hence for that course,
# the user will be enrolled. In the other cases, initially_enrolled will be False.
self
.
assertEqual
(
initially_enrolled
,
is_enrolled_in_course
(
self
.
user
,
course_id
))
def
test_create_course_duplicate_number
(
self
):
def
test_create_course_duplicate_number
(
self
):
"""Test new course creation - error path"""
"""Test new course creation - error path"""
...
...
cms/djangoapps/contentstore/tests/test_users.py
View file @
4c95078e
"""
Tests for contentstore/views/user.py.
"""
import
json
import
json
from
.utils
import
CourseTestCase
from
.utils
import
CourseTestCase
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.models
import
User
,
Group
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
auth.authz
import
get_course_groupname_for_role
from
auth.authz
import
get_course_groupname_for_role
from
student.views
import
is_enrolled_in_course
class
UsersTestCase
(
CourseTestCase
):
class
UsersTestCase
(
CourseTestCase
):
...
@@ -90,6 +94,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -90,6 +94,7 @@ class UsersTestCase(CourseTestCase):
# no content: should not be in any roles
# no content: should not be in any roles
self
.
assertNotIn
(
self
.
staff_groupname
,
groups
)
self
.
assertNotIn
(
self
.
staff_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assert_not_enrolled
()
def
test_detail_post_staff
(
self
):
def
test_detail_post_staff
(
self
):
resp
=
self
.
client
.
post
(
resp
=
self
.
client
.
post
(
...
@@ -104,6 +109,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -104,6 +109,7 @@ class UsersTestCase(CourseTestCase):
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assert_enrolled
()
def
test_detail_post_staff_other_inst
(
self
):
def
test_detail_post_staff_other_inst
(
self
):
inst_group
,
_
=
Group
.
objects
.
get_or_create
(
name
=
self
.
inst_groupname
)
inst_group
,
_
=
Group
.
objects
.
get_or_create
(
name
=
self
.
inst_groupname
)
...
@@ -122,6 +128,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -122,6 +128,7 @@ class UsersTestCase(CourseTestCase):
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assert_enrolled
()
# check that other user is unchanged
# check that other user is unchanged
user
=
User
.
objects
.
get
(
email
=
self
.
user
.
email
)
user
=
User
.
objects
.
get
(
email
=
self
.
user
.
email
)
groups
=
[
g
.
name
for
g
in
user
.
groups
.
all
()]
groups
=
[
g
.
name
for
g
in
user
.
groups
.
all
()]
...
@@ -141,6 +148,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -141,6 +148,7 @@ class UsersTestCase(CourseTestCase):
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
self
.
assertNotIn
(
self
.
staff_groupname
,
groups
)
self
.
assertNotIn
(
self
.
staff_groupname
,
groups
)
self
.
assertIn
(
self
.
inst_groupname
,
groups
)
self
.
assertIn
(
self
.
inst_groupname
,
groups
)
self
.
assert_enrolled
()
def
test_detail_post_missing_role
(
self
):
def
test_detail_post_missing_role
(
self
):
resp
=
self
.
client
.
post
(
resp
=
self
.
client
.
post
(
...
@@ -152,6 +160,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -152,6 +160,7 @@ class UsersTestCase(CourseTestCase):
self
.
assert4XX
(
resp
.
status_code
)
self
.
assert4XX
(
resp
.
status_code
)
result
=
json
.
loads
(
resp
.
content
)
result
=
json
.
loads
(
resp
.
content
)
self
.
assertIn
(
"error"
,
result
)
self
.
assertIn
(
"error"
,
result
)
self
.
assert_not_enrolled
()
def
test_detail_post_bad_json
(
self
):
def
test_detail_post_bad_json
(
self
):
resp
=
self
.
client
.
post
(
resp
=
self
.
client
.
post
(
...
@@ -163,6 +172,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -163,6 +172,7 @@ class UsersTestCase(CourseTestCase):
self
.
assert4XX
(
resp
.
status_code
)
self
.
assert4XX
(
resp
.
status_code
)
result
=
json
.
loads
(
resp
.
content
)
result
=
json
.
loads
(
resp
.
content
)
self
.
assertIn
(
"error"
,
result
)
self
.
assertIn
(
"error"
,
result
)
self
.
assert_not_enrolled
()
def
test_detail_post_no_json
(
self
):
def
test_detail_post_no_json
(
self
):
resp
=
self
.
client
.
post
(
resp
=
self
.
client
.
post
(
...
@@ -176,6 +186,7 @@ class UsersTestCase(CourseTestCase):
...
@@ -176,6 +186,7 @@ class UsersTestCase(CourseTestCase):
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assertNotIn
(
self
.
inst_groupname
,
groups
)
self
.
assert_enrolled
()
def
test_detail_delete_staff
(
self
):
def
test_detail_delete_staff
(
self
):
group
,
_
=
Group
.
objects
.
get_or_create
(
name
=
self
.
staff_groupname
)
group
,
_
=
Group
.
objects
.
get_or_create
(
name
=
self
.
staff_groupname
)
...
@@ -317,3 +328,57 @@ class UsersTestCase(CourseTestCase):
...
@@ -317,3 +328,57 @@ class UsersTestCase(CourseTestCase):
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
ext_user
=
User
.
objects
.
get
(
email
=
self
.
ext_user
.
email
)
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
groups
=
[
g
.
name
for
g
in
ext_user
.
groups
.
all
()]
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
self
.
assertIn
(
self
.
staff_groupname
,
groups
)
def
test_user_not_initially_enrolled
(
self
):
# Verify that ext_user is not enrolled in the new course before being added as a staff member.
self
.
assert_not_enrolled
()
def
test_remove_staff_does_not_unenroll
(
self
):
# Add user with staff permissions.
self
.
client
.
post
(
self
.
detail_url
,
data
=
json
.
dumps
({
"role"
:
"staff"
}),
content_type
=
"application/json"
,
HTTP_ACCEPT
=
"application/json"
,
)
self
.
assert_enrolled
()
# Remove user from staff on course. Will not un-enroll them from the course.
resp
=
self
.
client
.
delete
(
self
.
detail_url
,
HTTP_ACCEPT
=
"application/json"
,
)
self
.
assert2XX
(
resp
.
status_code
)
self
.
assert_enrolled
()
def
test_staff_to_instructor_still_enrolled
(
self
):
# Add user with staff permission.
self
.
client
.
post
(
self
.
detail_url
,
data
=
json
.
dumps
({
"role"
:
"staff"
}),
content_type
=
"application/json"
,
HTTP_ACCEPT
=
"application/json"
,
)
self
.
assert_enrolled
()
# Now add with instructor permission. Verify still enrolled.
resp
=
self
.
client
.
post
(
self
.
detail_url
,
data
=
json
.
dumps
({
"role"
:
"instructor"
}),
content_type
=
"application/json"
,
HTTP_ACCEPT
=
"application/json"
,
)
self
.
assert2XX
(
resp
.
status_code
)
self
.
assert_enrolled
()
def
assert_not_enrolled
(
self
):
""" Asserts that self.ext_user is not enrolled in self.course. """
self
.
assertFalse
(
is_enrolled_in_course
(
self
.
ext_user
,
self
.
course
.
location
.
course_id
),
'Did not expect ext_user to be enrolled in course'
)
def
assert_enrolled
(
self
):
""" Asserts that self.ext_user is enrolled in self.course. """
self
.
assertTrue
(
is_enrolled_in_course
(
self
.
ext_user
,
self
.
course
.
location
.
course_id
),
'User ext_user should have been enrolled in the course'
)
cms/djangoapps/contentstore/views/course.py
View file @
4c95078e
...
@@ -44,6 +44,8 @@ from .component import (
...
@@ -44,6 +44,8 @@ from .component import (
from
django_comment_common.utils
import
seed_permissions_roles
from
django_comment_common.utils
import
seed_permissions_roles
from
student.views
import
enroll_in_course
from
xmodule.html_module
import
AboutDescriptor
from
xmodule.html_module
import
AboutDescriptor
__all__
=
[
'course_index'
,
'create_new_course'
,
'course_info'
,
__all__
=
[
'course_index'
,
'create_new_course'
,
'course_info'
,
'course_info_updates'
,
'get_course_settings'
,
'course_info_updates'
,
'get_course_settings'
,
...
@@ -162,6 +164,9 @@ def create_new_course(request):
...
@@ -162,6 +164,9 @@ def create_new_course(request):
# seed the forums
# seed the forums
seed_permissions_roles
(
new_course
.
location
.
course_id
)
seed_permissions_roles
(
new_course
.
location
.
course_id
)
# auto-enroll the course creator in the course so that "View Live" will work.
enroll_in_course
(
request
.
user
,
new_course
.
location
.
course_id
)
return
JsonResponse
({
'id'
:
new_course
.
location
.
url
()})
return
JsonResponse
({
'id'
:
new_course
.
location
.
url
()})
...
...
cms/djangoapps/contentstore/views/user.py
View file @
4c95078e
...
@@ -23,6 +23,8 @@ from course_creators.views import (
...
@@ -23,6 +23,8 @@ from course_creators.views import (
from
.access
import
has_access
from
.access
import
has_access
from
student.views
import
enroll_in_course
@login_required
@login_required
@ensure_csrf_cookie
@ensure_csrf_cookie
...
@@ -204,6 +206,8 @@ def course_team_user(request, org, course, name, email):
...
@@ -204,6 +206,8 @@ def course_team_user(request, org, course, name, email):
return
JsonResponse
(
msg
,
400
)
return
JsonResponse
(
msg
,
400
)
user
.
groups
.
add
(
groups
[
"instructor"
])
user
.
groups
.
add
(
groups
[
"instructor"
])
user
.
save
()
user
.
save
()
# auto-enroll the course creator in the course so that "View Live" will work.
enroll_in_course
(
user
,
location
.
course_id
)
elif
role
==
"staff"
:
elif
role
==
"staff"
:
# if we're trying to downgrade a user from "instructor" to "staff",
# if we're trying to downgrade a user from "instructor" to "staff",
# make sure we have at least one other instructor in the course team.
# make sure we have at least one other instructor in the course team.
...
@@ -217,6 +221,9 @@ def course_team_user(request, org, course, name, email):
...
@@ -217,6 +221,9 @@ def course_team_user(request, org, course, name, email):
user
.
groups
.
remove
(
groups
[
"instructor"
])
user
.
groups
.
remove
(
groups
[
"instructor"
])
user
.
groups
.
add
(
groups
[
"staff"
])
user
.
groups
.
add
(
groups
[
"staff"
])
user
.
save
()
user
.
save
()
# auto-enroll the course creator in the course so that "View Live" will work.
enroll_in_course
(
user
,
location
.
course_id
)
return
JsonResponse
()
return
JsonResponse
()
...
...
common/djangoapps/student/tests/tests.py
View file @
4c95078e
...
@@ -23,6 +23,7 @@ from textwrap import dedent
...
@@ -23,6 +23,7 @@ from textwrap import dedent
from
student.models
import
unique_id_for_user
from
student.models
import
unique_id_for_user
from
student.views
import
process_survey_link
,
_cert_info
,
password_reset
,
password_reset_confirm_wrapper
from
student.views
import
process_survey_link
,
_cert_info
,
password_reset
,
password_reset_confirm_wrapper
from
student.views
import
enroll_in_course
,
is_enrolled_in_course
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
student.tests.test_email
import
mock_render_to_string
from
student.tests.test_email
import
mock_render_to_string
COURSE_1
=
'edX/toy/2012_Fall'
COURSE_1
=
'edX/toy/2012_Fall'
...
@@ -205,3 +206,15 @@ class CourseEndingTest(TestCase):
...
@@ -205,3 +206,15 @@ class CourseEndingTest(TestCase):
'show_survey_button'
:
False
,
'show_survey_button'
:
False
,
'grade'
:
'67'
'grade'
:
'67'
})
})
class
EnrollInCourseTest
(
TestCase
):
""" Tests the helper method for enrolling a user in a class """
def
test_enroll_in_course
(
self
):
user
=
User
.
objects
.
create_user
(
"joe"
,
"joe@joe.com"
,
"password"
)
user
.
save
()
course_id
=
"course_id"
self
.
assertFalse
(
is_enrolled_in_course
(
user
,
course_id
))
enroll_in_course
(
user
,
course_id
)
self
.
assertTrue
(
is_enrolled_in_course
(
user
,
course_id
))
common/djangoapps/student/views.py
View file @
4c95078e
...
@@ -378,7 +378,7 @@ def change_enrollment(request):
...
@@ -378,7 +378,7 @@ def change_enrollment(request):
"run:{0}"
.
format
(
run
)])
"run:{0}"
.
format
(
run
)])
try
:
try
:
enroll
ment
,
_created
=
CourseEnrollment
.
objects
.
get_or_create
(
user
=
user
,
course_id
=
course
.
id
)
enroll
_in_course
(
user
,
course
.
id
)
except
IntegrityError
:
except
IntegrityError
:
# If we've already created this enrollment in a separate transaction,
# If we've already created this enrollment in a separate transaction,
# then just continue
# then just continue
...
@@ -403,6 +403,23 @@ def change_enrollment(request):
...
@@ -403,6 +403,23 @@ def change_enrollment(request):
return
HttpResponseBadRequest
(
_
(
"Enrollment action is invalid"
))
return
HttpResponseBadRequest
(
_
(
"Enrollment action is invalid"
))
def
enroll_in_course
(
user
,
course_id
):
"""
Helper method to enroll a user in a particular class.
It is expected that this method is called from a method which has already
verified the user authentication and access.
"""
CourseEnrollment
.
objects
.
get_or_create
(
user
=
user
,
course_id
=
course_id
)
def
is_enrolled_in_course
(
user
,
course_id
):
"""
Helper method that returns whether or not the user is enrolled in a particular course.
"""
return
CourseEnrollment
.
objects
.
filter
(
user
=
user
,
course_id
=
course_id
)
.
count
()
>
0
@ensure_csrf_cookie
@ensure_csrf_cookie
def
accounts_login
(
request
,
error
=
""
):
def
accounts_login
(
request
,
error
=
""
):
...
...
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