示例#1
0
文件: core.py 项目: piehei/prplatform
def create_submission_for(submission_exercise, aplus_submission, user):
    """
       1. check if there's an user with the aplus submitter's email
       2. if not, crate one and set temporary = True
       3. get the submissions file from aplus API
       4. create a new original submission with the file and submitter
    """

    file_url = aplus_submission["files"][0]["url"]
    filename = aplus_submission["files"][0]["filename"]
    file_blob = requests.get(file_url, headers={ 'Authorization': f'Token {submission_exercise.course.aplus_apikey}' })

    temp_file = NamedTemporaryFile(delete=True)
    temp_file.name = filename
    temp_file.write(file_blob.content)
    temp_file.flush()

    new_orig_sub = OriginalSubmission(
                        course=submission_exercise.course,
                        submitter_user=user,
                        exercise=submission_exercise,
                        file=File(temp_file)
                        )
    new_orig_sub.save()
    logger.info(new_orig_sub)
示例#2
0
    def test_student_cannot_download_answer_file_not_owned(self):
        s_exercise = SubmissionExercise.objects.get(name="T1 TEXT")
        r_exercise = ReviewExercise.objects.get(name="T1 TEXT REVIEW")

        sub = OriginalSubmission(course=self.course,
                                 text="juups",
                                 submitter_user=self.s1,
                                 exercise=s_exercise)
        sub.save()

        r_exercise.question_order = ['3']
        r_exercise.save()

        rev_sub = ReviewSubmission(course=self.course,
                                   reviewed_submission=sub,
                                   submitter_user=self.s2,
                                   exercise=r_exercise)
        rev_sub.save()

        temp_file = SimpleUploadedFile(name='lorem_ipsum.txt',
                                       content=bytearray('jada jada', 'utf-8'))

        answer_with_file = Answer(
            question=Question.objects.get(pk=3),
            submission=rev_sub,
            uploaded_file=temp_file,
        )
        answer_with_file.save()

        request = self.factory.get(
            f'/courses/prog1/F2018/submissions/download/{answer_with_file.pk}/?type=answer'
        )
        request.user = self.s3
        self.kwargs['pk'] = answer_with_file.pk

        self.assertRaises(PermissionDenied, DownloadSubmissionView.as_view(),
                          request, **self.kwargs)

        g = StudentGroup(name="g1",
                         course=self.course,
                         student_usernames=[self.s1.email, self.s3.email])
        g.save()
        sub.submitter_group = g
        sub.save()

        for user in self.students + [self.t1]:
            request = self.factory.get(
                f'/courses/prog1/F2018/submissions/download/{answer_with_file.pk}/?type=answer'
            )
            request.user = user
            self.kwargs['pk'] = answer_with_file.pk

            if user == self.s4:
                self.assertRaises(PermissionDenied,
                                  DownloadSubmissionView.as_view(), request,
                                  **self.kwargs)
            else:
                response = DownloadSubmissionView.as_view()(request,
                                                            **self.kwargs)
                self.assertEqual(response.status_code, 200)
示例#3
0
    def test_save_and_destroy_lock_reviewsubmission(self):

        os = OriginalSubmission(course=self.course,
                                exercise=self.se,
                                submitter_user=self.s1,
                                text="jadajada")
        os.save()

        rl = ReviewLock(review_exercise=self.re,
                        user=self.s2,
                        original_submission=os)
        rl.save()

        rs = ReviewSubmission(course=self.course,
                              exercise=self.re,
                              submitter_user=self.s2,
                              reviewed_submission=os)

        self.assertEqual(ReviewLock.objects.count(), 1)
        rs.save_and_destroy_lock()
        self.assertEqual(ReviewLock.objects.count(), 0)

        rs2 = ReviewSubmission(course=self.course,
                               exercise=self.re,
                               submitter_user=self.s2,
                               reviewed_submission=os)
        self.assertRaises(OperationalError, rs2.save_and_destroy_lock)

        rs2 = ReviewSubmission(course=self.course,
                               exercise=self.re,
                               submitter_user=self.s3,
                               reviewed_submission=os)
        self.assertRaises(OperationalError, rs2.save_and_destroy_lock)
