Example #1
0
    def test_available_polls(self):
        Record.objects.create(student=self.student,
                              group=self.groups[0],
                              status=RecordStatus.ENROLLED)
        time_in_semester = self.semester.semester_beginning + (
            self.semester.semester_ending -
            self.semester.semester_beginning) / 2
        time_after_semester = self.semester.semester_ending + timedelta(days=1)
        with freeze_time(time_after_semester):
            # When semester is gone, no Polls should be available.
            self.assertListEqual(Poll.get_all_polls_for_student(self.student),
                                 [])
        with freeze_time(time_in_semester):
            # When grade is closed, no Polls should be available.
            self.assertListEqual(Poll.get_all_polls_for_student(self.student),
                                 [])

        self.semester.is_grade_active = True
        self.semester.save()
        with freeze_time(time_after_semester):
            # This still should be empty.
            self.assertListEqual(Poll.get_all_polls_for_student(self.student),
                                 [])
        with freeze_time(time_in_semester):
            # Three Polls should be available to the student.
            self.assertEqual(len(Poll.get_all_polls_for_student(self.student)),
                             3)
Example #2
0
def get_poll_data(request):
    """Lists Polls available to the student.

    The response follows the format:
    [
        # Every poll comes in a record.
        {
            "key": {
                "n": 12345...,
                "e": 12345...,
            },
            "poll_info": {
                "id": 123,
                # Name and Type only serve as a description. Name specifies the
                # exact poll (exam, group), Type says which course it concerns.
                "name": "Egzamin: Zbigniew Religa",
                "type": "Przeszczep serca dla zuchwałych",
            }
        },
    ]
    """
    students_polls = Poll.get_all_polls_for_student(request.user.student)
    keys = RSAKeys.objects.filter(poll__in=students_polls).select_related(
        'poll', 'poll__group', 'poll__course', 'poll__semester')
    response_data = []
    for key in keys:
        poll = key.poll
        poll_data = {
            'key': key.serialize_for_signing_protocol(),
            'poll_info': poll.serialize_for_signing_protocol(),
        }
        response_data.append(poll_data)
    return JsonResponse(response_data, safe=False)
Example #3
0
def make_poll_from_template(request, template):
    """Returns a poll object based on the template.

    Raises:
        Employee.DoesNotExist: If the user is not an employee.
    """
    poll = Poll()
    poll.author = request.user.employee
    poll.title = template['title']
    poll.description = template['description']
    poll.semester = template['semester']
    poll.group = template['iterate_group']
    poll.studies_type = template['studies_type']
    poll.save()

    return poll
Example #4
0
 def test_polls_list(self):
     c = test.Client()
     time_in_semester = self.semester.semester_beginning + (
         self.semester.semester_ending -
         self.semester.semester_beginning) / 2
     with freeze_time(time_in_semester):
         c.force_login(self.student.user)
         polls = Poll.get_all_polls_for_student(self.student)
         keys = RSAKeys.objects.filter(poll__in=polls)
         self.assertEqual(len(keys), len(polls))
         r = c.get('/grade/ticket/get-poll-data')
         self.assertEqual(len(r.json()), len(polls))
Example #5
0
def make_polls_for_groups(request, groups, template):
    polls = []

    origin = Origin()
    origin.save()
    for group in groups:
        if template['groups_without'] == 'on' and Poll.get_all_polls_for_group(
                group, template.semeter).count() > 0:
            continue

        poll = make_poll(request, template, group, origin)
        polls.append(str(poll))

    if not len(polls):
        raise NoPollException
    return polls
Example #6
0
def generate_keys_for_polls(semester=None):
    from apps.enrollment.courses.models.semester import Semester
    if not semester:
        semester = Semester.get_current_semester()
    poll_list = Poll.get_polls_without_keys(semester)
    pub_list = []
    priv_list = []
    i = 1
    for el in poll_list:
        (pub, priv) = generate_rsa_key()
        pub_list.append(pub)
        priv_list.append(priv)
        i = i + 1
    save_public_keys(list(zip(poll_list, pub_list)))
    save_private_keys(list(zip(poll_list, priv_list)))
    print(i - 1)
    return
Example #7
0
def sign_tickets(request):
    """Signs the tickets sent by a student and returns list of signatures.

    The student must request to sign all the tickets he is entitled to. The
    signing may only be performed once in a semester.

    Request must be a dict of objects:
    {
        "signing_requests": [
            # An object for every poll.
            {
                # Id of the poll.
                "id": 123,
                # A blinded ticket.
                "ticket": 12345...,
            },
        ]
    }

    Returns:
        A list of signed tickets, each being a dict like below.
        {
            # Id of the poll.
            'id': 123,
            # The ticket from the request signed using a private key
            # corresponding to the poll.
            'signature': 1234...
        }

    Errors:
        400 BadRequest: When JSON request could not be parsed.
        403 Forbidden: When the student tries to sign a ticket for a poll he is
        not entitled to, fails to request a ticket he is entitled to, or has
        already been signing this semester.
    """
    try:
        signing_requests_dict = json.loads(request.body.decode('utf-8'))
    except json.decoder.JSONDecodeError:
        return HttpResponseBadRequest("Couldn't parse JSON")

    signing_requests = signing_requests_dict['signing_requests']
    semester = Semester.get_current_semester()
    student_polls = {
        poll.pk
        for poll in Poll.get_all_polls_for_student(request.user.student,
                                                   semester)
    }
    request_polls = {int(req['id']) for req in signing_requests}

    if request_polls - student_polls:
        return HttpResponseForbidden(
            f"Student nie jest upoważniony do tych ankiet: {request_polls - student_polls}."
        )
    if student_polls - request_polls:
        return HttpResponseForbidden(
            f"Student powinien również wygenerować bilety dla tych "
            "ankiet: {student_polls - request_polls}.")
    if len(request_polls) != len(signing_requests):
        return HttpResponseForbidden(
            f"Próbowano podpisać wiele biletów do jednej ankiety.")
    # Now we made sure that student_polls == request_polls

    # We obtain a lock on RSA keys.
    keys = RSAKeys.objects.filter(poll__in=request_polls).select_for_update()
    keys_by_poll = {key.poll_id: key for key in keys}

    _, created = StudentGraded.objects.get_or_create(
        student=request.user.student, semester=semester)
    if not created:
        return HttpResponseForbidden(
            f"Student już podpisywał bilety w tym semestrze.")

    response = []
    for signing_request in signing_requests:
        key = keys_by_poll[int(signing_request['id'])]
        signed_ticket = key.sign_ticket(signing_request['ticket'])
        signing_response = {
            'id': signing_request['id'],
            'signature': str(signed_ticket),
        }
        response.append(signing_response)
    return JsonResponse(response, safe=False)
