Example #1
0
    def create(self, request):
        """Create a new course.

        Arguments:
        request -- request data
            name -- name of the course
            abbreviation -- abbreviation of the course
            startdate -- (optional) date when the course starts
            enddate -- (optional) date when the course ends
            lti_id -- (optional) lti_id to link the course to

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            forbidden -- when the user has no permission to create new courses
        On succes:
            success -- with the course data
        """
        request.user.check_permission('can_add_course')

        name, abbr = utils.required_params(request.data, 'name',
                                           'abbreviation')
        startdate, enddate, lti_id = utils.optional_params(
            request.data, 'startdate', 'enddate', 'lti_id')

        course = factory.make_course(name, abbr, startdate, enddate,
                                     request.user, lti_id)

        serializer = self.serializer_class(course, many=False)
        return response.created({'course': serializer.data})
Example #2
0
    def create(self, request):
        """Create course role.

        Arguments:
        request -- request data
            course_id -- course ID
            name -- role name
            permissions -- permissions to change (default everything is false)

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when the course does not exist
            forbidden -- when the user is not in the course
            forbidden -- when the user is unauthorized to edit its roles
        On success:
            success -- newly created course

        """
        course_id, name, permissions = utils.required_params(
            request.data, 'course_id', 'name', 'permissions')
        course = Course.objects.get(pk=course_id)

        # TODO: P Is this the right permission
        request.user.check_permission('can_edit_course_roles', course)

        try:
            role = factory.make_role_default_no_perms(name, course,
                                                      **permissions)
        except Exception:
            return response.bad_request()

        serializer = RoleSerializer(role, many=False)
        return response.created({'role': serializer.data})
Example #3
0
    def create(self, request):
        """Create a new course group.

        Arguments:
        request -- the request that was send with
            name -- name of the course group
            course_id -- course ID of the course
            lti_id -- (optional) lti_id to link the course to

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            forbidden -- when the user has no permission to create new groups
        On success, with the course group.
        """
        name, course_id = utils.required_params(request.data, "name", "course_id")
        lti_id, = utils.optional_params(request.data, 'lti_id')

        course = Course.objects.get(pk=course_id)

        request.user.check_permission('can_add_course_user_group', course)

        if lti_id and Group.objects.filter(lti_id=lti_id, course=course).exists():
            return response.bad_request('Course group with the desired name already exists.')

        course_group = factory.make_course_group(name, course, lti_id)
        serializer = GroupSerializer(course_group, many=False)
        return response.created({'group': serializer.data})
Example #4
0
    def create(self, request):
        """Create a new comment.

        Arguments:
        request -- request data
            entry_id -- entry ID
            text -- comment text
            published -- publishment state

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            key_error -- missing keys
            not_found -- could not find the entry, author or assignment

        On success:
            succes -- with the assignment data

        """
        entry_id, text, published = utils.required_params(request.data, "entry_id", "text", "published")

        entry = Entry.objects.get(pk=entry_id)
        journal = entry.node.journal
        assignment = journal.assignment

        request.user.check_permission('can_comment', assignment)
        request.user.check_can_view(journal)

        # By default a comment will be published, only users who can grade can delay publishing.
        published = published or not request.user.has_permission('can_grade', assignment)
        comment = factory.make_comment(entry, request.user, text, published)
        return response.created({'comment': CommentSerializer(comment).data})
Example #5
0
    def create(self, request):
        group_id, user_id = utils.required_typed_params(request.data, (int, 'group_id'), (int, 'user_id'))
        group = Group.objects.get(pk=group_id)
        member = Participation.objects.get(user=user_id, course=group.course)

        request.user.check_permission('can_edit_course_user_group', group.course)

        member.groups.add(group)
        member.save()
        users = UserSerializer(group.course.users, context={'course': group.course}, many=True).data
        return response.created({'participants': users})
Example #6
0
    def create(self, request):
        """Set a new grade for an entry.

        Arguments:
        request -- request data
            entry_id -- entry ID
            grade -- grade
            published -- published state

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            key_error -- missing keys
            not_found -- could not find the entry, author or assignment

        On success:
            success -- with the assignment data
        """
        entry_id, grade, published = utils.required_typed_params(
            request.data, (int, 'entry_id'), (float, 'grade'),
            (bool, 'published'))

        entry = Entry.objects.get(pk=entry_id)
        journal = entry.node.journal
        assignment = journal.assignment

        request.user.check_permission('can_grade', assignment)

        if published:
            request.user.check_permission('can_publish_grades', assignment)

        if grade is not None and grade < 0:
            return response.bad_request(
                'Grade must be greater than or equal to zero.')

        grade = factory.make_grade(entry, request.user.pk, grade, published)

        if published:
            Comment.objects.filter(entry=entry).update(published=True)

        # TODO: Is the lti flag ever used? Else move replace_result to celery
        return response.created({
            'entry':
            EntrySerializer(entry, context={
                'user': request.user
            }).data,
            'lti':
            lti_grade.replace_result(journal)
        })