示例#4
0
    def test_student_can_download_submission(self):
        exercise = SubmissionExercise.objects.get(pk=1)

        group = StudentGroup(name="g-1",
                             student_usernames=[self.s1.email, self.s2.email],
                             course=self.course)
        group.save()

        exercise.type = 'FILE_UPLOAD'
        exercise.accepted_filetypes = '.txt'
        exercise.save()

        temp_file = SimpleUploadedFile(name='lorem_ipsum.txt',
                                       content=bytearray('jada jada', 'utf-8'))
        sub = OriginalSubmission(course=self.course,
                                 file=temp_file,
                                 submitter_user=self.s1,
                                 submitter_group=group,
                                 exercise=exercise)
        sub.save()

        for user, code in [(self.s1, 200), (self.s2, 200), (self.s3, 403)]:
            request = self.factory.get(
                f'/courses/prog1/F2018/submissions/download/{sub.pk}/')
            request.user = user
            self.kwargs['pk'] = sub.pk

            if code == 403:
                self.assertRaises(PermissionDenied,
                                  DownloadSubmissionView.as_view(), request,
                                  **self.kwargs)
            else:
                response = DownloadSubmissionView.as_view()(request,
                                                            **self.kwargs)
                self.assertEqual(response.status_code, code)
示例#5
0
    def create_submission_for(self, exercise, users):

        submissions = []
        for user in users:
            sub = OriginalSubmission(course=self.course,
                                     submitter_user=user,
                                     exercise=exercise,
                                     text=f"text by {user}")
            sub.save()
            submissions.append(sub)
        return submissions
示例#6
0
    def create_originalsubmission_for(self, exercise, users):
        if type(users) is not list:
            users = [users]

        submissions = []
        for user in users:
            sub = OriginalSubmission(course=self.course,
                                     submitter_user=user,
                                     exercise=exercise,
                                     text=f"text by {user}")
            sub.save()
            submissions.append(sub)
        return submissions if len(submissions) > 1 else submissions[0]
示例#7
0
    def test_student_can_download_via_reviewlock(self):
        exercise = SubmissionExercise.objects.get(pk=1)

        exercise.type = 'FILE_UPLOAD'
        exercise.accepted_filetypes = '.txt'
        exercise.save()

        temp_file = SimpleUploadedFile(name='lorem_ipsum.txt',
                                       content=bytearray('jada jada', 'utf-8'))
        sub = OriginalSubmission(course=self.course,
                                 file=temp_file,
                                 submitter_user=self.s1,
                                 exercise=exercise)
        sub.save()

        re = ReviewExercise.objects.get(pk=1)
        re.type = ReviewExercise.RANDOM
        re.save()

        rlock = ReviewLock(user=self.s2,
                           original_submission=sub,
                           review_exercise=re,
                           review_submission=None)
        rlock.save()

        # user with reviewlock can download
        request = self.factory.get(
            f'/courses/prog1/F2018/submissions/download/{sub.pk}/')
        request.user = self.s2
        self.kwargs['pk'] = sub.pk
        response = DownloadSubmissionView.as_view()(request, **self.kwargs)
        self.assertEqual(response.status_code, 200)

        re.use_groups = True
        re.save()
        group = StudentGroup(name="g-1",
                             student_usernames=[self.s2.email, self.s3.email],
                             course=self.course)
        group.save()
        rlock.group = group
        rlock.save()

        # user in a group that has a reviewlock can download
        request = self.factory.get(
            f'/courses/prog1/F2018/submissions/download/{sub.pk}/')
        request.user = self.s3
        self.kwargs['pk'] = sub.pk
        response = DownloadSubmissionView.as_view()(request, **self.kwargs)
        self.assertEqual(response.status_code, 200)
示例#8
0
    def test_student_cannot_download_hide_from_receiver_answer_file(self):
        s_exercise = SubmissionExercise.objects.get(name="T1 TEXT")
        r_exercise = ReviewExercise.objects.get(name="T1 TEXT REVIEW")

        sub = OriginalSubmission(course=self.course,
                                 text="juups",
                                 submitter_user=self.s1,
                                 exercise=s_exercise)
        sub.save()

        r_exercise.question_order = ['3']
        r_exercise.save()

        rev_sub = ReviewSubmission(course=self.course,
                                   reviewed_submission=sub,
                                   submitter_user=self.s2,
                                   exercise=r_exercise)
        rev_sub.save()

        temp_file = SimpleUploadedFile(name='lorem_ipsum.txt',
                                       content=bytearray('jada jada', 'utf-8'))
        question = Question.objects.get(pk=3)

        answer_with_file = Answer(
            question=question,
            submission=rev_sub,
            uploaded_file=temp_file,
        )
        answer_with_file.save()

        request = self.factory.get(
            f'/courses/prog1/F2018/submissions/download/{answer_with_file.pk}/?type=answer'
        )
        request.user = self.s1
        self.kwargs['pk'] = answer_with_file.pk

        self.assertEqual(
            DownloadSubmissionView.as_view()(request,
                                             **self.kwargs).status_code, 200)
        question.hide_from_receiver = True
        question.save()
        self.assertRaises(PermissionDenied, DownloadSubmissionView.as_view(),
                          request, **self.kwargs)
