test_users.py 14.2 KB
Newer Older
1 2 3
"""
Tests for contentstore/views/user.py.
"""
4
import json
5
from .utils import CourseTestCase
6 7 8
from django.contrib.auth.models import User, Group
from django.core.urlresolvers import reverse
from auth.authz import get_course_groupname_for_role
9
from student.models import CourseEnrollment
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53


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)
54 55
        # ext_user is not currently a member of the course team, and so should
        # not show up on the page.
56 57
        self.assertNotContains(resp, self.ext_user.email)

58 59 60 61 62 63 64 65
    def test_index_member(self):
        group, _ = Group.objects.get_or_create(name=self.staff_groupname)
        self.ext_user.groups.add(group)
        self.ext_user.save()

        resp = self.client.get(self.index_url)
        self.assertContains(resp, self.ext_user.email)

66 67 68 69 70 71 72 73 74
    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)
75
        self.assertEqual(resp.status_code, 200)
76 77 78 79 80
        result = json.loads(resp.content)
        self.assertFalse(result["active"])

    def test_detail_invalid(self):
        resp = self.client.get(self.invalid_detail_url)
81
        self.assertEqual(resp.status_code, 404)
82 83 84 85 86 87 88 89
        result = json.loads(resp.content)
        self.assertIn("error", result)

    def test_detail_post(self):
        resp = self.client.post(
            self.detail_url,
            data={"role": None},
        )
90
        self.assertEqual(resp.status_code, 204)
91 92 93 94 95 96
        # 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)
97
        self.assert_not_enrolled()
98 99 100 101 102 103 104 105

    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",
        )
106
        self.assertEqual(resp.status_code, 204)
107 108 109 110 111
        # 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)
112
        self.assert_enrolled()
113

114 115 116 117 118 119 120 121 122 123 124
    def test_detail_post_staff_other_inst(self):
        inst_group, _ = Group.objects.get_or_create(name=self.inst_groupname)
        self.user.groups.add(inst_group)
        self.user.save()

        resp = self.client.post(
            self.detail_url,
            data=json.dumps({"role": "staff"}),
            content_type="application/json",
            HTTP_ACCEPT="application/json",
        )
125
        self.assertEqual(resp.status_code, 204)
126 127 128 129 130
        # 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)
131
        self.assert_enrolled()
132 133 134 135 136 137
        # check that other user is unchanged
        user = User.objects.get(email=self.user.email)
        groups = [g.name for g in user.groups.all()]
        self.assertNotIn(self.staff_groupname, groups)
        self.assertIn(self.inst_groupname, groups)

138 139 140 141 142 143 144
    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",
        )
145
        self.assertEqual(resp.status_code, 204)
146 147 148 149 150
        # 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)
151
        self.assert_enrolled()
152 153 154 155 156 157 158 159

    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",
        )
160
        self.assertEqual(resp.status_code, 400)
161 162
        result = json.loads(resp.content)
        self.assertIn("error", result)
163
        self.assert_not_enrolled()
164 165 166 167 168 169 170 171

    def test_detail_post_bad_json(self):
        resp = self.client.post(
            self.detail_url,
            data="{foo}",
            content_type="application/json",
            HTTP_ACCEPT="application/json",
        )
172
        self.assertEqual(resp.status_code, 400)
173 174
        result = json.loads(resp.content)
        self.assertIn("error", result)
175
        self.assert_not_enrolled()
176 177 178 179 180 181 182

    def test_detail_post_no_json(self):
        resp = self.client.post(
            self.detail_url,
            data={"role": "staff"},
            HTTP_ACCEPT="application/json",
        )
183
        self.assertEqual(resp.status_code, 204)
184 185 186 187 188
        # 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)
189
        self.assert_enrolled()
190 191 192 193 194 195 196 197 198 199

    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",
        )
200
        self.assertEqual(resp.status_code, 204)
201 202 203 204 205 206 207
        # 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)
208
        self.user.groups.add(group)
209
        self.ext_user.groups.add(group)
210
        self.user.save()
