def has_object_permission(self, request, view, obj):
            try:
                fdbk_category = ag_models.FeedbackCategory(
                    request.query_params.get('feedback_category'))
            except KeyError:
                raise exceptions.ValidationError(
                    {'feedback_category': 'Missing required query param: feedback_category'})
            except ValueError:
                raise exceptions.ValidationError(
                    {'feedback_category': 'Invalid feedback category requested: {}'.format(
                        request.query_params.get('feedback_category'))})

            submission = get_submission_fn(obj)
            group = submission.group
            project = group.project
            course = project.course
            deadline_past = _deadline_is_past(submission)

            in_group = group.members.filter(pk=request.user.pk).exists()
            if course.is_staff(request.user):
                # Staff can always request any feedback category for
                # their own submissions.
                if in_group:
                    return True

                # Staff can always request staff_viewer feedback
                # for other groups' submissions.
                if fdbk_category == ag_models.FeedbackCategory.staff_viewer:
                    return True

                # Staff can only request staff_viewer or max feedback
                # for other groups' submissions.
                if fdbk_category != ag_models.FeedbackCategory.max:
                    return False

                # Staff can only request max feedback for other groups'
                # ultimate submissions if the project deadline and group's
                # extension have passed.
                group_ultimate_submission = get_ultimate_submission(group)
                return deadline_past and group_ultimate_submission == submission

            # Non-staff users cannot view other groups' submissions
            if not group.members.filter(pk=request.user.pk).exists():
                return False

            if fdbk_category == ag_models.FeedbackCategory.normal:
                return not submission.is_past_daily_limit

            if fdbk_category == ag_models.FeedbackCategory.past_limit_submission:
                return submission.is_past_daily_limit

            if fdbk_category == ag_models.FeedbackCategory.ultimate_submission:
                user_ultimate_submission = get_ultimate_submission(group, request.user)
                return (not project.hide_ultimate_submission_fdbk
                        and user_ultimate_submission == submission
                        and deadline_past)

            return False
示例#2
0
    def test_two_best_dont_count_for_user(self):
        self.project.validate_and_update(
            ultimate_submission_policy=ag_models.UltimateSubmissionPolicy.best)

        suite = ag_models.StudentTestSuite.objects.validate_and_create(
            name='suite',
            project=self.project,
            buggy_impl_names=[f'bug{i}' for i in range(3)],
            points_per_exposed_bug=1)

        best_submission = obj_build.make_finished_submission(
            self.group,
            does_not_count_for=[self.does_not_count_for_user.username])
        ag_models.StudentTestSuiteResult.objects.validate_and_create(
            student_test_suite=suite,
            submission=best_submission,
            bugs_exposed=suite.buggy_impl_names)
        self.assertEqual(
            3,
            get_submission_fdbk(best_submission,
                                ag_models.FeedbackCategory.max).total_points)

        second_best_submission = obj_build.make_finished_submission(
            self.group,
            does_not_count_for=[self.does_not_count_for_user.username])
        ag_models.StudentTestSuiteResult.objects.validate_and_create(
            student_test_suite=suite,
            submission=second_best_submission,
            bugs_exposed=suite.buggy_impl_names[:-1])
        self.assertEqual(
            2,
            get_submission_fdbk(second_best_submission,
                                ag_models.FeedbackCategory.max).total_points)

        other_submission = obj_build.make_finished_submission(self.group)
        self.assertEqual(
            0,
            get_submission_fdbk(other_submission,
                                ag_models.FeedbackCategory.max).total_points)

        counts_for_user_ultimate_submission = get_ultimate_submission(
            self.group, user=self.counts_for_user)
        self.assertEqual(best_submission, counts_for_user_ultimate_submission)

        does_not_count_for_user_ultimate_submission = get_ultimate_submission(
            self.group, user=self.does_not_count_for_user)
        self.assertEqual(other_submission,
                         does_not_count_for_user_ultimate_submission)
    def create(self, *args, **kwargs):
        """
        Creates a new HandgradingResult for the specified Group, or returns
        an already existing one.
        """
        group = self.get_object()
        try:
            handgrading_rubric = group.project.handgrading_rubric
        except ObjectDoesNotExist:
            raise exceptions.ValidationError(
                {'handgrading_rubric':
                    'Project {} has not enabled handgrading'.format(group.project.pk)})

        ultimate_submission = get_ultimate_submission(group)
        if not ultimate_submission:
            raise exceptions.ValidationError(
                {'num_submissions': 'Group {} has no submissions'.format(group.pk)})

        handgrading_result, created = handgrading_models.HandgradingResult.objects.get_or_create(
            defaults={'submission': ultimate_submission},
            handgrading_rubric=handgrading_rubric,
            group=group)

        for criterion in handgrading_rubric.criteria.all():
            handgrading_models.CriterionResult.objects.get_or_create(
                defaults={'selected': False},
                criterion=criterion,
                handgrading_result=handgrading_result,
            )

        serializer = self.get_serializer(handgrading_result)
        return response.Response(
            serializer.data, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)