示例#9
0
    def test_student_cannot_download_submission_not_owned(self):
        exercise = SubmissionExercise.objects.get(pk=1)

        exercise.type = 'FILE_UPLOAD'
        exercise.accepted_filetypes = '.txt'
        exercise.save()

        temp_file = SimpleUploadedFile(name='lorem_ipsum.txt',
                                       content=bytearray('jada jada', 'utf-8'))
        sub = OriginalSubmission(course=self.course,
                                 file=temp_file,
                                 submitter_user=self.s1,
                                 exercise=exercise)
        sub.save()

        request = self.factory.get(
            f'/courses/prog1/F2018/submissions/download/{sub.pk}/')
        request.user = self.s2
        self.kwargs['pk'] = sub.pk

        self.assertRaises(PermissionDenied, DownloadSubmissionView.as_view(),
                          request, **self.kwargs)
示例#10
0
    def test_original_submission_delete_confirmation_page_shows_cascades(self):

        os = OriginalSubmission(
            course=self.course,
            exercise=SubmissionExercise.objects.get(name="T1 TEXT"),
            submitter_user=self.s1,
            text="jada jada jada jada",
        )
        os.save()

        request = self.factory.get(os.get_delete_url())
        self.kwargs['pk'] = os.exercise.pk
        self.kwargs['sub_pk'] = os.pk
        request.user = self.s1

        # students cannot access
        self.assertRaises(PermissionDenied,
                          OriginalSubmissionDeleteView.as_view(), request,
                          **self.kwargs)

        request.user = self.t1
        response = OriginalSubmissionDeleteView.as_view()(request,
                                                          **self.kwargs)
        self.assertContains(response, "No peer-reviews exist yet")

        res = []
        for s in [self.s2, self.s3]:
            re = ReviewSubmission(
                course=self.course,
                exercise=ReviewExercise.objects.get(name="T1 TEXT REVIEW"),
                reviewed_submission=os,
                submitter_user=s,
            )
            re.save()
            res.append(re)

        response = OriginalSubmissionDeleteView.as_view()(request,
                                                          **self.kwargs)
        self.assertNotContains(response, "No peer-reviews exist yet")
        # -> is turned into -> in the response -> just replace that when looking for
        self.assertContains(response, str(res[0]).replace(">", ">"))
        self.assertContains(response, str(res[1]).replace(">", ">"))

        self.assertEqual(OriginalSubmission.objects.count(), 1)
        self.assertEqual(ReviewSubmission.objects.count(), 2)

        request = self.factory.get(res[0].get_delete_url())
        self.kwargs['pk'] = res[0].exercise.pk
        self.kwargs['sub_pk'] = res[0].pk
        request.user = self.s1

        # students cannot access
        self.assertRaises(PermissionDenied,
                          ReviewSubmissionDeleteView.as_view(), request,
                          **self.kwargs)

        # delete page doesn't list any useful information, no need to check

        os.delete()

        self.assertEqual(OriginalSubmission.objects.count(), 0)
        self.assertEqual(ReviewSubmission.objects.count(), 0)