Example #7
0
    def create(self, request):
        """Add a user to a course.

        Arguments:
        request -- request data
            user_id -- user ID
            course_id -- course ID

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not found -- when course or user is not found
            forbidden -- when the logged in user is not connected to the course
            bad request -- when the new user is already connected to the course
            not found -- when the role doesnt exist
        On success:
            success -- success message
        """
        user_id, course_id = utils.required_typed_params(
            request.data, (int, 'user_id'), (int, 'course_id'))
        role_name = 'Student'

        user = User.objects.get(pk=user_id)
        course = Course.objects.get(pk=course_id)

        request.user.check_permission('can_add_course_users', course)

        if user.is_participant(course):
            return response.bad_request(
                'User already participates in the course.')

        role = Role.objects.get(name=role_name, course=course)

        factory.make_participation(user, course, role)

        assignments = course.assignment_set.all()
        for assignment in assignments:
            if not Journal.objects.filter(assignment=assignment,
                                          user=user).exists():
                factory.make_journal(assignment, user)

        serializer = UserSerializer(user, context={'course': course})
        return response.created(
            {'participant': serializer.data},
            description='Successfully added student to course.')
Example #8
0
    def create(self, request):
        """Create a new assignment.

        Arguments:
        request -- request data
            name -- name of the assignment
            description -- description of the assignment
            course_id -- id of the course the assignment belongs to
            points_possible -- the possible amount of points for the assignment
            unlock_date -- (optional) date the assignment becomes available on
            due_date -- (optional) date the assignment is due for
            lock_date -- (optional) date the assignment becomes unavailable on
            lti_id -- id labeled link to LTI instance

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            not_found -- could not find the course with the given id
            key_error -- missing keys
            forbidden -- the user is not allowed to create assignments in this course

        On success:
            succes -- with the assignment data

        """
        name, description, course_id = utils.required_params(request.data, "name", "description", "course_id")
        points_possible, unlock_date, due_date, lock_date, lti_id, is_published = \
            utils.optional_params(request.data, "points_possible", "unlock_date", "due_date", "lock_date", "lti_id",
                                  "is_published")
        course = Course.objects.get(pk=course_id)

        request.user.check_permission('can_add_assignment', course)

        assignment = factory.make_assignment(name, description, courses=[course],
                                             author=request.user, lti_id=lti_id,
                                             points_possible=points_possible,
                                             unlock_date=unlock_date, due_date=due_date,
                                             lock_date=lock_date, is_published=is_published)

        for user in course.users.all():
            factory.make_journal(assignment, user)

        serializer = AssignmentSerializer(assignment, context={'user': request.user, 'course': course})
        return response.created({'assignment': serializer.data})
Example #9
0
    def create(self, request):
        """Create a new entry.

        Deletes remaining temporary user files if successful.

        Arguments:
        request -- the request that was send with
            journal_id -- the journal id
            template_id -- the template id to create the entry with
            node_id -- optional: the node to bind the entry to (only for entrydeadlines)
            content -- the list of {tag, data} tuples to bind data to a template field.
        """
        journal_id, template_id, content_list = utils.required_params(
            request.data, "journal_id", "template_id", "content")
        node_id, = utils.optional_params(request.data, "node_id")

        journal = Journal.objects.get(pk=journal_id, user=request.user)
        assignment = journal.assignment
        template = Template.objects.get(pk=template_id)

        request.user.check_permission('can_have_journal', assignment)

        if assignment.is_locked():
            return response.forbidden(
                'The assignment is locked, entries can no longer be edited/changed.'
            )

        if journal.needs_lti_link():
            return response.forbidden(journal.outdated_link_warning_msg)

        # Check if the template is available
        if not (node_id or assignment.format.template_set.filter(
                archived=False, preset_only=False, pk=template.pk).exists()):
            return response.forbidden('Entry template is not available.')

        entry_utils.check_fields(template, content_list)

        # Node specific entry
        if node_id:
            node = Node.objects.get(pk=node_id, journal=journal)
            entry = entry_utils.add_entry_to_node(node, template)
        # Template specific entry
        else:
            entry = factory.make_entry(template)
            node = factory.make_node(journal, entry)

        for content in content_list:
            field_id, = utils.required_typed_params(content, (int, 'id'))
            data, = utils.required_params(content, 'data')
            field = Field.objects.get(pk=field_id)

            created_content = factory.make_content(node.entry, data, field)

            if field.type in field.FILE_TYPES:  # Image, file or PDF
                user_file = file_handling.get_temp_user_file(
                    request.user, assignment, content['data'])
                if user_file is None and field.required:
                    node.entry.delete()
                    # If there is a newly created node, delete that as well
                    if not node_id:
                        node.delete()
                    return response.bad_request(
                        'One of your files was not correctly uploaded, please try again.'
                    )
                elif user_file:
                    file_handling.make_permanent_file_content(
                        user_file, created_content, node)

        # Notify teacher on new entry
        if (node.journal.sourcedid
                and node.entry.vle_coupling == Entry.NEED_SUBMISSION):
            lti_tasks.needs_grading.delay(node.pk)

        # Delete old user files
        file_handling.remove_temp_user_files(request.user)

        return response.created({
            'added':
            entry_utils.get_node_index(journal, node, request.user),
            'nodes':
            timeline.get_nodes(journal, request.user),
            'entry':
            serialize.EntrySerializer(entry, context={
                'user': request.user
            }).data
        })