示例#4
0
    def test_no_submissions_count_for_user(self):
        oldest_submission = obj_build.make_finished_submission(
            self.group,
            does_not_count_for=[self.does_not_count_for_user.username])
        most_recent_submission = obj_build.make_finished_submission(
            self.group,
            does_not_count_for=[self.does_not_count_for_user.username])

        counts_for_user_ultimate_submission = get_ultimate_submission(
            self.group, user=self.counts_for_user)
        self.assertEqual(most_recent_submission,
                         counts_for_user_ultimate_submission)

        does_not_count_for_user_ultimate_submission = get_ultimate_submission(
            self.group, user=self.does_not_count_for_user)
        self.assertIsNone(does_not_count_for_user_ultimate_submission)
示例#5
0
    def test_most_recent_does_not_count_for_user(self):
        self.project.validate_and_update(ultimate_submission_policy=ag_models.
                                         UltimateSubmissionPolicy.most_recent)

        oldest_submission = obj_build.make_finished_submission(self.group)
        most_recent_submission = obj_build.make_finished_submission(
            self.group,
            does_not_count_for=[self.does_not_count_for_user.username])

        counts_for_user_ultimate_submission = get_ultimate_submission(
            self.group, user=self.counts_for_user)
        self.assertEqual(most_recent_submission,
                         counts_for_user_ultimate_submission)

        does_not_count_for_user_ultimate_submission = get_ultimate_submission(
            self.group, user=self.does_not_count_for_user)
        self.assertEqual(oldest_submission,
                         does_not_count_for_user_ultimate_submission)
示例#6
0
    def test_get_ultimate_submission(self):
        data = self.prepare_data(self.project)
        group = data[0].group
        best_sub = data[0].best_submission
        most_recent = data[0].most_recent_submission

        print(group.submissions.count())
        print(group.submissions.all())

        self.assertEqual(ag_models.UltimateSubmissionPolicy.most_recent,
                         self.project.ultimate_submission_policy)
        ultimate_most_recent = get_ultimate_submission(group)
        self.assertEqual(most_recent, ultimate_most_recent)

        self.project.validate_and_update(
            ultimate_submission_policy=ag_models.UltimateSubmissionPolicy.best)
        ultimate_best = get_ultimate_submission(group)
        self.assertEqual(best_sub, ultimate_best)
示例#7
0
    def test_get_ultimate_submission_no_finished_submissions(self):
        for policy in ag_models.UltimateSubmissionPolicy:
            self.project.validate_and_update(ultimate_submission_policy=policy)
            group = obj_build.make_group(project=self.project)
            submission = obj_build.make_submission(group=group)

            self.assertEqual(1, group.submissions.count())
            self.assertNotEqual(
                ag_models.Submission.GradingStatus.finished_grading,
                submission.status)
            ultimate_submission = get_ultimate_submission(group)
            self.assertIsNone(ultimate_submission)
示例#8
0
    def test_get_ultimate_submission_group_has_no_submissions(self):
        group_with_submissions_data = self.prepare_data(self.project)[0]

        self.project.validate_and_update(ultimate_submission_policy=ag_models.
                                         UltimateSubmissionPolicy.most_recent)
        group_with_no_submissions = obj_build.make_group(project=self.project)

        self.assertEqual(0, group_with_no_submissions.submissions.count())
        ultimate_submission = get_ultimate_submission(
            group_with_no_submissions)
        self.assertIsNone(ultimate_submission)

        ultimate_submissions = [
            fdbk.submission for fdbk in get_ultimate_submissions(
                self.project,
                filter_groups=None,
                ag_test_preloader=AGTestPreLoader(self.project))
        ]
        self.assertSequenceEqual(
            [group_with_submissions_data.most_recent_submission],
            ultimate_submissions)

        self.project.validate_and_update(
            ultimate_submission_policy=ag_models.UltimateSubmissionPolicy.best)

        self.assertEqual(0, group_with_no_submissions.submissions.count())
        ultimate_submission = get_ultimate_submission(
            group_with_no_submissions)
        self.assertIsNone(ultimate_submission)

        ultimate_submissions = [
            fdbk.submission for fdbk in get_ultimate_submissions(
                self.project,
                filter_groups=None,
                ag_test_preloader=AGTestPreLoader(self.project))
        ]
        self.assertSequenceEqual([group_with_submissions_data.best_submission],
                                 ultimate_submissions)