Example #8
0
def get_grouped_polls(student: Student) -> Dict:
    """Groups polls into a format used by the grade/ticket_create app."""
    polls = Poll.get_all_polls_for_student(student)

    return group_submissions(polls)
Example #9
0
    def handle(self, *args, **kwargs):
        semester_id = kwargs["semester"]
        created, skipped = 0, 0

        if semester_id:
            semester = Semester.objects.get(id=semester_id)
        else:
            semester = Semester.get_current_semester()

        self.stdout.write(f"Selected semester: `{semester}` with id {semester.id}")

        # Check whether poll exists for a selected semester
        self.stdout.write(f"\n{HEADER}Semester polls")
        semester_poll = Poll.objects.filter(semester=semester).count() > 0
        if semester_poll:
            self.stdout.write(f"{MARGIN}Poll for a selected semester already exists")
            skipped += 1
        else:
            new_poll = Poll(group=None, course=None, semester=semester)
            new_poll.save()
            self.stdout.write(
                f"{CREATED}Poll for a selected semester does not exist, creating"
            )
            created += 1

        # Check whether poll exists for courses held in a selected semester
        self.stdout.write(f"\n{HEADER}Course/group polls")
        courses = CourseInstance.objects.filter(semester=semester)

        for course in courses:
            course_poll = Poll.objects.filter(course=course).count() > 0
            if not course.has_exam or course_poll:
                self.stdout.write(f"{MARGIN}{course}")
                skipped += 1
            else:
                new_poll = Poll(group=None, course=course, semester=None)
                new_poll.save()
                self.stdout.write(f"{CREATED}{course}")
                created += 1

            groups = Group.objects.filter(course=course)

            for group in groups:
                group_poll = Poll.objects.filter(group=group).count() > 0
                if group_poll:
                    self.stdout.write(f"{MARGIN}{MARGIN}{group}")
                    skipped += 1
                else:
                    new_poll = Poll(group=group, course=None, semester=None)
                    new_poll.save()
                    self.stdout.write(f"{CREATED}{MARGIN}{group}")
                    created += 1

        self.stdout.write(f"\n{HEADER}Summary")
        self.stdout.write(f"{MARGIN}Created: {created}, skipped: {skipped}")
Example #10
0
    def get(self, request, semester_id=None, poll_id=None, submission_id=None):
        """Controls the main logic of passing the data to the template
        responsible for presenting the results of the poll.

        :param semester_id: if given, fetches polls from requested semester.
        :param poll_id: if given, displays summary for a given poll.
        :param submission_id: if given, displays detailed submission view.
        """
        is_grade_active = check_grade_status()
        if semester_id is None:
            semester_id = Semester.get_current_semester().id
        current_semester = Semester.get_current_semester()
        selected_semester = Semester.objects.filter(pk=semester_id).get()

        available_polls = Poll.get_all_polls_for_semester(
            user=request.user, semester=selected_semester)
        current_poll = Poll.objects.filter(id=poll_id).first()
        if poll_id is not None:
            submissions = Submission.objects.filter(
                poll=poll_id, submitted=True).order_by('modified')
            if current_poll not in available_polls:
                # User does not have permission to view details about
                # the selected poll
                messages.error(
                    request, "Nie masz uprawnień do wyświetlenia tej ankiety.")
                return redirect('grade-poll-results', semester_id=semester_id)
        else:
            submissions = []

        semesters = Semester.objects.all()

        if request.user.is_superuser or request.user.employee:
            return render(
                request,
                self.template_name,
                {
                    'is_grade_active':
                    is_grade_active,
                    'polls':
                    group(entries=available_polls, sort=True),
                    'results':
                    self.__get_processed_results(submissions),
                    'results_iterator':
                    itertools.count(),
                    'semesters':
                    semesters,
                    'current_semester':
                    current_semester,
                    'current_poll_id':
                    poll_id,
                    'current_poll':
                    current_poll,
                    'selected_semester':
                    selected_semester,
                    'submissions_count':
                    self.__get_counter_for_categories(available_polls),
                    'iterator':
                    itertools.count(),
                },
            )

        messages.error(request,
                       "Nie masz uprawnień do wyświetlania wyników oceny.")
        return redirect('grade-main')
Example #11
0
def make_poll(request, template, group=None, origin=None):
    """Prepares a poll object for the group based on the template.

    Raises:
        Employee.DoesNotExist: If the user in the request is not an employee.
    """
    poll = Poll()
    poll.author = request.user.employee
    poll.title = template['title']
    poll.description = template['description']
    poll.semester = template['semester']
    poll.group = group
    poll.studies_type = template['studies_type']
    poll.origin = origin
    poll.save()

    make_section_for_poll(request, poll, template)
    return poll