211 212 213 214 215 216
        self.ext_user.save()

        resp = self.client.delete(
            self.detail_url,
            HTTP_ACCEPT="application/json",
        )
217
        self.assertEqual(resp.status_code, 204)
218 219 220 221
        # 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)
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256

    def test_delete_last_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.assertEqual(resp.status_code, 400)
        result = json.loads(resp.content)
        self.assertIn("error", result)
        # 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.inst_groupname, groups)

    def test_post_last_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.post(
            self.detail_url,
            data={"role": "staff"},
            HTTP_ACCEPT="application/json",
        )
        self.assertEqual(resp.status_code, 400)
        result = json.loads(resp.content)
        self.assertIn("error", result)
        # 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.inst_groupname, groups)
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275

    def test_permission_denied_self(self):
        group, _ = Group.objects.get_or_create(name=self.staff_groupname)
        self.user.groups.add(group)
        self.user.is_staff = False
        self.user.save()

        self_url = reverse("course_team_user", kwargs={
            "org": self.course.location.org,
            "course": self.course.location.course,
            "name": self.course.location.name,
            "email": self.user.email,
        })

        resp = self.client.post(
            self_url,
            data={"role": "instructor"},
            HTTP_ACCEPT="application/json",
        )
276
        self.assertEqual(resp.status_code, 400)
277 278 279 280 281 282 283 284 285 286 287 288 289 290
        result = json.loads(resp.content)
        self.assertIn("error", result)

    def test_permission_denied_other(self):
        group, _ = Group.objects.get_or_create(name=self.staff_groupname)
        self.user.groups.add(group)
        self.user.is_staff = False
        self.user.save()

        resp = self.client.post(
            self.detail_url,
            data={"role": "instructor"},
            HTTP_ACCEPT="application/json",
        )
291
        self.assertEqual(resp.status_code, 400)
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
        result = json.loads(resp.content)
        self.assertIn("error", result)

    def test_staff_can_delete_self(self):
        group, _ = Group.objects.get_or_create(name=self.staff_groupname)
        self.user.groups.add(group)
        self.user.is_staff = False
        self.user.save()

        self_url = reverse("course_team_user", kwargs={
            "org": self.course.location.org,
            "course": self.course.location.course,
            "name": self.course.location.name,
            "email": self.user.email,
        })

        resp = self.client.delete(self_url)
309
        self.assertEqual(resp.status_code, 204)
310 311 312 313 314 315 316 317 318 319 320 321 322 323
        # reload user from DB
        user = User.objects.get(email=self.user.email)
        groups = [g.name for g in user.groups.all()]
        self.assertNotIn(self.staff_groupname, groups)

    def test_staff_cannot_delete_other(self):
        group, _ = Group.objects.get_or_create(name=self.staff_groupname)
        self.user.groups.add(group)
        self.user.is_staff = False
        self.user.save()
        self.ext_user.groups.add(group)
        self.ext_user.save()

        resp = self.client.delete(self.detail_url)
324
        self.assertEqual(resp.status_code, 400)
325 326 327 328 329 330
        result = json.loads(resp.content)
        self.assertIn("error", result)
        # 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)
331 332 333 334 335

    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()

336
    def test_remove_staff_does_not_unenroll(self):
337 338 339 340 341 342 343 344 345 346 347 348 349
        # 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",
        )
350
        self.assertEqual(resp.status_code, 204)
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
        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",
        )
369
        self.assertEqual(resp.status_code, 204)
370 371 372 373
        self.assert_enrolled()

    def assert_not_enrolled(self):
        """ Asserts that self.ext_user is not enrolled in self.course. """
374
        self.assertFalse(
375
            CourseEnrollment.is_enrolled(self.ext_user, self.course.location.course_id),
376 377 378 379 380
            'Did not expect ext_user to be enrolled in course'
        )

    def assert_enrolled(self):
        """ Asserts that self.ext_user is enrolled in self.course. """
381
        self.assertTrue(
382
            CourseEnrollment.is_enrolled(self.ext_user, self.course.location.course_id),
383 384
            'User ext_user should have been enrolled in the course'
        )