示例#9
0
    def test_get_ultimate_submission_group_has_no_submissions(self):
        for policy in ag_models.UltimateSubmissionPolicy:
            self.project.validate_and_update(ultimate_submission_policy=policy)
            group = obj_build.make_group(project=self.project)

            self.assertEqual(0, group.submissions.count())
            ultimate_submission = get_ultimate_submission(group)
            self.assertIsNone(ultimate_submission)

            ultimate_submissions = list(
                get_ultimate_submissions(self.project,
                                         filter_groups=[group],
                                         ag_test_preloader=AGTestPreLoader(
                                             self.project)))
            self.assertSequenceEqual([], ultimate_submissions)
示例#10
0
    def ultimate_submission(self, request, *args, **kwargs):
        """
        Permissions details:
        - The normal group and submission viewing permissions apply
          first.
        - Staff members can always view their own ultimate submission.
        - Staff members can only view student and other staff ultimate
          submissions if the project closing time has passed.
        - If the project closing time has passed, staff can view student
          and other staff ultimate submissions regardless of whether
          ultimate submissions are marked as hidden.
        - Students can view their ultimate submissions as long as the
          closing time has passed and ultimate submissions are not
          overridden as being hidden.
        """
        group = self.get_object()
        ultimate_submission = get_ultimate_submission(group, user=request.user)
        if ultimate_submission is None:
            return response.Response(status=status.HTTP_404_NOT_FOUND)

        return response.Response(
            ag_serializers.SubmissionSerializer(ultimate_submission).data)
示例#11
0
def serialize_ultimate_submission_results(ultimate_submissions: Iterable[SubmissionResultFeedback],
                                          *, full_results: bool,
                                          include_handgrading: bool = False) -> List[dict]:
    """
    Returns serialized ultimate submission data for each user in the
    groups linked to ultimate_submissions.
    This function also accounts for submissions that don't count for
    a partecular user due to late day usage.

    :param ultimate_submissions:
    :param full_results: Whether to include information about individual
        test cases.
    :param include_handgrading:
    :return: [
        {
            "username": <username>,
            "group": <group>,
            "ultimate_submission": {
                "results": {
                    "total_points": <int>,
                    "total_points_possible": <int>,

                    // Only present if full_points is True
                    "ag_test_suite_results": [<ag test suite result details>],
                    "student_test_suite_results": [<student test suite result details>],

                    // Only present if include_handgrading is True
                    "handgrading_total_points": <int>,
                    "handgrading_total_points_possible": <int>
                },
                <submission data>
            }
        },
        ...
    ]
    """
    results = []
    for submission_fdbk in ultimate_submissions:
        submission = submission_fdbk.submission
        group = submission.group
        if group.extended_due_date is not None and group.extended_due_date > timezone.now():
            submission_data = None
        else:
            submission_data = _get_submission_data_with_results(submission_fdbk, full_results,
                                                                include_handgrading)

        group_data = group.to_dict()

        for username in group.member_names:
            user_data = {
                'username': username,
                'group': group_data,
            }

            if username in submission.does_not_count_for:
                user_ultimate_submission = get_ultimate_submission(
                    group, group.members.get(username=username))
                # NOTE: Do NOT overwrite submission_data
                user_submission_data = _get_submission_data_with_results(
                    SubmissionResultFeedback(
                        user_ultimate_submission, ag_models.FeedbackCategory.max,
                        submission_fdbk.ag_test_preloader),
                    full_results,
                    include_handgrading
                )
                user_data['ultimate_submission'] = user_submission_data
            else:
                user_data['ultimate_submission'] = submission_data

            results.append(user_data)

    return results