def test_set_global_course_creator_status(self): """ Test that "set_global_course_creator_status" method sets/removes a User as Global Course Creator correctly. """ self._create_edly_sub_organization() response = cookies_api.set_logged_in_edly_cookies( self.request, HttpResponse(), self.user, cookie_settings(self.request)) self._copy_cookies_to_request(response, self.request) edly_user_info_cookie = self.request.COOKIES.get( settings.EDLY_USER_INFO_COOKIE_NAME) edx_org = get_edx_org_from_cookie(edly_user_info_cookie) self.request.user = self.admin_user set_global_course_creator_status(self.request, self.user, True) assert self._get_course_creator_status(self.user) == 'granted' assert auth.user_has_role(self.user, GlobalCourseCreatorRole(edx_org)) set_global_course_creator_status(self.request, self.user, False) assert self._get_course_creator_status(self.user) == 'unrequested' assert not auth.user_has_role(self.user, GlobalCourseCreatorRole(edx_org)) self.admin_user.is_staff = False self.admin_user.save() with self.assertRaises(PermissionDenied): set_global_course_creator_status(self.request, self.user, True) edly_panel_admin_user_group, __ = Group.objects.get_or_create( name=settings.EDLY_PANEL_ADMIN_USERS_GROUP) self.admin_user.groups.add(edly_panel_admin_user_group) set_global_course_creator_status(self.request, self.user, True) assert self._get_course_creator_status(self.user) == 'granted' assert auth.user_has_role(self.user, CourseCreatorRole())
def test_update_creator_group(self): with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) update_course_creator_group(self.admin, self.user, True) self.assertTrue(auth.user_has_role(self.user, CourseCreatorRole())) update_course_creator_group(self.admin, self.user, False) self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole()))
def test_remove_user_from_course_group(self): """ Tests removing user from course group (happy path). """ add_users(self.global_admin, CourseInstructorRole(self.course_key), self.creator) add_users(self.global_admin, CourseStaffRole(self.course_key), self.creator) add_users(self.creator, CourseStaffRole(self.course_key), self.staff) self.assertTrue( user_has_role(self.staff, CourseStaffRole(self.course_key))) remove_users(self.creator, CourseStaffRole(self.course_key), self.staff) self.assertFalse( user_has_role(self.staff, CourseStaffRole(self.course_key))) add_users(self.creator, CourseAssistantRole(self.course_key), self.assistant) self.assertTrue( user_has_role(self.assistant, CourseAssistantRole(self.course_key))) remove_users(self.creator, CourseAssistantRole(self.course_key), self.assistant) self.assertFalse( user_has_role(self.assistant, CourseAssistantRole(self.course_key))) remove_users(self.creator, CourseInstructorRole(self.course_key), self.creator) self.assertFalse( user_has_role(self.creator, CourseInstructorRole(self.course_key)))
def test_detail_post_no_json(self): resp = self.client.post(self.detail_url, data={"role": "staff"}, HTTP_ACCEPT="application/json") self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_enrolled()
def test_creator_group_enabled_but_empty(self): """ Tests creator group feature on, but group empty. """ with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): self.assertFalse(user_has_role(self.user, CourseCreatorRole())) # Make user staff. This will cause CourseCreatorRole().has_user to return True. self.user.is_staff = True self.assertTrue(user_has_role(self.user, CourseCreatorRole()))
def test_detail_post(self): resp = self.client.post(self.detail_url, data={"role": ""}) self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) # no content: should not be in any roles self.assertFalse(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_not_enrolled()
def test_detail_post_no_json(self): resp = self.client.post( self.detail_url, data={"role": "staff"}, HTTP_ACCEPT="application/json", ) self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_enrolled()
def test_detail_post(self): resp = self.client.post( self.detail_url, data={"role": ""}, ) self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) # no content: should not be in any roles self.assertFalse(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_not_enrolled()
def test_add_granted(self): with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): # Calling add_user_with_status_granted impacts is_user_in_course_group_role. self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) add_user_with_status_granted(self.admin, self.user) self.assertEqual('granted', get_course_creator_status(self.user)) # Calling add again will be a no-op (even if state is different). add_user_with_status_unrequested(self.user) self.assertEqual('granted', get_course_creator_status(self.user)) self.assertTrue(auth.user_has_role(self.user, CourseCreatorRole()))
def test_creator_group_enabled_nonempty(self): """ Tests creator group feature on, user added. """ with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): add_users(self.admin, CourseCreatorRole(), self.user) self.assertTrue(user_has_role(self.user, CourseCreatorRole())) # check that a user who has not been added to the group still returns false user_not_added = User.objects.create_user('testuser2', '*****@*****.**', 'foo2') self.assertFalse(user_has_role(user_not_added, CourseCreatorRole())) # remove first user from the group and verify that CourseCreatorRole().has_user now returns false remove_users(self.admin, CourseCreatorRole(), self.user) self.assertFalse(user_has_role(self.user, CourseCreatorRole()))
def test_add_user_to_course_group(self): """ Tests adding user to course group (happy path). """ # Create groups for a new course (and assign instructor role to the creator). self.assertFalse(user_has_role(self.creator, CourseInstructorRole(self.course_key))) add_users(self.global_admin, CourseInstructorRole(self.course_key), self.creator) add_users(self.global_admin, CourseStaffRole(self.course_key), self.creator) self.assertTrue(user_has_role(self.creator, CourseInstructorRole(self.course_key))) # Add another user to the staff role. self.assertFalse(user_has_role(self.staff, CourseStaffRole(self.course_key))) add_users(self.creator, CourseStaffRole(self.course_key), self.staff) self.assertTrue(user_has_role(self.staff, CourseStaffRole(self.course_key)))
def test_remove_user_from_course_group(self): """ Tests removing user from course group (happy path). """ add_users(self.global_admin, CourseInstructorRole(self.course_key), self.creator) add_users(self.global_admin, CourseStaffRole(self.course_key), self.creator) add_users(self.creator, CourseStaffRole(self.course_key), self.staff) self.assertTrue(user_has_role(self.staff, CourseStaffRole(self.course_key))) remove_users(self.creator, CourseStaffRole(self.course_key), self.staff) self.assertFalse(user_has_role(self.staff, CourseStaffRole(self.course_key))) remove_users(self.creator, CourseInstructorRole(self.course_key), self.creator) self.assertFalse(user_has_role(self.creator, CourseInstructorRole(self.course_key)))
def get(self, request): """Gets a list of all course enrollments for a user. Returns a list for the currently logged in user, or for the user named by the 'user' GET parameter. If the username does not match the currently logged in user, only courses the requesting user has staff permissions for are listed. Only staff or instructor permissions on individual courses are taken into account when deciding whether the requesting user is permitted to see a particular enrollment, i.e. organizational staff access doesn't grant permission to see the enrollments in all courses of the organization. This may change in the future. However, users with global staff access can see all enrollments of all students. """ username = request.GET.get('user', request.user.username) try: enrollment_data = api.get_enrollments(username) except CourseEnrollmentError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ "message": ( u"An error occurred while retrieving enrollments for user '{username}'" ).format(username=username) } ) if username == request.user.username or GlobalStaff().has_user(request.user) or \ self.has_api_key_permissions(request): return Response(enrollment_data) filtered_data = [] for enrollment in enrollment_data: course_key = CourseKey.from_string(enrollment["course_details"]["course_id"]) if user_has_role(request.user, CourseStaffRole(course_key)): filtered_data.append(enrollment) return Response(filtered_data)
def is_course_staff(self, user, course_id): """ Returns True if the user is the course staff else Returns False """ return auth.user_has_role( user, CourseStaffRole(CourseKey.from_string(course_id)))
def get(self, request): """Gets a list of all course enrollments for a user. Returns a list for the currently logged in user, or for the user named by the 'user' GET parameter. If the username does not match the currently logged in user, only courses the requesting user has staff permissions for are listed. Only staff or instructor permissions on individual courses are taken into account when deciding whether the requesting user is permitted to see a particular enrollment, i.e. organizational staff access doesn't grant permission to see the enrollments in all courses of the organization. This may change in the future. However, users with global staff access can see all enrollments of all students. """ username = request.GET.get('user', request.user.username) try: enrollment_data = api.get_enrollments(username) except CourseEnrollmentError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ "message": (u"An error occurred while retrieving enrollments for user '{username}'" ).format(username=username) }) if username == request.user.username or GlobalStaff().has_user(request.user) or \ self.has_api_key_permissions(request): return Response(enrollment_data) filtered_data = [] for enrollment in enrollment_data: course_key = CourseKey.from_string( enrollment["course_details"]["course_id"]) if user_has_role(request.user, CourseStaffRole(course_key)): filtered_data.append(enrollment) return Response(filtered_data)
def _get_edly_user_info_cookie_string(request): """ Returns JWT encoded cookie string with edly user info. Arguments: request (HttpRequest): Django request object Returns: string """ try: edly_sub_organization = request.site.edly_sub_org_for_lms edly_user_info_cookie_data = { 'edly-org': edly_sub_organization.edly_organization.slug, 'edly-sub-org': edly_sub_organization.slug, 'edx-org': edly_sub_organization.edx_organization.short_name, 'is_course_creator': auth.user_has_role(request.user, CourseCreatorRole()) if getattr( request, 'user', None) else False, } return encode_edly_user_info_cookie(edly_user_info_cookie_data) except EdlySubOrganization.DoesNotExist: return ''
def get(self, request, course_id=None): """ List a course's enrollment roster; requires staff access **Example Request** GET /api/enrollment/v1/roster/course-v1:foo+bar+foobar { } """ try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid or missing course_id', }, ) if not user_has_role(request.user, CourseStaffRole(course_key)): return Response( status=status.HTTP_403_FORBIDDEN, data={ "message": u"User does not have permission to view roster for [{course_id}]." .format(course_id=course_id) }, ) roster = get_roster(course_id) return Response(data=json.dumps({'roster': roster}))
def put(self, request, course_id): """ Enroll a user in a course; requires staff access **Example Request** PUT /api/enrollment/v1/roster/course-v1:foo+bar+foobar { 'email': '*****@*****.**', 'email_students': false, 'auto_enroll': true } """ try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid or missing course_id', }, ) if not user_has_role(request.user, CourseStaffRole(course_key)): return Response( status=status.HTTP_403_FORBIDDEN, data={ 'message': u'User does not have permission to update enrollment for [{course_id}].' .format(course_id=course_id, ), }, ) email = request.data.get('email') try: validate_email(email) except ValidationError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid email address', }, ) email_students = request.data.get('email_students', False) in ['true', 'True', True] auto_enroll = request.data.get('auto_enroll', False) in ['true', 'True', True] email_params = {} language = None if email_students: course = get_course_by_id(course_key) email_params = get_email_params(course, auto_enroll) if User.objects.filter(email=email).exists(): user = User.objects.get(email=email) language = get_user_email_language(user) enroll_email(course_key, email, auto_enroll, email_students, email_params, language=language) return Response(status=status.HTTP_204_NO_CONTENT)
def test_detail_delete_instructor(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.ext_user, self.user) resp = self.client.delete(self.detail_url, HTTP_ACCEPT="application/json") self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id)))
def test_course_creation_disabled(self): """ Tests that the COURSE_CREATION_DISABLED flag overrides course creator group settings. """ with mock.patch.dict('django.conf.settings.FEATURES', {'DISABLE_COURSE_CREATION': True, "ENABLE_CREATOR_GROUP": True}): # Add user to creator group. add_users(self.admin, CourseCreatorRole(), self.user) # DISABLE_COURSE_CREATION overrides (user is not marked as staff). self.assertFalse(user_has_role(self.user, CourseCreatorRole())) # Mark as staff. Now CourseCreatorRole().has_user returns true. self.user.is_staff = True self.assertTrue(user_has_role(self.user, CourseCreatorRole())) # Remove user from creator group. CourseCreatorRole().has_user still returns true because is_staff=True remove_users(self.admin, CourseCreatorRole(), self.user) self.assertTrue(user_has_role(self.user, CourseCreatorRole()))
def test_detail_post_staff_other_inst(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.user) resp = self.client.post( self.detail_url, data=json.dumps({"role": "staff"}), content_type="application/json", HTTP_ACCEPT="application/json", ) self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id))) self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id))) self.assert_enrolled() # check that other user is unchanged user = User.objects.get(email=self.user.email) self.assertTrue(auth.user_has_role(user, CourseInstructorRole(self.course.id))) self.assertFalse(CourseStaffRole(self.course.id).has_user(user))
def test_post_last_instructor(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.ext_user) 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) self.assertTrue(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id)))
def test_add_user_not_active(self): """ Tests that adding to creator group fails if user is not active """ with mock.patch.dict('django.conf.settings.FEATURES', { 'DISABLE_COURSE_CREATION': False, "ENABLE_CREATOR_GROUP": True }): self.user.is_active = False add_users(self.admin, CourseCreatorRole(), self.user) self.assertFalse(user_has_role(self.user, CourseCreatorRole()))
def test_detail_delete_instructor(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.ext_user, self.user) resp = self.client.delete( self.detail_url, HTTP_ACCEPT="application/json", ) self.assertEqual(resp.status_code, 204) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertFalse(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id)))
def test_add_user_not_active(self): """ Tests that adding to creator group fails if user is not active """ with mock.patch.dict( 'django.conf.settings.FEATURES', {'DISABLE_COURSE_CREATION': False, "ENABLE_CREATOR_GROUP": True} ): self.user.is_active = False add_users(self.admin, CourseCreatorRole(), self.user) self.assertFalse(user_has_role(self.user, CourseCreatorRole()))
def is_mobile_available_for_user(user, descriptor): """ Returns whether the given course is mobile_available for the given user. Checks: mobile_available flag on the course Beta User and staff access overrides the mobile_available flag Arguments: descriptor (CourseDescriptor|CourseOverview): course or overview of course in question """ return (auth.user_has_role(user, CourseBetaTesterRole(descriptor.id)) or _has_staff_access_to_descriptor(user, descriptor, descriptor.id) or _is_descriptor_mobile_available(descriptor))
def test_staff_cannot_delete_other(self): auth.add_users(self.user, CourseStaffRole(self.course.id), self.user, self.ext_user) self.user.is_staff = False self.user.save() resp = self.client.delete(self.detail_url) self.assertEqual(resp.status_code, 403) result = json.loads(resp.content.decode('utf-8')) self.assertIn("error", result) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id)))
def test_staff_can_delete_self(self): auth.add_users(self.user, CourseStaffRole(self.course.id), self.user) self.user.is_staff = False self.user.save() self_url = self.course_team_url(email=self.user.email) resp = self.client.delete(self_url) self.assertEqual(resp.status_code, 204) # reload user from DB user = User.objects.get(email=self.user.email) self.assertFalse(auth.user_has_role(user, CourseStaffRole(self.course.id)))
def test_add_user_not_authenticated(self): """ Tests that adding to creator group fails if user is not authenticated """ with mock.patch.dict('django.conf.settings.FEATURES', { 'DISABLE_COURSE_CREATION': False, "ENABLE_CREATOR_GROUP": True }): anonymous_user = AnonymousUser() role = CourseCreatorRole() add_users(self.admin, role, anonymous_user) self.assertFalse(user_has_role(anonymous_user, role))
def test_staff_cannot_delete_other(self): auth.add_users(self.user, CourseStaffRole(self.course.id), self.user, self.ext_user) self.user.is_staff = False self.user.save() resp = self.client.delete(self.detail_url) self.assertEqual(resp.status_code, 403) result = json.loads(resp.content) self.assertIn("error", result) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertTrue(auth.user_has_role(ext_user, CourseStaffRole(self.course.id)))
def test_add_user_not_authenticated(self): """ Tests that adding to creator group fails if user is not authenticated """ with mock.patch.dict( 'django.conf.settings.FEATURES', {'DISABLE_COURSE_CREATION': False, "ENABLE_CREATOR_GROUP": True} ): anonymous_user = AnonymousUser() role = CourseCreatorRole() add_users(self.admin, role, anonymous_user) self.assertFalse(user_has_role(anonymous_user, role))
def test_delete_last_instructor(self): auth.add_users(self.user, CourseInstructorRole(self.course.id), self.ext_user) resp = self.client.delete( self.detail_url, HTTP_ACCEPT="application/json", ) self.assertEqual(resp.status_code, 400) result = json.loads(resp.content.decode('utf-8')) self.assertIn("error", result) # reload user from DB ext_user = User.objects.get(email=self.ext_user.email) self.assertTrue(auth.user_has_role(ext_user, CourseInstructorRole(self.course.id)))
def is_mobile_available_for_user(user, descriptor): """ Returns whether the given course is mobile_available for the given user. Checks: mobile_available flag on the course Beta User and staff access overrides the mobile_available flag Arguments: descriptor (CourseDescriptor|CourseOverview): course or overview of course in question """ return ( auth.user_has_role(user, CourseBetaTesterRole(descriptor.id)) or _has_staff_access_to_descriptor(user, descriptor, descriptor.id) or _is_descriptor_mobile_available(descriptor) )
def test_update_course_creator_status(self): """ Test that "update_course_creator_status" method sets/removes a User as Course Creator correctly. """ settings.FEATURES['ENABLE_CREATOR_GROUP'] = True update_course_creator_status(self.admin_user, self.user, True) assert self._get_course_creator_status(self.user) == 'granted' assert auth.user_has_role(self.user, CourseCreatorRole()) update_course_creator_status(self.admin_user, self.user, False) assert self._get_course_creator_status(self.user) == 'unrequested' assert not auth.user_has_role(self.user, CourseCreatorRole()) self.admin_user.is_staff = False self.admin_user.save() with self.assertRaises(PermissionDenied): update_course_creator_status(self.admin_user, self.user, True) edly_panel_admin_user_group, __ = Group.objects.get_or_create( name=settings.EDLY_PANEL_ADMIN_USERS_GROUP) self.admin_user.groups.add(edly_panel_admin_user_group) update_course_creator_status(self.admin_user, self.user, False) assert self._get_course_creator_status(self.user) == 'unrequested' assert not auth.user_has_role(self.user, CourseCreatorRole())
def load_data(self): """Pull dates information from edx-when.""" # (usage_key, 'due'): datetime.datetime(2019, 12, 11, 15, 0, tzinfo=<UTC>) # TODO: Merge https://github.com/edx/edx-when/pull/48 and add `outline_only=True` self.dates = get_dates_for_course(self.course_key, self.user) for (usage_key, field_name), date in self.dates.items(): self.keys_to_schedule_fields[usage_key][field_name] = date course_usage_key = self.course_key.make_usage_key('course', 'course') self._course_start = self.keys_to_schedule_fields[ course_usage_key].get('start') self._course_end = self.keys_to_schedule_fields[course_usage_key].get( 'end') self._is_beta_tester = user_has_role( self.user, CourseBetaTesterRole(self.course_key))
def get_user_role(user, course_id): """ What type of access: staff or instructor does this user have in Studio? No code should use this for access control, only to quickly serialize the type of access where this code knows that Instructor trumps Staff and assumes the user has one or the other. This will not return student role because its purpose for using in Studio. :param course_id: the course_id of the course we're interested in """ # afaik, this is only used in lti if auth.user_has_role(user, CourseInstructorRole(course_id)): return 'instructor' else: return 'staff'
def delete(self, request, course_id): """ Unenroll a user from a course; requires staff access **Example Request** DELETE /api/enrollment/v1/roster/course-v1:foo+bar+foobar { 'email': '*****@*****.**', 'email_students': false, 'auto_enroll': true } """ try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid or missing course_id', }, ) if not user_has_role(request.user, CourseStaffRole(course_key)): return Response( status=status.HTTP_403_FORBIDDEN, data={ 'message': u'User does not have permission to update enrollment for [{course_id}].'.format( course_id=course_id, ), }, ) email = request.data.get('email') try: validate_email(email) except ValidationError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid email address', }, ) email_students, auto_enroll, email_params, language = self.api_params_helper(request, course_key, email) unenroll_email( course_key, email, email_students, email_params, language=language ) return Response(status=status.HTTP_204_NO_CONTENT)
def put(self, request, course_id): """ Enroll a user in a course; requires staff access **Example Request** PUT /api/enrollment/v1/roster/course-v1:foo+bar+foobar { 'email': '*****@*****.**', 'email_students': false, 'auto_enroll': true } """ try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid or missing course_id', }, ) if not user_has_role(request.user, CourseStaffRole(course_key)): return Response( status=status.HTTP_403_FORBIDDEN, data={ 'message': u'User does not have permission to update enrollment for [{course_id}].'.format( course_id=course_id, ), }, ) email = request.data.get('email') try: validate_email(email) except ValidationError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid email address', }, ) email_students, auto_enroll, email_params, language = self.api_params_helper(request, course_key, email) enroll_email( course_key, email, auto_enroll, email_students, email_params, language=language ) return Response(status=status.HTTP_204_NO_CONTENT)
def change_state_and_verify_email(state, is_creator): """ Changes user state, verifies creator status, and verifies e-mail is sent based on transition """ self._change_state(state) self.assertEqual(is_creator, auth.user_has_role(self.user, CourseCreatorRole())) context = {'studio_request_email': self.studio_request_email} if state == CourseCreator.GRANTED: template = 'emails/course_creator_granted.txt' elif state == CourseCreator.DENIED: template = 'emails/course_creator_denied.txt' else: template = 'emails/course_creator_revoked.txt' email_user.assert_called_with( mock_render_to_string('emails/course_creator_subject.txt', context), mock_render_to_string(template, context), self.studio_request_email )
def test_change_status(self, email_user): """ Tests that updates to state impact the creator group maintained in authz.py and that e-mails are sent. """ def change_state_and_verify_email(state, is_creator): """ Changes user state, verifies creator status, and verifies e-mail is sent based on transition """ self._change_state(state) self.assertEqual( is_creator, auth.user_has_role(self.user, CourseCreatorRole())) context = {'studio_request_email': self.studio_request_email} if state == CourseCreator.GRANTED: template = 'emails/course_creator_granted.txt' elif state == CourseCreator.DENIED: template = 'emails/course_creator_denied.txt' else: template = 'emails/course_creator_revoked.txt' email_user.assert_called_with( mock_render_to_string('emails/course_creator_subject.txt', context), mock_render_to_string(template, context), self.studio_request_email) with mock.patch.dict('django.conf.settings.FEATURES', self.enable_creator_group_patch): # User is initially unrequested. self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) change_state_and_verify_email(CourseCreator.GRANTED, True) change_state_and_verify_email(CourseCreator.DENIED, False) change_state_and_verify_email(CourseCreator.GRANTED, True) change_state_and_verify_email(CourseCreator.PENDING, False) change_state_and_verify_email(CourseCreator.GRANTED, True) change_state_and_verify_email(CourseCreator.UNREQUESTED, False) change_state_and_verify_email(CourseCreator.DENIED, False)
def get(self, request, course_id=None): """ HTTP endpoint for retrieving roster """ try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: return Response( status=status.HTTP_400_BAD_REQUEST, data={"message": u"Invalid or missing course_id"}, ) if not user_has_role(request.user, CourseStaffRole(course_key)): return Response( status=status.HTTP_403_FORBIDDEN, data={"message": u"User does not have permission to view roster for [{course_id}].".format(course_id=course_id)}, ) roster = api.get_roster(course_id) return Response(data=json.dumps({'roster': roster}))
def test_change_status(self, email_user): """ Tests that updates to state impact the creator group maintained in authz.py and that e-mails are sent. """ def change_state_and_verify_email(state, is_creator): """ Changes user state, verifies creator status, and verifies e-mail is sent based on transition """ self._change_state(state) self.assertEqual(is_creator, auth.user_has_role(self.user, CourseCreatorRole())) context = {'studio_request_email': self.studio_request_email} if state == CourseCreator.GRANTED: template = 'emails/course_creator_granted.txt' elif state == CourseCreator.DENIED: template = 'emails/course_creator_denied.txt' else: template = 'emails/course_creator_revoked.txt' email_user.assert_called_with( mock_render_to_string('emails/course_creator_subject.txt', context), mock_render_to_string(template, context), self.studio_request_email ) with mock.patch.dict('django.conf.settings.FEATURES', self.enable_creator_group_patch): # User is initially unrequested. self.assertFalse(auth.user_has_role(self.user, CourseCreatorRole())) change_state_and_verify_email(CourseCreator.GRANTED, True) change_state_and_verify_email(CourseCreator.DENIED, False) change_state_and_verify_email(CourseCreator.GRANTED, True) change_state_and_verify_email(CourseCreator.PENDING, False) change_state_and_verify_email(CourseCreator.GRANTED, True) change_state_and_verify_email(CourseCreator.UNREQUESTED, False) change_state_and_verify_email(CourseCreator.DENIED, False)
def get(self, request): """Gets a list of all course enrollments for a user. Returns a list for the currently logged in user, or for the user named by the 'user' GET parameter. If the username does not match that of the currently logged in user, only courses for which the currently logged in user has the Staff or Admin role are listed. As a result, a course team member can find out which of his or her own courses a particular learner is enrolled in. Only the Staff or Admin role (granted on the Django administrative console as the staff or instructor permission) in individual courses gives the requesting user access to enrollment data. Permissions granted at the organizational level do not give a user access to enrollment data for all of that organization's courses. Users who have the global staff permission can access all enrollment data for all courses. """ username = request.GET.get('user', request.user.username) try: # Edraak: pass request to api.get_enrollments enrollment_data = api.get_enrollments(username, request=request) except CourseEnrollmentError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ "message": ( u"An error occurred while retrieving enrollments for user '{username}'" ).format(username=username) } ) if username == request.user.username or GlobalStaff().has_user(request.user) or \ self.has_api_key_permissions(request): return Response(enrollment_data) filtered_data = [] for enrollment in enrollment_data: course_key = CourseKey.from_string(enrollment["course_details"]["course_id"]) if user_has_role(request.user, CourseStaffRole(course_key)): filtered_data.append(enrollment) return Response(filtered_data)
def get(self, request): """Gets a list of all course enrollments for a user. Returns a list for the currently logged in user, or for the user named by the 'user' GET parameter. If the username does not match that of the currently logged in user, only courses for which the currently logged in user has the Staff or Admin role are listed. As a result, a course team member can find out which of his or her own courses a particular learner is enrolled in. Only the Staff or Admin role (granted on the Django administrative console as the staff or instructor permission) in individual courses gives the requesting user access to enrollment data. Permissions granted at the organizational level do not give a user access to enrollment data for all of that organization's courses. Users who have the global staff permission can access all enrollment data for all courses. """ username = request.GET.get('user', request.user.username) try: enrollment_data = api.get_enrollments(username) print enrollment_data except CourseEnrollmentError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ "message": (u"An error occurred while retrieving enrollments for user '{username}'" ).format(username=username) }) if username == request.user.username or GlobalStaff().has_user(request.user) or \ self.has_api_key_permissions(request): return Response(enrollment_data) filtered_data = [] for enrollment in enrollment_data: course_key = CourseKey.from_string( enrollment["course_details"]["course_id"]) if user_has_role(request.user, CourseStaffRole(course_key)): filtered_data.append(enrollment) return Response(filtered_data)
def get(self, request, course_id=None): """ List a course's enrollment roster; requires staff access **Example Request** GET /api/enrollment/v1/roster/course-v1:foo+bar+foobar { } """ try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: return Response( status=status.HTTP_400_BAD_REQUEST, data={ 'message': u'Invalid or missing course_id', }, ) if not user_has_role(request.user, CourseStaffRole(course_key)): return Response( status=status.HTTP_403_FORBIDDEN, data={"message": u"User does not have permission to view roster for [{course_id}].".format(course_id=course_id)}, ) roster = get_roster(course_id) return Response(data=json.dumps({'roster': roster}))
def test_creator_group_not_enabled(self): """ Tests that CourseCreatorRole().has_user always returns True if ENABLE_CREATOR_GROUP and DISABLE_COURSE_CREATION are both not turned on. """ self.assertTrue(user_has_role(self.user, CourseCreatorRole()))
def is_course_staff(self, user, course_id): """ Returns True if the user is the course staff else Returns False """ return auth.user_has_role(user, CourseStaffRole(CourseKey.from_string(course_id)))