def restore_object(self, attrs, instance=None): user = self.context['request'].user classgroup = attrs.get('classgroup') attributes = ["text", "source", "reply_to"] if (classgroup.class_settings is not None and classgroup.class_settings.enable_posting is False and not ClassGroupPermissions.is_teacher(classgroup, user)): raise serializers.ValidationError( "You are not allowed to make a post right now.") if instance is None: instance = Message(user=user, classgroup=classgroup) else: if instance.user != user: raise serializers.ValidationError( "Attempting to edit a message that is not yours.") message_type = attrs.get('message_type') if message_type == "A" and not ClassGroupPermissions.is_teacher( classgroup, user): raise serializers.ValidationError( "You cannot make an announcement unless you own a course.") instance.message_type = message_type instance = set_attributes(attributes, attrs, instance) instance.save() return instance
def restore_object(self, attrs, instance=None): user = self.context['request'].user classgroup = attrs.get('classgroup') attributes = ["text", "source", "reply_to"] if (classgroup.class_settings is not None and classgroup.class_settings.enable_posting is False and not ClassGroupPermissions.is_teacher(classgroup, user)): raise serializers.ValidationError("You are not allowed to make a post right now.") if instance is None: instance = Message(user=user, classgroup=classgroup) else: if instance.user != user: raise serializers.ValidationError("Attempting to edit a message that is not yours.") message_type = attrs.get('message_type') if message_type == "A" and not ClassGroupPermissions.is_teacher(classgroup, user): raise serializers.ValidationError("You cannot make an announcement unless you own a course.") instance.message_type = message_type instance = set_attributes(attributes, attrs, instance) instance.save() return instance
def child_user_views(self): """ Gets the user views for the children of this module. Used when rendering a vertical. """ child_views = [] children = self.get_children() # Store data to prevent descriptor overwrite by children. self.module.store_data() for child in children: child_access_level = ClassGroupPermissions.get_permission_level( child.classgroup, child, "change_resource") user_access_level = ClassGroupPermissions.access_level( child.classgroup, self.user) if ClassGroupPermissions.PERMISSION_LEVELS[ user_access_level] >= ClassGroupPermissions.PERMISSION_LEVELS[ child_access_level]: user_state, created = UserResourceState.objects.get_or_create( user=self.user, resource=child) renderer = ResourceRenderer(child, user_resource_state=user_state, static_data=self.static_data, user=self.user) child_views.append(renderer.user_view()) # Read data back in. self.module.read_data() return child_views
def test_enroll_in_course(self): """ Try enrolling in a course with an access code. """ access_key = self.cg.class_settings.access_key self.c1.post(reverse('verify_code'), {'class_name': self.cg.name, 'code': access_key}) # Check that the user has the right permissions. self.assertIn(self.user1, self.cg.users.all()) self.assertTrue(ClassGroupPermissions.is_student(self.cg, self.user1)) self.assertEqual(ClassGroupPermissions.access_level(self.cg, self.user1), ClassGroupPermissions.student)
def test_get_classgroup_list(self): """ See if we can get the list of classgroups. """ cg_list_url = reverse('class_list') response = self.c0.get(cg_list_url) courses = response.data # We should have the one class we made in setup. self.assertEqual(len(courses), 1) self.assertEqual(courses[0]['pk'], self.cg.id) # The user should have all permissions in the course, as they are the course owner. self.assertTrue(ClassGroupPermissions.is_teacher(self.cg, self.user0)) self.assertTrue(ClassGroupPermissions.is_administrator(self.cg, self.user0)) self.assertEqual(ClassGroupPermissions.access_level(self.cg, self.user0), ClassGroupPermissions.administrator)
def author_view(self): resource_html = ResourceHTML() current_role = ClassGroupPermissions.get_permission_level( self.resource.classgroup, self.resource, "change_resource") resource_html.add_html( render_to_string( self.resource_author_template, { 'content': self.render_module_author(), 'resource_id': self.resource_id, 'js_class_name': self.author_js_class_name, 'resource_type': self.resource_type, 'class_name': self.class_name, 'roles': [ ClassGroupPermissions.student, ClassGroupPermissions.teacher ], 'current_role': current_role, })) for js in self.author_js: resource_html.add_js(js) for css in self.author_css: resource_html.add_css(css) return resource_html
def verify_classgroup(self): if "classgroup" in self.query_dict: cg = Classgroup.objects.get(name=self.query_dict['classgroup']) if not ClassGroupPermissions.is_student(cg, self.request.user): error_msg = "Attempting to query a class that you are not part of." log.error(error_msg) raise PermissionDenied(error_msg)
def __init__(self, classgroup, user): self.cg = classgroup self.user = user if not ClassGroupPermissions.is_teacher(self.cg, self.user): raise IsNotTeacher("User must be teacher in order to have a queue.") self.key_name = self.cg.name + "_grading_queue"
def delete(self, request, pk, format=None): classgroup = request.DATA.get('classgroup', None) if classgroup is None: error_msg = "Need a classgroup in order to delete a user." log.error(error_msg) return Response(error_msg, status=status.HTTP_400_BAD_REQUEST) if classgroup.startswith("#"): classgroup = classgroup[1:] try: classgroup_model = Classgroup.objects.get(name=classgroup) except Classgroup.DoesNotExist: error_msg = "Cannot find the specified tag." log.error(error_msg) return Response(error_msg, status=status.HTTP_400_BAD_REQUEST) if not ClassGroupPermissions.is_teacher(classgroup_model, request.user): error_msg = "User not authorized to delete others." log.error(error_msg) return Response(error_msg, status=status.HTTP_400_BAD_REQUEST) user = self.get_object(pk) user.classgroups.remove(classgroup_model) return Response(status=status.HTTP_204_NO_CONTENT)
def __init__(self, classgroup, user): self.cg = classgroup self.user = user if not ClassGroupPermissions.is_teacher(self.cg, self.user): raise IsNotTeacher( "User must be teacher in order to have a queue.") self.key_name = self.cg.name + "_grading_queue"
def test_get_classgroup_list_fail(self): """ Test to see if an empty class list is shown to someone with no permissions. """ cg_list_url = reverse('class_list') response = self.c1.get(cg_list_url) courses = json.loads(response.content) self.assertEqual(len(courses), 0) # User 1 should not be able to access the course. self.assertEqual(ClassGroupPermissions.access_level(self.cg, self.user1), ClassGroupPermissions.none)
def get_to_be_graded_count(user, classgroup): """ Get the length of the grading queue for a given classgroup and user. Right now only teachers can grade. """ to_be_graded = 0 if ClassGroupPermissions.is_teacher(classgroup, user): grading_queue = GradingQueue(classgroup, user) queue = grading_queue.retrieve() if queue is not None: to_be_graded = len(queue) return to_be_graded
def get(self, request, classgroup): self.query_dict = {'classgroup': classgroup} self.verify_membership() if not ClassGroupPermissions.is_teacher(self.cg, request.user): error_msg = "You are not a teacher in this class, and cannot edit class settings." return Response(error_msg, status=status.HTTP_400_BAD_REQUEST) settings = self.cg.class_settings serializer = ClassSettingsSerializer(settings, context={'request': request}) return Response(serializer.data)
def verify_membership(self): try: self.cg = Classgroup.objects.get( name=self.query_dict['classgroup']) except Classgroup.DoesNotExist: error_msg = "Invalid class name given." log.error(error_msg) raise PermissionDenied(error_msg) if not ClassGroupPermissions.is_student(self.cg, self.request.user): error_msg = "User not authorized to see given class." log.error(error_msg) raise PermissionDenied(error_msg)
def delete(self, request, pk, format=None): message = self.get_object(pk) if not ClassGroupPermissions.is_teacher(message.classgroup, request.user): error_msg = "User not authorized to delete this message." log.error(error_msg) return Response(error_msg, status=status.HTTP_400_BAD_REQUEST) message.classgroup = None message.save() return Response(status=status.HTTP_204_NO_CONTENT)
def child_user_views(self): """ Gets the user views for the children of this module. Used when rendering a vertical. """ child_views = [] children = self.get_children() # Store data to prevent descriptor overwrite by children. self.module.store_data() for child in children: child_access_level = ClassGroupPermissions.get_permission_level(child.classgroup, child, "change_resource") user_access_level = ClassGroupPermissions.access_level(child.classgroup, self.user) if ClassGroupPermissions.PERMISSION_LEVELS[user_access_level] >= ClassGroupPermissions.PERMISSION_LEVELS[child_access_level]: user_state, created = UserResourceState.objects.get_or_create( user=self.user, resource=child ) renderer = ResourceRenderer(child, user_resource_state=user_state, static_data=self.static_data, user=self.user) child_views.append(renderer.user_view()) # Read data back in. self.module.read_data() return child_views
def add_user_data(self, serializer): for user in serializer.data: user_obj = User.objects.get(id=user['pk']) user['message_count_today'] = Classgroup.objects.get( name=self.query_dict['classgroup']).messages.filter( user=user['pk'], modified__gt=now() - timedelta(days=1)).count() user['message_count'] = Classgroup.objects.get( name=self.query_dict['classgroup']).messages.filter( user=user['pk']).count() user['role'] = ClassGroupPermissions.access_level( self.cg, user_obj) user['grade'] = self.add_user_grades(user_obj) return serializer
def restore_object(self, attrs, instance=None): classgroup = attrs.get('classgroup') name = attrs.get('name') user = self.context['request'].user if instance is None: instance = Section(classgroup=classgroup, name=alphanumeric_name(name), display_name=name) instance.save() else: if not ClassGroupPermissions.is_teacher(classgroup, user): raise serializers.ValidationError("You do not have permission to modify this section.") instance.name = alphanumeric_name(name) instance.display_name = name return instance
def author_view(self): resource_html = ResourceHTML() current_role = ClassGroupPermissions.get_permission_level(self.resource.classgroup, self.resource, "change_resource") resource_html.add_html(render_to_string(self.resource_author_template, { 'content': self.render_module_author(), 'resource_id': self.resource_id, 'js_class_name': self.author_js_class_name, 'resource_type': self.resource_type, 'class_name': self.class_name, 'roles': [ClassGroupPermissions.student, ClassGroupPermissions.teacher], 'current_role': current_role, })) for js in self.author_js: resource_html.add_js(js) for css in self.author_css: resource_html.add_css(css) return resource_html
def restore_object(self, attrs, instance=None): classgroup = attrs.get('classgroup') name = attrs.get('name') attributes = ['grading_policy'] user = self.context['request'].user if instance is None: instance = Skill(classgroup=classgroup, name=alphanumeric_name(name), display_name=name) instance.save() else: if not ClassGroupPermissions.is_teacher(classgroup, user): raise serializers.ValidationError( "You do not have permission to modify this skill.") instance.name = alphanumeric_name(name) instance.display_name = name resources = self.context['request'].DATA.get('resources') if isinstance(resources, basestring): resources = [resources] if resources is not None: resources = [str(r).strip() for r in resources] else: resources = [] skill_resources = [] for (i, r) in enumerate(resources): if len(r) < 1: continue resource = Resource.objects.get(display_name=r, classgroup=classgroup) skill_resource, created = SkillResource.objects.get_or_create( resource=resource, skill=instance) skill_resource.priority = i skill_resource.save() skill_resources.append(skill_resource) for s in SkillResource.objects.filter(skill=instance): if s not in skill_resources: s.delete() instance = set_attributes(attributes, attrs, instance) return instance
def create_message_notification(sender, instance, **kwargs): if instance.reply_to is not None: if instance.user != instance.reply_to.user: try: MessageNotification.objects.get_or_create( receiving_message=instance.reply_to, receiving_user=instance.reply_to.user, origin_message=instance, notification_type="reply_to_discussion", ) except IntegrityError: log.warn( "MessageNotification already exists with receiver message {0} and origin message {1}" .format(instance.reply_to.id, instance.id)) for m in instance.reply_to.replies.all(): if m.user != instance.reply_to.user and m.user != instance.user: try: MessageNotification.objects.get_or_create( receiving_message=instance.reply_to, receiving_user=m.user, origin_message=instance, notification_type="reply_to_watched_thread", ) except IntegrityError: log.warn( "MessageNotification already exists with receiver message {0} and origin message {1}" .format(m.id, instance.id)) elif instance.reply_to is None and instance.classgroup is not None and ClassGroupPermissions.is_teacher( instance.classgroup, instance.user) and instance.message_type == "A": for user in instance.classgroup.users.all(): if user != instance.user: try: MessageNotification.objects.get_or_create( receiving_message=instance, receiving_user=user, origin_message=instance, notification_type="instructor_announcement_made", ) except IntegrityError: log.warn( "MessageNotification already exists for instructor post with receiver message {0} and origin message {1}" .format(instance.id, instance.id)) process_saved_message.delay(instance.id)
def restore_object(self, attrs, instance=None): classgroup = attrs.get('classgroup') name = attrs.get('name') user = self.context['request'].user if instance is None: instance = Section(classgroup=classgroup, name=alphanumeric_name(name), display_name=name) instance.save() else: if not ClassGroupPermissions.is_teacher(classgroup, user): raise serializers.ValidationError( "You do not have permission to modify this section.") instance.name = alphanumeric_name(name) instance.display_name = name return instance
def restore_object(self, attrs, instance=None): classgroup = attrs.get('classgroup') name = attrs.get('name') attributes = ['grading_policy'] user = self.context['request'].user if instance is None: instance = Skill(classgroup=classgroup, name=alphanumeric_name(name), display_name=name) instance.save() else: if not ClassGroupPermissions.is_teacher(classgroup, user): raise serializers.ValidationError("You do not have permission to modify this skill.") instance.name = alphanumeric_name(name) instance.display_name = name resources = self.context['request'].DATA.get('resources') if isinstance(resources, basestring): resources = [resources] if resources is not None: resources = [str(r).strip() for r in resources] else: resources = [] skill_resources = [] for (i, r) in enumerate(resources): if len(r) < 1: continue resource = Resource.objects.get(display_name=r, classgroup=classgroup) skill_resource, created = SkillResource.objects.get_or_create( resource=resource, skill=instance ) skill_resource.priority = i skill_resource.save() skill_resources.append(skill_resource) for s in SkillResource.objects.filter(skill=instance): if s not in skill_resources: s.delete() instance = set_attributes(attributes, attrs, instance) return instance
def create_message_notification(sender, instance, **kwargs): if instance.reply_to is not None: if instance.user != instance.reply_to.user: try: MessageNotification.objects.get_or_create( receiving_message=instance.reply_to, receiving_user=instance.reply_to.user, origin_message=instance, notification_type="reply_to_discussion", ) except IntegrityError: log.warn("MessageNotification already exists with receiver message {0} and origin message {1}".format(instance.reply_to.id, instance.id)) for m in instance.reply_to.replies.all(): if m.user != instance.reply_to.user and m.user != instance.user: try: MessageNotification.objects.get_or_create( receiving_message=instance.reply_to, receiving_user=m.user, origin_message=instance, notification_type="reply_to_watched_thread", ) except IntegrityError: log.warn("MessageNotification already exists with receiver message {0} and origin message {1}".format(m.id, instance.id)) elif instance.reply_to is None and instance.classgroup is not None and ClassGroupPermissions.is_teacher(instance.classgroup, instance.user) and instance.message_type == "A": for user in instance.classgroup.users.all(): if user != instance.user: try: MessageNotification.objects.get_or_create( receiving_message=instance, receiving_user=user, origin_message=instance, notification_type="instructor_announcement_made", ) except IntegrityError: log.warn("MessageNotification already exists for instructor post with receiver message {0} and origin message {1}".format(instance.id, instance.id)) process_saved_message.delay(instance.id)
def restore_object(self, attrs, instance=None): user = self.context['request'].user name = attrs.get('name') class_settings_values = attrs.get('class_settings') attributes = ["description"] settings_attributes = ['moderate_posts', 'is_public', 'allow_signups'] if instance is None: try: instance = Classgroup(owner=user, name=alphanumeric_name(name), display_name=name) instance.save() user.classgroups.add(instance) user.save() cg_perm = ClassGroupPermissions(instance) cg_perm.setup() cg_perm.assign_access_level(user, cg_perm.administrator) try: class_settings = ClassSettings(classgroup=instance, access_key=make_random_key()) class_settings.save() except IntegrityError: class_settings = ClassSettings.objects.get(classgroup=instance) try: message = Message( user=user, classgroup=instance, source="welcome", text=WELCOME_MESSAGE2_TEMPLATE, message_type="A", ) message.save() message = Message( user=user, classgroup=instance, source="welcome", text=WELCOME_MESSAGE_TEMPLATE.format( class_name=instance.display_name, class_link=get_current_site(self.context['request']).domain + instance.link(), access_key=class_settings.access_key ), message_type="A", ) message.save() except IntegrityError: pass except IntegrityError: error_msg = "Class name is already taken." log.exception(error_msg) raise serializers.ValidationError(error_msg) else: if not ClassGroupPermissions.is_teacher(instance, user): raise serializers.ValidationError("Class name is already taken.") class_settings = instance.class_settings instance = set_attributes(attributes, attrs, instance) if class_settings_values is not None: class_settings = set_attributes(settings_attributes, class_settings_values, class_settings) class_settings.save() return instance
def restore_object(self, attrs, instance=None): user = self.context['request'].user name = attrs.get('name') class_settings_values = attrs.get('class_settings') attributes = ["description"] settings_attributes = ['moderate_posts', 'is_public', 'allow_signups'] if instance is None: try: instance = Classgroup(owner=user, name=alphanumeric_name(name), display_name=name) instance.save() user.classgroups.add(instance) user.save() cg_perm = ClassGroupPermissions(instance) cg_perm.setup() cg_perm.assign_access_level(user, cg_perm.administrator) try: class_settings = ClassSettings( classgroup=instance, access_key=make_random_key()) class_settings.save() except IntegrityError: class_settings = ClassSettings.objects.get( classgroup=instance) try: message = Message( user=user, classgroup=instance, source="welcome", text=WELCOME_MESSAGE2_TEMPLATE, message_type="A", ) message.save() message = Message( user=user, classgroup=instance, source="welcome", text=WELCOME_MESSAGE_TEMPLATE.format( class_name=instance.display_name, class_link=get_current_site( self.context['request']).domain + instance.link(), access_key=class_settings.access_key), message_type="A", ) message.save() except IntegrityError: pass except IntegrityError: error_msg = "Class name is already taken." log.exception(error_msg) raise serializers.ValidationError(error_msg) else: if not ClassGroupPermissions.is_teacher(instance, user): raise serializers.ValidationError( "Class name is already taken.") class_settings = instance.class_settings instance = set_attributes(attributes, attrs, instance) if class_settings_values is not None: class_settings = set_attributes(settings_attributes, class_settings_values, class_settings) class_settings.save() return instance
def change_visibility(self, post_data): ClassGroupPermissions.assign_perms(self.resource.classgroup, self.resource, "change_resource", post_data.get("new_role")) return {'success': True}
def verify_ownership(self): if not ClassGroupPermissions.is_teacher(self.cg, self.request.user): error_msg = "User is not a teacher for the given class." log.error(error_msg) raise PermissionDenied(error_msg)
def verify_teacher_or_creator(self, user): if not ClassGroupPermissions.is_teacher( self.cg, self.request.user) and user != self.request.user: error_msg = "User is not a teacher for the given class or did not create the resource." log.error(error_msg) raise PermissionDenied(error_msg)