Commit f438552b by David Baumgold

Added unit tests for new course team API

parent 97a02d41
import json
from .utils import CourseTestCase
from django.contrib.auth.models import User, Group
from django.core.urlresolvers import reverse
from auth.authz import get_course_groupname_for_role
class UsersTestCase(CourseTestCase):
def setUp(self):
super(UsersTestCase, self).setUp()
self.ext_user = User.objects.create_user(
"joe", "joe@comedycentral.com", "haha")
self.ext_user.is_active = True
self.ext_user.is_staff = False
self.ext_user.save()
self.inactive_user = User.objects.create_user(
"carl", "carl@comedycentral.com", "haha")
self.inactive_user.is_active = False
self.inactive_user.is_staff = False
self.inactive_user.save()
self.index_url = reverse("manage_users", kwargs={
"org": self.course.location.org,
"course": self.course.location.course,
"name": self.course.location.name,
})
self.detail_url = reverse("course_team_user", kwargs={
"org": self.course.location.org,
"course": self.course.location.course,
"name": self.course.location.name,
"email": self.ext_user.email,
})
self.inactive_detail_url = reverse("course_team_user", kwargs={
"org": self.course.location.org,
"course": self.course.location.course,
"name": self.course.location.name,
"email": self.inactive_user.email,
})
self.invalid_detail_url = reverse("course_team_user", kwargs={
"org": self.course.location.org,
"course": self.course.location.course,
"name": self.course.location.name,
"email": "nonexistent@user.com",
})
self.staff_groupname = get_course_groupname_for_role(self.course.location, "staff")
self.inst_groupname = get_course_groupname_for_role(self.course.location, "instructor")
def test_index(self):
resp = self.client.get(self.index_url)
self.assertNotContains(resp, self.ext_user.email)
def test_detail(self):
resp = self.client.get(self.detail_url)
self.assertEqual(resp.status_code, 200)
result = json.loads(resp.content)
self.assertEqual(result["role"], None)
self.assertTrue(result["active"])
def test_detail_inactive(self):
resp = self.client.get(self.inactive_detail_url)
self.assert2XX(resp.status_code)
result = json.loads(resp.content)
self.assertFalse(result["active"])
def test_detail_invalid(self):
resp = self.client.get(self.invalid_detail_url)
self.assert4XX(resp.status_code)
result = json.loads(resp.content)
self.assertIn("error", result)
def test_detail_post(self):
resp = self.client.post(
self.detail_url,
data={"role": None},
)
self.assert2XX(resp.status_code)
# reload user from DB
ext_user = User.objects.get(email=self.ext_user.email)
groups = [g.name for g in ext_user.groups.all()]
# no content: should not be in any roles
self.assertNotIn(self.staff_groupname, groups)
self.assertNotIn(self.inst_groupname, groups)
def test_detail_post_staff(self):
resp = self.client.post(
self.detail_url,
data=json.dumps({"role": "staff"}),
content_type="application/json",
HTTP_ACCEPT="application/json",
)
self.assert2XX(resp.status_code)
# reload user from DB
ext_user = User.objects.get(email=self.ext_user.email)
groups = [g.name for g in ext_user.groups.all()]
self.assertIn(self.staff_groupname, groups)
self.assertNotIn(self.inst_groupname, groups)
def test_detail_post_instructor(self):
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)
# reload user from DB
ext_user = User.objects.get(email=self.ext_user.email)
groups = [g.name for g in ext_user.groups.all()]
self.assertNotIn(self.staff_groupname, groups)
self.assertIn(self.inst_groupname, groups)
def test_detail_post_missing_role(self):
resp = self.client.post(
self.detail_url,
data=json.dumps({"toys": "fun"}),
content_type="application/json",
HTTP_ACCEPT="application/json",
)
self.assert4XX(resp.status_code)
result = json.loads(resp.content)
self.assertIn("error", result)
def test_detail_post_bad_json(self):
resp = self.client.post(
self.detail_url,
data="{foo}",
content_type="application/json",
HTTP_ACCEPT="application/json",
)
self.assert4XX(resp.status_code)
result = json.loads(resp.content)
self.assertIn("error", result)
def test_detail_post_no_json(self):
resp = self.client.post(
self.detail_url,
data={"role": "staff"},
HTTP_ACCEPT="application/json",
)
self.assert2XX(resp.status_code)
# reload user from DB
ext_user = User.objects.get(email=self.ext_user.email)
groups = [g.name for g in ext_user.groups.all()]
self.assertIn(self.staff_groupname, groups)
self.assertNotIn(self.inst_groupname, groups)
def test_detail_delete_staff(self):
group, _ = Group.objects.get_or_create(name=self.staff_groupname)
self.ext_user.groups.add(group)
self.ext_user.save()
resp = self.client.delete(
self.detail_url,
HTTP_ACCEPT="application/json",
)
self.assert2XX(resp.status_code)
# reload user from DB
ext_user = User.objects.get(email=self.ext_user.email)
groups = [g.name for g in ext_user.groups.all()]
self.assertNotIn(self.staff_groupname, groups)
def test_detail_delete_instructor(self):
group, _ = Group.objects.get_or_create(name=self.inst_groupname)
self.ext_user.groups.add(group)
self.ext_user.save()
resp = self.client.delete(
self.detail_url,
HTTP_ACCEPT="application/json",
)
self.assert2XX(resp.status_code)
# reload user from DB
ext_user = User.objects.get(email=self.ext_user.email)
groups = [g.name for g in ext_user.groups.all()]
self.assertNotIn(self.inst_groupname, groups)
...@@ -111,20 +111,23 @@ def course_team_user(request, org, course, name, email): ...@@ -111,20 +111,23 @@ def course_team_user(request, org, course, name, email):
} }
return JsonResponse(msg, 404) return JsonResponse(msg, 404)
# role hierarchy: "instructor" has more permissions than "staff" (in a course)
roles = ["instructor", "staff"]
if request.method == "GET": if request.method == "GET":
# just return info about the user # just return info about the user
roles = set()
for group in user.groups.all():
if not "_" in group.name:
continue
role, coursename = group.name.split("_", 1)
if coursename in (location.course, location.course_id):
roles.add(role)
msg = { msg = {
"email": user.email, "email": user.email,
"active": user.is_active, "active": user.is_active,
"roles": list(roles), "role": None,
} }
# what's the highest role that this user has?
groupnames = set(g.name for g in user.groups.all())
for role in roles:
role_groupname = get_course_groupname_for_role(location, role)
if role_groupname in groupnames:
msg["role"] = role
break
return JsonResponse(msg) return JsonResponse(msg)
# can't modify an inactive user # can't modify an inactive user
...@@ -134,11 +137,14 @@ def course_team_user(request, org, course, name, email): ...@@ -134,11 +137,14 @@ def course_team_user(request, org, course, name, email):
} }
return JsonResponse(msg, 400) return JsonResponse(msg, 400)
# all other operations require the requesting user to specify a role -- if request.method == "DELETE":
# or if no role is specified, default to "staff" # remove all roles in this course from this user
if not request.body: for role in roles:
role = STAFF_ROLE_NAME remove_user_from_course_group(request.user, user, location, role)
else: return JsonResponse()
# all other operations require the requesting user to specify a role
if request.META.get("CONTENT_TYPE", "") == "application/json" and request.body:
try: try:
payload = json.loads(request.body) payload = json.loads(request.body)
except: except:
...@@ -147,15 +153,21 @@ def course_team_user(request, org, course, name, email): ...@@ -147,15 +153,21 @@ def course_team_user(request, org, course, name, email):
role = payload["role"] role = payload["role"]
except KeyError: except KeyError:
return JsonResponse({"error": "`role` is required"}, 400) return JsonResponse({"error": "`role` is required"}, 400)
else:
if not "role" in request.POST:
return JsonResponse({"error": "`role` is required"}, 400)
role = request.POST["role"]
# make sure that the role group exists
groupname = get_course_groupname_for_role(location, role) groupname = get_course_groupname_for_role(location, role)
group = Group.objects.get_or_create(name=groupname) Group.objects.get_or_create(name=groupname)
if request.method in ("POST", "PUT"): if role == "instructor":
add_user_to_course_group(request.user, user, location, role) add_user_to_course_group(request.user, user, location, role)
return JsonResponse() elif role == "staff":
elif request.method == "DELETE": add_user_to_course_group(request.user, user, location, role)
remove_user_from_course_group(request.user, user, location, role) remove_user_from_course_group(request.user, user, location, "instructor")
return JsonResponse() return JsonResponse()
def _get_course_creator_status(user): def _get_course_creator_status(user):
......
...@@ -140,9 +140,6 @@ ...@@ -140,9 +140,6 @@
type: 'DELETE', type: 'DELETE',
dataType: 'json', dataType: 'json',
contentType: 'application/json', contentType: 'application/json',
data: JSON.stringify({
role: 'staff',
}),
complete: function() { complete: function() {
location.reload(); location.reload();
} }
...@@ -153,18 +150,18 @@ ...@@ -153,18 +150,18 @@
e.preventDefault() e.preventDefault()
var type; var type;
if($(this).hasClass("add-admin")) { if($(this).hasClass("add-admin")) {
type = 'POST'; role = 'instructor';
} else { } else {
type = 'DELETE'; role = 'staff';
} }
var url = $(this).closest("li").data("url"); var url = $(this).closest("li").data("url");
$.ajax({ $.ajax({
url: url, url: url,
type: type, type: 'POST',
dataType: 'json', dataType: 'json',
contentType: 'application/json', contentType: 'application/json',
data: JSON.stringify({ data: JSON.stringify({
role: 'instructor', role: role
}), }),
complete: function() { complete: function() {
location.reload(); location.reload();
......
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