Example #10
0
    def create(self, request):
        """Create a new user.

        Arguments:
        request -- request data
            username -- username
            password -- password
            first_name -- (optinal) first name
            last_name -- (optinal) last name
            email -- (optinal) email
            jwt_params -- (optinal) jwt params to get the lti information from
                user_id -- id of the user
                user_image -- user image
                roles -- role of the user

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            bad request -- when email/username/lti id already exists
            bad request -- when email/password is invalid
        On succes:
            success -- with the newly created user data
        """

        lti_id, user_image, full_name, email, is_teacher = get_lti_params(
            request, 'user_id', 'custom_user_image', 'custom_user_full_name', 'custom_user_email')
        if full_name:
            first_name, last_name = lti.split_fullname(full_name)

        if lti_id is None:
            # Check if instance allows standalone registration if user did not register through some LTI instance
            try:
                instance = Instance.objects.get(pk=1)
                if not instance.allow_standalone_registration:
                    return response.bad_request(('{} does not allow you to register through the website,' +
                                                ' please use an LTI instance.').format(instance.name))
            except Instance.DoesNotExist:
                pass

            first_name, last_name, email = utils.optional_params(request.data, 'first_name', 'last_name', 'email')

        username, password = utils.required_params(request.data, 'username', 'password')

        if email and User.objects.filter(email=email).exists():
            return response.bad_request('User with this email already exists.')

        validate_email(email)

        if User.objects.filter(username=username).exists():
            return response.bad_request('User with this username already exists.')

        if lti_id is not None and User.objects.filter(lti_id=lti_id).exists():
            return response.bad_request('User with this lti id already exists.')

        validators.validate_password(password)

        user = factory.make_user(username, password, email=email, lti_id=lti_id, is_teacher=is_teacher,
                                 first_name=first_name, last_name=last_name, profile_picture=user_image,
                                 verified_email=True if lti_id else False)

        if lti_id is None:
            try:
                email_handling.send_email_verification_link(user)
            except SMTPAuthenticationError as err:
                user.delete()
                raise err

        return response.created({'user': UserSerializer(user).data})
Example #11
0
    def create(self, request):
        """Create a new user.

        Arguments:
        request -- request data
            username -- username
            password -- password
            full_name -- full name
            email -- (optinal) email
            jwt_params -- (optinal) jwt params to get the lti information from
                user_id -- id of the user
                user_image -- user image
                roles -- role of the user

        Returns:
        On failure:
            unauthorized -- when the user is not logged in
            bad request -- when email/username/lti id already exists
            bad request -- when email/password is invalid
        On success:
            success -- with the newly created user data
        """

        lti_id, user_image, full_name, email, is_teacher = get_lti_params(
            request, 'user_id', 'custom_user_image', 'custom_user_full_name',
            'custom_user_email')
        is_test_student = bool(lti_id) and not bool(
            email) and full_name == settings.LTI_TEST_STUDENT_FULL_NAME

        if lti_id is None:
            # Check if instance allows standalone registration if user did not register through some LTI instance
            try:
                instance = Instance.objects.get(pk=1)
                if not instance.allow_standalone_registration:
                    return response.bad_request((
                        '{} does not allow you to register through the website,'
                        + ' please use an LTI instance.').format(
                            instance.name))
            except Instance.DoesNotExist:
                pass

            full_name, email = utils.required_params(request.data, 'full_name',
                                                     'email')

        username, password = utils.required_params(request.data, 'username',
                                                   'password')

        if email and User.objects.filter(email=email).exists():
            return response.bad_request('User with this email already exists.')

        if User.objects.filter(username=username).exists():
            return response.bad_request(
                'User with this username already exists.')

        if lti_id is not None and User.objects.filter(lti_id=lti_id).exists():
            return response.bad_request(
                'User with this lti id already exists.')

        user = factory.make_user(username=username,
                                 email=email,
                                 lti_id=lti_id,
                                 full_name=full_name,
                                 is_teacher=is_teacher,
                                 verified_email=bool(lti_id) and bool(email),
                                 password=password,
                                 profile_picture=user_image
                                 if user_image else '/unknown-profile.png',
                                 is_test_student=is_test_student)

        if lti_id is None:
            send_email_verification_link.delay(user.pk)

        return response.created({'user': UserSerializer(user).data})