示例#11
0
    def test_download_tokens_allow_downloading(self):

        exercise = SubmissionExercise.objects.get(pk=1)
        exercise.type = 'FILE_UPLOAD'
        exercise.accepted_filetypes = '.txt'
        exercise.save()

        temp_file = SimpleUploadedFile(name='lorem_ipsum.txt',
                                       content=bytearray('jada jada', 'utf-8'))
        sub = OriginalSubmission(course=self.course,
                                 file=temp_file,
                                 submitter_user=self.s1,
                                 exercise=exercise)
        sub.save()

        rev = ReviewSubmission(course=self.course,
                               submitter_user=self.s1,
                               exercise=exercise.review_exercise,
                               reviewed_submission=sub)
        rev.save()

        answer_with_file = Answer(
            question=Question.objects.get(pk=3),
            submission=rev,
            uploaded_file=temp_file,
        )
        answer_with_file.save()

        view_request = self.factory.get(exercise.get_absolute_url() +
                                        "?some=queryparams")
        osub_token = sub.get_download_token_for(self.s1, view_request)
        view_request = self.factory.get(
            exercise.review_exercise.get_absolute_url() + "?some=queryparams")
        rsub_token = rev.get_download_token_for(self.s1, view_request)

        cases = [
            (AnonymousUser, 403, sub, ""),
            (AnonymousUser, 200, sub, f"?dl_token={osub_token}"),
            (AnonymousUser, 403, sub,
             f"?dl_token={osub_token}_THIS_SHOULD_CAUSE_PROBLEMS"),
            (AnonymousUser, 403, answer_with_file, ""),
            (AnonymousUser, 200, answer_with_file, f"&dl_token={rsub_token}"),
            (AnonymousUser, 403, answer_with_file,
             f"&dl_token={rsub_token}_THIS_SHOULD_CAUSE_PROBLEMS"),
        ]

        for user, code, sub, query in cases:
            url = f"{sub.get_file_download_url()}{query}"
            request = self.factory.get(url)
            request.user = user
            self.kwargs['pk'] = sub.pk

            if code == 403:
                self.assertRaises(PermissionDenied,
                                  DownloadSubmissionView.as_view(), request,
                                  **self.kwargs)
            else:
                response = DownloadSubmissionView.as_view()(request,
                                                            **self.kwargs)
                self.assertEqual(response.status_code, code)

        DownloadToken.objects.all().delete()

        for user, _, sub, query in cases:
            url = f"{sub.get_file_download_url()}{query}"
            request = self.factory.get(url)
            request.user = user
            self.kwargs['pk'] = sub.pk
            self.assertRaises(PermissionDenied,
                              DownloadSubmissionView.as_view(), request,
                              **self.kwargs)
示例#12
0
def prepare_group_review_exercise_for(exercise, user, LTI_MODE):
    """
    This is called just before showing the student a group peer-review
    page where the student can peer-review other students in his/her group.

    Because of the design of the system, there has to exist an OriginalSubmission
    for each ReviewSubmission. This function will do two things:

    1. if the receiver of the feedback (student in the same group) has never
       logged into the system (and thus his/her account doesn't exist yet),
       a new temporary user account with his/her email will be created.
       for that new temp user account, temporary=True will be set.
       if the current user is using the system through LTI integration,
       lti=True will also be set since all users of a particular course
       either use the system through LTI or don't. this distinction makes it
       possible for a user to be attending two courses of which one uses
       LTI and one doesn't and the user accounts don't mix mistakenly.

    2. create one OriginalSubmission for each of the group members so that
       the peer-reviews  (ReviewSubmissions) can point to them

    3. when the real user logins in the future, this temporary account will be
       removed and all submissions transerred to the actual, real user account.
       this logic is implemented in prplatform.users.receivers
    """

    course = exercise.course
    group = course.find_studentgroup_by_user(user)

    if not group:
        return

    for student_email in group.student_usernames:
        logger.info(f"FINDING: {student_email}, LTI_MODE: {LTI_MODE}")
        student = User.objects.filter(email=student_email,
                                      lti=LTI_MODE).first()

        if not student:
            logger.info(
                f'ReviewExericse (pk={exercise.pk}): User not found for {student_email} '
                f'(lti={LTI_MODE}) -> creating temp user in perpare_group_review_exercise_for'
            )
            # temp_str distinguishes temp users created through LTI and outside of it
            # for the username is a unique field
            temp_str = 'lti-' if LTI_MODE else ''
            student = User(username=f"temp-{temp_str}{student_email}",
                           email=student_email,
                           lti=LTI_MODE,
                           temporary=True)
            student.save()

        if exercise.reviewable_exercise.submissions \
                                       .filter(submitter_user=student).exists():
            logger.info(f'Prev sub found for {student} --> not creating new')
        else:
            logger.info(f'Prev sub NOT FOUND for {student} --> creating new')
            osub = OriginalSubmission(
                course=course,
                exercise=exercise.reviewable_exercise,
                submitter_user=student,
                text=
                ("This is *automatically* created submission for group peer-review. "
                 "This is needed because every peer-review has to point to some original "
                 "submission."))
            osub.save()